imporve features

This commit is contained in:
Urtzi Alfaro
2025-11-14 07:23:56 +01:00
parent 9bc048d360
commit a8d8828935
32 changed files with 5436 additions and 271 deletions

View File

@@ -21,10 +21,10 @@ from app.core.redis_client import get_redis_client
logger = structlog.get_logger()
router = APIRouter(prefix="/poi-context", tags=["POI Context"])
router = APIRouter(prefix="/tenants", tags=["POI Context"])
@router.post("/{tenant_id}/detect")
@router.post("/{tenant_id}/poi-context/detect")
async def detect_pois_for_tenant(
tenant_id: str,
latitude: float = Query(..., description="Bakery latitude"),
@@ -209,13 +209,79 @@ async def detect_pois_for_tenant(
relevant_categories=len(feature_selection.get("relevant_categories", []))
)
# Phase 3: Auto-trigger calendar suggestion after POI detection
# This helps admins by providing intelligent calendar recommendations
calendar_suggestion = None
try:
from app.utils.calendar_suggester import CalendarSuggester
from app.repositories.calendar_repository import CalendarRepository
# Get tenant's location context
calendar_repo = CalendarRepository(db)
location_context = await calendar_repo.get_tenant_location_context(tenant_uuid)
if location_context and location_context.school_calendar_id is None:
# Only suggest if no calendar assigned yet
city_id = location_context.city_id
# Get available calendars for city
calendars_result = await calendar_repo.get_calendars_by_city(city_id, enabled_only=True)
calendars = calendars_result.get("calendars", []) if calendars_result else []
if calendars:
# Generate suggestion using POI data
suggester = CalendarSuggester()
calendar_suggestion = suggester.suggest_calendar_for_tenant(
city_id=city_id,
available_calendars=calendars,
poi_context=poi_context.to_dict(),
tenant_data=None
)
logger.info(
"Calendar suggestion auto-generated after POI detection",
tenant_id=tenant_id,
suggested_calendar=calendar_suggestion.get("calendar_name"),
confidence=calendar_suggestion.get("confidence_percentage"),
should_auto_assign=calendar_suggestion.get("should_auto_assign")
)
# TODO: Send notification to admin about available suggestion
# This will be implemented when notification service is integrated
else:
logger.info(
"No calendars available for city, skipping suggestion",
tenant_id=tenant_id,
city_id=city_id
)
elif location_context and location_context.school_calendar_id:
logger.info(
"Calendar already assigned, skipping suggestion",
tenant_id=tenant_id,
calendar_id=str(location_context.school_calendar_id)
)
else:
logger.warning(
"No location context found, skipping calendar suggestion",
tenant_id=tenant_id
)
except Exception as e:
# Non-blocking: POI detection should succeed even if suggestion fails
logger.warning(
"Failed to auto-generate calendar suggestion (non-blocking)",
tenant_id=tenant_id,
error=str(e)
)
return {
"status": "success",
"source": "detection",
"poi_context": poi_context.to_dict(),
"feature_selection": feature_selection,
"competitor_analysis": competitor_analysis,
"competitive_insights": competitive_insights
"competitive_insights": competitive_insights,
"calendar_suggestion": calendar_suggestion # Include suggestion in response
}
except Exception as e:
@@ -231,7 +297,7 @@ async def detect_pois_for_tenant(
)
@router.get("/{tenant_id}")
@router.get("/{tenant_id}/poi-context")
async def get_poi_context(
tenant_id: str,
db: AsyncSession = Depends(get_db)
@@ -265,7 +331,7 @@ async def get_poi_context(
}
@router.post("/{tenant_id}/refresh")
@router.post("/{tenant_id}/poi-context/refresh")
async def refresh_poi_context(
tenant_id: str,
db: AsyncSession = Depends(get_db)
@@ -299,7 +365,7 @@ async def refresh_poi_context(
)
@router.delete("/{tenant_id}")
@router.delete("/{tenant_id}/poi-context")
async def delete_poi_context(
tenant_id: str,
db: AsyncSession = Depends(get_db)
@@ -327,7 +393,7 @@ async def delete_poi_context(
}
@router.get("/{tenant_id}/feature-importance")
@router.get("/{tenant_id}/poi-context/feature-importance")
async def get_feature_importance(
tenant_id: str,
db: AsyncSession = Depends(get_db)
@@ -364,7 +430,7 @@ async def get_feature_importance(
}
@router.get("/{tenant_id}/competitor-analysis")
@router.get("/{tenant_id}/poi-context/competitor-analysis")
async def get_competitor_analysis(
tenant_id: str,
db: AsyncSession = Depends(get_db)