Интегрирован 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,133 @@
"""Хелперы: мастер-рацион vs план на день vs экран оператора загрузки."""
from __future__ import annotations
from datetime import date
from typing import Any
from flask.testing import FlaskClient
DAILY_PLAN_SYNC_TABLES: tuple[str, ...] = (
"daily_trip_skip",
"daily_ingredient_skip",
"daily_unloading_group_skip",
"daily_ingredient_replacement",
"daily_component_norm_adjustment",
)
KIOSK_HEADERS = {"X-Wesp-Kiosk": "1"}
def plan_date_today() -> str:
return date.today().isoformat()
def master_recipe_json(client: FlaskClient, recipe_id: str) -> dict[str, Any]:
resp = client.get(f"/api/recipes/{recipe_id}")
assert resp.status_code == 200, resp.get_data(as_text=True)
return resp.get_json()
def plan_recipe_json(
client: FlaskClient,
recipe_id: str,
*,
plan_date: str | None = None,
kiosk: bool = True,
) -> dict[str, Any]:
iso = (plan_date or plan_date_today())[:10]
headers = KIOSK_HEADERS if kiosk else {}
resp = client.get(
f"/api/recipes/{recipe_id}?date={iso}",
headers=headers,
)
assert resp.status_code == 200, resp.get_data(as_text=True)
return resp.get_json()
def first_ingredient_amount(payload: dict[str, Any]) -> float:
ingredients = payload.get("ingredients") or []
assert ingredients, "expected at least one ingredient"
return float(ingredients[0].get("amount") or 0)
def ingredient_amounts(payload: dict[str, Any]) -> list[float]:
return [float(i.get("amount") or 0) for i in (payload.get("ingredients") or [])]
def operator_weight_display(client: FlaskClient, recipe_id: str) -> dict[str, Any]:
set_resp = client.post("/api/set_current_recipe", json={"recipe_id": recipe_id})
assert set_resp.status_code == 200, set_resp.get_data(as_text=True)
display = client.get("/api/weight_display_data")
assert display.status_code == 200, display.get_data(as_text=True)
return display.get_json()
def assert_operator_matches_plan_not_master(
client: FlaskClient,
recipe_id: str,
*,
plan_date: str | None = None,
expect_plan_differs_from_master: bool = True,
) -> dict[str, Any]:
"""Оператор (weight_display) = план; мастер — базовый рецепт без date=."""
master = master_recipe_json(client, recipe_id)
plan = plan_recipe_json(client, recipe_id, plan_date=plan_date)
operator = operator_weight_display(client, recipe_id)
assert operator.get("status") == "active", operator
plan_amounts = ingredient_amounts(plan)
master_amounts = ingredient_amounts(master)
assert plan_amounts, "plan must expose ingredients"
if expect_plan_differs_from_master:
assert plan_amounts != master_amounts or plan.get("ingredients") != master.get(
"ingredients"
), "plan should differ from master for this scenario"
assert operator["total_component"] == int(round(plan_amounts[0]))
assert operator["total_mixture"] == int(round(sum(plan_amounts)))
assert operator["total_component"] != int(round(master_amounts[0])) or len(
plan_amounts
) != len(master_amounts)
return {
"master": master,
"plan": plan,
"operator": operator,
"master_amounts": master_amounts,
"plan_amounts": plan_amounts,
}
def assert_daily_plan_tables_registered() -> None:
from app.models import (
DailyComponentNormAdjustment,
DailyIngredientReplacement,
DailyIngredientSkip,
DailyTripSkip,
DailyUnloadingGroupSkip,
_sync_models,
)
from app.services.sync_manager import SERVER_MASTER_TABLES, SNAPSHOT_MODELS
from app.services.sync_record_data import get_record_data_for_sync
model_by_table = {
DailyTripSkip.__tablename__: DailyTripSkip,
DailyIngredientSkip.__tablename__: DailyIngredientSkip,
DailyUnloadingGroupSkip.__tablename__: DailyUnloadingGroupSkip,
DailyIngredientReplacement.__tablename__: DailyIngredientReplacement,
DailyComponentNormAdjustment.__tablename__: DailyComponentNormAdjustment,
}
assert set(DAILY_PLAN_SYNC_TABLES) == set(model_by_table)
sync_model_tables = {m.__tablename__ for m in _sync_models if m.__tablename__.startswith("daily_")}
assert sync_model_tables == set(DAILY_PLAN_SYNC_TABLES)
snapshot_tables = {m.__tablename__ for m in SNAPSHOT_MODELS}
for table in DAILY_PLAN_SYNC_TABLES:
assert table in snapshot_tables, f"{table} missing from SNAPSHOT_MODELS"
assert table in SERVER_MASTER_TABLES, f"{table} missing from SERVER_MASTER_TABLES"
# smoke: get_record_data_for_sync resolves model (None без строки — ок)
assert get_record_data_for_sync("daily_trip_skip", "nonexistent-id") is None