Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
@@ -0,0 +1,76 @@
from __future__ import annotations
from app import db
from app.lab.commands.write_audit import write_audit
from app.lab.db_guard import retry_locked
from app.lab.loaders.execution_loader import load_execution
from app.lab.loaders.ration_loader import load_ration
from app.models import Component, Ingredient, Recipe
from app.models.base import default_uuid
from app.services.recipe_update_service import _enqueue_recipe_children_sync
@retry_locked
def apply_from_master(recipe_id: str, user_id: str = "system") -> dict:
snapshot = load_ration(recipe_id)
if not snapshot.exists:
raise LookupError("Мастер рациона не найден")
recipe = Recipe.query.filter_by(id=recipe_id, is_deleted=False).first()
if recipe is None:
raise LookupError("Рецепт не найден")
heads = int(recipe.heads_per_trip or 0)
if heads <= 0:
raise ValueError("Количество голов должно быть > 0")
execution = load_execution(recipe_id)
by_component = {str(l.component_id): l for l in execution.lines if l.component_id}
master_by_component = {
str(l.component_id): l
for l in snapshot.lines
if l.component_id and l.in_ration
}
touched_ingredient_ids: list[str] = []
for comp_id, master_line in master_by_component.items():
daily_kg = float(master_line.daily_kg or 0)
weight_per_head = daily_kg / heads
ing = by_component.get(comp_id)
comp = Component.query.get(comp_id)
dm_pct = float(comp.dry_matter or 0) if comp else float(master_line.dry_matter or 0)
if ing:
row = Ingredient.query.get(ing.ingredient_id)
if row is None:
continue
row.weight_per_head = weight_per_head
row.amount = weight_per_head
row.dry_matter = dm_pct
row.updated_by = user_id
touched_ingredient_ids.append(row.id)
else:
comp_name = master_line.ingredient_name or comp_id
new_ing = Ingredient(
id=default_uuid(),
recipe_id=recipe_id,
component_id=comp_id,
name=comp_name[:100],
amount=weight_per_head,
weight_per_head=weight_per_head,
dry_matter=dm_pct,
order=len(touched_ingredient_ids),
created_by=user_id,
updated_by=user_id,
)
db.session.add(new_ing)
touched_ingredient_ids.append(new_ing.id)
master_ids = set(master_by_component)
for line in execution.lines:
if line.component_id and str(line.component_id) not in master_ids:
row = Ingredient.query.get(line.ingredient_id)
if row and not row.is_deleted:
row.soft_delete(user_id)
_enqueue_recipe_children_sync(recipe_id)
write_audit("APPLY_FROM_MASTER", "lab_recipe_ration", recipe_id, user_id)
db.session.commit()
return {"recipeId": recipe_id, "ingredientsUpdated": len(touched_ingredient_ids)}