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 перед первым периодом);
|
open_books(...) входящие остатки на book_start (31.12 перед первым периодом);
|
||||||
для каждого месяца: post_month(...) внешние операции месяца,
|
для каждого месяца: post_month(...) внешние операции месяца,
|
||||||
hook(...) операции внутри группы (extra),
|
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` — эта последовательность целиком.
|
`build_ledgers` — эта последовательность целиком.
|
||||||
|
|
||||||
Аналитика контрагента: `An(cp=<ИНН Org>)` для внешних, `An(cp=<код члена>)` для компаний группы (последние — Task 4).
|
Аналитика контрагента: `An(cp=<ИНН Org>)` для внешних, `An(cp=<код члена>)` для компаний группы (последние — Task 4).
|
||||||
@ -359,6 +359,26 @@ def _close_all(lg: Ledger, day: date, prefix: str) -> Decimal:
|
|||||||
return result
|
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:
|
def close_month(ledgers: dict[str, Ledger], year: int, month: int) -> None:
|
||||||
day = last_day(year, month)
|
day = last_day(year, month)
|
||||||
for code in sorted(ledgers):
|
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():
|
for (acct, an), bal in lg.balance(day, cost).items():
|
||||||
if bal > 0:
|
if bal > 0:
|
||||||
lg.post(day, target, None, acct, an, bal, "закрытие затрат")
|
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)
|
tax = q(result * PROFIT_TAX)
|
||||||
if tax > 0:
|
if tax > 0:
|
||||||
lg.post(day, "99", None, "68.04", FNS, tax, "налог на прибыль")
|
lg.post(day, "99", None, "68.04", FNS, tax, "налог на прибыль")
|
||||||
|
|||||||
@ -118,3 +118,24 @@ def test_deterministic_and_zero_mean():
|
|||||||
b = _build(mean=0)[4]
|
b = _build(mean=0)[4]
|
||||||
assert [p for p in a["C01"].postings] == [p for p in b["C01"].postings]
|
assert [p for p in a["C01"].postings] == [p for p in b["C01"].postings]
|
||||||
assert a["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