## 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.