7.2 KiB
ADDED Requirements
Requirement: Пары участников без встречных записей
Ядро SHALL вычислять по своду версии пары участников без встречных записей (§3 п. 9 05-domain-rules.md, AURORA-1746):
для участников периметра А ≠ Б (consolidation_member версии) пара (А, Б) входит в список, если в своде есть хотя бы одна
строка ЮЛ А с counterparty_id = Б (сохранённым или дорезолвленным на чтение) и нет ни одной строки ЮЛ Б с
counterparty_id = А. А — сторона, у которой записи есть (holder), Б — сторона без встречных записей (missing).
Пара, где записей нет ни у А, ни у Б, в список MUST NOT входить. Строки ЮЛ с контрагентом — самим собой не
учитываются. Счета, суммы и тип строки (data_type) на признак не влияют: учитываются все строки свода. Расчёт —
чистая функция в domain/ от строк свода и периметра; результат MUST NOT сохраняться. Порядок списка — по имени Б,
затем по имени А.
У каждой пары SHALL быть: holder_id, holder_name, missing_id, missing_name, holder_rows (число строк А с
контрагентом Б), missing_unmapped_rows (число строк Б с unmapped = true), missing_rows_total (число всех строк Б в
своде; 0 — у Б нет строк, например не привязано ни одной ОСВ или все её пары счетов — пробелы).
Scenario: Русский бисквит до сопоставления
- WHEN версия ГК «Русский бисквит» 2024 Q3 с периметром {АО «Русский бисквит», ООО «Пекарня Счастливочная»}, 22 ОСВ
из
fixtures/osv/{rb,schastl}/2024-Q{1,2,3}подтверждены; у Счастливочной контрагент «Русский бисквит» с ИНН 3528052718 сопоставлен по ИНН; у РБ контрагент «Пекарня Счастливочная ООО» без ИНН не сопоставлен - THEN список содержит одну пару:
holder— ООО «Пекарня Счастливочная»,missing— АО «Русский бисквит»,holder_rows≥ 1,missing_unmapped_rows≥ 1
Scenario: Пара закрыта ручным сопоставлением
- WHEN в той же версии строка РБ «Пекарня Счастливочная ООО» связана с ООО «Пекарня Счастливочная»
(
POST …/osv/entries/{entry_id}/counterparty) - THEN список пар пуст
Scenario: Компании не связаны
- WHEN в периметре три участника; у А и Б нет записей друг с другом ни в одну сторону
- THEN пары (А, Б) и (Б, А) в списке нет
Scenario: У стороны нет строк
- WHEN у А есть строки с контрагентом Б, а у Б в своде нет ни одной строки (ОСВ не привязаны)
- THEN пара (А, Б) в списке,
missing_rows_total = 0,missing_unmapped_rows = 0
MODIFIED Requirements
Requirement: Страница свода и сводка
GET …/osv (CONSOLIDATION_VIEW, policy) SHALL отдавать Page строк свода в порядке: имя ЮЛ, account_code,
row_number, первый entry_id; limit ≤ 2000 (по умолчанию 500). Фильтры: legal_entity_id, account_root,
counterparty_type, counterparty_id (строка с этим counterparty_id после дорезолва; AURORA-1746), unmapped=true
(строка требует сопоставления: counterparty_id пуст после дорезолва и counterparty_inn пуст или из пробелов;
строка с ИНН из файла, которого нет в справочнике, сопоставления не требует — решение владельца 08.10.2026, отмена П-1;
unmapped=false — все остальные строки), match_kind (повторяемый), q (подстрока без регистра в counterparty_name
или префикс counterparty_inn). Те же фильтры SHALL принимать GET …/osv/export. GET …/osv/summary SHALL отдавать
rows_total, unmapped_total (строки unmapped=true), auto_matched_total (строки с match_kind ∈ {NAME, ALIAS}
независимо от match_stored), documents_total (привязанные ОСВ-документы), gaps[] (legal_entity_id,
legal_entity_name, account_code, missing_quarters) и counter_pairs[] — пары участников без встречных записей
(требование «Пары участников без встречных записей»). Версия в любом статусе, включая CANCELLED, SHALL читаться.
Scenario: Только несопоставленные
- WHEN запрошено
GET …/osv?unmapped=true - THEN все строки ответа с
counterparty_id = nullи безcounterparty_inn,total=summary.unmapped_total
Scenario: Строка с ИНН вне справочника не требует сопоставления
- WHEN у строки
counterparty_inn = "7701000001", такого ИНН и имени в справочнике нет (counterparty_id = null) - THEN строки нет в
GET …/osv?unmapped=true, она не входит вsummary.unmapped_total
Scenario: ИНН сопоставленного ЮЛ
- WHEN строка без ИНН в файле сопоставлена с ЮЛ по алиасу (на лету или хранимо)
- THEN
counterparty_inn = null,counterparty_entity_inn— ИНН этого ЮЛ из справочника
Scenario: Фильтр по способу
- WHEN запрошено
GET …/osv?match_kind=NAME&match_kind=ALIAS - THEN в ответе только строки с этими
match_kind,total=summary.auto_matched_total
Scenario: Строки одной стороны пары
- WHEN в
summary.counter_pairsесть параholder_id = А,missing_id = Би запрошеноGET …/osv?legal_entity_id=А&counterparty_id=Б - THEN
total=holder_rowsпары, у всех строк ответа ЮЛ А иcounterparty_id = Б
Scenario: Кандидаты другой стороны пары
- WHEN для той же пары запрошено
GET …/osv?legal_entity_id=Б&unmapped=true - THEN
total=missing_unmapped_rowsпары