66 lines
2.6 KiB
Python
66 lines
2.6 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 LabRationLine, LabRecipeRation
|
|
from app.models import Recipe
|
|
from app.models.base import default_uuid
|
|
|
|
|
|
@retry_locked
|
|
def upsert_ration(recipe_id: str, payload: dict[str, Any], user_id: str = "system") -> dict[str, Any]:
|
|
recipe = Recipe.query.filter_by(id=recipe_id, is_deleted=False).first()
|
|
if recipe is None:
|
|
raise LookupError("Рецепт не найден")
|
|
|
|
header = LabRecipeRation.query.filter_by(recipe_id=recipe_id).first()
|
|
if header is None:
|
|
header = LabRecipeRation(recipe_id=recipe_id, created_by=user_id, updated_by=user_id)
|
|
db.session.add(header)
|
|
header.animal_profile_id = payload.get("animalProfileId") or payload.get("animal_profile_id")
|
|
if "params" in payload:
|
|
params = payload.get("params") or {}
|
|
if isinstance(params, dict):
|
|
seeded = params.get("seeded_from") or params.get("synced_from")
|
|
if seeded:
|
|
header.seed_source = str(seeded)
|
|
if "rationType" in payload or "ration_type" in payload:
|
|
recipe.ration_type = (payload.get("rationType") or payload.get("ration_type") or "").upper() or None
|
|
header.updated_by = user_id
|
|
|
|
incoming = payload.get("lines") or []
|
|
existing = {
|
|
str(l.id): l
|
|
for l in LabRationLine.query.filter_by(recipe_id=recipe_id, is_deleted=False).all()
|
|
}
|
|
seen_ids: set[str] = set()
|
|
for idx, row in enumerate(incoming):
|
|
line_id = str(row.get("id") or "")
|
|
line = existing.get(line_id) if line_id else None
|
|
if line is None:
|
|
line = LabRationLine(
|
|
id=default_uuid(),
|
|
recipe_id=recipe_id,
|
|
created_by=user_id,
|
|
updated_by=user_id,
|
|
)
|
|
db.session.add(line)
|
|
line.row_index = int(row.get("rowIndex", row.get("row_index", idx)))
|
|
line.component_id = row.get("componentId") or row.get("component_id")
|
|
line.ingredient_name = row.get("ingredientName") or row.get("ingredient_name")
|
|
line.daily_kg = row.get("dailyKg", row.get("daily_kg"))
|
|
line.in_ration = bool(row.get("inRation", row.get("in_ration", True)))
|
|
line.in_compound = bool(row.get("inCompound", row.get("in_compound", False)))
|
|
line.updated_by = user_id
|
|
if line.id:
|
|
seen_ids.add(str(line.id))
|
|
|
|
for lid, line in existing.items():
|
|
if lid not in seen_ids:
|
|
line.soft_delete(user_id)
|
|
|
|
db.session.commit()
|
|
return {"recipeId": recipe_id, "ok": True}
|