63 lines
3.0 KiB
Python
63 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from app import db
|
|
from app.lab.db_guard import retry_locked
|
|
from app.lab.models import LabAnimalProfile
|
|
from app.lab.calc.nutrients import parse_num
|
|
from app.lab.calc.norms_resolver import normalize_norms_method
|
|
from app.lab.services.norms_params import save_norms_params
|
|
from app.lab.services.profile_norms import save_norms_from_payload, sync_racion_norms_to_profile
|
|
from app.models.base import default_uuid
|
|
|
|
|
|
@retry_locked
|
|
def upsert_animal_profile(profile_id: str | None, payload: dict[str, Any], user_id: str = "system") -> dict:
|
|
pid = (profile_id or payload.get("id") or "").strip() or default_uuid()
|
|
profile = LabAnimalProfile.query.filter_by(id=pid, is_deleted=False).first()
|
|
is_new = profile is None
|
|
if is_new:
|
|
profile = LabAnimalProfile(id=pid, created_by=user_id)
|
|
db.session.add(profile)
|
|
|
|
key = (payload.get("profileKey") or payload.get("profile_key") or "").strip()
|
|
label = (payload.get("label") or "").strip()
|
|
ration_type = (payload.get("rationType") or payload.get("ration_type") or "BEEF").strip().upper()
|
|
if not key or not label:
|
|
raise ValueError("profileKey и label обязательны")
|
|
|
|
profile.profile_key = key
|
|
profile.label = label
|
|
profile.ration_type = ration_type
|
|
if "normsMethod" in payload or "norms_method" in payload:
|
|
profile.norms_method = normalize_norms_method(
|
|
payload.get("normsMethod", payload.get("norms_method"))
|
|
)
|
|
if "normsParams" in payload or "norms_params" in payload:
|
|
raw_params = payload.get("normsParams", payload.get("norms_params"))
|
|
save_norms_params(profile, raw_params if isinstance(raw_params, dict) else None)
|
|
if "milkYieldKg" in payload or "milk_yield_kg" in payload:
|
|
profile.milk_yield_kg = parse_num(payload.get("milkYieldKg", payload.get("milk_yield_kg")))
|
|
|
|
norms_payload: dict[str, Any] = {}
|
|
if "normsData" in payload or "norms_data" in payload:
|
|
raw = payload.get("normsData") if "normsData" in payload else payload.get("norms_data")
|
|
if isinstance(raw, dict):
|
|
norms_payload = dict(raw)
|
|
if payload.get("massKg") is not None or payload.get("mass_kg") is not None:
|
|
norms_payload["massKg"] = payload.get("massKg", payload.get("mass_kg"))
|
|
if "milkYieldKg" in payload or "milk_yield_kg" in payload:
|
|
norms_payload["milkYieldKg"] = payload.get("milkYieldKg", payload.get("milk_yield_kg"))
|
|
if payload.get("externalNo") is not None or payload.get("external_no") is not None:
|
|
norms_payload["externalNo"] = payload.get("externalNo", payload.get("external_no"))
|
|
if isinstance(payload.get("indicators"), dict):
|
|
norms_payload["indicators"] = payload["indicators"]
|
|
if norms_payload:
|
|
save_norms_from_payload(profile, norms_payload)
|
|
|
|
profile.updated_by = user_id
|
|
sync_racion_norms_to_profile(profile)
|
|
db.session.commit()
|
|
return {"id": profile.id, "profileKey": profile.profile_key, "label": profile.label}
|