Files
2026-07-17 12:57:18 +03:00

156 lines
5.1 KiB
Python

"""Импорт и загрузка справочников RACION из БД."""
from __future__ import annotations
import json
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
from app import db
from app.lab.calc.racion.tables import clear_tables_cache
from app.lab.models.racion_normy import (
LabRacionNormyInfo,
LabRacionNormyMoskwa,
LabRacionNormyMoskwaMeta,
LabRacionNormyPiter,
LabRacionNormyPiterMeta,
)
from app.models.base import default_uuid
_SEED_DIR = Path(__file__).resolve().parents[3] / "data" / "seed" / "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}