68 lines
7.0 KiB
Markdown
68 lines
7.0 KiB
Markdown
## Why
|
||
|
||
AURORA-1746 и замечание заказчика (Циликов А.В., 23.10.2026, строка 10 чек-листа, AURORA-1865): «при загрузке ОСВ без
|
||
ИНН необходимо сопоставить все организации без ИНН… нужно, чтобы система несопоставленные организации считала внешними и
|
||
позволяла формировать консолидацию без прокликивания каждой».
|
||
|
||
Расчёт уже так работает: несопоставленный контрагент — «Внешний» (§3 п. 5), переход к шахматке не блокируется (решение
|
||
заказчика 16.10.2026, AURORA-1388). Ощущение обязательности создают баннер над сводом «Для перехода к следующему шагу
|
||
сопоставьте все внешние организации без ИНН» и модалка [31-00], которая всплывает при каждом уходе с «ОСВ», пока
|
||
`unmapped_total > 0`. Счётчик до нуля на реальных данных не доходит: в него попадают зарплата, подотчётные лица и прочие
|
||
строки без организации.
|
||
|
||
Для шахматки важны не все строки без ИНН, а только те, где прячется участник периметра. Признак этого — пара участников,
|
||
где у одного есть записи с другим, а у другого встречных записей нет. Такие пары и нужно показать аналитику перед
|
||
шахматкой, с местом для разбора (решение владельца 27.10.2026).
|
||
|
||
## What Changes
|
||
|
||
Репозиторий — arm-core (`api/`, `web/`). Срез 4 (сводная ОСВ), доработка. Правило — `05-domain-rules.md` §3 п. 9
|
||
(отдельный PR в docs).
|
||
|
||
- **Ядро.** Чистая функция «пары без встречных записей» в `domain/consolidated_osv.py`: для участников периметра А ≠ Б
|
||
пара (А, Б) — у А есть строка свода с `counterparty_id = Б`, у Б нет строки с `counterparty_id = А`. `GET …/osv/summary`
|
||
отдаёт список `counter_pairs[]`; `GET …/osv` и экспорт получают фильтр `counterparty_id`. Ничего не хранится.
|
||
- **Фронт, режим «Встречные записи».** Над сводом — переключатель «Свод | Встречные записи (N)». Во втором режиме: сверху
|
||
список пар, под ним две таблицы на всю ширину: строки А с контрагентом Б и строки Б без ИНН и без сопоставления с «Указать» (та же
|
||
модалка сопоставления, что в своде).
|
||
- **Фронт, модалка перед шахматкой.** Вместо [31-00] «Остались неуказанные ИНН» — «Нет встречных записей: N пар у M
|
||
участников», кнопки «Показать пары» / «Остаться» / «Перейти». Показывается при уходе с «ОСВ», если пары есть, один раз
|
||
на версию за сессию браузера и снова — если список пар изменился. Строки без ИНН сами по себе модалку не вызывают.
|
||
- **Фронт, баннер.** Текст без «сопоставьте все»: несопоставленные учитываются как внешние; счётчик «Осталось: N» и
|
||
кнопка «Показать ЮЛ без ИНН» остаются.
|
||
|
||
## Non-goals
|
||
|
||
- Подсветка строки-кандидата у Б по совпадению суммы с зеркальной суммой у А (правила элиминации) — отдельная задача.
|
||
- Хранение решения аналитика «встречных записей нет, это пропуск в учёте» — в БД ничего не пишется (решение владельца
|
||
27.10.2026); DBML не меняется.
|
||
- Отсев строк, не являющихся организациями (зарплата, подотчётники), из счётчика `unmapped_total`.
|
||
- Сверка по счетам и суммам внутри пары — это делает шахматка (§6).
|
||
- Поиск участника, ошибочно сопоставленного с другим ЮЛ: во второй (нижней) таблице показываются только несопоставленные строки без ИНН.
|
||
- Строки Б с ИНН из файла, которого нет в справочнике (старый ИНН, опечатка): по решению 08.10.2026 они не требуют
|
||
сопоставления, в правую таблицу не попадают, и такая пара из режима не закрывается. Оставлено как есть (решение
|
||
владельца 27.10.2026), разбор — отдельная задача Jira; модалка и пустое состояние называют эту причину.
|
||
|
||
## Capabilities
|
||
|
||
### New Capabilities
|
||
|
||
### Modified Capabilities
|
||
|
||
- `consolidated-osv`: ADDED «Пары участников без встречных записей»; MODIFIED «Страница свода и сводка» (фильтр
|
||
`counterparty_id`, `counter_pairs[]` в сводке).
|
||
- `consolidated-osv-ui`: ADDED «Режим «Встречные записи»», ADDED «Баннер строк без ИНН».
|
||
- `consolidations-ui`: REMOVED «Предупреждение «Остались неуказанные ИНН»»; ADDED «Предупреждение «Нет встречных
|
||
записей»».
|
||
|
||
## Impact
|
||
|
||
- Таблицы DBML v5.23 — только чтение: `consolidation_member`, `osv_entry`, `legal_entity`, `consolidation_document`.
|
||
- `api/src/domain/consolidated_osv.py`, `api/src/services/consolidated_osv.py`, `api/src/schemas/consolidations.py`,
|
||
`api/src/api/endpoints/consolidations/osv.py` (+ export), тесты `api/tests/`.
|
||
- `web/src/widgets/ConsolidatedOsvContent/`, `web/src/widgets/ConsolidatedOsv/` (`OsvTabs.tsx`, новый режим),
|
||
`web/src/layouts/ConsolidationReportPage.tsx`, `web/src/utils/consolidations.ts`, `web/src/services/api/osv.ts`,
|
||
`web/src/types/api.ts`.
|
||
- Документация: `../docs/context/05-domain-rules.md` §3 п. 9, `../docs/context/10-user-journey.md` (строка 3.1),
|
||
`../docs/dev/api-contract-slice-4.md` — отдельный PR в docs.
|