# -*- coding: utf-8 -*- """Оркестратор: связывает чтение источников, запись реестра и журнала.""" from __future__ import annotations import logging from dataclasses import dataclass, field from pathlib import Path from typing import List from . import config from .mapping import discover_sources from .models import JournalEntry from .readers import get_reader from .writers import JournalWriter, RegisterWriter log = logging.getLogger("priem") @dataclass class Result: entries: List[JournalEntry] notes: List[str] = field(default_factory=list) warnings: List[str] = field(default_factory=list) @property def total(self) -> int: return sum(e.count for e in self.entries) class Pipeline: def __init__( self, register_src: Path = config.REGISTER_SRC, register_out: Path = config.REGISTER_OUT, journal_src: Path = config.JOURNAL_SRC, journal_out: Path = config.JOURNAL_OUT, priem_dir: Path = config.PRIEM_DIR, entry_date=config.ENTRY_DATE, ): self.register_src = Path(register_src) self.register_out = Path(register_out) self.journal_src = Path(journal_src) self.journal_out = Path(journal_out) self.priem_dir = Path(priem_dir) self.entry_date = entry_date if self.register_out == self.register_src: raise ValueError("register_out совпадает с оригиналом — он был бы перезаписан") if self.journal_out == self.journal_src: raise ValueError("journal_out совпадает с оригиналом — он был бы перезаписан") def run(self) -> Result: sources = discover_sources(self.priem_dir) log.info("Найдено файлов приёма: %d", len(sources)) register = RegisterWriter(self.register_src) entries: List[JournalEntry] = [] notes: List[str] = [] warnings: List[str] = [] for src in sources: if not register.has_sheet(src.sheet): raise ValueError( "В реестре нет листа '%s' (файл %s)" % (src.sheet, src.name)) try: read = get_reader(src.path).read() except Exception as exc: raise RuntimeError( "Не удалось прочитать файл %s: %s" % (src.path.name, exc)) from exc count = register.append(src.sheet, read.records) entries.append(JournalEntry(self.entry_date, src.name, count)) log.info(" %-22s -> %-8s : %3d записей", src.name, src.sheet, count) for n in read.notes: notes.append("%s: %s" % (src.name, n)) log.info(" • %s", n) for w in read.warnings: warnings.append("%s: %s" % (src.name, w)) log.warning(" ⚠ %s", w) register.save(self.register_out) log.info("Реестр сохранён: %s", self.register_out.name) journal = JournalWriter(self.journal_src) journal.write(entries) journal.save(self.journal_out) log.info("Журнал сохранён: %s", self.journal_out.name) result = Result(entries, notes, warnings) log.info("ИТОГО записей: %d", result.total) if notes: log.info("Присоединено заметок: %d (данные не потеряны, см. выше)", len(notes)) if warnings: log.warning("ВНИМАНИЕ: %d строк НЕ удалось привязать — проверьте вручную:", len(warnings)) for w in warnings: log.warning(" • %s", w) return result