synthgen: закрытие 90 через 90.09, тест детерминизма книг (#38)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
418f066bd8
commit
f0f60b1839
@ -7,7 +7,7 @@
|
||||
open_books(...) входящие остатки на book_start (31.12 перед первым периодом);
|
||||
для каждого месяца: post_month(...) внешние операции месяца,
|
||||
hook(...) операции внутри группы (extra),
|
||||
close_month(...) закрытие 26/44 → 90, 90/91 → 99, налог, в декабре 99 → 84.
|
||||
close_month(...) закрытие 26/44 → 90, 90.01..90.08 → 90.09 → 99, 91 → 99, налог, в декабре 99 → 84.
|
||||
`build_ledgers` — эта последовательность целиком.
|
||||
|
||||
Аналитика контрагента: `An(cp=<ИНН Org>)` для внешних, `An(cp=<код члена>)` для компаний группы (последние — Task 4).
|
||||
@ -359,6 +359,26 @@ def _close_all(lg: Ledger, day: date, prefix: str) -> Decimal:
|
||||
return result
|
||||
|
||||
|
||||
def _close_90(lg: Ledger, day: date) -> Decimal:
|
||||
"""Как в 1С: сальдо 90.01..90.08 переносятся на 90.09 (проводки с memo «закрытие на 90.09»), затем 90.09 — на 99
|
||||
(memo «закрытие на 99»). Обороты 90.09 — только закрывающие; свёртка ОФР различает их по memo."""
|
||||
result = D(0)
|
||||
for (acct, an), bal in sorted(lg.balance(day, "90").items(), key=lambda kv: (kv[0][0], str(kv[0][1]))):
|
||||
if acct == "90.09":
|
||||
continue
|
||||
if bal > 0:
|
||||
lg.post(day, "90.09", None, acct, an, bal, "закрытие на 90.09")
|
||||
else:
|
||||
lg.post(day, acct, an, "90.09", None, -bal, "закрытие на 90.09")
|
||||
result -= bal
|
||||
bal09 = lg.balance(day, "90.09").get(("90.09", None), D(0))
|
||||
if bal09 > 0:
|
||||
lg.post(day, "99", None, "90.09", None, bal09, "закрытие на 99")
|
||||
elif bal09 < 0:
|
||||
lg.post(day, "90.09", None, "99", None, -bal09, "закрытие на 99")
|
||||
return result
|
||||
|
||||
|
||||
def close_month(ledgers: dict[str, Ledger], year: int, month: int) -> None:
|
||||
day = last_day(year, month)
|
||||
for code in sorted(ledgers):
|
||||
@ -370,7 +390,7 @@ def close_month(ledgers: dict[str, Ledger], year: int, month: int) -> None:
|
||||
for (acct, an), bal in lg.balance(day, cost).items():
|
||||
if bal > 0:
|
||||
lg.post(day, target, None, acct, an, bal, "закрытие затрат")
|
||||
result = _close_all(lg, day, "90") + _close_all(lg, day, "91")
|
||||
result = _close_90(lg, day) + _close_all(lg, day, "91")
|
||||
tax = q(result * PROFIT_TAX)
|
||||
if tax > 0:
|
||||
lg.post(day, "99", None, "68.04", FNS, tax, "налог на прибыль")
|
||||
|
||||
@ -118,3 +118,24 @@ def test_deterministic_and_zero_mean():
|
||||
b = _build(mean=0)[4]
|
||||
assert [p for p in a["C01"].postings] == [p for p in b["C01"].postings]
|
||||
assert a["C01"].postings
|
||||
|
||||
|
||||
def test_90_closes_via_909():
|
||||
cfg, g, ps, pl, books = _build()
|
||||
for lg in books.values():
|
||||
day = date(2025, 3, 31)
|
||||
assert lg.balance(day, "90") == {}
|
||||
t = lg.turnover(date(2025, 1, 1), day, "90.09")
|
||||
assert t and all(dt and ct for dt, ct in t.values())
|
||||
for p in lg.postings:
|
||||
if p.ct == "90.09" or p.dt == "90.09":
|
||||
assert p.memo.startswith("закрытие на ")
|
||||
assert not [p for p in lg.postings if p.memo == "закрытие на 99" and p.dt == "99" and p.ct.startswith("90.0") and p.ct != "90.09"]
|
||||
|
||||
|
||||
def test_build_ledgers_deterministic_with_counterparties():
|
||||
a = _build(mean=30, seed=3)[4]
|
||||
b = _build(mean=30, seed=3)[4]
|
||||
assert a.keys() == b.keys()
|
||||
for code in a:
|
||||
assert a[code].postings == b[code].postings
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user