# corrections-api Specification ## Purpose Предоставляет backend-контракт для просмотра, сохранения и экспорта корректировок агрегатов бухгалтерского баланса, вычисленных сервисом разнесения ОСВ. ## Requirements ### Requirement: Чтение таблицы корректировок Система SHALL вызывать сервис разнесения AURORA-1751 через `CorrectionAggregateSource` и возвращать его агрегаты ББ с компаниями, статьями, счетами, позициями, сопоставленными парами, суммами, отклонением и сохранённой корректировкой. GET MUST NOT записывать вычисленное разнесение, пары или корректировки в БД. #### Scenario: Чтение доступной версии - **WHEN** пользователь с правом просмотра запрашивает таблицу доступной версии - **THEN** система возвращает вычисленные агрегаты, сопоставленные пары и оставшиеся позиции в стабильном порядке - **THEN** в БД не создаются назначения или корректировки #### Scenario: Сопоставленная пара - **WHEN** сервис AURORA-1751 возвращает элемент в `matched` или `with_discrepancy` - **THEN** агрегат содержит `pairs` с обеими сторонами этого элемента - **THEN** каждая сторона пары содержит относящиеся к ней идентификаторы строк ОСВ, счета и сумму - **THEN** суммы и отклонение пары совпадают с результатом AURORA-1751 без повторного сопоставления в сервисе корректировок #### Scenario: Позиция без сопоставленной стороны - **WHEN** ручная или односторонняя позиция агрегата не входит ни в одну вычисленную пару - **THEN** она присутствует в соответствующей стороне агрегата без искусственно созданной встречной позиции ### Requirement: Расчёт отклонения и элиминации Система SHALL считать абсолютное отклонение и процент к меньшей положительной сумме без предварительного округления. При отклонении не более 5 % справочная сумма элиминации SHALL равняться меньшей сумме; остаток SHALL относиться к большей статье. #### Scenario: Отклонение не более пяти процентов - **WHEN** меньшая сторона положительна и отклонение составляет ровно 5 % или меньше - **THEN** сумма элиминации равна меньшей стороне - **THEN** разница остаётся в большей статье #### Scenario: Отклонение больше пяти процентов - **WHEN** отклонение больше 5 % - **THEN** агрегат помечается как требующий корректировки #### Scenario: Нулевая меньшая сторона - **WHEN** одна сторона равна нулю - **THEN** процент отклонения равен `null` - **THEN** агрегат считается односторонним ### Requirement: Сохранение корректировки агрегата Система SHALL атомарно заменять корневые и дочерние строки корректировки существующего агрегата. Комментарий после trim MUST быть непустым при каждом сохранении. Успешное сохранение SHALL устанавливать статус `APPLIED`. #### Scenario: Сохранение с комментарием - **WHEN** аналитик сохраняет допустимые суммы и статьи обеих сторон с непустым комментарием - **THEN** система полностью заменяет набор корректировки и возвращает `APPLIED` - **THEN** создаётся аудит `CORRECTION_CREATE` или `CORRECTION_EDIT` #### Scenario: Пустой комментарий - **WHEN** аналитик сохраняет корректировку с пустым или состоящим из пробелов комментарием - **THEN** система возвращает `COMMENT_REQUIRED` - **THEN** ни одна строка корректировки не изменяется #### Scenario: Ошибка одной дочерней строки - **WHEN** одна из сумм или статей недопустима - **THEN** весь запрос отклоняется без частичной записи ### Requirement: Конкурентное и статусное ограничение Система MUST разрешать изменение только владельцу активной блокировки редактируемой версии. Клиент SHALL передавать ожидаемую редакцию существующей корректировки. #### Scenario: Конфликт редакции - **WHEN** ожидаемая редакция не совпадает с текущей - **THEN** система возвращает `CORRECTION_VERSION_CONFLICT` без записи #### Scenario: Верифицированная версия - **WHEN** пользователь пытается сохранить корректировку после верификации версии - **THEN** система отклоняет изменение ### Requirement: XLSX-экспорт корректировок Система SHALL экспортировать таблицу одним листом XLSX. Строка агрегата SHALL сопровождаться следующими за ней раскрываемыми строками детализации; колонка правила у строки детализации SHALL быть пустой. Каждая сопоставленная пара SHALL занимать одну строку с одновременно заполненными колонками обеих компаний. #### Scenario: Экспорт ББ - **WHEN** пользователь экспортирует таблицу корректировок - **THEN** файл называется `Корректировки_<название ГК>_<год>_<квартал>.xlsx` - **THEN** книга содержит один лист с агрегатами, детализацией и итогами в рублях - **THEN** позиции сопоставленной пары не дублируются отдельными строками под той же парой - **THEN** ручные и односторонние позиции выводятся отдельными строками - **THEN** система создаёт событие аудита `EXPORT` ### Requirement: Граница этапа Система MUST NOT предоставлять в этом capability импорт XLSX, собственный алгоритм разнесения строк ОСВ, ручной перенос строк между правилами или операции изменения назначений. Вызов готового расчёта AURORA-1751 для чтения таблицы SHALL считаться интеграцией с источником, а не реализацией разнесения в capability корректировок. #### Scenario: Контракт этапа - **WHEN** публикуется OpenAPI этапа корректировок - **THEN** в нём отсутствуют операции импорта и назначения строк правилам ### Requirement: Инвалидация корректировки при ручном назначении После успешного ASSIGN/UNASSIGN система SHALL определять затронутые пары компаний непосредственно по `entry_ids` в `osv_entry` и переводить все их `APPLIED`-корректировки в `DRAFT`. Суммы, статьи и комментарий SHALL сохраняться. Операция MUST NOT выполнять полный расчёт `assignment_candidates`; статус `REVOKED` на этом этапе не устанавливается. #### Scenario: Изменено назначение строки пары компаний - **WHEN** аналитик назначает строку правилу или снимает назначение - **THEN** все `APPLIED`-корректировки этой пары компаний получают `DRAFT` - **THEN** корректировки других пар и уже находящиеся в `DRAFT` не изменяются