Внесение данных из файлов приёма в реестр невостребованных документов и заполнение журнала. Дата внесения — текущая; журнал заполняется чисто (без строк-примеров шаблона). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
98 lines
3.8 KiB
Python
98 lines
3.8 KiB
Python
# -*- 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
|