"""Operational flow: save_report → save_unloading_report.""" from __future__ import annotations import unittest from app import create_app, db from sqlalchemy import select from app.models import Recipe from app.models.feed_alert import FeedAlert from app.services.feed_quality.rules import EVENT_LEFT_IN_MIXER from app.services.setup_state import mark_setup_complete from tests.helpers.zootech_test_helpers import ZootechTestConfig class UnloadingReportFlowTests(unittest.TestCase): def setUp(self) -> None: self.app = create_app(ZootechTestConfig) self.client = self.app.test_client() self.ctx = self.app.app_context() self.ctx.push() db.create_all() mark_setup_complete(self.app) db.session.add( Recipe( id="unload-flow-r1", name="Unload flow", heads_per_trip=10, mixing_time=5, content_hash="", ) ) db.session.commit() def tearDown(self) -> None: db.session.remove() db.drop_all() self.ctx.pop() def test_save_report_then_unloading_report(self) -> None: loading = self.client.post( "/api/save_report", json={ "recipe_id": "unload-flow-r1", "total_weight": 80.0, "target_mixing_time": 5, "actual_mixing_time": 5, "components": [ {"name": "C", "target_weight": 80, "actual_weight": 80, "overload": 0} ], }, ) self.assertEqual(loading.status_code, 200) report_id = loading.get_json()["report_id"] unloading = self.client.post( "/api/save_unloading_report", json={ "loading_report_id": report_id, "recipe_id": "unload-flow-r1", "total_weight": 80.0, "total_unloaded_weight": 75.0, "remaining_weight": 5.0, "unloading_groups": [ { "name": "G", "target_weight": 80.0, "unloaded_weight": 75.0, "remaining_weight": 5.0, "distribution_type": "percent", "distribution_value": 100, "order": 1, } ], }, ) self.assertEqual(unloading.status_code, 200) self.assertIn("unloading_report_id", unloading.get_json()) alerts = ( db.session.execute( select(FeedAlert).where(FeedAlert.loading_report_id == report_id) ) .scalars() .all() ) types = {a.event_type for a in alerts} self.assertIn(EVENT_LEFT_IN_MIXER, types) if __name__ == "__main__": unittest.main()