New enterprise feature2

This commit is contained in:
Urtzi Alfaro
2025-11-30 16:29:38 +01:00
parent 972db02f6d
commit 0da0470786
18 changed files with 698 additions and 76 deletions

View File

@@ -19,6 +19,7 @@ from .tenant_client import TenantServiceClient
from .ai_insights_client import AIInsightsClient
from .alerts_client import AlertsServiceClient
from .procurement_client import ProcurementServiceClient
from .distribution_client import DistributionServiceClient
# Import config
from shared.config.base import BaseServiceSettings
@@ -146,6 +147,16 @@ def get_procurement_client(config: BaseServiceSettings = None, service_name: str
_client_cache[cache_key] = ProcurementServiceClient(config, service_name)
return _client_cache[cache_key]
def get_distribution_client(config: BaseServiceSettings = None, service_name: str = "unknown") -> DistributionServiceClient:
"""Get or create a distribution service client"""
if config is None:
from app.core.config import settings as config
cache_key = f"distribution_{service_name}"
if cache_key not in _client_cache:
_client_cache[cache_key] = DistributionServiceClient(config, service_name)
return _client_cache[cache_key]
class ServiceClients:
"""Convenient wrapper for all service clients"""
@@ -257,6 +268,7 @@ __all__ = [
'SuppliersServiceClient',
'AlertsServiceClient',
'TenantServiceClient',
'DistributionServiceClient',
'ServiceClients',
'get_training_client',
'get_sales_client',
@@ -270,6 +282,7 @@ __all__ = [
'get_alerts_client',
'get_tenant_client',
'get_procurement_client',
'get_distribution_client',
'get_service_clients',
'create_forecast_client'
]

View File

@@ -386,6 +386,46 @@ class ForecastServiceClient(BaseServiceClient):
forecast_days=forecast_days
)
async def get_aggregated_forecast(
self,
parent_tenant_id: str,
start_date: date,
end_date: date,
product_id: Optional[str] = None
) -> Dict[str, Any]:
"""
Get aggregated forecast for enterprise tenant and all children.
This method calls the enterprise forecasting aggregation endpoint which
combines demand forecasts across the parent tenant and all child tenants
in the network. Used for centralized production planning.
Args:
parent_tenant_id: The parent tenant (central bakery) UUID
start_date: Start date for forecast range
end_date: End date for forecast range
product_id: Optional product ID to filter forecasts
Returns:
Aggregated forecast data including:
- total_demand: Sum of all child demands
- child_contributions: Per-child demand breakdown
- forecast_date_range: Date range for the forecast
- cached: Whether data was served from Redis cache
"""
params = {
"start_date": start_date.isoformat(),
"end_date": end_date.isoformat()
}
if product_id:
params["product_id"] = product_id
return await self.get(
"forecasting/enterprise/aggregated",
tenant_id=parent_tenant_id,
params=params
)
async def create_forecast(
self,
tenant_id: str,

View File

@@ -6,6 +6,7 @@ Handles all API calls to the sales service
import httpx
import structlog
from datetime import date
from typing import Dict, Any, Optional, List, Union
from .base_service_client import BaseServiceClient
from shared.config.base import BaseServiceSettings
@@ -183,6 +184,37 @@ class SalesServiceClient(BaseServiceClient):
tenant_id=tenant_id)
return None
async def get_sales_summary(
self,
tenant_id: str,
start_date: date,
end_date: date
) -> Dict[str, Any]:
"""
Get sales summary/analytics for a tenant.
This method calls the sales analytics summary endpoint which provides
aggregated sales metrics over a date range.
Args:
tenant_id: The tenant UUID
start_date: Start date for summary range
end_date: End date for summary range
Returns:
Sales summary data including metrics like total sales, revenue, etc.
"""
params = {
"start_date": start_date.isoformat(),
"end_date": end_date.isoformat()
}
return await self.get(
"sales/analytics/summary",
tenant_id=tenant_id,
params=params
)
# ================================================================
# DATA IMPORT
# ================================================================

View File

@@ -310,7 +310,7 @@ class TenantServiceClient(BaseServiceClient):
List of child tenant dictionaries
"""
try:
result = await self.get(f"tenants/{parent_tenant_id}/children", tenant_id=parent_tenant_id)
result = await self.get("children", tenant_id=parent_tenant_id)
if result:
logger.info("Retrieved child tenants",
parent_tenant_id=parent_tenant_id,