import sys from unittest.mock import MagicMock, AsyncMock, patch from datetime import date, datetime, timedelta import uuid import pytest # Mock shared.config.base and pydantic_settings mock_base = MagicMock() mock_base.BASE_REFERENCE_DATE = date(2025, 11, 25) sys.modules["shared.config.base"] = mock_base sys.modules["pydantic_settings"] = MagicMock() sys.modules["shared.database.base"] = MagicMock() sys.modules["app.models.distribution"] = MagicMock() sys.modules["shared.clients.tenant_client"] = MagicMock() sys.modules["shared.clients.inventory_client"] = MagicMock() sys.modules["shared.clients.procurement_client"] = MagicMock() sys.modules["httpx"] = MagicMock() from app.services.distribution_service import DistributionService @pytest.mark.asyncio async def test_setup_demo_enterprise_distribution_clones_history(): # Setup mocks route_repo = AsyncMock() shipment_repo = AsyncMock() schedule_repo = AsyncMock() procurement_client = AsyncMock() tenant_client = AsyncMock() inventory_client = AsyncMock() routing_optimizer = AsyncMock() service = DistributionService( route_repository=route_repo, shipment_repository=shipment_repo, schedule_repository=schedule_repo, procurement_client=procurement_client, tenant_client=tenant_client, inventory_client=inventory_client, routing_optimizer=routing_optimizer ) # Mock data parent_tenant_id = str(uuid.uuid4()) child_tenant_ids = [str(uuid.uuid4()), str(uuid.uuid4()), str(uuid.uuid4())] session_id = "test-session" # Mock tenant client responses async def get_locations(tenant_id): if tenant_id == parent_tenant_id: return [{"location_type": "central_production", "latitude": 40.0, "longitude": -3.0, "name": "Central"}] else: return [{"location_type": "retail_outlet", "latitude": 40.1, "longitude": -3.1, "name": "Outlet"}] tenant_client.get_tenant_locations.side_effect = get_locations # Mock routing optimizer routing_optimizer.optimize_daily_routes.return_value = { "total_distance_km": 50.0, "estimated_duration_minutes": 60, "routes": [ { "vehicle_id": "VEH-NEW", "driver_id": "DRV-NEW", "total_distance_km": 50.0, "estimated_duration_minutes": 60, "route_sequence": [ {"stop": 1, "tenant_id": child_tenant_ids[0], "location": "Outlet"} ] } ] } # Mock historical data start_date = date(2025, 10, 26) end_date = date(2025, 11, 25) mock_routes = [ { "id": "old-route-1", "route_number": "DEMO-20251120-001", "route_date": datetime(2025, 11, 20), "vehicle_id": "VEH-001", "total_distance_km": 100.0, "estimated_duration_minutes": 120, "route_sequence": [ {"stop": 1, "tenant_id": "d4e5f6a7-b8c9-40d1-e2f3-a4b5c6d7e8f9"}, # Template child 1 {"stop": 2, "tenant_id": "e5f6a7b8-c9d0-41e2-f3a4-b5c6d7e8f9a0"} # Template child 2 ], "status": "completed" } ] mock_shipments = [ { "id": "old-shipment-1", "child_tenant_id": "d4e5f6a7-b8c9-40d1-e2f3-a4b5c6d7e8f9", # Template child 1 "delivery_route_id": "old-route-1", "shipment_number": "DEMOSHP-20251120-001", "shipment_date": datetime(2025, 11, 20), "status": "delivered", "total_weight_kg": 50.0, "total_volume_m3": 0.5 } ] route_repo.get_routes_by_date_range.return_value = mock_routes shipment_repo.get_shipments_by_date_range.return_value = mock_shipments route_repo.create_route.return_value = {"id": "new-route-1"} # Execute result = await service.setup_demo_enterprise_distribution( parent_tenant_id=parent_tenant_id, child_tenant_ids=child_tenant_ids, session_id=session_id ) # Verify assert result["status"] == "completed" assert result["routes_count"] == 1 assert result["shipment_count"] == 1 # Verify route creation route_repo.create_route.assert_called() call_args = route_repo.create_route.call_args[0][0] assert call_args["tenant_id"] == parent_tenant_id assert call_args["route_number"] == "DEMO-20251120-001" # Verify child ID mapping in sequence assert call_args["route_sequence"][0]["tenant_id"] == child_tenant_ids[0] # Verify shipment creation shipment_repo.create_shipment.assert_called() call_args = shipment_repo.create_shipment.call_args[0][0] assert call_args["tenant_id"] == parent_tenant_id assert call_args["child_tenant_id"] == child_tenant_ids[0] assert call_args["delivery_route_id"] == "new-route-1"