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

85 lines
2.7 KiB
Python

"""Удаление legacy/fp_* профилей стада (одноразовая ops-команда)."""
from __future__ import annotations
import logging
import re
from dataclasses import dataclass, field
from app import db
from app.lab.models import LabAnimalProfile, LabProfileNorm, LabRecipeRation
_log = logging.getLogger(__name__)
_LEGACY_KEY = re.compile(r"^(dairy|beef)-\d+$", re.IGNORECASE)
_FP_KEY = re.compile(r"^fp_", re.IGNORECASE)
@dataclass
class CleanupReport:
dry_run: bool = True
profiles_to_delete: list[str] = field(default_factory=list)
recipe_ids_cleared: list[str] = field(default_factory=list)
norms_deleted: int = 0
profiles_deleted: int = 0
errors: list[str] = field(default_factory=list)
def _should_delete(profile_key: str | None) -> bool:
key = (profile_key or "").strip()
if not key:
return False
if key.startswith("lab_math_"):
return False
if _LEGACY_KEY.match(key):
return True
if _FP_KEY.match(key):
return True
return False
def cleanup_legacy_profiles(*, dry_run: bool = True, user_id: str = "system") -> CleanupReport:
report = CleanupReport(dry_run=dry_run)
profiles = LabAnimalProfile.query.filter_by(is_deleted=False).all()
to_delete = [p for p in profiles if _should_delete(p.profile_key)]
for profile in to_delete:
report.profiles_to_delete.append(profile.profile_key or profile.id)
norms_count = LabProfileNorm.query.filter_by(profile_id=profile.id).count()
report.norms_deleted += norms_count
rations = LabRecipeRation.query.filter_by(animal_profile_id=profile.id, is_deleted=False).all()
for header in rations:
if header.recipe_id not in report.recipe_ids_cleared:
report.recipe_ids_cleared.append(header.recipe_id)
if dry_run:
continue
LabProfileNorm.query.filter_by(profile_id=profile.id).delete(synchronize_session=False)
for header in rations:
header.animal_profile_id = None
header.updated_by = user_id
if hasattr(profile, "soft_delete"):
profile.soft_delete(user_id)
else:
db.session.delete(profile)
report.profiles_deleted += 1
if not dry_run:
db.session.commit()
_log.info(
"cleanup_legacy_profiles user=%s deleted=%s rations_cleared=%s",
user_id,
report.profiles_deleted,
len(report.recipe_ids_cleared),
)
else:
_log.info(
"cleanup_legacy_profiles dry_run profiles=%s rations=%s",
len(report.profiles_to_delete),
len(report.recipe_ids_cleared),
)
return report