Гудвилл: единицы ББ по словарю arm_statements
StatementsEngine.canonical_units — нормализация подписи единиц шаблонами пакета; УК ДО переводится в рубли и при единицах, исправленных аналитиком вручную. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
46fba8875b
commit
eeb0ce48da
@ -13,6 +13,9 @@ from src.domain.goodwill import Investment
|
||||
from src.domain.statement_aggregate import AggLine, aggregate_by_code
|
||||
from src.repositories import goodwill as repo
|
||||
from src.services.consolidated_osv import ConsolidatedOsvBuildResult, ConsolidatedOsvService
|
||||
from src.services.statements_engine import default_engine
|
||||
|
||||
UNIT_FACTORS: dict[str | None, Decimal] = {"руб.": Decimal(1), "тыс. руб.": Decimal(1000), "млн руб.": Decimal(1000000)}
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -26,7 +29,7 @@ class Sources:
|
||||
|
||||
def capital_amounts(meta_id, units, columns, values, date) -> tuple[Decimal | None, Decimal | None]:
|
||||
selected = [c.id for c in columns if c.meta_id == meta_id and c.period_date == date]
|
||||
factor = {"руб.": Decimal(1), "тыс. руб.": Decimal(1000), "млн руб.": Decimal(1000000)}.get(units)
|
||||
factor = UNIT_FACTORS.get(default_engine().canonical_units(units))
|
||||
if len(selected) != 1 or factor is None:
|
||||
return None, None
|
||||
lines = {}
|
||||
|
||||
@ -29,6 +29,7 @@ from arm_statements import (
|
||||
statements_version,
|
||||
status_input_from_contract,
|
||||
)
|
||||
from arm_statements.text import normalize_caption
|
||||
|
||||
__all__ = [
|
||||
"ArmStatementsEngine",
|
||||
@ -62,6 +63,7 @@ class StatementsEngine(Protocol):
|
||||
def editions(self) -> tuple[Edition, ...]: ...
|
||||
def resolve_relative(self, kind: PeriodKind, effective_date: datetime.date | None) -> datetime.date | None: ...
|
||||
def tolerance(self) -> Decimal: ...
|
||||
def canonical_units(self, text: str | None) -> str | None: ...
|
||||
|
||||
|
||||
class ArmStatementsEngine:
|
||||
@ -105,6 +107,13 @@ class ArmStatementsEngine:
|
||||
def tolerance(self) -> Decimal:
|
||||
return self._rules.checks.tolerance
|
||||
|
||||
def canonical_units(self, text: str | None) -> str | None:
|
||||
"""Единица формы по словарю пакета («тыс.руб.», «в тысячах рублей» → «тыс. руб.»); не узнали — None."""
|
||||
if text is None:
|
||||
return None
|
||||
caption = normalize_caption(text)
|
||||
return next((canonical for pattern, canonical in self._rules.units.spellings if pattern.search(caption)), None)
|
||||
|
||||
|
||||
@functools.cache
|
||||
def default_engine() -> StatementsEngine:
|
||||
|
||||
@ -58,6 +58,9 @@ class FakeEngine:
|
||||
def version(self) -> str | None:
|
||||
return self._version
|
||||
|
||||
def canonical_units(self, text: str | None) -> str | None:
|
||||
return text
|
||||
|
||||
def recompute(self, form: StoredForm) -> RecomputeResult:
|
||||
self.forms.append(form)
|
||||
return self.result
|
||||
|
||||
@ -57,3 +57,29 @@ def test_capital_aggregates_duplicates_at_period_end() -> None:
|
||||
assert capital_amounts(mid, "тыс. руб.", columns, values, dt.date(2025, 9, 30)) == (Decimal("120000"), None)
|
||||
assert capital_amounts(mid, "тыс. руб.", columns, values, dt.date(2025, 6, 30)) == (None, None)
|
||||
assert capital_amounts(mid, None, columns, values, dt.date(2025, 9, 30)) == (None, None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("units", "factor"),
|
||||
[
|
||||
("тыс. руб.", Decimal(1000)),
|
||||
("тыс.руб.", Decimal(1000)),
|
||||
("в тысячах рублей", Decimal(1000)),
|
||||
("руб", Decimal(1)),
|
||||
("млн. руб.", Decimal(1000000)),
|
||||
],
|
||||
)
|
||||
def test_capital_units_spellings(units: str, factor: Decimal) -> None:
|
||||
"""Единицы, исправленные аналитиком вручную, читаются словарём единиц arm_statements."""
|
||||
mid, col = UUID(int=1), UUID(int=2)
|
||||
columns = [N(id=col, meta_id=mid, period_date=dt.date(2025, 9, 30), is_current=True)]
|
||||
line = N(id=UUID(int=4), meta_id=mid, line_code="1310", row_index=0, line_status=StatementLineStatus.ok)
|
||||
values = [(line, col, Decimal("7"))]
|
||||
assert capital_amounts(mid, units, columns, values, dt.date(2025, 9, 30)) == (Decimal("7") * factor, None)
|
||||
|
||||
|
||||
def test_capital_unknown_units() -> None:
|
||||
mid, col = UUID(int=1), UUID(int=2)
|
||||
columns = [N(id=col, meta_id=mid, period_date=dt.date(2025, 9, 30), is_current=True)]
|
||||
line = N(id=UUID(int=4), meta_id=mid, line_code="1310", row_index=0, line_status=StatementLineStatus.ok)
|
||||
assert capital_amounts(mid, "штук", columns, [(line, col, Decimal("7"))], dt.date(2025, 9, 30)) == (None, None)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user