imporve features
This commit is contained in:
@@ -245,7 +245,7 @@ class ExternalServiceClient(BaseServiceClient):
|
||||
|
||||
result = await self._make_request(
|
||||
"GET",
|
||||
f"external/tenants/{tenant_id}/location-context",
|
||||
"external/location-context",
|
||||
tenant_id=tenant_id,
|
||||
timeout=5.0
|
||||
)
|
||||
@@ -257,6 +257,128 @@ class ExternalServiceClient(BaseServiceClient):
|
||||
logger.info("No location context found for tenant", tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
async def create_tenant_location_context(
|
||||
self,
|
||||
tenant_id: str,
|
||||
city_id: str,
|
||||
school_calendar_id: Optional[str] = None,
|
||||
neighborhood: Optional[str] = None,
|
||||
local_events: Optional[List[Dict[str, Any]]] = None,
|
||||
notes: Optional[str] = None
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Create or update location context for a tenant.
|
||||
|
||||
This establishes the city association for a tenant and optionally assigns
|
||||
a school calendar. Typically called during tenant registration to set up
|
||||
location-based context for ML features.
|
||||
|
||||
Args:
|
||||
tenant_id: Tenant UUID
|
||||
city_id: Normalized city ID (e.g., "madrid", "barcelona")
|
||||
school_calendar_id: Optional school calendar UUID to assign
|
||||
neighborhood: Optional neighborhood name
|
||||
local_events: Optional list of local events with impact data
|
||||
notes: Optional notes about the location context
|
||||
|
||||
Returns:
|
||||
Dict with created location context including nested calendar details,
|
||||
or None if creation failed
|
||||
"""
|
||||
payload = {"city_id": city_id}
|
||||
|
||||
if school_calendar_id:
|
||||
payload["school_calendar_id"] = school_calendar_id
|
||||
if neighborhood:
|
||||
payload["neighborhood"] = neighborhood
|
||||
if local_events:
|
||||
payload["local_events"] = local_events
|
||||
if notes:
|
||||
payload["notes"] = notes
|
||||
|
||||
logger.info(
|
||||
"Creating tenant location context",
|
||||
tenant_id=tenant_id,
|
||||
city_id=city_id,
|
||||
has_calendar=bool(school_calendar_id)
|
||||
)
|
||||
|
||||
result = await self._make_request(
|
||||
"POST",
|
||||
"external/location-context",
|
||||
tenant_id=tenant_id,
|
||||
json=payload,
|
||||
timeout=10.0
|
||||
)
|
||||
|
||||
if result:
|
||||
logger.info(
|
||||
"Successfully created tenant location context",
|
||||
tenant_id=tenant_id,
|
||||
city_id=city_id
|
||||
)
|
||||
return result
|
||||
else:
|
||||
logger.warning(
|
||||
"Failed to create tenant location context",
|
||||
tenant_id=tenant_id,
|
||||
city_id=city_id
|
||||
)
|
||||
return None
|
||||
|
||||
async def suggest_calendar_for_tenant(
|
||||
self,
|
||||
tenant_id: str
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Get smart calendar suggestion for a tenant based on POI data and location.
|
||||
|
||||
Analyzes tenant's location context, nearby schools from POI detection,
|
||||
and available calendars to provide an intelligent suggestion with
|
||||
confidence score and reasoning.
|
||||
|
||||
Args:
|
||||
tenant_id: Tenant UUID
|
||||
|
||||
Returns:
|
||||
Dict with:
|
||||
- suggested_calendar_id: Suggested calendar UUID
|
||||
- calendar_name: Name of suggested calendar
|
||||
- confidence: Float 0.0-1.0
|
||||
- confidence_percentage: Percentage format
|
||||
- reasoning: List of reasoning steps
|
||||
- fallback_calendars: Alternative suggestions
|
||||
- should_auto_assign: Boolean recommendation
|
||||
- admin_message: Formatted message for display
|
||||
- school_analysis: Analysis of nearby schools
|
||||
Or None if request failed
|
||||
"""
|
||||
logger.info("Requesting calendar suggestion", tenant_id=tenant_id)
|
||||
|
||||
result = await self._make_request(
|
||||
"POST",
|
||||
"external/location-context/suggest-calendar",
|
||||
tenant_id=tenant_id,
|
||||
timeout=10.0
|
||||
)
|
||||
|
||||
if result:
|
||||
confidence = result.get("confidence_percentage", 0)
|
||||
suggested = result.get("calendar_name", "None")
|
||||
logger.info(
|
||||
"Calendar suggestion received",
|
||||
tenant_id=tenant_id,
|
||||
suggested_calendar=suggested,
|
||||
confidence=confidence
|
||||
)
|
||||
return result
|
||||
else:
|
||||
logger.warning(
|
||||
"Failed to get calendar suggestion",
|
||||
tenant_id=tenant_id
|
||||
)
|
||||
return None
|
||||
|
||||
async def get_school_calendar(
|
||||
self,
|
||||
calendar_id: str,
|
||||
@@ -379,6 +501,11 @@ class ExternalServiceClient(BaseServiceClient):
|
||||
"""
|
||||
Get POI context for a tenant including ML features for forecasting.
|
||||
|
||||
With the new tenant-based architecture:
|
||||
- Gateway receives at: /api/v1/tenants/{tenant_id}/external/poi-context
|
||||
- Gateway proxies to external service at: /api/v1/tenants/{tenant_id}/poi-context
|
||||
- This client calls: /tenants/{tenant_id}/poi-context
|
||||
|
||||
This retrieves stored POI detection results and calculated ML features
|
||||
that should be included in demand forecasting predictions.
|
||||
|
||||
@@ -394,14 +521,11 @@ class ExternalServiceClient(BaseServiceClient):
|
||||
"""
|
||||
logger.info("Fetching POI context for forecasting", tenant_id=tenant_id)
|
||||
|
||||
# Note: POI context endpoint structure is /external/poi-context/{tenant_id}
|
||||
# We pass tenant_id to _make_request which will build: /api/v1/tenants/{tenant_id}/external/poi-context/{tenant_id}
|
||||
# But the actual endpoint in external service is just /poi-context/{tenant_id}
|
||||
# So we need to use the operations prefix correctly
|
||||
# Updated endpoint path to follow tenant-based pattern: /tenants/{tenant_id}/poi-context
|
||||
result = await self._make_request(
|
||||
"GET",
|
||||
f"external/operations/poi-context/{tenant_id}",
|
||||
tenant_id=None, # Don't auto-prefix, we're including tenant_id in the path
|
||||
f"tenants/{tenant_id}/poi-context", # Updated path: /tenants/{tenant_id}/poi-context
|
||||
tenant_id=tenant_id, # Pass tenant_id to include in headers for authentication
|
||||
timeout=5.0
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user