Интегрирован 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,86 @@
from __future__ import annotations
from typing import Any
from app.lab.calc.feed_groups import classify_feed_group
from app.lab.calc.gfe_policies import default_om_digestibility_pct
from app.lab.nutrient_schema import read_from_mapping
from app.lab.services.component_nutrients import derive_context_for_component, nutrients_full_dict, nutrients_is_empty
from app.models import Component
_REQUIRED_EAV_KEYS = ("Сыр. Протеин", "Сырая клетч", "Сырой жир")
_MAIN_FEED_KEYS = ("Осн.Корм", "СВ Основной корм")
_OMD_KEYS = ("ВРХ Орг Вещ", "КРС Орг Вещ")
def main_feed_dm_g_per_kg(component_id: str | None) -> float | None:
if not component_id:
return None
full = nutrients_full_dict(component_id)
val = read_from_mapping(full, _MAIN_FEED_KEYS)
return float(val) if val is not None else None
def validate_component(component_id: str) -> dict[str, Any]:
comp = Component.query.filter_by(id=component_id, is_deleted=False).first()
if comp is None:
return {
"id": component_id,
"name": None,
"eligible": False,
"missing": ["component_not_found"],
"warnings": [],
"dryMatterPct": None,
"hasPrice": False,
"price": None,
}
missing: list[str] = []
warnings: list[str] = []
dry_matter_pct = comp.dry_matter
if dry_matter_pct is None or float(dry_matter_pct) <= 0:
missing.append("dry_matter")
full = nutrients_full_dict(component_id)
if nutrients_is_empty(component_id):
missing.append("nutrients_empty")
else:
for key in _REQUIRED_EAV_KEYS:
if read_from_mapping(full, (key,)) is None:
missing.append(key)
has_price = comp.price is not None and float(comp.price) >= 0
if not has_price:
warnings.append("price_missing")
main_feed_dm = read_from_mapping(full, _MAIN_FEED_KEYS)
if main_feed_dm is None:
warnings.append("main_feed_unset")
feed_group = classify_feed_group(comp)
omd = read_from_mapping(full, _OMD_KEYS)
if feed_group in ("rough", "succulent") and omd is None:
warnings.append("omd_missing")
elif omd is None and comp.dry_matter and float(comp.dry_matter) > 0:
ctx = derive_context_for_component(component_id, full)
warnings.append(
f"omd_defaulted:{default_om_digestibility_pct(ctx):.0f}"
)
return {
"id": comp.id,
"name": comp.name,
"eligible": len(missing) == 0,
"missing": missing,
"warnings": warnings,
"dryMatterPct": dry_matter_pct,
"hasPrice": has_price,
"price": comp.price,
"mainFeedDmGPerKg": main_feed_dm,
"isMainFeed": main_feed_dm is not None and float(main_feed_dm) > 0,
"feedGroup": feed_group,
}
def validate_components(component_ids: list[str]) -> list[dict[str, Any]]:
return [validate_component(cid) for cid in component_ids]