72 lines
3.0 KiB
Python
72 lines
3.0 KiB
Python
"""Сборка набора (спека §7): группа → периоды → книги → файлы ЕЦП, ОСВ, ББ и ОФР, config.yaml и README прогона."""
|
||
|
||
import shutil
|
||
from dataclasses import dataclass, field, replace
|
||
from pathlib import Path
|
||
|
||
from synthgen import dictionary, ecp, forms, forms_xlsx, osv, report
|
||
from synthgen.config import Config, dump_config
|
||
from synthgen.counterparties import OSV_ACCOUNTS, CounterpartyPlan
|
||
from synthgen.counterparties import plan as make_plan
|
||
from synthgen.group import build_group
|
||
from synthgen.intragroup import VgoPair, build
|
||
from synthgen.periods import build_periods
|
||
|
||
|
||
@dataclass
|
||
class Manifest:
|
||
files: list[Path] = field(default_factory=list)
|
||
pairs: list[VgoPair] = field(default_factory=list)
|
||
capped: bool = False
|
||
|
||
|
||
def default_out(cfg: Config) -> Path:
|
||
return cfg.out if cfg.out is not None else Path("out") / cfg.prefix
|
||
|
||
|
||
def _prepare(out: Path, force: bool) -> None:
|
||
if out.exists() and any(out.iterdir()):
|
||
if not force:
|
||
raise FileExistsError(f"каталог результата не пуст: {out} (--force перезапишет)")
|
||
for item in out.iterdir():
|
||
shutil.rmtree(item) if item.is_dir() and not item.is_symlink() else item.unlink()
|
||
out.mkdir(parents=True, exist_ok=True)
|
||
|
||
|
||
def generate(cfg: Config, out: Path, *, force: bool = False) -> Manifest:
|
||
"""Строит набор в каталоге `out`; непустой `out` без `force` — FileExistsError."""
|
||
_prepare(out, force)
|
||
group = build_group(cfg, dictionary.load())
|
||
periods = build_periods(cfg.start, cfg.periods)
|
||
plan: CounterpartyPlan = make_plan(cfg, group)
|
||
books, pairs = build(cfg, group, periods, plan)
|
||
manifest = Manifest(pairs=pairs, capped=plan.capped)
|
||
|
||
def keep(path: Path) -> Path:
|
||
manifest.files.append(path)
|
||
return path
|
||
|
||
ecp.write_ecp(group, keep(out / "directories" / f"ecp-{cfg.prefix}.xlsx"))
|
||
for member in group.members:
|
||
ledger = books[member.code]
|
||
with_inn = member.code not in group.no_inn
|
||
for period in periods:
|
||
for account in OSV_ACCOUNTS:
|
||
data = osv.rows(ledger, account, period, member, group)
|
||
path = out / "osv" / member.code / period.key / osv.file_name(account, period)
|
||
osv.write(path, member, account, period, data, with_inn=with_inn)
|
||
keep(path)
|
||
for form in (
|
||
forms.balance(ledger, member, period, periods, cfg.seed),
|
||
forms.income(ledger, member, period, periods, cfg.seed),
|
||
):
|
||
path = out / "statements" / member.code / period.key / forms_xlsx.file_name(form)
|
||
forms_xlsx.write(form, path)
|
||
keep(path)
|
||
(out / "config.yaml").write_text(dump_config(replace(cfg, out=None)), encoding="utf-8")
|
||
keep(out / "config.yaml")
|
||
readme = out / "README.md"
|
||
manifest.files.append(readme)
|
||
readme.write_text(report.render(cfg, group, pairs, plan, manifest), encoding="utf-8")
|
||
return manifest
|