arm-core/api/src/services/statements_engine.py

113 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Адаптер пакета `arm_statements` за протоколом `StatementsEngine` (часть Б, B1).
Единственная точка вызова функций пакета в ядре; остальной код работает с протоколом, модульные тесты подменяют
его `FakeEngine`. Правила пакета читаются один раз на процесс (`default_engine` кэширует адаптер).
"""
import datetime
import functools
from collections.abc import Mapping, Sequence
from decimal import Decimal
from typing import Any, Protocol
from arm_statements import (
DocStatus,
DocumentType,
Edition,
FailedRelation,
FormVariant,
PeriodKind,
RecomputeResult,
Rules,
StatementChecks,
StoredForm,
choose_edition,
default_rules,
document_status,
recompute,
resolve_relative,
statements_version,
status_input_from_contract,
)
__all__ = [
"ArmStatementsEngine",
"DocStatus",
"DocumentType",
"Edition",
"FailedRelation",
"FormVariant",
"PeriodKind",
"StatementChecks",
"StatementsEngine",
"default_engine",
]
class StatementsEngine(Protocol):
@property
def version(self) -> str | None: ...
def recompute(self, form: StoredForm) -> RecomputeResult: ...
def contract_document_status(self, document: Mapping[str, Any]) -> DocStatus: ...
def edition(
self,
document_type: DocumentType,
codes: Sequence[tuple[str, bool]],
effective_date: datetime.date | None,
form_variant: FormVariant | None,
) -> Edition | None: ...
def code_order(
self, edition: Edition, document_type: DocumentType, form_variant: FormVariant
) -> tuple[str, ...]: ...
def editions(self) -> tuple[Edition, ...]: ...
def resolve_relative(self, kind: PeriodKind, effective_date: datetime.date | None) -> datetime.date | None: ...
def tolerance(self) -> Decimal: ...
class ArmStatementsEngine:
"""Реализация поверх пакета: правила — `default_rules()` пакета."""
def __init__(self, rules: Rules) -> None:
self._rules = rules
@property
def version(self) -> str | None:
return statements_version()
def recompute(self, form: StoredForm) -> RecomputeResult:
return recompute(form, self._rules)
def contract_document_status(self, document: Mapping[str, Any]) -> DocStatus:
return document_status(status_input_from_contract(document))
def edition(
self,
document_type: DocumentType,
codes: Sequence[tuple[str, bool]],
effective_date: datetime.date | None,
form_variant: FormVariant | None,
) -> Edition | None:
return choose_edition(document_type, codes, effective_date, self._rules, variant=form_variant)
def code_order(self, edition: Edition, document_type: DocumentType, form_variant: FormVariant) -> tuple[str, ...]:
if document_type is DocumentType.DISCLOSURE:
return ()
return self._rules.code_orders.sequence(edition, document_type, form_variant)
def editions(self) -> tuple[Edition, ...]:
return self._rules.code_orders.editions
def resolve_relative(self, kind: PeriodKind, effective_date: datetime.date | None) -> datetime.date | None:
if kind in (PeriodKind.ABSOLUTE, PeriodKind.NONE):
return None
return resolve_relative(kind, effective_date)
def tolerance(self) -> Decimal:
return self._rules.checks.tolerance
@functools.cache
def default_engine() -> StatementsEngine:
"""Адаптер с правилами пакета; кэш на процесс."""
return ArmStatementsEngine(default_rules())