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.models import LabRationLine, LabRecipeRation from app.models import Component from app.models.base import default_uuid @retry_locked def sync_from_execution(recipe_id: str, user_id: str = "system") -> dict: """Обновить мастер из execution (обратный перенос /recipes → lab).""" execution = load_execution(recipe_id) header = LabRecipeRation.query.filter_by(recipe_id=recipe_id, is_deleted=False).first() if header is None: header = LabRecipeRation(recipe_id=recipe_id, created_by=user_id, updated_by=user_id) db.session.add(header) else: header.updated_by = user_id existing = LabRationLine.query.filter_by(recipe_id=recipe_id, is_deleted=False).all() for line in existing: line.soft_delete(user_id) created = 0 for idx, line in enumerate(execution.lines): comp = Component.query.get(line.component_id) if line.component_id else None db.session.add( LabRationLine( id=default_uuid(), recipe_id=recipe_id, component_id=line.component_id, ingredient_name=line.name or (comp.name if comp else None), row_index=idx, daily_kg=line.daily_kg_total, in_ration=True, in_compound=False, created_by=user_id, updated_by=user_id, ) ) created += 1 header.seed_source = "synced_from" write_audit("SYNC_FROM_EXECUTION", "lab_recipe_ration", recipe_id, user_id) db.session.commit() return {"recipeId": recipe_id, "lines": created}