Files
bakery-ia/shared/clients/orders_client.py

252 lines
11 KiB
Python
Raw Permalink Normal View History

2025-08-21 20:28:14 +02:00
# shared/clients/orders_client.py
"""
Orders Service Client for Inter-Service Communication
Provides access to orders and procurement planning from other services
"""
import structlog
from typing import Dict, Any, Optional, List
from uuid import UUID
from shared.clients.base_service_client import BaseServiceClient
from shared.config.base import BaseServiceSettings
logger = structlog.get_logger()
class OrdersServiceClient(BaseServiceClient):
"""Client for communicating with the Orders Service"""
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
def __init__(self, config: BaseServiceSettings):
super().__init__("orders", config)
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
def get_service_base_path(self) -> str:
return "/api/v1"
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
# ================================================================
# PROCUREMENT PLANNING
# ================================================================
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_demand_requirements(self, tenant_id: str, date: str) -> Optional[Dict[str, Any]]:
"""Get demand requirements for production planning"""
try:
params = {"date": date}
2025-10-06 15:27:01 +02:00
result = await self.get("orders/demand-requirements", tenant_id=tenant_id, params=params)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Retrieved demand requirements from orders service",
2025-08-21 20:28:14 +02:00
date=date, tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting demand requirements",
2025-08-21 20:28:14 +02:00
error=str(e), date=date, tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_procurement_requirements(self, tenant_id: str, horizon: Optional[str] = None) -> Optional[Dict[str, Any]]:
"""Get procurement requirements for purchasing planning"""
try:
params = {}
if horizon:
params["horizon"] = horizon
2025-10-06 15:27:01 +02:00
result = await self.get("orders/procurement-requirements", tenant_id=tenant_id, params=params)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Retrieved procurement requirements from orders service",
2025-08-21 20:28:14 +02:00
horizon=horizon, tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting procurement requirements",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_weekly_ingredient_needs(self, tenant_id: str) -> Optional[Dict[str, Any]]:
"""Get weekly ingredient ordering needs for dashboard"""
try:
2025-10-06 15:27:01 +02:00
result = await self.get("orders/dashboard/weekly-ingredient-needs", tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Retrieved weekly ingredient needs from orders service",
2025-08-21 20:28:14 +02:00
tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting weekly ingredient needs",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
# ================================================================
# CUSTOMER ORDERS
# ================================================================
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_customer_orders(self, tenant_id: str, params: Optional[Dict[str, Any]] = None) -> Optional[Dict[str, Any]]:
"""Get customer orders with optional filtering"""
try:
2025-10-06 15:27:01 +02:00
result = await self.get("orders/list", tenant_id=tenant_id, params=params)
2025-08-21 20:28:14 +02:00
if result:
orders_count = len(result.get('orders', [])) if isinstance(result, dict) else len(result) if isinstance(result, list) else 0
2025-10-06 15:27:01 +02:00
logger.info("Retrieved customer orders from orders service",
2025-08-21 20:28:14 +02:00
orders_count=orders_count, tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting customer orders",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def create_customer_order(self, tenant_id: str, order_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""Create a new customer order"""
try:
2025-10-06 15:27:01 +02:00
result = await self.post("orders/list", data=order_data, tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Created customer order",
2025-08-21 20:28:14 +02:00
order_id=result.get('id'), tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error creating customer order",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def update_customer_order(self, tenant_id: str, order_id: str, order_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""Update an existing customer order"""
try:
2025-10-06 15:27:01 +02:00
result = await self.put(f"orders/list/{order_id}", data=order_data, tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Updated customer order",
2025-08-21 20:28:14 +02:00
order_id=order_id, tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error updating customer order",
2025-08-21 20:28:14 +02:00
error=str(e), order_id=order_id, tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
# ================================================================
# CENTRAL BAKERY ORDERS
# ================================================================
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_daily_finalized_orders(self, tenant_id: str, date: Optional[str] = None) -> Optional[Dict[str, Any]]:
"""Get daily finalized orders for central bakery"""
try:
params = {}
if date:
params["date"] = date
2025-10-06 15:27:01 +02:00
result = await self.get("orders/daily-finalized", tenant_id=tenant_id, params=params)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Retrieved daily finalized orders from orders service",
2025-08-21 20:28:14 +02:00
date=date, tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting daily finalized orders",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_weekly_order_summaries(self, tenant_id: str) -> Optional[Dict[str, Any]]:
"""Get weekly order summaries for central bakery dashboard"""
try:
2025-10-06 15:27:01 +02:00
result = await self.get("orders/dashboard/weekly-summaries", tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Retrieved weekly order summaries from orders service",
2025-08-21 20:28:14 +02:00
tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting weekly order summaries",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
# ================================================================
# DASHBOARD AND ANALYTICS
# ================================================================
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_dashboard_summary(self, tenant_id: str) -> Optional[Dict[str, Any]]:
"""Get orders dashboard summary data"""
try:
2025-10-06 15:27:01 +02:00
result = await self.get("orders/dashboard/summary", tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Retrieved orders dashboard summary",
2025-08-21 20:28:14 +02:00
tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting orders dashboard summary",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_order_trends(self, tenant_id: str, start_date: str, end_date: str) -> Optional[Dict[str, Any]]:
"""Get order trends analysis"""
try:
params = {
"start_date": start_date,
"end_date": end_date
}
2025-10-06 15:27:01 +02:00
result = await self.get("orders/analytics/trends", tenant_id=tenant_id, params=params)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Retrieved order trends from orders service",
2025-08-21 20:28:14 +02:00
start_date=start_date, end_date=end_date, tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting order trends",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
# ================================================================
# ALERTS AND NOTIFICATIONS
# ================================================================
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def get_central_bakery_alerts(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
"""Get central bakery specific alerts"""
try:
2025-10-06 15:27:01 +02:00
result = await self.get("orders/alerts", tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
alerts = result.get('alerts', []) if result else []
2025-10-06 15:27:01 +02:00
logger.info("Retrieved central bakery alerts from orders service",
2025-08-21 20:28:14 +02:00
alerts_count=len(alerts), tenant_id=tenant_id)
return alerts
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error getting central bakery alerts",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return []
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def acknowledge_alert(self, tenant_id: str, alert_id: str) -> Optional[Dict[str, Any]]:
"""Acknowledge an order-related alert"""
try:
2025-10-06 15:27:01 +02:00
result = await self.post(f"orders/alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Acknowledged order alert",
2025-08-21 20:28:14 +02:00
alert_id=alert_id, tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error acknowledging order alert",
2025-08-21 20:28:14 +02:00
error=str(e), alert_id=alert_id, tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
# ================================================================
# UTILITY METHODS
# ================================================================
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def download_orders_pdf(self, tenant_id: str, order_ids: List[str], format_type: str = "supplier_communication") -> Optional[bytes]:
"""Download orders as PDF for supplier communication"""
try:
data = {
"order_ids": order_ids,
"format": format_type,
"include_delivery_schedule": True
}
# Note: This would need special handling for binary data
2025-10-06 15:27:01 +02:00
result = await self.post("orders/operations/download-pdf", data=data, tenant_id=tenant_id)
2025-08-21 20:28:14 +02:00
if result:
2025-10-06 15:27:01 +02:00
logger.info("Generated orders PDF",
2025-08-21 20:28:14 +02:00
orders_count=len(order_ids), tenant_id=tenant_id)
return result
except Exception as e:
2025-10-06 15:27:01 +02:00
logger.error("Error generating orders PDF",
2025-08-21 20:28:14 +02:00
error=str(e), tenant_id=tenant_id)
return None
2025-10-06 15:27:01 +02:00
2025-08-21 20:28:14 +02:00
async def health_check(self) -> bool:
"""Check if orders service is healthy"""
try:
result = await self.get("../health") # Health endpoint is not tenant-scoped
return result is not None
except Exception as e:
logger.error("Orders service health check failed", error=str(e))
return False
# Factory function for dependency injection
def create_orders_client(config: BaseServiceSettings) -> OrdersServiceClient:
"""Create orders service client instance"""
2025-10-06 15:27:01 +02:00
return OrdersServiceClient(config)