Интегрирован 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,239 @@
"""Dual sync: reorder ингредиентов + группы выгрузки (баготест #5–#6)."""
from __future__ import annotations
import unittest
import uuid
from sqlalchemy import select
from app import db
from app.models import Ingredient, Recipe, UnloadingGroup
from app.services.recipe_update_service import update_recipe_from_payload
from app.services.sync_manager import enqueue_sync_queue_task
from tests.helpers.mill_recipe_fixtures import (
create_recipe_with_children,
group_payload_from_row,
ingredient_payload_from_row,
recipe_update_payload,
)
from tests.helpers.sync_dual_harness import SyncDualInstanceHarness
SCENARIO_DUAL_REORDER_AND_NEW_GROUP = "DUAL_REORDER_AND_NEW_GROUP"
SCENARIO_DUAL_ADD_GROUP_UPDATES_EXISTING = "DUAL_ADD_GROUP_UPDATES_EXISTING"
class SyncRecipeChildrenDualTests(unittest.TestCase):
def setUp(self) -> None:
self.harness = SyncDualInstanceHarness()
self.harness.start()
def tearDown(self) -> None:
self.harness.stop()
def _seed_recipe_on_terminals(self, recipe_id: str) -> None:
with self.harness.server_ctx():
enqueue_sync_queue_task("recipe", recipe_id, "create", priority=2, target_node_id=None)
for ing in db.session.execute(
select(Ingredient).where(
Ingredient.recipe_id == recipe_id,
Ingredient.is_deleted.is_(False),
)
).scalars().all():
enqueue_sync_queue_task("ingredient", str(ing.id), "create", priority=2)
for grp in db.session.execute(
select(UnloadingGroup).where(
UnloadingGroup.recipe_id == recipe_id,
UnloadingGroup.is_deleted.is_(False),
)
).scalars().all():
enqueue_sync_queue_task("unloading_group", str(grp.id), "create", priority=2)
db.session.commit()
self.harness.drain_sync()
def _ingredient_orders(self, which: str, recipe_id: str) -> list[tuple[str, int]]:
with self.harness.terminal_ctx(which):
rows = db.session.execute(
select(Ingredient.id, Ingredient.order)
.where(
Ingredient.recipe_id == recipe_id,
Ingredient.is_deleted.is_(False),
)
.order_by(Ingredient.order.asc())
).all()
return [(str(rid), int(ord_)) for rid, ord_ in rows]
def _group_snapshot(self, which: str, recipe_id: str) -> list[tuple[str, str, float]]:
with self.harness.terminal_ctx(which):
rows = db.session.execute(
select(
UnloadingGroup.name,
UnloadingGroup.distribution_type,
UnloadingGroup.value,
)
.where(
UnloadingGroup.recipe_id == recipe_id,
UnloadingGroup.is_deleted.is_(False),
)
.order_by(UnloadingGroup.order.asc())
).all()
return [(n, t, float(v)) for n, t, v in rows]
def test_reorder_ingredients_and_add_group_reach_both_terminals(self) -> None:
SCENARIO_DUAL_REORDER_AND_NEW_GROUP # noqa: F841
with self.harness.server_ctx():
recipe_id, ing_ids, _ = create_recipe_with_children(with_groups=False)
grp_id = str(uuid.uuid4())
db.session.add(
UnloadingGroup(
id=grp_id,
name="1 заезд",
distribution_type="percent",
value=75.0,
weight=1000.0,
order=1,
recipe_id=recipe_id,
created_by="system",
updated_by="system",
)
)
db.session.commit()
self._seed_recipe_on_terminals(recipe_id)
with self.harness.server_ctx():
recipe = db.session.get(Recipe, recipe_id)
ing_a = db.session.get(Ingredient, ing_ids[0])
ing_b = db.session.get(Ingredient, ing_ids[1])
grp1 = db.session.get(UnloadingGroup, grp_id)
payload = recipe_update_payload(
recipe,
ingredients=[
ingredient_payload_from_row(ing_b, order=1),
ingredient_payload_from_row(ing_a, order=2),
],
groups=[
group_payload_from_row(grp1, order=1),
{
"name": "2 заезд",
"distribution_type": "percent",
"value": 25.0,
"weight": 400.0,
"order": 2,
},
],
)
update_recipe_from_payload(recipe_id, payload)
db.session.commit()
self.harness.drain_sync()
for term in ("a", "b"):
self.assertEqual(
self._ingredient_orders(term, recipe_id),
[(ing_ids[1], 1), (ing_ids[0], 2)],
msg=f"ingredient order terminal {term}",
)
snap = self._group_snapshot(term, recipe_id)
self.assertEqual(len(snap), 2, msg=f"groups count terminal {term}")
self.assertEqual(snap[0][2], 75.0)
self.assertEqual(snap[1], ("2 заезд", "percent", 25.0))
def test_split_groups_60_40_on_both_terminals_not_140_percent(self) -> None:
SCENARIO_DUAL_ADD_GROUP_UPDATES_EXISTING # noqa: F841
with self.harness.server_ctx():
recipe_id, ing_ids, _ = create_recipe_with_children(with_groups=False)
grp_id = str(uuid.uuid4())
db.session.add(
UnloadingGroup(
id=grp_id,
name="4 гр 1 зам",
distribution_type="percent",
value=100.0,
weight=1590.0,
order=1,
recipe_id=recipe_id,
created_by="system",
updated_by="system",
)
)
db.session.commit()
self._seed_recipe_on_terminals(recipe_id)
with self.harness.server_ctx():
recipe = db.session.get(Recipe, recipe_id)
grp1 = db.session.get(UnloadingGroup, grp_id)
ings = [
ingredient_payload_from_row(db.session.get(Ingredient, iid))
for iid in ing_ids
]
payload = recipe_update_payload(
recipe,
ingredients=ings,
groups=[
{
**group_payload_from_row(grp1, order=1),
"value": 60.0,
},
{
"name": "еще одна",
"distribution_type": "percent",
"value": 40.0,
"weight": 635.0,
"order": 2,
},
],
)
update_recipe_from_payload(recipe_id, payload)
db.session.commit()
self.harness.drain_sync()
for term in ("a", "b"):
snap = self._group_snapshot(term, recipe_id)
self.assertEqual(len(snap), 2, msg=f"terminal {term}")
self.assertEqual(snap[0][2], 60.0, msg=f"grp1 value terminal {term}")
self.assertEqual(snap[1][2], 40.0, msg=f"grp2 value terminal {term}")
total_percent = sum(v for _, t, v in snap if t == "percent")
self.assertAlmostEqual(total_percent, 100.0, places=1)
def test_dry_matter_locked_syncs_to_both_terminals(self) -> None:
with self.harness.server_ctx():
recipe_id, ing_ids, _ = create_recipe_with_children(with_groups=False)
recipe = db.session.get(Recipe, recipe_id)
recipe.dry_matter_locked = True
db.session.commit()
self._seed_recipe_on_terminals(recipe_id)
with self.harness.server_ctx():
recipe = db.session.get(Recipe, recipe_id)
comp_id = db.session.get(Ingredient, ing_ids[0]).component_id
update_recipe_from_payload(
recipe_id,
recipe_update_payload(
recipe,
ingredients=[
{
"id": ing_ids[0],
"component_id": comp_id,
"dry_matter": 50.0,
"dry_matter_per_head": 1.0,
"order": 1,
}
],
groups=[],
)
| {"dry_matter_locked": True, "heads_count": 10, "trip_percent": 100.0},
)
db.session.commit()
self.harness.drain_sync()
for term in ("a", "b"):
row = self.harness.recipe_on_terminal(term, recipe_id)
self.assertTrue(row.dry_matter_locked, msg=f"terminal {term}")
if __name__ == "__main__":
unittest.main()