openspec(#116): план 1 — resolve_relative и порядок редакций в публичном API, сверка с планом 3 (O-5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
This commit is contained in:
parent
14dcb0fbee
commit
f84e89288b
@ -411,8 +411,9 @@ git -C "$R" commit -m "feat: типы шага 1 и выхода шагов 2–
|
|||||||
auditor: tuple[re.Pattern[str], ...], legal_form: tuple[re.Pattern[str], ...])`
|
auditor: tuple[re.Pattern[str], ...], legal_form: tuple[re.Pattern[str], ...])`
|
||||||
- `UnitRules(spellings: tuple[tuple[re.Pattern[str], str], ...], okei: Mapping[str, str], thousands: str,
|
- `UnitRules(spellings: tuple[tuple[re.Pattern[str], str], ...], okei: Mapping[str, str], thousands: str,
|
||||||
fractional_share_percent: int)`
|
fractional_share_percent: int)`
|
||||||
- `CodeOrders(sequences: Mapping[tuple[Edition, DocumentType, FormVariant], tuple[str, ...]])` с методом
|
- `CodeOrders(editions: tuple[Edition, ...], sequences: Mapping[tuple[Edition, DocumentType, FormVariant],
|
||||||
`sequence(edition: Edition, form: DocumentType, variant: FormVariant) -> tuple[str, ...]`
|
tuple[str, ...]])` с методом `sequence(edition: Edition, form: DocumentType, variant: FormVariant) ->
|
||||||
|
tuple[str, ...]`; `editions` — порядок редакций в файле (`(RAS_66N, FSBU4)`)
|
||||||
- `WarningRule(code: str, severity: Severity, scope: Literal["document", "file"])`
|
- `WarningRule(code: str, severity: Severity, scope: Literal["document", "file"])`
|
||||||
- `Rules(checks: CheckRules, periods: PeriodRules, headers: HeaderRules, units: UnitRules, code_ranges: CodeRanges,
|
- `Rules(checks: CheckRules, periods: PeriodRules, headers: HeaderRules, units: UnitRules, code_ranges: CodeRanges,
|
||||||
code_orders: CodeOrders, lookalikes: Mapping[str, str], warnings: Mapping[str, WarningRule])`
|
code_orders: CodeOrders, lookalikes: Mapping[str, str], warnings: Mapping[str, WarningRule])`
|
||||||
@ -512,6 +513,7 @@ def test_code_orders_with_repeats(rules: Rules) -> None:
|
|||||||
assert fsbu.count("1220") == len(("1220", "1220")) and "1120" not in fsbu
|
assert fsbu.count("1220") == len(("1220", "1220")) and "1120" not in fsbu
|
||||||
ras = rules.code_orders.sequence(Edition.RAS_66N, DocumentType.BALANCE, FormVariant.FULL)
|
ras = rules.code_orders.sequence(Edition.RAS_66N, DocumentType.BALANCE, FormVariant.FULL)
|
||||||
assert "1120" in ras and ras.index("1110") < ras.index("1100")
|
assert "1120" in ras and ras.index("1110") < ras.index("1100")
|
||||||
|
assert rules.code_orders.editions == (Edition.RAS_66N, Edition.FSBU4)
|
||||||
|
|
||||||
|
|
||||||
def test_no_code_to_name_mapping_anywhere() -> None:
|
def test_no_code_to_name_mapping_anywhere() -> None:
|
||||||
@ -2629,6 +2631,7 @@ PUBLIC = {
|
|||||||
"StatementLine", "FailedRelation", "StatementChecks", "StatementDocument", "CandidateResult",
|
"StatementLine", "FailedRelation", "StatementChecks", "StatementDocument", "CandidateResult",
|
||||||
"NormalizationResult", "Rules", "RulesError", "load_rules", "default_rules", "normalize_candidate", "normalize",
|
"NormalizationResult", "Rules", "RulesError", "load_rules", "default_rules", "normalize_candidate", "normalize",
|
||||||
"parse_header", "type_hint", "continuation_type", "sheet_joins", "parse_code", "parse_amount", "parse_date",
|
"parse_header", "type_hint", "continuation_type", "sheet_joins", "parse_code", "parse_amount", "parse_date",
|
||||||
|
"resolve_relative",
|
||||||
"fix_lookalikes", "make_warning", "StatusInput", "StatusLine", "StatusValue", "document_status",
|
"fix_lookalikes", "make_warning", "StatusInput", "StatusLine", "StatusValue", "document_status",
|
||||||
"envelope_status", "StoredForm", "StoredColumn", "StoredLine", "StoredValue", "StoredWarning", "RecomputeResult",
|
"envelope_status", "StoredForm", "StoredColumn", "StoredLine", "StoredValue", "StoredWarning", "RecomputeResult",
|
||||||
"recompute", "to_jsonable", "candidate_from_dict", "statements_version",
|
"recompute", "to_jsonable", "candidate_from_dict", "statements_version",
|
||||||
@ -2748,6 +2751,8 @@ parse_code(text: str | None, rules: Rules) -> CodeParse #
|
|||||||
parse_amount(text: str | None, source: Source, rules: Rules) -> AmountParse
|
parse_amount(text: str | None, source: Source, rules: Rules) -> AmountParse
|
||||||
# AmountParse(amount: Decimal | None, string_value: str | None, is_recognized: bool, sign_form: SignForm | None)
|
# AmountParse(amount: Decimal | None, string_value: str | None, is_recognized: bool, sign_form: SignForm | None)
|
||||||
parse_date(text: str | None, rules: Rules) -> date | None
|
parse_date(text: str | None, rules: Rules) -> date | None
|
||||||
|
resolve_relative(kind: PeriodKind, effective: date | None) -> date | None
|
||||||
|
# дата относительной колонки от эффективной даты (ядро — после правки даты отчёта)
|
||||||
fix_lookalikes(text: str, lookalikes: Mapping[str, str], *, anywhere: bool = False) -> str
|
fix_lookalikes(text: str, lookalikes: Mapping[str, str], *, anywhere: bool = False) -> str
|
||||||
make_warning(code: str, message: str, rules: Rules, *, line_refs: Sequence[str] = (), column_index: int | None = None,
|
make_warning(code: str, message: str, rules: Rules, *, line_refs: Sequence[str] = (), column_index: int | None = None,
|
||||||
field: str | None = None, locator: str | None = None) -> StatementWarning
|
field: str | None = None, locator: str | None = None) -> StatementWarning
|
||||||
@ -2799,8 +2804,9 @@ RecomputeResult(form_variant: FormVariant | None, edition: Edition | None, check
|
|||||||
### Словари (`Rules`) — что нужно хостам
|
### Словари (`Rules`) — что нужно хостам
|
||||||
|
|
||||||
`Rules.headers.labels` / `auditor` / `legal_form` / `form_titles` / `okud` / `continuation` — метки шапки и заголовки
|
`Rules.headers.labels` / `auditor` / `legal_form` / `form_titles` / `okud` / `continuation` — метки шапки и заголовки
|
||||||
для адаптера Excel (план 3); `Rules.code_orders.sequence(edition, form, variant)` — перечень кодов редакции (ядру —
|
для адаптера Excel; `Rules.code_orders.sequence(edition, form, variant)` и `Rules.code_orders.editions` — перечень
|
||||||
порядок и состав строк формы, план 4); `Rules.lookalikes` — буквы-двойники; `Rules.warnings` — уровни предупреждений.
|
кодов редакции и порядок редакций (ядру — порядок и состав строк формы); `Rules.checks.tolerance` — допуск ±1 (ядру —
|
||||||
|
для межформенной проверки); `Rules.lookalikes` — буквы-двойники; `Rules.warnings` — уровни предупреждений.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -2874,3 +2880,15 @@ RecomputeResult(form_variant: FormVariant | None, edition: Edition | None, check
|
|||||||
`pytest.ini` хоста задаёт `env` (`APP_ENV=test`) — тестам пакета он не нужен и не мешает; подтверждение — в плане 2.
|
`pytest.ini` хоста задаёт `env` (`APP_ENV=test`) — тестам пакета он не нужен и не мешает; подтверждение — в плане 2.
|
||||||
- **O-4.** Dockerfile хостов должен копировать `api/arm_statements/rules/*.yaml` в образ (словари читаются с диска) —
|
- **O-4.** Dockerfile хостов должен копировать `api/arm_statements/rules/*.yaml` в образ (словари читаются с диска) —
|
||||||
в план 2 или планы сервисов.
|
в план 2 или планы сервисов.
|
||||||
|
- **O-5.** План 3 (arm-core, `2026-10-18-plan-3-arm-core.md`, таблица «Ожидаемые имена пакета») написан параллельно
|
||||||
|
и ждёт сверки с этим разделом (его O-8). Расхождения, которые правит адаптер `statements_engine.py` плана 3:
|
||||||
|
`recompute_stored_form` / `StoredFormResult` → `recompute` / `RecomputeResult`; `load_code_orders()`,
|
||||||
|
`CodeOrders.order`, `.editions` → `default_rules().code_orders.sequence(...)`, `.editions`; `relative_period_date` →
|
||||||
|
`resolve_relative`; `load_check_rules().tolerance` → `default_rules().checks.tolerance`; уверенности —
|
||||||
|
`float | None`, а не `Decimal`; `StoredValue.is_recognized` — `bool` (не `bool | None`); `StoredColumn.column_index`
|
||||||
|
— `int | None`; `period_kind`, `line_status`, `severity`, `document_type`, `edition`, `form_variant` — `StrEnum`
|
||||||
|
пакета (подкласс `str`, значения — строки контракта); `edition` результата — `Edition | None`;
|
||||||
|
`FailedRelation` — `column_index: int | None` плюс `column_key: str`, `expected` и `actual` — `Decimal` (не
|
||||||
|
`None`); `StatusInput` — `lines: tuple[StatusLine, ...]`, `values: tuple[StatusValue, ...]`, `hard_failures`
|
||||||
|
вместо `relations_failed`, дополнительно `needs_review_fields`. Решить, какая сторона меняется (по умолчанию —
|
||||||
|
адаптер плана 3, как он сам предусматривает).
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user