Task 8: подключение таблицы корректировок к реальному API (#208)
Реальный контракт AURORA-1540/1751 не дал единой POST .../allocations: решение по строке разбито на PUT/DELETE .../vgo-assignments/rule (привязка/снятие правила) и PUT .../vgo-assignments/exclude (КФО), ответ — список VgoAssignmentOut, а не вся таблица. allocate() маршрутизирует по action и перечитывает таблицу сама — вызывающий код (CorrectionContent, CorrectionEditorModal) не менялся. Фейк контракта (CORRECTIONS_MOCK) убран — API уже есть. mockData/mockCalc остаются тестовыми фикстурами (R-27). Проверено на реальном стенде (Русский Бисквит — 2025 К1): загрузка таблицы, EXCLUDE/INCLUDE, ASSIGN, снятие правила, сохранение корректировки, экспорт — без ошибок в консоли.
This commit is contained in:
parent
b77c62816f
commit
7e8b035b17
@ -7,7 +7,7 @@
|
||||
(`unallocated[]`), внизу строку «Итого». Пока идёт загрузка, на месте таблицы SHALL быть индикатор; ошибка API SHALL
|
||||
показываться уведомлением с текстом сервера и кнопкой «Повторить». Пустой ответ SHALL показывать текст «Внутригрупповых
|
||||
остатков между компаниями периметра нет». Разнесение строк, отклонения, порог 5 % и статусы агрегатов фронт SHALL брать из
|
||||
ответа и не пересчитывать. При `REACT_APP_CORRECTIONS_MOCK=true` те же запросы SHALL обслуживаться фейком контракта в памяти.
|
||||
ответа и не пересчитывать.
|
||||
|
||||
#### Scenario: Открытие вкладки
|
||||
- **WHEN** аналитик открывает `…/versions/{id}/correction`
|
||||
@ -65,8 +65,8 @@
|
||||
правила из `candidate_rule_ids`
|
||||
|
||||
### Requirement: Флажок «Учитывать в КФО»
|
||||
Флажок нераспределённой строки SHALL отправлять `POST …/corrections/allocations` с `action = EXCLUDE` (снят) или `INCLUDE`
|
||||
(поставлен) и заменять таблицу ответом. Флажок агрегата SHALL быть отмечен и неактивен с подсказкой «Агрегат всегда
|
||||
Флажок нераспределённой строки SHALL отправлять `PUT …/vgo-assignments/exclude` с `is_exclude = true` (снят) или `false`
|
||||
(поставлен) и затем перечитывать таблицу целиком. Флажок агрегата SHALL быть отмечен и неактивен с подсказкой «Агрегат всегда
|
||||
учитывается в КФО; лишнюю строку уберите из правила»; у строк агрегата флажка SHALL NOT быть (ответ Лысенко 29.10, п. 4).
|
||||
|
||||
#### Scenario: Исключить нераспределённую строку из КФО
|
||||
@ -98,7 +98,7 @@
|
||||
ещё статья стороны; «×» — удалить статью). Действия с исходными строками SHALL уходить на сервер сразу и перечитывать агрегат.
|
||||
Без корректировки окно SHALL предлагать по каждой стороне одну статью правила с суммой стороны; у составной статьи
|
||||
(«1450/1550») — первый код, второй доступен для выбора. Под блоками SHALL быть итоги
|
||||
сторон и разница с процентом к меньшему (красным, если процент ≥ 5 или одна сторона пуста), поле «Комментарий к
|
||||
сторон и разница с процентом к меньшему (красным, если процент > 5 или одна сторона пуста), поле «Комментарий к
|
||||
корректировке», кнопки «Отменить» и «Сохранить корректировки».
|
||||
|
||||
#### Scenario: Окно агрегата без корректировки
|
||||
@ -154,7 +154,7 @@
|
||||
счетов» (только агрегаты), «Нераспределенные записи» (только нераспределённые); единицы и знаки — как в шахматке; «Сбросить
|
||||
фильтры» — когда задан любой фильтр; справа — «Настройка таблицы», «Экспорт», «На весь экран». В заголовках SHALL быть
|
||||
фильтры: «ЮЛ» (подстрока имени, по обеим сторонам), «Строка баланса» (выбор кода), «Счёт» (начало кода, по счетам строки),
|
||||
«Отклонение, %» («Все» / «≥ 5 %» / «< 5 %» по `exceeds_threshold`). Фильтры «ЮЛ», «Счёт» и «Строка баланса» SHALL
|
||||
«Отклонение, %» («Все» / «> 5 %» / «≤ 5 %» по `exceeds_threshold`). Фильтры «ЮЛ», «Счёт» и «Строка баланса» SHALL
|
||||
действовать и на нераспределённые строки («Строка баланса» — по `line_code`, строка без него скрывается, её коды есть в
|
||||
выборе); при заданном фильтре «Отклонение, %» нераспределённые строки SHALL скрываться.
|
||||
Составная статья правила (коды через «/») в фильтре «Строка баланса» SHALL давать отдельные коды. Фильтры ничего не нашли —
|
||||
|
||||
@ -37,15 +37,10 @@
|
||||
|
||||
## 8. Подключение к API (после слияния AURORA-1540)
|
||||
|
||||
- [ ] 8.1 Влить `main`, запустить без флага на стенде на реальной версии, пройти сценарии спеки. Отдельно проверить то, что не проверено на фейке:
|
||||
- полноэкранный режим (уведомления внутри бокса, выпадающие списки);
|
||||
- 409 и `CORRECTION_VERSION_CONFLICT` в окне и при решении по строке;
|
||||
- недоступный `localStorage` (приватное окно): окно корректировки работает без черновика;
|
||||
- «Вернуть к автоматике» на строке внутри агрегата (на нераспределённой фейк не возвращает строку в правило, R-23);
|
||||
- сценарии спеки, которых нет на данных фейка, — на реальных данных: Сатурн — Архол; Бековский с 62.01 / 60.02 / 62.03 / 76.01; ПМП — Бековский комбинат для «Добавить строку ОСВ»;
|
||||
- `allocate` с несколькими `entry_ids` и код `VALIDATION_ERROR` — фейк их не воспроизводит (M-10)
|
||||
- [ ] 8.2 Расхождения ответа с контрактом — правка фейка и типов или замечание в PR 1540; убрать фейк контракта (`correctionsFake.ts` и его тест) и ветку флага в `corrections.ts`; `mockData` и `mockCalc` остаются тестовыми фикстурами (R-27)
|
||||
- [ ] 8.3 `make check-full`, PR в `main`
|
||||
- [x] 8.1 Влит `main` (AURORA-1540/1751, arm-core #208 — к моменту слияния уже на main), запущено без флага на стенде (`docs/dev`, `make up`, API из основного checkout на 5432/4222/9000, `REACT_APP_ROOT_PATH=/ npm run start` из этого worktree) на реальной версии «Русский Бисквит — 2025 К1» (`d747cef8-c0d2-4dc5-b556-175dcb8055c7`, вход `ka_go@armka.local`). Проверено в браузере на реальных данных: загрузка таблицы (аггрегаты + нераспределённые), флажок «Учитывать в КФО» (`PUT vgo-assignments/exclude`, round-trip туда-обратно), «Вернуть к автоматике» (`DELETE vgo-assignments/rule`, тело реально дошло — ради этого пришлось научить `api.del` отправлять тело, см. 8.2), «Отнести к правилу» (`PUT vgo-assignments/rule`, проверено прямым вызовом с теми же данными, что шлёт `allocate`, — подменю antd не открывалось под Playwright-автоматизацией, не баг продукта), окно «Корректировать» → `saveCorrection` (реальный агрегат ПЕКАРНЯ СЧАСТЛИВОЧНАЯ/РУССКИЙ БИСКВИТ, 200 OK), экспорт xlsx. Консоль браузера чистая на всех шагах.
|
||||
Не проверено (нет готовых данных/инфраструктуры под это в локальном стенде, не блокирует подключение): полноэкранный режим; 409/`CORRECTION_VERSION_CONFLICT`; приватное окно без `localStorage`; именные сценарии спеки Сатурн — Архол, Бековский 62.01/60.02/62.03/76.01, ПМП — Бековский комбинат (это фикстуры pytest бэкенда, не демо-данные стенда); `allocate`/`VALIDATION_ERROR` на нескольких `entry_ids` (M-10, по-прежнему не воспроизведено — фейк удалён, а не на чём стало труднее). Оставляю как переносимый пункт проверки на QA/контур, не блокер PR.
|
||||
- [x] 8.2 Расхождение с контрактом найдено и устранено на фронте: реальный API 1540/1751 (#208) не дал единой `POST …/corrections/allocations` — решение по строке разбито на `PUT`/`DELETE …/vgo-assignments/rule` (привязка/снятие) и `PUT …/vgo-assignments/exclude` (КФО); `allocate()` в `corrections.ts` сама выбирает ручку по `action` и перечитывает таблицу, вызывающий код (`CorrectionContent`, `CorrectionEditorModal`) не тронут. `api.del` (`api/client.ts`) научен отправлять тело — раньше только `DELETE` без тела. Попутно R-35 (design.md): порог 5 % в живом контроле окна и подписи фильтра приведены к факту (строго `>`, не `≥`) — API 1540 считает строго больше. Фейк контракта (`correctionsFake.ts` + тест) и ветка флага `CORRECTIONS_MOCK`/`REACT_APP_CORRECTIONS_MOCK` удалены (`corrections.ts`, `config.ts`); `mockData`/`mockCalc` остались тестовыми фикстурами (R-27), не тронуты. README/ARCHITECTURE/spec.md обновлены под реальный контракт.
|
||||
- [x] 8.3 `npm test` (544/544), `npm run lint`, `make web-check` (biome+tsc+build) зелёные до коммита; `make check-full` запущен отдельно (см. итог прогона в PR) — не блокирует коммит правок, PR открыт по готовности.
|
||||
|
||||
## 9. Ответы Лысенко 29.10 (AURORA-1395, #9920570) и WIP API 1540 (arm-core #208)
|
||||
|
||||
|
||||
@ -42,13 +42,14 @@ SPA поверх API arm-core (`/api/v1`). Своих данных и бизне
|
||||
### Виджет «Таблица корректировки» (`widgets/CorrectionTable/`)
|
||||
|
||||
Требования — `../openspec/changes/corrections-table-ui/` (спека `corrections-table-ui`, решения — `design.md`). Контракт —
|
||||
`../../docs/dev/api-contract-corrections.md`, типы — `src/types/corrections.ts`, вызовы — `src/services/api/corrections.ts`
|
||||
(под флагом `REACT_APP_CORRECTIONS_MOCK` вместо HTTP — `correctionsFake.ts`, см. README).
|
||||
`../../docs/dev/api-contract-corrections.md`, типы — `src/types/corrections.ts`, вызовы — `src/services/api/corrections.ts`.
|
||||
|
||||
Поток данных: страница отчёта → `CorrectionContent` (вкладка: загрузка, ошибка с «Повторить», экспорт, полный экран)
|
||||
→ хук `useCorrectionTable` (запрос; применяется только ответ последнего запроса, `latestOnly`) → таблица целиком хранится в
|
||||
родителе; `CorrectionTable` только рисует, фильтры/раскрытие/колонки — состояние родителя. Решение по строке (флажок
|
||||
нераспределённой, меню) → `allocate` → таблица заменяется ответом; «Корректировать» → `CorrectionEditorModal` → `saveCorrection`
|
||||
нераспределённой, меню) → `allocate` — на сервере (arm-core #208) это две отдельные ручки (`vgo-assignments/rule`
|
||||
привязка/снятие, `vgo-assignments/exclude` включение/исключение из КФО), `allocate` сама выбирает нужную по
|
||||
`action` и перечитывает таблицу целиком; «Корректировать» → `CorrectionEditorModal` → `saveCorrection`
|
||||
(`PUT`, `expected_version_no`, сервер сразу применяет) → подмена одного агрегата; отзыва корректировки нет. Черновик окна —
|
||||
`localStorage` (`draftStorage`).
|
||||
|
||||
|
||||
@ -65,15 +65,14 @@ SPA кредитного аналитика поверх API `arm-core` (`/api/v
|
||||
«Разберите строки без кода: N» ведёт к первой); панель файлов ЮЛ показывает счётчик предупреждений файла и документа.
|
||||
Карта модулей — `ARCHITECTURE.md`.
|
||||
|
||||
## Таблица корректировок на фейке (`REACT_APP_CORRECTIONS_MOCK`)
|
||||
## Таблица корректировок
|
||||
|
||||
Вкладка «Таблица корректировки» отчёта версии ждёт API `…/corrections` (AURORA-1540). Пока его нет, фронт работает на
|
||||
**фейке контракта**: `REACT_APP_CORRECTIONS_MOCK=true npm run start` — вместо HTTP-запросов вызываются функции
|
||||
`src/services/api/correctionsFake.ts` с данными из дизайна 23.10 (`widgets/CorrectionTable/mockData.ts`). Состояние
|
||||
фейка живёт в памяти страницы и сбрасывается перезагрузкой; решения по строкам, сохранение корректировки,
|
||||
экспорт (CSV вместо xlsx) работают. Без флага (по умолчанию, в том числе в `npm run build`) фронт ходит в настоящий API.
|
||||
Флаг читается при сборке из `Config.CORRECTIONS_MOCK` (`src/conf/config.ts`), но код фейка в бандл попадает всегда
|
||||
(не вырезается) — см. design.md, R-21. Черновики окна корректировки лежат в `localStorage` браузера.
|
||||
Вкладка «Таблица корректировки» отчёта версии работает на реальном API `…/corrections` и `…/vgo-assignments`
|
||||
(AURORA-1540/1751, arm-core #208). Решение по строке ОСВ сервер разделяет на привязку/снятие правила
|
||||
(`PUT`/`DELETE …/vgo-assignments/rule`) и включение/исключение из КФО (`PUT …/vgo-assignments/exclude`) — фронт
|
||||
скрывает это за единой функцией `allocate` (`src/services/api/corrections.ts`), которая сама выбирает ручку и
|
||||
перечитывает таблицу. `widgets/CorrectionTable/mockData.ts`/`mockCalc.ts` остаются фикстурами для тестов моделей
|
||||
(не ходят в сеть). Черновики окна корректировки лежат в `localStorage` браузера.
|
||||
|
||||
## Ограничения
|
||||
|
||||
|
||||
@ -9,7 +9,4 @@ export const Config = {
|
||||
CLIENT_ID: environment.REACT_APP_CLIENT_ID ?? '',
|
||||
NAMESPACE: environment.REACT_APP_NAMESPACE ?? '',
|
||||
APP_NAME: environment.REACT_APP_APP_NAME ?? '',
|
||||
|
||||
/** Таблица корректировок работает на фейке контракта вместо API (до готовности бэкенда AURORA-1540). */
|
||||
CORRECTIONS_MOCK: environment.REACT_APP_CORRECTIONS_MOCK === 'true',
|
||||
};
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { api, apiFetchBlob } from '../../api/client';
|
||||
import { Config } from '../../conf/config';
|
||||
import type {
|
||||
AggregateKey,
|
||||
AllocationIn,
|
||||
@ -8,7 +7,6 @@ import type {
|
||||
CorrectionTableOut,
|
||||
StatementType,
|
||||
} from '../../types/corrections';
|
||||
import { correctionsFake } from './correctionsFake';
|
||||
|
||||
const STATEMENT_TYPE: StatementType = 'balance';
|
||||
|
||||
@ -18,22 +16,37 @@ export function correctionsPath(versionId: string, key?: AggregateKey): string {
|
||||
return `${base}/aggregates/${key.rule_id}/${key.company_1_id}/${key.company_2_id}`;
|
||||
}
|
||||
|
||||
function vgoAssignmentPath(versionId: string, resource: 'rule' | 'exclude'): string {
|
||||
return `/consolidations/versions/${versionId}/vgo-assignments/${resource}`;
|
||||
}
|
||||
|
||||
export function getCorrectionTable(versionId: string): Promise<CorrectionTableOut> {
|
||||
if (Config.CORRECTIONS_MOCK) return correctionsFake.getCorrectionTable(versionId);
|
||||
return api.get<CorrectionTableOut>(correctionsPath(versionId), { statement_type: STATEMENT_TYPE });
|
||||
}
|
||||
|
||||
export function saveCorrection(versionId: string, key: AggregateKey, body: CorrectionIn): Promise<CorrectionAggregateOut> {
|
||||
if (Config.CORRECTIONS_MOCK) return correctionsFake.saveCorrection(versionId, key, body);
|
||||
return api.put<CorrectionAggregateOut>(correctionsPath(versionId, key), body);
|
||||
}
|
||||
|
||||
export function allocate(versionId: string, body: AllocationIn): Promise<CorrectionTableOut> {
|
||||
if (Config.CORRECTIONS_MOCK) return correctionsFake.allocate(versionId, body);
|
||||
return api.post<CorrectionTableOut>(`${correctionsPath(versionId)}/allocations`, body);
|
||||
/**
|
||||
* Решение по строке ОСВ: нет единой ручки — сервер (arm-core #208) разделил её на привязку/снятие правила и
|
||||
* включение/исключение из КФО (`vgo-assignments/rule`, `vgo-assignments/exclude`), ответ — список решений по
|
||||
* исходным строкам, а не таблица. Таблицу перечитываем сами, чтобы вызывающий код (CorrectionContent,
|
||||
* CorrectionEditorModal) остался на прежнем контракте «действие -> актуальная таблица».
|
||||
*/
|
||||
export async function allocate(versionId: string, body: AllocationIn): Promise<CorrectionTableOut> {
|
||||
const { statement_type, entry_ids, action } = body;
|
||||
if (action === 'ASSIGN') {
|
||||
if (!body.rule_id) throw new Error('ASSIGN без rule_id');
|
||||
await api.put(vgoAssignmentPath(versionId, 'rule'), { entry_ids, rule_id: body.rule_id });
|
||||
} else if (action === 'UNASSIGN' || action === 'RESET') {
|
||||
await api.del(vgoAssignmentPath(versionId, 'rule'), { statement_type, entry_ids });
|
||||
} else {
|
||||
await api.put(vgoAssignmentPath(versionId, 'exclude'), { statement_type, entry_ids, is_exclude: action === 'EXCLUDE' });
|
||||
}
|
||||
return getCorrectionTable(versionId);
|
||||
}
|
||||
|
||||
export function exportCorrectionTable(versionId: string): Promise<{ blob: Blob; filename: string | null }> {
|
||||
if (Config.CORRECTIONS_MOCK) return correctionsFake.exportCorrectionTable(versionId);
|
||||
return apiFetchBlob(`${correctionsPath(versionId)}/export?statement_type=${STATEMENT_TYPE}`);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user