@@ -0,0 +1,124 @@
|
||||
"""Unit-тесты пересчёта весов при замене компонента в плане."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from app.models import Component, Ingredient, Recipe
|
||||
from app.services.daily_plan.ingredient_weights import resolve_plan_ingredient_weights
|
||||
|
||||
|
||||
class PlanIngredientWeightsTests(unittest.TestCase):
|
||||
def _make(self, *, locked: bool, wph: float, dm_pct: float, repl_dm: float, dm_ph=None):
|
||||
recipe = Recipe(id="r1", name="R", dry_matter_locked=locked, content_hash="")
|
||||
ing = Ingredient(
|
||||
id="i1",
|
||||
name="Ing",
|
||||
weight_per_head=wph,
|
||||
amount=0.0,
|
||||
dry_matter=dm_pct,
|
||||
dry_matter_per_head=dm_ph,
|
||||
order=1,
|
||||
recipe_id="r1",
|
||||
component_id="c1",
|
||||
created_by="system",
|
||||
updated_by="system",
|
||||
)
|
||||
components = {
|
||||
"c1": Component(id="c1", name="A", type="grain", dry_matter=dm_pct),
|
||||
"c2": Component(id="c2", name="B", type="silage", dry_matter=repl_dm),
|
||||
}
|
||||
return ing, recipe, components
|
||||
|
||||
def test_weight_mode_keeps_kg_per_head(self) -> None:
|
||||
ing, recipe, components = self._make(locked=False, wph=2.0, dm_pct=55.0, repl_dm=35.0)
|
||||
out = resolve_plan_ingredient_weights(
|
||||
ing, recipe, heads=10, components_by_id=components, replacement_component_id="c2"
|
||||
)
|
||||
self.assertEqual(out["recalculationMode"], "weight")
|
||||
self.assertEqual(out["weightPerHead"], 2.0)
|
||||
self.assertEqual(out["totalKg"], 20.0)
|
||||
self.assertEqual(out["dryMatterPct"], 35.0)
|
||||
self.assertAlmostEqual(out["dryMatterPerHead"], 0.7, places=4)
|
||||
|
||||
def test_dry_matter_mode_keeps_dm_per_head(self) -> None:
|
||||
ing, recipe, components = self._make(
|
||||
locked=True, wph=1.0, dm_pct=55.0, repl_dm=35.0, dm_ph=0.55
|
||||
)
|
||||
out = resolve_plan_ingredient_weights(
|
||||
ing, recipe, heads=20, components_by_id=components, replacement_component_id="c2"
|
||||
)
|
||||
self.assertEqual(out["recalculationMode"], "dry_matter")
|
||||
self.assertAlmostEqual(out["weightPerHead"], 1.57, places=2)
|
||||
self.assertAlmostEqual(out["totalKg"], 31.4, places=1)
|
||||
self.assertAlmostEqual(out["dryMatterPerHead"], 0.55, places=4)
|
||||
|
||||
def test_dry_matter_pct_adjustment_locked(self) -> None:
|
||||
ing, recipe, components = self._make(
|
||||
locked=True, wph=1.0, dm_pct=55.0, repl_dm=35.0, dm_ph=0.55
|
||||
)
|
||||
out = resolve_plan_ingredient_weights(
|
||||
ing,
|
||||
recipe,
|
||||
heads=10,
|
||||
components_by_id=components,
|
||||
component_adjustment={
|
||||
"dry_matter": 40.0,
|
||||
"dry_matter_locked": True,
|
||||
"weight_per_head": None,
|
||||
"dry_matter_per_head": None,
|
||||
},
|
||||
)
|
||||
self.assertTrue(out["adjustedToday"])
|
||||
self.assertEqual(out["dryMatterPct"], 40.0)
|
||||
self.assertAlmostEqual(out["dryMatterPerHead"], 0.55, places=4)
|
||||
self.assertAlmostEqual(out["weightPerHead"], 1.38, places=2)
|
||||
|
||||
def test_dry_matter_pct_adjustment(self) -> None:
|
||||
ing, recipe, components = self._make(locked=False, wph=2.0, dm_pct=55.0, repl_dm=35.0)
|
||||
out = resolve_plan_ingredient_weights(
|
||||
ing,
|
||||
recipe,
|
||||
heads=10,
|
||||
components_by_id=components,
|
||||
component_adjustment={"dry_matter": 40.0, "weight_per_head": None, "dry_matter_per_head": None},
|
||||
)
|
||||
self.assertTrue(out["adjustedToday"])
|
||||
self.assertEqual(out["weightPerHead"], 2.0)
|
||||
self.assertEqual(out["dryMatterPct"], 40.0)
|
||||
self.assertAlmostEqual(out["dryMatterPerHead"], 0.8, places=4)
|
||||
self.assertEqual(out["originalWeightPerHead"], 2.0)
|
||||
self.assertEqual(out["originalDryMatterPct"], 55.0)
|
||||
|
||||
def test_weight_mode_adjustment(self) -> None:
|
||||
ing, recipe, components = self._make(locked=False, wph=2.0, dm_pct=55.0, repl_dm=35.0)
|
||||
out = resolve_plan_ingredient_weights(
|
||||
ing,
|
||||
recipe,
|
||||
heads=10,
|
||||
components_by_id=components,
|
||||
component_adjustment={"weight_per_head": 3.0, "dry_matter_per_head": None},
|
||||
)
|
||||
self.assertTrue(out["adjustedToday"])
|
||||
self.assertEqual(out["weightPerHead"], 3.0)
|
||||
self.assertAlmostEqual(out["dryMatterPerHead"], 1.65, places=4)
|
||||
self.assertEqual(out["originalWeightPerHead"], 2.0)
|
||||
|
||||
def test_dry_matter_mode_adjustment(self) -> None:
|
||||
ing, recipe, components = self._make(
|
||||
locked=True, wph=1.0, dm_pct=55.0, repl_dm=35.0, dm_ph=0.55
|
||||
)
|
||||
out = resolve_plan_ingredient_weights(
|
||||
ing,
|
||||
recipe,
|
||||
heads=20,
|
||||
components_by_id=components,
|
||||
component_adjustment={"weight_per_head": None, "dry_matter_per_head": 0.7},
|
||||
)
|
||||
self.assertTrue(out["adjustedToday"])
|
||||
self.assertAlmostEqual(out["dryMatterPerHead"], 0.7, places=4)
|
||||
self.assertAlmostEqual(out["weightPerHead"], 1.27, places=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user