REFACTOR ALL APIs
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
# shared/clients/forecast_client.py
|
||||
"""
|
||||
Forecast Service Client
|
||||
Forecast Service Client - Updated for refactored backend structure
|
||||
Handles all API calls to the forecasting service
|
||||
|
||||
Backend structure:
|
||||
- ATOMIC: /forecasting/forecasts (CRUD)
|
||||
- BUSINESS: /forecasting/operations/* (single, multi-day, batch, etc.)
|
||||
- ANALYTICS: /forecasting/analytics/* (predictions-performance)
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, Optional, List
|
||||
@@ -12,17 +17,172 @@ from shared.config.base import BaseServiceSettings
|
||||
|
||||
class ForecastServiceClient(BaseServiceClient):
|
||||
"""Client for communicating with the forecasting service"""
|
||||
|
||||
|
||||
def __init__(self, config: BaseServiceSettings, calling_service_name: str = "unknown"):
|
||||
super().__init__(calling_service_name, config)
|
||||
|
||||
|
||||
def get_service_base_path(self) -> str:
|
||||
return "/api/v1"
|
||||
|
||||
|
||||
# ================================================================
|
||||
# FORECASTS
|
||||
# ATOMIC: Forecast CRUD Operations
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_forecast(self, tenant_id: str, forecast_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get forecast details by ID"""
|
||||
return await self.get(f"forecasting/forecasts/{forecast_id}", tenant_id=tenant_id)
|
||||
|
||||
async def list_forecasts(
|
||||
self,
|
||||
tenant_id: str,
|
||||
inventory_product_id: Optional[str] = None,
|
||||
start_date: Optional[date] = None,
|
||||
end_date: Optional[date] = None,
|
||||
limit: int = 50,
|
||||
offset: int = 0
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
"""List forecasts for a tenant with optional filters"""
|
||||
params = {"limit": limit, "offset": offset}
|
||||
if inventory_product_id:
|
||||
params["inventory_product_id"] = inventory_product_id
|
||||
if start_date:
|
||||
params["start_date"] = start_date.isoformat()
|
||||
if end_date:
|
||||
params["end_date"] = end_date.isoformat()
|
||||
|
||||
return await self.get("forecasting/forecasts", tenant_id=tenant_id, params=params)
|
||||
|
||||
async def delete_forecast(self, tenant_id: str, forecast_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Delete a forecast"""
|
||||
return await self.delete(f"forecasting/forecasts/{forecast_id}", tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# BUSINESS: Forecasting Operations
|
||||
# ================================================================
|
||||
|
||||
async def generate_single_forecast(
|
||||
self,
|
||||
tenant_id: str,
|
||||
inventory_product_id: str,
|
||||
forecast_date: date,
|
||||
include_recommendations: bool = False
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Generate a single product forecast"""
|
||||
data = {
|
||||
"inventory_product_id": inventory_product_id,
|
||||
"forecast_date": forecast_date.isoformat(),
|
||||
"include_recommendations": include_recommendations
|
||||
}
|
||||
return await self.post("forecasting/operations/single", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def generate_multi_day_forecast(
|
||||
self,
|
||||
tenant_id: str,
|
||||
inventory_product_id: str,
|
||||
forecast_date: date,
|
||||
forecast_days: int = 7,
|
||||
include_recommendations: bool = False
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Generate multiple daily forecasts for the specified period"""
|
||||
data = {
|
||||
"inventory_product_id": inventory_product_id,
|
||||
"forecast_date": forecast_date.isoformat(),
|
||||
"forecast_days": forecast_days,
|
||||
"include_recommendations": include_recommendations
|
||||
}
|
||||
return await self.post("forecasting/operations/multi-day", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def generate_batch_forecast(
|
||||
self,
|
||||
tenant_id: str,
|
||||
inventory_product_ids: List[str],
|
||||
forecast_date: date,
|
||||
forecast_days: int = 1
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Generate forecasts for multiple products in batch"""
|
||||
data = {
|
||||
"inventory_product_ids": inventory_product_ids,
|
||||
"forecast_date": forecast_date.isoformat(),
|
||||
"forecast_days": forecast_days
|
||||
}
|
||||
return await self.post("forecasting/operations/batch", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def generate_realtime_prediction(
|
||||
self,
|
||||
tenant_id: str,
|
||||
inventory_product_id: str,
|
||||
model_id: str,
|
||||
features: Dict[str, Any],
|
||||
model_path: Optional[str] = None,
|
||||
confidence_level: float = 0.8
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Generate real-time prediction"""
|
||||
data = {
|
||||
"inventory_product_id": inventory_product_id,
|
||||
"model_id": model_id,
|
||||
"features": features,
|
||||
"confidence_level": confidence_level
|
||||
}
|
||||
if model_path:
|
||||
data["model_path"] = model_path
|
||||
|
||||
return await self.post("forecasting/operations/realtime", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def validate_predictions(
|
||||
self,
|
||||
tenant_id: str,
|
||||
start_date: date,
|
||||
end_date: date
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Validate predictions against actual sales data"""
|
||||
params = {
|
||||
"start_date": start_date.isoformat(),
|
||||
"end_date": end_date.isoformat()
|
||||
}
|
||||
return await self.post("forecasting/operations/validate-predictions", params=params, tenant_id=tenant_id)
|
||||
|
||||
async def get_forecast_statistics(
|
||||
self,
|
||||
tenant_id: str,
|
||||
start_date: Optional[date] = None,
|
||||
end_date: Optional[date] = None
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Get forecast statistics"""
|
||||
params = {}
|
||||
if start_date:
|
||||
params["start_date"] = start_date.isoformat()
|
||||
if end_date:
|
||||
params["end_date"] = end_date.isoformat()
|
||||
|
||||
return await self.get("forecasting/operations/statistics", tenant_id=tenant_id, params=params)
|
||||
|
||||
async def clear_prediction_cache(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Clear prediction cache"""
|
||||
return await self.delete("forecasting/operations/cache", tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# ANALYTICS: Forecasting Analytics
|
||||
# ================================================================
|
||||
|
||||
async def get_predictions_performance(
|
||||
self,
|
||||
tenant_id: str,
|
||||
start_date: Optional[date] = None,
|
||||
end_date: Optional[date] = None
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Get predictions performance analytics"""
|
||||
params = {}
|
||||
if start_date:
|
||||
params["start_date"] = start_date.isoformat()
|
||||
if end_date:
|
||||
params["end_date"] = end_date.isoformat()
|
||||
|
||||
return await self.get("forecasting/analytics/predictions-performance", tenant_id=tenant_id, params=params)
|
||||
|
||||
# ================================================================
|
||||
# Legacy/Compatibility Methods (deprecated)
|
||||
# ================================================================
|
||||
|
||||
async def create_forecast(
|
||||
self,
|
||||
tenant_id: str,
|
||||
@@ -33,180 +193,16 @@ class ForecastServiceClient(BaseServiceClient):
|
||||
include_confidence_intervals: bool = True,
|
||||
**kwargs
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Create a new forecast"""
|
||||
data = {
|
||||
"model_id": model_id,
|
||||
"start_date": start_date,
|
||||
"end_date": end_date,
|
||||
"include_confidence_intervals": include_confidence_intervals,
|
||||
**kwargs
|
||||
}
|
||||
"""
|
||||
DEPRECATED: Use generate_single_forecast or generate_batch_forecast instead
|
||||
Legacy method for backward compatibility
|
||||
"""
|
||||
# Map to new batch forecast operation
|
||||
if product_ids:
|
||||
data["product_ids"] = product_ids
|
||||
|
||||
return await self.post("forecasts", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def get_forecast(self, tenant_id: str, forecast_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get forecast details"""
|
||||
return await self.get(f"forecasts/{forecast_id}", tenant_id=tenant_id)
|
||||
|
||||
async def list_forecasts(
|
||||
self,
|
||||
tenant_id: str,
|
||||
status: Optional[str] = None,
|
||||
model_id: Optional[str] = None,
|
||||
limit: int = 50
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
"""List forecasts for a tenant"""
|
||||
params = {"limit": limit}
|
||||
if status:
|
||||
params["status"] = status
|
||||
if model_id:
|
||||
params["model_id"] = model_id
|
||||
|
||||
result = await self.get("forecasts", tenant_id=tenant_id, params=params)
|
||||
return result.get("forecasts", []) if result else None
|
||||
|
||||
async def delete_forecast(self, tenant_id: str, forecast_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Delete a forecast"""
|
||||
return await self.delete(f"forecasts/{forecast_id}", tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# PREDICTIONS
|
||||
# ================================================================
|
||||
|
||||
async def get_predictions(
|
||||
self,
|
||||
tenant_id: str,
|
||||
forecast_id: str,
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None,
|
||||
product_id: Optional[str] = None
|
||||
) -> Optional[List[Dict[str, Any]]]:
|
||||
"""Get predictions from a forecast"""
|
||||
params = {}
|
||||
if start_date:
|
||||
params["start_date"] = start_date
|
||||
if end_date:
|
||||
params["end_date"] = end_date
|
||||
if product_id:
|
||||
params["product_id"] = product_id
|
||||
|
||||
result = await self.get(f"forecasts/{forecast_id}/predictions", tenant_id=tenant_id, params=params)
|
||||
return result.get("predictions", []) if result else None
|
||||
|
||||
async def create_realtime_prediction(
|
||||
self,
|
||||
tenant_id: str,
|
||||
model_id: str,
|
||||
target_date: str,
|
||||
features: Dict[str, Any],
|
||||
inventory_product_id: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Create a real-time prediction"""
|
||||
data = {
|
||||
"model_id": model_id,
|
||||
"target_date": target_date,
|
||||
"features": features,
|
||||
**kwargs
|
||||
}
|
||||
|
||||
# Add inventory_product_id if provided (required by forecasting service)
|
||||
if inventory_product_id:
|
||||
data["inventory_product_id"] = inventory_product_id
|
||||
|
||||
return await self.post("forecasts/single", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def create_single_forecast(
|
||||
self,
|
||||
tenant_id: str,
|
||||
inventory_product_id: str,
|
||||
forecast_date: date,
|
||||
location: str = "default",
|
||||
forecast_days: int = 1,
|
||||
confidence_level: float = 0.8,
|
||||
**kwargs
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Create a single product forecast using new API format"""
|
||||
from datetime import date as date_type
|
||||
|
||||
# Convert date to string if needed
|
||||
if isinstance(forecast_date, date_type):
|
||||
forecast_date_str = forecast_date.isoformat()
|
||||
else:
|
||||
forecast_date_str = str(forecast_date)
|
||||
|
||||
data = {
|
||||
"inventory_product_id": inventory_product_id,
|
||||
"forecast_date": forecast_date_str,
|
||||
"forecast_days": forecast_days,
|
||||
"location": location,
|
||||
"confidence_level": confidence_level,
|
||||
**kwargs
|
||||
}
|
||||
|
||||
return await self.post("forecasts/single", data=data, tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# FORECAST VALIDATION & METRICS
|
||||
# ================================================================
|
||||
|
||||
async def get_forecast_accuracy(
|
||||
self,
|
||||
tenant_id: str,
|
||||
forecast_id: str,
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Get forecast accuracy metrics"""
|
||||
params = {}
|
||||
if start_date:
|
||||
params["start_date"] = start_date
|
||||
if end_date:
|
||||
params["end_date"] = end_date
|
||||
|
||||
return await self.get(f"forecasts/{forecast_id}/accuracy", tenant_id=tenant_id, params=params)
|
||||
|
||||
async def compare_forecasts(
|
||||
self,
|
||||
tenant_id: str,
|
||||
forecast_ids: List[str],
|
||||
metric: str = "mape"
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Compare multiple forecasts"""
|
||||
data = {
|
||||
"forecast_ids": forecast_ids,
|
||||
"metric": metric
|
||||
}
|
||||
return await self.post("forecasts/compare", data=data, tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# FORECAST SCENARIOS
|
||||
# ================================================================
|
||||
|
||||
async def create_scenario_forecast(
|
||||
self,
|
||||
tenant_id: str,
|
||||
model_id: str,
|
||||
scenario_name: str,
|
||||
scenario_data: Dict[str, Any],
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
**kwargs
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Create a scenario-based forecast"""
|
||||
data = {
|
||||
"model_id": model_id,
|
||||
"scenario_name": scenario_name,
|
||||
"scenario_data": scenario_data,
|
||||
"start_date": start_date,
|
||||
"end_date": end_date,
|
||||
**kwargs
|
||||
}
|
||||
return await self.post("scenarios", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def list_scenarios(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
|
||||
"""List forecast scenarios for a tenant"""
|
||||
result = await self.get("scenarios", tenant_id=tenant_id)
|
||||
return result.get("scenarios", []) if result else None
|
||||
return await self.generate_batch_forecast(
|
||||
tenant_id=tenant_id,
|
||||
inventory_product_ids=product_ids,
|
||||
forecast_date=date.fromisoformat(start_date),
|
||||
forecast_days=1
|
||||
)
|
||||
return None
|
||||
|
||||
@@ -31,13 +31,13 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
async def get_ingredient_by_id(self, ingredient_id: UUID, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get ingredient details by ID"""
|
||||
try:
|
||||
result = await self.get(f"ingredients/{ingredient_id}", tenant_id=tenant_id)
|
||||
result = await self.get(f"inventory/ingredients/{ingredient_id}", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved ingredient from inventory service",
|
||||
logger.info("Retrieved ingredient from inventory service",
|
||||
ingredient_id=ingredient_id, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error fetching ingredient by ID",
|
||||
logger.error("Error fetching ingredient by ID",
|
||||
error=str(e), ingredient_id=ingredient_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
@@ -64,10 +64,10 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
if is_active is not None:
|
||||
params["is_active"] = is_active
|
||||
|
||||
result = await self.get("ingredients", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("inventory/ingredients", tenant_id=tenant_id, params=params)
|
||||
ingredients = result if isinstance(result, list) else []
|
||||
|
||||
logger.info("Searched ingredients in inventory service",
|
||||
|
||||
logger.info("Searched ingredients in inventory service",
|
||||
search_term=search, count=len(ingredients), tenant_id=tenant_id)
|
||||
return ingredients
|
||||
|
||||
@@ -83,7 +83,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
if is_active is not None:
|
||||
params["is_active"] = is_active
|
||||
|
||||
ingredients = await self.get_paginated("ingredients", tenant_id=tenant_id, params=params)
|
||||
ingredients = await self.get_paginated("inventory/ingredients", tenant_id=tenant_id, params=params)
|
||||
|
||||
logger.info("Retrieved all ingredients from inventory service",
|
||||
count=len(ingredients), tenant_id=tenant_id)
|
||||
@@ -101,7 +101,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
if is_active is not None:
|
||||
params["is_active"] = is_active
|
||||
|
||||
result = await self.get("ingredients/count", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("inventory/ingredients/count", tenant_id=tenant_id, params=params)
|
||||
count = result.get("ingredient_count", 0) if isinstance(result, dict) else 0
|
||||
|
||||
logger.info("Retrieved ingredient count from inventory service",
|
||||
@@ -116,7 +116,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
async def create_ingredient(self, ingredient_data: Dict[str, Any], tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Create a new ingredient"""
|
||||
try:
|
||||
result = await self.post("ingredients", data=ingredient_data, tenant_id=tenant_id)
|
||||
result = await self.post("inventory/ingredients", data=ingredient_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Created ingredient in inventory service",
|
||||
ingredient_name=ingredient_data.get('name'), tenant_id=tenant_id)
|
||||
@@ -134,7 +134,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Update an existing ingredient"""
|
||||
try:
|
||||
result = await self.put(f"ingredients/{ingredient_id}", data=ingredient_data, tenant_id=tenant_id)
|
||||
result = await self.put(f"inventory/ingredients/{ingredient_id}", data=ingredient_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Updated ingredient in inventory service",
|
||||
ingredient_id=ingredient_id, tenant_id=tenant_id)
|
||||
@@ -147,7 +147,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
async def delete_ingredient(self, ingredient_id: UUID, tenant_id: str) -> bool:
|
||||
"""Delete (deactivate) an ingredient"""
|
||||
try:
|
||||
result = await self.delete(f"ingredients/{ingredient_id}", tenant_id=tenant_id)
|
||||
result = await self.delete(f"inventory/ingredients/{ingredient_id}", tenant_id=tenant_id)
|
||||
success = result is not None
|
||||
if success:
|
||||
logger.info("Deleted ingredient in inventory service",
|
||||
@@ -170,7 +170,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
if include_unavailable:
|
||||
params["include_unavailable"] = include_unavailable
|
||||
|
||||
result = await self.get(f"ingredients/{ingredient_id}/stock", tenant_id=tenant_id, params=params)
|
||||
result = await self.get(f"inventory/ingredients/{ingredient_id}/stock", tenant_id=tenant_id, params=params)
|
||||
stock_entries = result if isinstance(result, list) else []
|
||||
|
||||
logger.info("Retrieved ingredient stock from inventory service",
|
||||
@@ -193,7 +193,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
if ingredient_ids:
|
||||
params["ingredient_ids"] = [str(id) for id in ingredient_ids]
|
||||
|
||||
result = await self.get("stock", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("inventory/stock", tenant_id=tenant_id, params=params)
|
||||
stock_levels = result if isinstance(result, list) else []
|
||||
|
||||
logger.info("Retrieved stock levels from inventory service",
|
||||
@@ -208,7 +208,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
async def get_low_stock_alerts(self, tenant_id: str) -> List[Dict[str, Any]]:
|
||||
"""Get low stock alerts"""
|
||||
try:
|
||||
result = await self.get("alerts", tenant_id=tenant_id, params={"type": "low_stock"})
|
||||
result = await self.get("inventory/alerts", tenant_id=tenant_id, params={"type": "low_stock"})
|
||||
alerts = result if isinstance(result, list) else []
|
||||
|
||||
logger.info("Retrieved low stock alerts from inventory service",
|
||||
@@ -227,7 +227,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Record stock consumption"""
|
||||
try:
|
||||
result = await self.post("stock/consume", data=consumption_data, tenant_id=tenant_id)
|
||||
result = await self.post("inventory/operations/consume-stock", data=consumption_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Recorded stock consumption",
|
||||
tenant_id=tenant_id)
|
||||
@@ -244,7 +244,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Record stock receipt"""
|
||||
try:
|
||||
result = await self.post("stock/receive", data=receipt_data, tenant_id=tenant_id)
|
||||
result = await self.post("inventory/operations/receive-stock", data=receipt_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Recorded stock receipt",
|
||||
tenant_id=tenant_id)
|
||||
@@ -271,7 +271,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
"sales_volume": sales_volume
|
||||
}
|
||||
|
||||
result = await self.post("inventory/classify-product", data=classification_data, tenant_id=tenant_id)
|
||||
result = await self.post("inventory/operations/classify-product", data=classification_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Classified product",
|
||||
product=product_name,
|
||||
@@ -296,7 +296,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
"products": products
|
||||
}
|
||||
|
||||
result = await self.post("inventory/classify-products-batch", data=classification_data, tenant_id=tenant_id)
|
||||
result = await self.post("inventory/operations/classify-products-batch", data=classification_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
suggestions = result.get('suggestions', [])
|
||||
business_model = result.get('business_model_analysis', {}).get('model', 'unknown')
|
||||
@@ -319,7 +319,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
async def get_inventory_dashboard(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get inventory dashboard data"""
|
||||
try:
|
||||
result = await self.get("dashboard", tenant_id=tenant_id)
|
||||
result = await self.get("inventory/dashboard/overview", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved inventory dashboard data", tenant_id=tenant_id)
|
||||
return result
|
||||
@@ -331,7 +331,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
async def get_inventory_summary(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get inventory summary statistics"""
|
||||
try:
|
||||
result = await self.get("dashboard/summary", tenant_id=tenant_id)
|
||||
result = await self.get("inventory/dashboard/summary", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved inventory summary", tenant_id=tenant_id)
|
||||
return result
|
||||
@@ -351,7 +351,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Create a product transformation (e.g., par-baked to fully baked)"""
|
||||
try:
|
||||
result = await self.post("transformations", data=transformation_data, tenant_id=tenant_id)
|
||||
result = await self.post("inventory/transformations", data=transformation_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Created product transformation",
|
||||
transformation_reference=result.get('transformation_reference'),
|
||||
@@ -388,7 +388,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
if notes:
|
||||
params["notes"] = notes
|
||||
|
||||
result = await self.post("transformations/par-bake-to-fresh", params=params, tenant_id=tenant_id)
|
||||
result = await self.post("inventory/transformations/par-bake-to-fresh", params=params, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Created par-bake transformation",
|
||||
transformation_id=result.get('transformation_id'),
|
||||
@@ -426,7 +426,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
if days_back:
|
||||
params["days_back"] = days_back
|
||||
|
||||
result = await self.get("transformations", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("inventory/transformations", tenant_id=tenant_id, params=params)
|
||||
transformations = result if isinstance(result, list) else []
|
||||
|
||||
logger.info("Retrieved transformations from inventory service",
|
||||
@@ -445,7 +445,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Get specific transformation by ID"""
|
||||
try:
|
||||
result = await self.get(f"transformations/{transformation_id}", tenant_id=tenant_id)
|
||||
result = await self.get(f"inventory/transformations/{transformation_id}", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved transformation by ID",
|
||||
transformation_id=transformation_id, tenant_id=tenant_id)
|
||||
@@ -463,7 +463,7 @@ class InventoryServiceClient(BaseServiceClient):
|
||||
"""Get transformation summary for dashboard"""
|
||||
try:
|
||||
params = {"days_back": days_back}
|
||||
result = await self.get("transformations/summary", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("inventory/dashboard/transformations-summary", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved transformation summary",
|
||||
days_back=days_back, tenant_id=tenant_id)
|
||||
|
||||
@@ -15,156 +15,156 @@ logger = structlog.get_logger()
|
||||
|
||||
class OrdersServiceClient(BaseServiceClient):
|
||||
"""Client for communicating with the Orders Service"""
|
||||
|
||||
|
||||
def __init__(self, config: BaseServiceSettings):
|
||||
super().__init__("orders", config)
|
||||
|
||||
|
||||
def get_service_base_path(self) -> str:
|
||||
return "/api/v1"
|
||||
|
||||
|
||||
# ================================================================
|
||||
# PROCUREMENT PLANNING
|
||||
# ================================================================
|
||||
|
||||
|
||||
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}
|
||||
result = await self.get("demand-requirements", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("orders/demand-requirements", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved demand requirements from orders service",
|
||||
logger.info("Retrieved demand requirements from orders service",
|
||||
date=date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting demand requirements",
|
||||
logger.error("Error getting demand requirements",
|
||||
error=str(e), date=date, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
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
|
||||
|
||||
result = await self.get("procurement-requirements", tenant_id=tenant_id, params=params)
|
||||
|
||||
result = await self.get("orders/procurement-requirements", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved procurement requirements from orders service",
|
||||
logger.info("Retrieved procurement requirements from orders service",
|
||||
horizon=horizon, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting procurement requirements",
|
||||
logger.error("Error getting procurement requirements",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_weekly_ingredient_needs(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get weekly ingredient ordering needs for dashboard"""
|
||||
try:
|
||||
result = await self.get("weekly-ingredient-needs", tenant_id=tenant_id)
|
||||
result = await self.get("orders/dashboard/weekly-ingredient-needs", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved weekly ingredient needs from orders service",
|
||||
logger.info("Retrieved weekly ingredient needs from orders service",
|
||||
tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting weekly ingredient needs",
|
||||
logger.error("Error getting weekly ingredient needs",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# CUSTOMER ORDERS
|
||||
# ================================================================
|
||||
|
||||
|
||||
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:
|
||||
result = await self.get("customer-orders", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("orders/list", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
orders_count = len(result.get('orders', [])) if isinstance(result, dict) else len(result) if isinstance(result, list) else 0
|
||||
logger.info("Retrieved customer orders from orders service",
|
||||
logger.info("Retrieved customer orders from orders service",
|
||||
orders_count=orders_count, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting customer orders",
|
||||
logger.error("Error getting customer orders",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def create_customer_order(self, tenant_id: str, order_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""Create a new customer order"""
|
||||
try:
|
||||
result = await self.post("customer-orders", data=order_data, tenant_id=tenant_id)
|
||||
result = await self.post("orders/list", data=order_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Created customer order",
|
||||
logger.info("Created customer order",
|
||||
order_id=result.get('id'), tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error creating customer order",
|
||||
logger.error("Error creating customer order",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
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:
|
||||
result = await self.put(f"customer-orders/{order_id}", data=order_data, tenant_id=tenant_id)
|
||||
result = await self.put(f"orders/list/{order_id}", data=order_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Updated customer order",
|
||||
logger.info("Updated customer order",
|
||||
order_id=order_id, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error updating customer order",
|
||||
logger.error("Error updating customer order",
|
||||
error=str(e), order_id=order_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# CENTRAL BAKERY ORDERS
|
||||
# ================================================================
|
||||
|
||||
|
||||
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
|
||||
|
||||
result = await self.get("daily-finalized-orders", tenant_id=tenant_id, params=params)
|
||||
|
||||
result = await self.get("orders/daily-finalized", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved daily finalized orders from orders service",
|
||||
logger.info("Retrieved daily finalized orders from orders service",
|
||||
date=date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting daily finalized orders",
|
||||
logger.error("Error getting daily finalized orders",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_weekly_order_summaries(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get weekly order summaries for central bakery dashboard"""
|
||||
try:
|
||||
result = await self.get("weekly-order-summaries", tenant_id=tenant_id)
|
||||
result = await self.get("orders/dashboard/weekly-summaries", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved weekly order summaries from orders service",
|
||||
logger.info("Retrieved weekly order summaries from orders service",
|
||||
tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting weekly order summaries",
|
||||
logger.error("Error getting weekly order summaries",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# DASHBOARD AND ANALYTICS
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_dashboard_summary(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get orders dashboard summary data"""
|
||||
try:
|
||||
result = await self.get("dashboard-summary", tenant_id=tenant_id)
|
||||
result = await self.get("orders/dashboard/summary", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved orders dashboard summary",
|
||||
logger.info("Retrieved orders dashboard summary",
|
||||
tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting orders dashboard summary",
|
||||
logger.error("Error getting orders dashboard summary",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_order_trends(self, tenant_id: str, start_date: str, end_date: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get order trends analysis"""
|
||||
try:
|
||||
@@ -172,50 +172,50 @@ class OrdersServiceClient(BaseServiceClient):
|
||||
"start_date": start_date,
|
||||
"end_date": end_date
|
||||
}
|
||||
result = await self.get("order-trends", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("orders/analytics/trends", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved order trends from orders service",
|
||||
logger.info("Retrieved order trends from orders service",
|
||||
start_date=start_date, end_date=end_date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting order trends",
|
||||
logger.error("Error getting order trends",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# ALERTS AND NOTIFICATIONS
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_central_bakery_alerts(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
|
||||
"""Get central bakery specific alerts"""
|
||||
try:
|
||||
result = await self.get("central-bakery-alerts", tenant_id=tenant_id)
|
||||
result = await self.get("orders/alerts", tenant_id=tenant_id)
|
||||
alerts = result.get('alerts', []) if result else []
|
||||
logger.info("Retrieved central bakery alerts from orders service",
|
||||
logger.info("Retrieved central bakery alerts from orders service",
|
||||
alerts_count=len(alerts), tenant_id=tenant_id)
|
||||
return alerts
|
||||
except Exception as e:
|
||||
logger.error("Error getting central bakery alerts",
|
||||
logger.error("Error getting central bakery alerts",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return []
|
||||
|
||||
|
||||
async def acknowledge_alert(self, tenant_id: str, alert_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Acknowledge an order-related alert"""
|
||||
try:
|
||||
result = await self.post(f"alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
|
||||
result = await self.post(f"orders/alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Acknowledged order alert",
|
||||
logger.info("Acknowledged order alert",
|
||||
alert_id=alert_id, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error acknowledging order alert",
|
||||
logger.error("Error acknowledging order alert",
|
||||
error=str(e), alert_id=alert_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# UTILITY METHODS
|
||||
# ================================================================
|
||||
|
||||
|
||||
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:
|
||||
@@ -225,16 +225,16 @@ class OrdersServiceClient(BaseServiceClient):
|
||||
"include_delivery_schedule": True
|
||||
}
|
||||
# Note: This would need special handling for binary data
|
||||
result = await self.post("download/pdf", data=data, tenant_id=tenant_id)
|
||||
result = await self.post("orders/operations/download-pdf", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Generated orders PDF",
|
||||
logger.info("Generated orders PDF",
|
||||
orders_count=len(order_ids), tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error generating orders PDF",
|
||||
logger.error("Error generating orders PDF",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def health_check(self) -> bool:
|
||||
"""Check if orders service is healthy"""
|
||||
try:
|
||||
@@ -248,4 +248,4 @@ class OrdersServiceClient(BaseServiceClient):
|
||||
# Factory function for dependency injection
|
||||
def create_orders_client(config: BaseServiceSettings) -> OrdersServiceClient:
|
||||
"""Create orders service client instance"""
|
||||
return OrdersServiceClient(config)
|
||||
return OrdersServiceClient(config)
|
||||
|
||||
@@ -15,51 +15,51 @@ logger = structlog.get_logger()
|
||||
|
||||
class ProductionServiceClient(BaseServiceClient):
|
||||
"""Client for communicating with the Production Service"""
|
||||
|
||||
|
||||
def __init__(self, config: BaseServiceSettings):
|
||||
super().__init__("production", config)
|
||||
|
||||
|
||||
def get_service_base_path(self) -> str:
|
||||
return "/api/v1"
|
||||
|
||||
|
||||
# ================================================================
|
||||
# PRODUCTION PLANNING
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_production_requirements(self, tenant_id: str, date: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Get production requirements for procurement planning"""
|
||||
try:
|
||||
params = {}
|
||||
if date:
|
||||
params["date"] = date
|
||||
|
||||
result = await self.get("requirements", tenant_id=tenant_id, params=params)
|
||||
|
||||
result = await self.get("production/requirements", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved production requirements from production service",
|
||||
logger.info("Retrieved production requirements from production service",
|
||||
date=date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting production requirements",
|
||||
logger.error("Error getting production requirements",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_daily_requirements(self, tenant_id: str, date: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Get daily production requirements"""
|
||||
try:
|
||||
params = {}
|
||||
if date:
|
||||
params["date"] = date
|
||||
|
||||
result = await self.get("daily-requirements", tenant_id=tenant_id, params=params)
|
||||
|
||||
result = await self.get("production/daily-requirements", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved daily production requirements from production service",
|
||||
logger.info("Retrieved daily production requirements from production service",
|
||||
date=date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting daily production requirements",
|
||||
logger.error("Error getting daily production requirements",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_production_schedule(self, tenant_id: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Get production schedule for a date range"""
|
||||
try:
|
||||
@@ -68,134 +68,134 @@ class ProductionServiceClient(BaseServiceClient):
|
||||
params["start_date"] = start_date
|
||||
if end_date:
|
||||
params["end_date"] = end_date
|
||||
|
||||
result = await self.get("schedule", tenant_id=tenant_id, params=params)
|
||||
|
||||
result = await self.get("production/schedules", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved production schedule from production service",
|
||||
logger.info("Retrieved production schedule from production service",
|
||||
start_date=start_date, end_date=end_date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting production schedule",
|
||||
logger.error("Error getting production schedule",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# BATCH MANAGEMENT
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_active_batches(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
|
||||
"""Get currently active production batches"""
|
||||
try:
|
||||
result = await self.get("batches/active", tenant_id=tenant_id)
|
||||
result = await self.get("production/batches/active", tenant_id=tenant_id)
|
||||
batches = result.get('batches', []) if result else []
|
||||
logger.info("Retrieved active production batches from production service",
|
||||
logger.info("Retrieved active production batches from production service",
|
||||
batches_count=len(batches), tenant_id=tenant_id)
|
||||
return batches
|
||||
except Exception as e:
|
||||
logger.error("Error getting active production batches",
|
||||
logger.error("Error getting active production batches",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return []
|
||||
|
||||
|
||||
async def create_production_batch(self, tenant_id: str, batch_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""Create a new production batch"""
|
||||
try:
|
||||
result = await self.post("batches", data=batch_data, tenant_id=tenant_id)
|
||||
result = await self.post("production/batches", data=batch_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Created production batch",
|
||||
batch_id=result.get('id'),
|
||||
logger.info("Created production batch",
|
||||
batch_id=result.get('id'),
|
||||
product_id=batch_data.get('product_id'),
|
||||
tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error creating production batch",
|
||||
logger.error("Error creating production batch",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def update_batch_status(self, tenant_id: str, batch_id: str, status: str, actual_quantity: Optional[float] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Update production batch status"""
|
||||
try:
|
||||
data = {"status": status}
|
||||
if actual_quantity is not None:
|
||||
data["actual_quantity"] = actual_quantity
|
||||
|
||||
result = await self.put(f"batches/{batch_id}/status", data=data, tenant_id=tenant_id)
|
||||
|
||||
result = await self.put(f"production/batches/{batch_id}/status", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Updated production batch status",
|
||||
logger.info("Updated production batch status",
|
||||
batch_id=batch_id, status=status, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error updating production batch status",
|
||||
logger.error("Error updating production batch status",
|
||||
error=str(e), batch_id=batch_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_batch_details(self, tenant_id: str, batch_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get detailed information about a production batch"""
|
||||
try:
|
||||
result = await self.get(f"batches/{batch_id}", tenant_id=tenant_id)
|
||||
result = await self.get(f"production/batches/{batch_id}", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved production batch details",
|
||||
logger.info("Retrieved production batch details",
|
||||
batch_id=batch_id, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting production batch details",
|
||||
logger.error("Error getting production batch details",
|
||||
error=str(e), batch_id=batch_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# CAPACITY MANAGEMENT
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_capacity_status(self, tenant_id: str, date: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Get production capacity status for a specific date"""
|
||||
try:
|
||||
params = {}
|
||||
if date:
|
||||
params["date"] = date
|
||||
|
||||
result = await self.get("capacity/status", tenant_id=tenant_id, params=params)
|
||||
|
||||
result = await self.get("production/capacity/status", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved production capacity status",
|
||||
logger.info("Retrieved production capacity status",
|
||||
date=date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting production capacity status",
|
||||
logger.error("Error getting production capacity status",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def check_capacity_availability(self, tenant_id: str, requirements: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
|
||||
"""Check if production capacity is available for requirements"""
|
||||
try:
|
||||
result = await self.post("capacity/check-availability",
|
||||
{"requirements": requirements},
|
||||
result = await self.post("production/capacity/check-availability",
|
||||
{"requirements": requirements},
|
||||
tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Checked production capacity availability",
|
||||
logger.info("Checked production capacity availability",
|
||||
requirements_count=len(requirements), tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error checking production capacity availability",
|
||||
logger.error("Error checking production capacity availability",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# QUALITY CONTROL
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def record_quality_check(self, tenant_id: str, batch_id: str, quality_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""Record quality control results for a batch"""
|
||||
try:
|
||||
result = await self.post(f"batches/{batch_id}/quality-check",
|
||||
data=quality_data,
|
||||
result = await self.post(f"production/batches/{batch_id}/quality-check",
|
||||
data=quality_data,
|
||||
tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Recorded quality check for production batch",
|
||||
logger.info("Recorded quality check for production batch",
|
||||
batch_id=batch_id, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error recording quality check",
|
||||
logger.error("Error recording quality check",
|
||||
error=str(e), batch_id=batch_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_yield_metrics(self, tenant_id: str, start_date: str, end_date: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get production yield metrics for analysis"""
|
||||
try:
|
||||
@@ -203,81 +203,81 @@ class ProductionServiceClient(BaseServiceClient):
|
||||
"start_date": start_date,
|
||||
"end_date": end_date
|
||||
}
|
||||
result = await self.get("metrics/yield", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("production/analytics/yield-metrics", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved production yield metrics",
|
||||
logger.info("Retrieved production yield metrics",
|
||||
start_date=start_date, end_date=end_date, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting production yield metrics",
|
||||
logger.error("Error getting production yield metrics",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# DASHBOARD AND ANALYTICS
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_dashboard_summary(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get production dashboard summary data"""
|
||||
try:
|
||||
result = await self.get("dashboard-summary", tenant_id=tenant_id)
|
||||
result = await self.get("production/dashboard/summary", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved production dashboard summary",
|
||||
logger.info("Retrieved production dashboard summary",
|
||||
tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting production dashboard summary",
|
||||
logger.error("Error getting production dashboard summary",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
async def get_efficiency_metrics(self, tenant_id: str, period: str = "last_30_days") -> Optional[Dict[str, Any]]:
|
||||
"""Get production efficiency metrics"""
|
||||
try:
|
||||
params = {"period": period}
|
||||
result = await self.get("metrics/efficiency", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("production/analytics/efficiency", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved production efficiency metrics",
|
||||
logger.info("Retrieved production efficiency metrics",
|
||||
period=period, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error getting production efficiency metrics",
|
||||
logger.error("Error getting production efficiency metrics",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# ALERTS AND NOTIFICATIONS
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def get_production_alerts(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
|
||||
"""Get production-related alerts"""
|
||||
try:
|
||||
result = await self.get("alerts", tenant_id=tenant_id)
|
||||
result = await self.get("production/alerts", tenant_id=tenant_id)
|
||||
alerts = result.get('alerts', []) if result else []
|
||||
logger.info("Retrieved production alerts",
|
||||
logger.info("Retrieved production alerts",
|
||||
alerts_count=len(alerts), tenant_id=tenant_id)
|
||||
return alerts
|
||||
except Exception as e:
|
||||
logger.error("Error getting production alerts",
|
||||
logger.error("Error getting production alerts",
|
||||
error=str(e), tenant_id=tenant_id)
|
||||
return []
|
||||
|
||||
|
||||
async def acknowledge_alert(self, tenant_id: str, alert_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Acknowledge a production-related alert"""
|
||||
try:
|
||||
result = await self.post(f"alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
|
||||
result = await self.post(f"production/alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Acknowledged production alert",
|
||||
logger.info("Acknowledged production alert",
|
||||
alert_id=alert_id, tenant_id=tenant_id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error("Error acknowledging production alert",
|
||||
logger.error("Error acknowledging production alert",
|
||||
error=str(e), alert_id=alert_id, tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
|
||||
# ================================================================
|
||||
# UTILITY METHODS
|
||||
# ================================================================
|
||||
|
||||
|
||||
async def health_check(self) -> bool:
|
||||
"""Check if production service is healthy"""
|
||||
try:
|
||||
@@ -291,4 +291,4 @@ class ProductionServiceClient(BaseServiceClient):
|
||||
# Factory function for dependency injection
|
||||
def create_production_client(config: BaseServiceSettings) -> ProductionServiceClient:
|
||||
"""Create production service client instance"""
|
||||
return ProductionServiceClient(config)
|
||||
return ProductionServiceClient(config)
|
||||
|
||||
@@ -29,7 +29,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
async def get_recipe_by_id(self, tenant_id: str, recipe_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get recipe details by ID"""
|
||||
try:
|
||||
result = await self.get(f"recipes/{recipe_id}", tenant_id=tenant_id)
|
||||
result = await self.get(f"recipes/recipes/{recipe_id}", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved recipe details from recipes service",
|
||||
recipe_id=recipe_id, tenant_id=tenant_id)
|
||||
@@ -43,7 +43,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
"""Get recipes for multiple products"""
|
||||
try:
|
||||
params = {"product_ids": ",".join(product_ids)}
|
||||
result = await self.get("recipes/by-products", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("recipes/recipes/by-products", tenant_id=tenant_id, params=params)
|
||||
recipes = result.get('recipes', []) if result else []
|
||||
logger.info("Retrieved recipes by product IDs from recipes service",
|
||||
product_ids_count=len(product_ids),
|
||||
@@ -82,7 +82,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
if recipe_ids:
|
||||
params["recipe_ids"] = ",".join(recipe_ids)
|
||||
|
||||
result = await self.get("requirements", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("recipes/requirements", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved recipe requirements from recipes service",
|
||||
recipe_ids_count=len(recipe_ids) if recipe_ids else 0,
|
||||
@@ -100,7 +100,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
if product_ids:
|
||||
params["product_ids"] = ",".join(product_ids)
|
||||
|
||||
result = await self.get("ingredient-requirements", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("recipes/ingredient-requirements", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved ingredient requirements from recipes service",
|
||||
product_ids_count=len(product_ids) if product_ids else 0,
|
||||
@@ -118,7 +118,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
"recipe_id": recipe_id,
|
||||
"quantity": quantity
|
||||
}
|
||||
result = await self.post("calculate-ingredients", data=data, tenant_id=tenant_id)
|
||||
result = await self.post("recipes/operations/calculate-ingredients", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Calculated ingredient quantities from recipes service",
|
||||
recipe_id=recipe_id, quantity=quantity, tenant_id=tenant_id)
|
||||
@@ -132,7 +132,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
"""Calculate total ingredient requirements for multiple production batches"""
|
||||
try:
|
||||
data = {"production_requests": production_requests}
|
||||
result = await self.post("calculate-batch-ingredients", data=data, tenant_id=tenant_id)
|
||||
result = await self.post("recipes/operations/calculate-batch-ingredients", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Calculated batch ingredient requirements from recipes service",
|
||||
batches_count=len(production_requests), tenant_id=tenant_id)
|
||||
@@ -149,7 +149,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
async def get_production_instructions(self, tenant_id: str, recipe_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get detailed production instructions for a recipe"""
|
||||
try:
|
||||
result = await self.get(f"recipes/{recipe_id}/production-instructions", tenant_id=tenant_id)
|
||||
result = await self.get(f"recipes/recipes/{recipe_id}/production-instructions", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved production instructions from recipes service",
|
||||
recipe_id=recipe_id, tenant_id=tenant_id)
|
||||
@@ -162,7 +162,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
async def get_recipe_yield_info(self, tenant_id: str, recipe_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get yield information for a recipe"""
|
||||
try:
|
||||
result = await self.get(f"recipes/{recipe_id}/yield", tenant_id=tenant_id)
|
||||
result = await self.get(f"recipes/recipes/{recipe_id}/yield", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved recipe yield info from recipes service",
|
||||
recipe_id=recipe_id, tenant_id=tenant_id)
|
||||
@@ -179,7 +179,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
"recipe_id": recipe_id,
|
||||
"quantity": quantity
|
||||
}
|
||||
result = await self.post("validate-feasibility", data=data, tenant_id=tenant_id)
|
||||
result = await self.post("recipes/operations/validate-feasibility", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Validated recipe feasibility from recipes service",
|
||||
recipe_id=recipe_id, quantity=quantity, tenant_id=tenant_id)
|
||||
@@ -196,7 +196,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
async def get_recipe_cost_analysis(self, tenant_id: str, recipe_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get cost analysis for a recipe"""
|
||||
try:
|
||||
result = await self.get(f"recipes/{recipe_id}/cost-analysis", tenant_id=tenant_id)
|
||||
result = await self.get(f"recipes/recipes/{recipe_id}/cost-analysis", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved recipe cost analysis from recipes service",
|
||||
recipe_id=recipe_id, tenant_id=tenant_id)
|
||||
@@ -210,7 +210,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
"""Optimize production batch to minimize waste and cost"""
|
||||
try:
|
||||
data = {"requirements": requirements}
|
||||
result = await self.post("optimize-batch", data=data, tenant_id=tenant_id)
|
||||
result = await self.post("recipes/operations/optimize-batch", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Optimized production batch from recipes service",
|
||||
requirements_count=len(requirements), tenant_id=tenant_id)
|
||||
@@ -227,7 +227,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
async def get_dashboard_summary(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get recipes dashboard summary data"""
|
||||
try:
|
||||
result = await self.get("dashboard-summary", tenant_id=tenant_id)
|
||||
result = await self.get("recipes/dashboard/summary", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved recipes dashboard summary",
|
||||
tenant_id=tenant_id)
|
||||
@@ -241,7 +241,7 @@ class RecipesServiceClient(BaseServiceClient):
|
||||
"""Get most popular recipes based on production frequency"""
|
||||
try:
|
||||
params = {"period": period}
|
||||
result = await self.get("popular-recipes", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("recipes/analytics/popular-recipes", tenant_id=tenant_id, params=params)
|
||||
recipes = result.get('recipes', []) if result else []
|
||||
logger.info("Retrieved popular recipes from recipes service",
|
||||
period=period, recipes_count=len(recipes), tenant_id=tenant_id)
|
||||
|
||||
@@ -44,7 +44,7 @@ class SalesServiceClient(BaseServiceClient):
|
||||
if product_id:
|
||||
params["product_id"] = product_id
|
||||
|
||||
result = await self.get("sales", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("sales/sales", tenant_id=tenant_id, params=params)
|
||||
return result.get("sales", []) if result else None
|
||||
|
||||
async def get_all_sales_data(
|
||||
@@ -72,7 +72,7 @@ class SalesServiceClient(BaseServiceClient):
|
||||
# Use the inherited paginated request method
|
||||
try:
|
||||
all_records = await self.get_paginated(
|
||||
"sales",
|
||||
"sales/sales",
|
||||
tenant_id=tenant_id,
|
||||
params=params,
|
||||
page_size=page_size,
|
||||
@@ -95,7 +95,7 @@ class SalesServiceClient(BaseServiceClient):
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Upload sales data"""
|
||||
data = {"sales": sales_data}
|
||||
return await self.post("sales", data=data, tenant_id=tenant_id)
|
||||
return await self.post("sales/sales", data=data, tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# PRODUCTS
|
||||
@@ -103,12 +103,12 @@ class SalesServiceClient(BaseServiceClient):
|
||||
|
||||
async def get_products(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
|
||||
"""Get all products for a tenant"""
|
||||
result = await self.get("products", tenant_id=tenant_id)
|
||||
result = await self.get("sales/products", tenant_id=tenant_id)
|
||||
return result.get("products", []) if result else None
|
||||
|
||||
|
||||
async def get_product(self, tenant_id: str, product_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get a specific product"""
|
||||
return await self.get(f"products/{product_id}", tenant_id=tenant_id)
|
||||
return await self.get(f"sales/products/{product_id}", tenant_id=tenant_id)
|
||||
|
||||
async def create_product(
|
||||
self,
|
||||
@@ -125,8 +125,8 @@ class SalesServiceClient(BaseServiceClient):
|
||||
"price": price,
|
||||
**kwargs
|
||||
}
|
||||
return await self.post("products", data=data, tenant_id=tenant_id)
|
||||
|
||||
return await self.post("sales/products", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def update_product(
|
||||
self,
|
||||
tenant_id: str,
|
||||
@@ -134,7 +134,7 @@ class SalesServiceClient(BaseServiceClient):
|
||||
**updates
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Update a product"""
|
||||
return await self.put(f"products/{product_id}", data=updates, tenant_id=tenant_id)
|
||||
return await self.put(f"sales/products/{product_id}", data=updates, tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# DATA IMPORT
|
||||
@@ -153,4 +153,4 @@ class SalesServiceClient(BaseServiceClient):
|
||||
"format": file_format,
|
||||
"filename": filename
|
||||
}
|
||||
return await self.post("import", data=data, tenant_id=tenant_id)
|
||||
return await self.post("sales/operations/import", data=data, tenant_id=tenant_id)
|
||||
@@ -28,7 +28,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
async def get_supplier_by_id(self, tenant_id: str, supplier_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get supplier details by ID"""
|
||||
try:
|
||||
result = await self.get(f"suppliers/{supplier_id}", tenant_id=tenant_id)
|
||||
result = await self.get(f"suppliers/list/{supplier_id}", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved supplier details from suppliers service",
|
||||
supplier_id=supplier_id, tenant_id=tenant_id)
|
||||
@@ -45,7 +45,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
if is_active is not None:
|
||||
params["is_active"] = is_active
|
||||
|
||||
result = await self.get_paginated("suppliers", tenant_id=tenant_id, params=params)
|
||||
result = await self.get_paginated("suppliers/list", tenant_id=tenant_id, params=params)
|
||||
logger.info("Retrieved all suppliers from suppliers service",
|
||||
suppliers_count=len(result), tenant_id=tenant_id)
|
||||
return result
|
||||
@@ -63,7 +63,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
if category:
|
||||
params["category"] = category
|
||||
|
||||
result = await self.get("suppliers/search", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("suppliers/list/search", tenant_id=tenant_id, params=params)
|
||||
suppliers = result.get('suppliers', []) if result else []
|
||||
logger.info("Searched suppliers from suppliers service",
|
||||
search_term=search, suppliers_count=len(suppliers), tenant_id=tenant_id)
|
||||
@@ -81,7 +81,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
"""Get supplier recommendations for procurement"""
|
||||
try:
|
||||
params = {"ingredient_id": ingredient_id}
|
||||
result = await self.get("recommendations", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("suppliers/recommendations", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved supplier recommendations from suppliers service",
|
||||
ingredient_id=ingredient_id, tenant_id=tenant_id)
|
||||
@@ -98,7 +98,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
"ingredient_id": ingredient_id,
|
||||
"criteria": criteria or {}
|
||||
}
|
||||
result = await self.post("find-best-supplier", data=data, tenant_id=tenant_id)
|
||||
result = await self.post("suppliers/operations/find-best-supplier", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved best supplier from suppliers service",
|
||||
ingredient_id=ingredient_id, tenant_id=tenant_id)
|
||||
@@ -115,7 +115,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
async def create_purchase_order(self, tenant_id: str, order_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""Create a new purchase order"""
|
||||
try:
|
||||
result = await self.post("purchase-orders", data=order_data, tenant_id=tenant_id)
|
||||
result = await self.post("suppliers/purchase-orders", data=order_data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Created purchase order",
|
||||
order_id=result.get('id'),
|
||||
@@ -136,7 +136,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
if supplier_id:
|
||||
params["supplier_id"] = supplier_id
|
||||
|
||||
result = await self.get("purchase-orders", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("suppliers/purchase-orders", tenant_id=tenant_id, params=params)
|
||||
orders = result.get('orders', []) if result else []
|
||||
logger.info("Retrieved purchase orders from suppliers service",
|
||||
orders_count=len(orders), tenant_id=tenant_id)
|
||||
@@ -150,7 +150,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
"""Update purchase order status"""
|
||||
try:
|
||||
data = {"status": status}
|
||||
result = await self.put(f"purchase-orders/{order_id}/status", data=data, tenant_id=tenant_id)
|
||||
result = await self.put(f"suppliers/purchase-orders/{order_id}/status", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Updated purchase order status",
|
||||
order_id=order_id, status=status, tenant_id=tenant_id)
|
||||
@@ -173,7 +173,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
if date:
|
||||
params["date"] = date
|
||||
|
||||
result = await self.get("deliveries", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("suppliers/deliveries", tenant_id=tenant_id, params=params)
|
||||
deliveries = result.get('deliveries', []) if result else []
|
||||
logger.info("Retrieved deliveries from suppliers service",
|
||||
deliveries_count=len(deliveries), tenant_id=tenant_id)
|
||||
@@ -190,7 +190,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
if notes:
|
||||
data["notes"] = notes
|
||||
|
||||
result = await self.put(f"deliveries/{delivery_id}/status", data=data, tenant_id=tenant_id)
|
||||
result = await self.put(f"suppliers/deliveries/{delivery_id}/status", data=data, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Updated delivery status",
|
||||
delivery_id=delivery_id, status=status, tenant_id=tenant_id)
|
||||
@@ -203,7 +203,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
async def get_supplier_order_summaries(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get supplier order summaries for central bakery dashboard"""
|
||||
try:
|
||||
result = await self.get("supplier-order-summaries", tenant_id=tenant_id)
|
||||
result = await self.get("suppliers/dashboard/order-summaries", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved supplier order summaries from suppliers service",
|
||||
tenant_id=tenant_id)
|
||||
@@ -221,7 +221,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
"""Get supplier performance metrics"""
|
||||
try:
|
||||
params = {"period": period}
|
||||
result = await self.get(f"suppliers/{supplier_id}/performance", tenant_id=tenant_id, params=params)
|
||||
result = await self.get(f"suppliers/analytics/performance/{supplier_id}", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved supplier performance from suppliers service",
|
||||
supplier_id=supplier_id, period=period, tenant_id=tenant_id)
|
||||
@@ -234,7 +234,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
async def get_performance_alerts(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
|
||||
"""Get supplier performance alerts"""
|
||||
try:
|
||||
result = await self.get("performance-alerts", tenant_id=tenant_id)
|
||||
result = await self.get("suppliers/alerts/performance", tenant_id=tenant_id)
|
||||
alerts = result.get('alerts', []) if result else []
|
||||
logger.info("Retrieved supplier performance alerts",
|
||||
alerts_count=len(alerts), tenant_id=tenant_id)
|
||||
@@ -264,7 +264,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
async def get_dashboard_summary(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get suppliers dashboard summary data"""
|
||||
try:
|
||||
result = await self.get("dashboard-summary", tenant_id=tenant_id)
|
||||
result = await self.get("suppliers/dashboard/summary", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved suppliers dashboard summary",
|
||||
tenant_id=tenant_id)
|
||||
@@ -281,7 +281,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
"start_date": start_date,
|
||||
"end_date": end_date
|
||||
}
|
||||
result = await self.get("cost-analysis", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("suppliers/analytics/cost-analysis", tenant_id=tenant_id, params=params)
|
||||
if result:
|
||||
logger.info("Retrieved supplier cost analysis",
|
||||
start_date=start_date, end_date=end_date, tenant_id=tenant_id)
|
||||
@@ -294,7 +294,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
async def get_supplier_reliability_metrics(self, tenant_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get supplier reliability and quality metrics"""
|
||||
try:
|
||||
result = await self.get("reliability-metrics", tenant_id=tenant_id)
|
||||
result = await self.get("suppliers/analytics/reliability-metrics", tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Retrieved supplier reliability metrics",
|
||||
tenant_id=tenant_id)
|
||||
@@ -311,7 +311,7 @@ class SuppliersServiceClient(BaseServiceClient):
|
||||
async def acknowledge_alert(self, tenant_id: str, alert_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Acknowledge a supplier-related alert"""
|
||||
try:
|
||||
result = await self.post(f"alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
|
||||
result = await self.post(f"suppliers/alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
|
||||
if result:
|
||||
logger.info("Acknowledged supplier alert",
|
||||
alert_id=alert_id, tenant_id=tenant_id)
|
||||
|
||||
@@ -37,12 +37,12 @@ class TrainingServiceClient(BaseServiceClient):
|
||||
"min_data_points": min_data_points,
|
||||
**kwargs
|
||||
}
|
||||
return await self.post("jobs", data=data, tenant_id=tenant_id)
|
||||
return await self.post("training/jobs", data=data, tenant_id=tenant_id)
|
||||
|
||||
async def get_training_job(self, tenant_id: str, job_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get training job details"""
|
||||
return await self.get(f"jobs/{job_id}", tenant_id=tenant_id)
|
||||
|
||||
return await self.get(f"training/jobs/{job_id}/status", tenant_id=tenant_id)
|
||||
|
||||
async def list_training_jobs(
|
||||
self,
|
||||
tenant_id: str,
|
||||
@@ -53,13 +53,13 @@ class TrainingServiceClient(BaseServiceClient):
|
||||
params = {"limit": limit}
|
||||
if status:
|
||||
params["status"] = status
|
||||
|
||||
result = await self.get("jobs", tenant_id=tenant_id, params=params)
|
||||
|
||||
result = await self.get("training/jobs", tenant_id=tenant_id, params=params)
|
||||
return result.get("jobs", []) if result else None
|
||||
|
||||
|
||||
async def cancel_training_job(self, tenant_id: str, job_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Cancel a training job"""
|
||||
return await self.delete(f"jobs/{job_id}", tenant_id=tenant_id)
|
||||
return await self.delete(f"training/jobs/{job_id}", tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# MODELS
|
||||
@@ -67,7 +67,7 @@ class TrainingServiceClient(BaseServiceClient):
|
||||
|
||||
async def get_model(self, tenant_id: str, model_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get model details"""
|
||||
return await self.get(f"models/{model_id}", tenant_id=tenant_id)
|
||||
return await self.get(f"training/models/{model_id}", tenant_id=tenant_id)
|
||||
|
||||
async def list_models(
|
||||
self,
|
||||
@@ -83,7 +83,7 @@ class TrainingServiceClient(BaseServiceClient):
|
||||
if model_type:
|
||||
params["model_type"] = model_type
|
||||
|
||||
result = await self.get("models", tenant_id=tenant_id, params=params)
|
||||
result = await self.get("training/models", tenant_id=tenant_id, params=params)
|
||||
return result.get("models", []) if result else None
|
||||
|
||||
async def get_active_model_for_product(
|
||||
@@ -95,16 +95,16 @@ class TrainingServiceClient(BaseServiceClient):
|
||||
Get the active model for a specific product by inventory product ID
|
||||
This is the preferred method since models are stored per product.
|
||||
"""
|
||||
result = await self.get(f"models/{inventory_product_id}/active", tenant_id=tenant_id)
|
||||
result = await self.get(f"training/models/{inventory_product_id}/active", tenant_id=tenant_id)
|
||||
return result
|
||||
|
||||
async def deploy_model(self, tenant_id: str, model_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Deploy a trained model"""
|
||||
return await self.post(f"models/{model_id}/deploy", data={}, tenant_id=tenant_id)
|
||||
return await self.post(f"training/models/{model_id}/deploy", data={}, tenant_id=tenant_id)
|
||||
|
||||
async def delete_model(self, tenant_id: str, model_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Delete a model"""
|
||||
return await self.delete(f"models/{model_id}", tenant_id=tenant_id)
|
||||
return await self.delete(f"training/models/{model_id}", tenant_id=tenant_id)
|
||||
|
||||
# ================================================================
|
||||
# MODEL METRICS & PERFORMANCE
|
||||
@@ -112,7 +112,7 @@ class TrainingServiceClient(BaseServiceClient):
|
||||
|
||||
async def get_model_metrics(self, tenant_id: str, model_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get model performance metrics"""
|
||||
return await self.get(f"models/{model_id}/metrics", tenant_id=tenant_id)
|
||||
return await self.get(f"training/models/{model_id}/metrics", tenant_id=tenant_id)
|
||||
|
||||
async def get_model_predictions(
|
||||
self,
|
||||
@@ -128,5 +128,5 @@ class TrainingServiceClient(BaseServiceClient):
|
||||
if end_date:
|
||||
params["end_date"] = end_date
|
||||
|
||||
result = await self.get(f"models/{model_id}/predictions", tenant_id=tenant_id, params=params)
|
||||
result = await self.get(f"training/models/{model_id}/predictions", tenant_id=tenant_id, params=params)
|
||||
return result.get("predictions", []) if result else None
|
||||
Reference in New Issue
Block a user