"""Импорт и загрузка справочников RACION из БД.""" from __future__ import annotations import json from dataclasses import dataclass, field from pathlib import Path from typing import Any from app.modules.zootech.wesp_bridge_db import db from app.modules.zootech.lab.calc.racion.tables import clear_tables_cache from app.modules.zootech.lab.models import ( LabRacionNormyInfo, LabRacionNormyMoskwa, LabRacionNormyMoskwaMeta, LabRacionNormyPiter, LabRacionNormyPiterMeta, ) from app.modules.zootech.lab.seed_paths import seed_dir from app.modules.zootech.wesp_bridge_models import default_uuid _SEED_DIR = seed_dir() / "racion" @dataclass class RacionReferenceImportStats: moskwa_rows: int = 0 piter_rows: int = 0 info_rows: int = 0 errors: list[str] = field(default_factory=list) def _read_seed(name: str) -> dict: path = _SEED_DIR / name return json.loads(path.read_text(encoding="utf-8")) def import_racion_reference(*, replace: bool = True) -> RacionReferenceImportStats: stats = RacionReferenceImportStats() try: moskwa = _read_seed("moskwa_lactir.json") piter = _read_seed("piter_lactir.json") info = _read_seed("normy_info.json") except (OSError, json.JSONDecodeError) as exc: stats.errors.append(str(exc)) return stats if replace: LabRacionNormyMoskwa.query.delete(synchronize_session=False) LabRacionNormyMoskwaMeta.query.delete(synchronize_session=False) LabRacionNormyPiter.query.delete(synchronize_session=False) LabRacionNormyPiterMeta.query.delete(synchronize_session=False) LabRacionNormyInfo.query.delete(synchronize_session=False) for row in moskwa.get("rows") or []: db.session.add( LabRacionNormyMoskwa( id=default_uuid(), npitv=int(row["npitv"]), pom=int(row.get("pom") or 1), koef=row.get("koef"), popr_k_json=json.dumps(row.get("popr_k") or [], ensure_ascii=False), ) ) stats.moskwa_rows += 1 db.session.add( LabRacionNormyMoskwaMeta( id=default_uuid(), meta_key="udoy_boundaries", meta_json=json.dumps(moskwa.get("udoy_boundaries") or [], ensure_ascii=False), ) ) for entry in piter.get("entries") or []: db.session.add( LabRacionNormyPiter( id=default_uuid(), npitv=int(entry["npitv"]), konc=float(entry["konc"]), udoy=float(entry["udoy"]), normy_json=json.dumps(entry.get("normy") or [], ensure_ascii=False), ) ) stats.piter_rows += 1 db.session.add( LabRacionNormyPiterMeta( id=default_uuid(), meta_key="mass_kg_values", meta_json=json.dumps(piter.get("mass_kg_values") or [], ensure_ascii=False), ) ) for row in info.get("rows") or []: db.session.add( LabRacionNormyInfo( id=default_uuid(), nperem=int(row["nperem"]), znachenie_json=json.dumps(row.get("znachenie") or [], ensure_ascii=False), ) ) stats.info_rows += 1 db.session.commit() clear_tables_cache() return stats def load_moskwa_lactir_from_db() -> dict | None: if LabRacionNormyMoskwa.query.count() == 0: return None rows = [] for r in LabRacionNormyMoskwa.query.order_by(LabRacionNormyMoskwa.npitv, LabRacionNormyMoskwa.pom).all(): rows.append( { "npitv": r.npitv, "pom": r.pom, "koef": r.koef, "popr_k": json.loads(r.popr_k_json or "[]"), } ) meta = LabRacionNormyMoskwaMeta.query.filter_by(meta_key="udoy_boundaries").first() boundaries = json.loads(meta.meta_json or "[]") if meta else [] return {"udoy_boundaries": boundaries, "rows": rows} def load_piter_lactir_from_db() -> dict | None: if LabRacionNormyPiter.query.count() == 0: return None entries = [] for r in LabRacionNormyPiter.query.order_by( LabRacionNormyPiter.npitv, LabRacionNormyPiter.konc, LabRacionNormyPiter.udoy ).all(): entries.append( { "npitv": r.npitv, "konc": r.konc, "udoy": r.udoy, "normy": json.loads(r.normy_json or "[]"), } ) meta = LabRacionNormyPiterMeta.query.filter_by(meta_key="mass_kg_values").first() masses = json.loads(meta.meta_json or "[]") if meta else [400, 450, 500, 550, 600, 650, 700, 750] return {"mass_kg_values": masses, "entries": entries} def load_normy_info_from_db() -> dict | None: if LabRacionNormyInfo.query.count() == 0: return None rows = [] for r in LabRacionNormyInfo.query.order_by(LabRacionNormyInfo.nperem).all(): rows.append({"nperem": r.nperem, "znachenie": json.loads(r.znachenie_json or "[]")}) by_nperem = {row["nperem"]: row["znachenie"] for row in rows} mass_kg_values = by_nperem.get(14) or by_nperem.get(13) or [400, 450, 500, 550, 600, 650, 700, 750] return {"rows": rows, "mass_kg_values": mass_kg_values}