"""Отчётные периоды (спека §5.1): кварталы подряд, каждый — нарастающим итогом с начала года, как выгружает 1С.""" from dataclasses import dataclass from datetime import date _LABELS = {1: "1 квартал {y} г.", 2: "1 полугодие {y} г.", 3: "9 месяцев {y} г.", 4: "{y} г."} _END = {1: (3, 31), 2: (6, 30), 3: (9, 30), 4: (12, 31)} @dataclass(frozen=True) class Period: key: str # 2025-Q1, 2025-Q2, 2025-Q3, 2025-FY year: int quarter: int start: date # всегда 1 января (нарастающий итог) end: date label_1c: str def _make(year: int, quarter: int) -> Period: month, day = _END[quarter] key = f"{year}-FY" if quarter == 4 else f"{year}-Q{quarter}" return Period(key, year, quarter, date(year, 1, 1), date(year, month, day), _LABELS[quarter].format(y=year)) def build_periods(start: str, n: int) -> list[Period]: """`n` периодов подряд начиная с `start` (`ГГГГ-Qn`); четвёртый квартал — годовой период `ГГГГ-FY`.""" year_s, q_s = start.split("-Q") year, quarter = int(year_s), int(q_s) out: list[Period] = [] for _ in range(n): out.append(_make(year, quarter)) quarter += 1 if quarter == 5: year, quarter = year + 1, 1 return out def book_start(ps: list[Period]) -> date: """Дата входящих остатков: 31 декабря года перед первым периодом.""" return date(ps[0].year - 1, 12, 31) def book_end(ps: list[Period]) -> date: """Конец книги — конец последнего периода.""" return ps[-1].end