207 lines
7.5 KiB
Python
207 lines
7.5 KiB
Python
"""Порядок рецептов в периоде и reorder ингредиентов/групп."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import tempfile
|
|
import unittest
|
|
import time
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import select
|
|
|
|
from app import create_app, db
|
|
from app.models import (
|
|
FeedDispenser,
|
|
FeedingPeriod,
|
|
Ingredient,
|
|
PeriodRecipe,
|
|
Recipe,
|
|
SyncQueue,
|
|
UnloadingGroup,
|
|
)
|
|
from app.services.recipe_update_service import update_recipe_from_payload
|
|
from config import TestingConfig
|
|
from tests.helpers.mill_recipe_fixtures import (
|
|
create_recipe_with_children,
|
|
group_payload_from_row,
|
|
ingredient_payload_from_row,
|
|
recipe_update_payload,
|
|
)
|
|
|
|
|
|
class RecipesOrderConfig(TestingConfig):
|
|
_TMP_DIR = tempfile.mkdtemp(prefix="wesp-recipes-order-")
|
|
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(_TMP_DIR, 'recipes_test.db')}"
|
|
SQLALCHEMY_BINDS = {"reports": f"sqlite:///{os.path.join(_TMP_DIR, 'reports_test.db')}"}
|
|
AUTH_LOGIN = "order-admin"
|
|
AUTH_PASSWORD = "order-secret"
|
|
|
|
|
|
class RecipesOrderTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.app = create_app(RecipesOrderConfig)
|
|
self.client = self.app.test_client()
|
|
self.ctx = self.app.app_context()
|
|
self.ctx.push()
|
|
db.create_all()
|
|
self.client.post(
|
|
"/api/auth/login", json={"login": "order-admin", "password": "order-secret"}
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
db.session.remove()
|
|
db.drop_all()
|
|
self.ctx.pop()
|
|
|
|
def _seed_period_two_recipes(self) -> tuple[str, str, str, str]:
|
|
disp = FeedDispenser(
|
|
id="ord-disp", name="D", farm="F", operator="O", type="dispenser"
|
|
)
|
|
period = FeedingPeriod(id="ord-period", name="P", dispenser_id=disp.id)
|
|
r1 = Recipe(id="ord-r1", name="R1", heads_per_trip=1, mixing_time=0)
|
|
r2 = Recipe(id="ord-r2", name="R2", heads_per_trip=1, mixing_time=0)
|
|
db.session.add_all([disp, period, r1, r2])
|
|
db.session.flush()
|
|
now = datetime.now()
|
|
for rid, ord_ in ((r1.id, 1), (r2.id, 2)):
|
|
db.session.add(
|
|
PeriodRecipe(
|
|
period_id=period.id,
|
|
recipe_id=rid,
|
|
order=ord_,
|
|
created_at=now,
|
|
created_by="system",
|
|
updated_by="system",
|
|
)
|
|
)
|
|
db.session.commit()
|
|
return disp.id, period.id, r1.id, r2.id
|
|
|
|
def _period_order(self, period_id: str) -> list[str]:
|
|
rows = db.session.execute(
|
|
select(PeriodRecipe.recipe_id)
|
|
.where(
|
|
PeriodRecipe.period_id == period_id,
|
|
PeriodRecipe.is_deleted.is_(False),
|
|
)
|
|
.order_by(PeriodRecipe.order.asc())
|
|
).scalars().all()
|
|
return [str(x) for x in rows]
|
|
|
|
def test_move_recipe_down_in_period(self) -> None:
|
|
_, period_id, r1, r2 = self._seed_period_two_recipes()
|
|
resp = self.client.put(
|
|
f"/api/recipes/{r1}/move",
|
|
json={"period_id": period_id, "from_index": 0, "to_index": 1},
|
|
)
|
|
self.assertEqual(resp.status_code, 200)
|
|
self.assertEqual(self._period_order(period_id), [r2, r1])
|
|
|
|
def test_move_recipe_up_in_period(self) -> None:
|
|
_, period_id, r1, r2 = self._seed_period_two_recipes()
|
|
self.client.put(
|
|
f"/api/recipes/{r2}/move",
|
|
json={"period_id": period_id, "from_index": 1, "to_index": 0},
|
|
)
|
|
self.assertEqual(self._period_order(period_id), [r2, r1])
|
|
|
|
def test_move_recipe_sync_enqueue_period_recipes(self) -> None:
|
|
_, period_id, r1, r2 = self._seed_period_two_recipes()
|
|
self.client.put(
|
|
f"/api/recipes/{r1}/move",
|
|
json={"period_id": period_id, "from_index": 0, "to_index": 1},
|
|
)
|
|
time.sleep(0.3)
|
|
tasks = db.session.execute(
|
|
select(SyncQueue).where(SyncQueue.table_name == "period_recipes")
|
|
).scalars().all()
|
|
self.assertGreaterEqual(len(tasks), 1)
|
|
record_ids = {t.record_id for t in tasks}
|
|
self.assertTrue(f"{period_id}:{r1}" in record_ids or f"{period_id}:{r2}" in record_ids)
|
|
|
|
def test_move_recipe_404_wrong_period(self) -> None:
|
|
_, period_id, r1, _ = self._seed_period_two_recipes()
|
|
other = FeedingPeriod(id="ord-other", name="X", dispenser_id="ord-disp")
|
|
db.session.add(other)
|
|
db.session.commit()
|
|
resp = self.client.put(
|
|
f"/api/recipes/{r1}/move",
|
|
json={"period_id": other.id, "from_index": 0, "to_index": 1},
|
|
)
|
|
self.assertEqual(resp.status_code, 404)
|
|
|
|
def test_update_reorders_ingredients_by_id(self) -> None:
|
|
recipe_id, ing_ids, _ = create_recipe_with_children(with_groups=False)
|
|
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])
|
|
update_recipe_from_payload(
|
|
recipe_id,
|
|
recipe_update_payload(
|
|
recipe,
|
|
ingredients=[
|
|
ingredient_payload_from_row(ing_b, order=1),
|
|
ingredient_payload_from_row(ing_a, order=2),
|
|
],
|
|
groups=[],
|
|
),
|
|
)
|
|
db.session.commit()
|
|
orders = 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()
|
|
self.assertEqual([str(x[0]) for x in orders], [ing_ids[1], ing_ids[0]])
|
|
|
|
def test_move_ingredient_up_down_reflected_in_save(self) -> None:
|
|
recipe_id, ing_ids, _ = create_recipe_with_children(with_groups=False)
|
|
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])
|
|
payload = recipe_update_payload(
|
|
recipe,
|
|
ingredients=[
|
|
ingredient_payload_from_row(ing_b, order=1),
|
|
ingredient_payload_from_row(ing_a, order=2),
|
|
],
|
|
groups=[],
|
|
)
|
|
update_recipe_from_payload(recipe_id, payload)
|
|
db.session.commit()
|
|
rows = db.session.execute(
|
|
select(Ingredient.order).where(
|
|
Ingredient.recipe_id == recipe_id, Ingredient.is_deleted.is_(False)
|
|
).order_by(Ingredient.order.asc())
|
|
).scalars().all()
|
|
self.assertEqual(list(rows), [1, 2])
|
|
|
|
def test_move_group_up_down_deleted_order_stable(self) -> None:
|
|
recipe_id, _, grp_ids = create_recipe_with_children()
|
|
recipe = db.session.get(Recipe, recipe_id)
|
|
g1 = db.session.get(UnloadingGroup, grp_ids[0])
|
|
g2 = db.session.get(UnloadingGroup, grp_ids[1])
|
|
update_recipe_from_payload(
|
|
recipe_id,
|
|
recipe_update_payload(
|
|
recipe,
|
|
ingredients=[],
|
|
groups=[
|
|
group_payload_from_row(g2, order=1),
|
|
group_payload_from_row(g1, order=2),
|
|
],
|
|
),
|
|
)
|
|
db.session.commit()
|
|
orders = db.session.execute(
|
|
select(UnloadingGroup.id, UnloadingGroup.order)
|
|
.where(UnloadingGroup.recipe_id == recipe_id, UnloadingGroup.is_deleted.is_(False))
|
|
.order_by(UnloadingGroup.order.asc())
|
|
).all()
|
|
self.assertEqual([str(x[0]) for x in orders], [grp_ids[1], grp_ids[0]])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|