from __future__ import annotations from typing import Any from app.modules.zootech.wesp_bridge_db import db from app.modules.zootech.lab.db_guard import retry_locked from app.modules.zootech.lab.models import LabAnimalProfile from app.modules.zootech.lab.calc.nutrients import parse_num from app.modules.zootech.lab.calc.norms_resolver import normalize_norms_method from app.modules.zootech.lab.services.norms_params import save_norms_params from app.modules.zootech.lab.services.profile_norms import save_norms_from_payload, sync_racion_norms_to_profile from app.modules.zootech.wesp_bridge_models 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}