Skip to content

feat: отдавать сумму иска числом в /extract - #17

Open
Gyxer513 wants to merge 1 commit into
legalops-toolkit:mainfrom
Gyxer513:feat/numeric-claim-amount
Open

feat: отдавать сумму иска числом в /extract#17
Gyxer513 wants to merge 1 commit into
legalops-toolkit:mainfrom
Gyxer513:feat/numeric-claim-amount

Conversation

@Gyxer513

Copy link
Copy Markdown
Contributor

feat: отдавать сумму иска числом в /extract

Проблема

Ответ /extract нельзя передать в /generate/claim как есть. Сумма отдаётся
только строкой в том виде, в каком она стояла в тексте решения, а
/generate/claim и /generate/appeal принимают claim_amount как
float > 0:

POST /extract   → {"claim_amount": "500 000", ...}
POST /generate/claim  ждёт  {"claim_amount": 500000.0, ...}

То есть клиент обязан сам убрать пробелы и заменить запятую на точку — при
том что весь сценарий продукта состоит ровно из связки «разобрали решение →
сгенерировали документ». Две половины сервиса не стыкуются в одном месте, и
именно там, где стык и предполагался.

Что сделано

В ExtractionResult добавлено поле claim_amount_value (float | None)
рядом с прежним claim_amount. Строка остаётся нетронутой: она передаёт
исходное написание, которое может понадобиться для сверки с текстом решения.
Добавление обратно совместимое — существующие поля не изменились, старые
клиенты ничего не заметят.

Разбор вынесен в parse_amount(): пробелы, включая неразрывные, убираются
целиком, запятая приводится к точке. Не разобравшаяся строка даёт None, а не
ноль — ноль в исковом заявлении хуже пустого поля, и /generate/* его всё
равно отклонят валидацией gt=0.

Что стоит обсудить на ревью

Неоднозначность «500.000». Точка здесь может означать и разделитель
разрядов, и копейки. Текущий разбор считает её десятичной и вернёт 500.0.
Формально это следует из паттерна claim_amount, который допускает
единственный разделитель и только в конце. В русских судебных актах разряды
разделяются пробелом, а копейки — запятой, так что случай редкий, но при
желании закрывается отдельным правилом: точка с ровно тремя цифрами после неё
— разряды, с двумя — копейки. Не стал делать, потому что эвристика тоже
ошибается, а тихо ошибиться в сумме иска дороже, чем отдать строку как есть.

Почему отдельное поле, а не смена типа claim_amount. Смена типа была бы
breaking-изменением ради косметики, а исходное написание при этом потерялось
бы. Два поля рядом честнее: одно про то, что написано в документе, другое про
то, что можно посчитать.

Проверка

  • parse_amount — параметризованные тесты, включая неразрывный пробел,
    копейки через запятую и через точку, а также ноль и пустую строку.
  • Сквозной тест в test_api.py прогоняет /extract → /generate/claim на
    тексте решения из фикстуры и проверяет, что документ отдаётся. Он покрывает
    сам стык, а не разбор суммы в отдельности, — то есть регрессия вернётся с
    падением именно этого теста.
  • Локально 113 passed, покрытие 96.60% при пороге 90%.

ruff и mypy по затронутым файлам чистые. По репозиторию в целом они дают
шесть и одно замечание соответственно, но все унаследованные и ни одно не
связано с этой веткой — их закрывает предыдущий PR про CI.

Ответ /extract нельзя было передать в /generate/claim как есть. Сумма
отдавалась только строкой в том виде, в каком стояла в тексте решения
(«500 000», «1 234 567,89»), а /generate/claim и /generate/appeal
принимают claim_amount как float > 0. То есть клиент обязан был сам
убрать пробелы и заменить запятую на точку — при том что весь сценарий
продукта состоит ровно из связки «разобрали решение → сгенерировали
документ».

В ExtractionResult добавлено поле claim_amount_value (float | None)
рядом с прежним claim_amount. Строка остаётся нетронутой: она передаёт
исходное написание, которое может понадобиться для сверки с текстом.
Добавление обратно совместимое, существующие поля не изменились.

Разбор вынесен в parse_amount(): пробелы (включая неразрывные) убираются
целиком, запятая приводится к точке. Неразобравшаяся строка даёт None, а
не ноль — ноль в исковом заявлении хуже пустого поля, и /generate/* его
всё равно отклонят валидацией.

Тесты: parse_amount параметризованно, включая неразрывный пробел и
неположительные значения; сквозной тест в test_api.py прогоняет
/extract → /generate/claim и проверяет, что документ отдаётся, — то есть
покрывает сам стык, а не разбор суммы в отдельности.

Известная неоднозначность, вынесена в описание PR: в «500.000» точка
может означать и разделитель разрядов, и копейки. Текущий разбор считает
её десятичной, потому что regex claim_amount допускает единственный
разделитель и только в конце. В русских актах разряды разделяются
пробелом, так что случай редкий, но при желании его можно закрыть
отдельным правилом.
@Gyxer513
Gyxer513 force-pushed the feat/numeric-claim-amount branch from b6f2291 to fc3b6d8 Compare August 17, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant