arm-ka-fixtures/synthgen/tests/test_ledger.py
2026-11-13 00:30:31 +04:00

94 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.

import csv
import os
from datetime import date
from decimal import Decimal
from pathlib import Path
import pytest
from synthgen import chart
from synthgen.ledger import An, Ledger, opening
D = Decimal
def test_double_entry():
lg = Ledger("AGRO")
lg.post(date(2025, 1, 10), "62.01", An("AGRO"), "90.01", None, D("1200.00"), "продажа")
lg.post(date(2025, 2, 10), "51", None, "62.01", An("AGRO"), D("200.00"), "оплата")
opening(lg, date(2025, 1, 1), "51", None, D("500.00"))
opening(lg, date(2025, 1, 1), "60.01", An("AGRO"), D("-70.00"))
for d in (date(2025, 1, 1), date(2025, 1, 31), date(2025, 12, 31)):
assert sum(lg.balance(d).values()) == 0
def test_balance_signs_and_prefix():
lg = Ledger("X")
lg.post(date(2025, 1, 10), "62.01", An("AGRO"), "90.01", None, D("1200.00"), "")
lg.post(date(2025, 2, 10), "51", None, "62.01", An("AGRO"), D("200.00"), "")
assert lg.balance(date(2025, 3, 31), "62") == {("62.01", An("AGRO")): D("1000.00")}
assert lg.balance(date(2025, 1, 31), "62") == {("62.01", An("AGRO")): D("1200.00")}
def test_turnover_window():
lg = Ledger("X")
lg.post(date(2024, 12, 31), "62.01", An("A"), "90.01", None, D("10.00"), "")
lg.post(date(2025, 1, 1), "62.01", An("A"), "90.01", None, D("20.00"), "")
lg.post(date(2025, 3, 31), "51", None, "62.01", An("A"), D("5.00"), "")
lg.post(date(2025, 4, 1), "62.01", An("A"), "90.01", None, D("40.00"), "")
t = lg.turnover(date(2025, 1, 1), date(2025, 3, 31), "62")
assert t == {("62.01", An("A")): (D("20.00"), D("5.00"))}
def test_csv_deterministic(tmp_path):
def build(p: Path):
lg = Ledger("X")
lg.post(date(2025, 1, 10), "62.01", An("A", contract="Д-1"), "90.01", None, D("1.50"), "м")
lg.to_csv(p)
return p.read_bytes()
a = build(tmp_path / "a.csv")
assert a == build(tmp_path / "b.csv")
rows = list(csv.reader(a.decode("utf-8").splitlines(), delimiter=";"))
assert rows[0] == "day;dt;dt_cp;dt_contract;dt_item;ct;ct_cp;ct_contract;ct_item;amount;memo".split(";")
assert rows[1][:3] == ["2025-01-10", "62.01", "A"]
def test_rejects_bad_amount():
lg = Ledger("X")
with pytest.raises(ValueError):
lg.post(date(2025, 1, 1), "51", None, "62.01", None, D("0"), "")
def test_chart_helpers():
assert chart.parent("76.07.1") == "76.07"
assert chart.parent("76.07") == "76"
assert chart.parent("58.01") == "58"
assert chart.is_off_balance("001") and chart.is_off_balance("011")
assert not chart.is_off_balance("01")
def test_chart_codes_in_core_seed():
ws = Path(os.environ.get("ARM_KA_WORKSPACE", "/Users/andrey.epifancev/projects/awp-ca"))
seed = ws / "arm-core/api/seed/core/chart_of_accounts.csv"
if not seed.exists():
pytest.skip("нет seed плана счетов")
codes = {r["code"] for r in csv.DictReader(seed.open(encoding="utf-8"))}
missing = [c for c in chart.ACCOUNTS if c != "000" and c not in codes]
assert not missing
def test_closing_postings_have_explicit_kind(osv_world):
"""T3.8: закрывающие проводки различаются полем kind, а не разбором memo."""
from synthgen.ledger import KIND_CLOSE_90, KIND_CLOSE_99, KIND_CLOSE_COST, KIND_ORDINARY
_, _, _, books = osv_world
kinds = {"закрытие на 90.09": KIND_CLOSE_90, "закрытие на 99": KIND_CLOSE_99, "закрытие затрат": KIND_CLOSE_COST}
seen = set()
for lg in books.values():
for p in lg.postings:
want = kinds.get(p.memo, KIND_ORDINARY)
assert p.kind == want, (p.memo, p.kind)
seen.add(p.kind)
assert {KIND_CLOSE_90, KIND_CLOSE_99, KIND_CLOSE_COST, KIND_ORDINARY} <= seen