Files
site/WESP_REL/app/lab/commands/upsert_ration.py
T
2026-07-17 12:57:18 +03:00

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}