Приём документов → реестр + журнал
Внесение данных из файлов приёма в реестр невостребованных документов и заполнение журнала. Дата внесения — текущая; журнал заполняется чисто (без строк-примеров шаблона). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
97
priem_register/pipeline.py
Normal file
97
priem_register/pipeline.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# -*- 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
|
||||
Reference in New Issue
Block a user