Гудвилл: единицы ББ по словарю 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.domain.statement_aggregate import AggLine, aggregate_by_code
|
||||||
from src.repositories import goodwill as repo
|
from src.repositories import goodwill as repo
|
||||||
from src.services.consolidated_osv import ConsolidatedOsvBuildResult, ConsolidatedOsvService
|
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
|
@dataclass
|
||||||
@ -26,7 +29,7 @@ class Sources:
|
|||||||
|
|
||||||
def capital_amounts(meta_id, units, columns, values, date) -> tuple[Decimal | None, Decimal | None]:
|
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]
|
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:
|
if len(selected) != 1 or factor is None:
|
||||||
return None, None
|
return None, None
|
||||||
lines = {}
|
lines = {}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ from arm_statements import (
|
|||||||
statements_version,
|
statements_version,
|
||||||
status_input_from_contract,
|
status_input_from_contract,
|
||||||
)
|
)
|
||||||
|
from arm_statements.text import normalize_caption
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"ArmStatementsEngine",
|
"ArmStatementsEngine",
|
||||||
@ -62,6 +63,7 @@ class StatementsEngine(Protocol):
|
|||||||
def editions(self) -> tuple[Edition, ...]: ...
|
def editions(self) -> tuple[Edition, ...]: ...
|
||||||
def resolve_relative(self, kind: PeriodKind, effective_date: datetime.date | None) -> datetime.date | None: ...
|
def resolve_relative(self, kind: PeriodKind, effective_date: datetime.date | None) -> datetime.date | None: ...
|
||||||
def tolerance(self) -> Decimal: ...
|
def tolerance(self) -> Decimal: ...
|
||||||
|
def canonical_units(self, text: str | None) -> str | None: ...
|
||||||
|
|
||||||
|
|
||||||
class ArmStatementsEngine:
|
class ArmStatementsEngine:
|
||||||
@ -105,6 +107,13 @@ class ArmStatementsEngine:
|
|||||||
def tolerance(self) -> Decimal:
|
def tolerance(self) -> Decimal:
|
||||||
return self._rules.checks.tolerance
|
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
|
@functools.cache
|
||||||
def default_engine() -> StatementsEngine:
|
def default_engine() -> StatementsEngine:
|
||||||
|
|||||||
@ -58,6 +58,9 @@ class FakeEngine:
|
|||||||
def version(self) -> str | None:
|
def version(self) -> str | None:
|
||||||
return self._version
|
return self._version
|
||||||
|
|
||||||
|
def canonical_units(self, text: str | None) -> str | None:
|
||||||
|
return text
|
||||||
|
|
||||||
def recompute(self, form: StoredForm) -> RecomputeResult:
|
def recompute(self, form: StoredForm) -> RecomputeResult:
|
||||||
self.forms.append(form)
|
self.forms.append(form)
|
||||||
return self.result
|
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, 9, 30)) == (Decimal("120000"), None)
|
||||||
assert capital_amounts(mid, "тыс. руб.", columns, values, dt.date(2025, 6, 30)) == (None, 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)
|
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