Improve the frontend 5

This commit is contained in:
Urtzi Alfaro
2025-11-02 20:24:44 +01:00
parent 0220da1725
commit 5adb0e39c0
90 changed files with 10658 additions and 2548 deletions

View File

@@ -228,4 +228,142 @@ class ExternalServiceClient(BaseServiceClient):
return result
else:
logger.warning("No current traffic data available")
return None
# ================================================================
# CALENDAR DATA (School Calendars and Hyperlocal Information)
# ================================================================
async def get_tenant_location_context(
self,
tenant_id: str
) -> Optional[Dict[str, Any]]:
"""
Get tenant location context including school calendar assignment
"""
logger.info("Fetching tenant location context", tenant_id=tenant_id)
result = await self._make_request(
"GET",
f"external/tenants/{tenant_id}/location-context",
tenant_id=tenant_id,
timeout=5.0
)
if result:
logger.info("Successfully fetched tenant location context", tenant_id=tenant_id)
return result
else:
logger.info("No location context found for tenant", tenant_id=tenant_id)
return None
async def get_school_calendar(
self,
calendar_id: str,
tenant_id: str
) -> Optional[Dict[str, Any]]:
"""
Get school calendar details by ID
"""
logger.info("Fetching school calendar", calendar_id=calendar_id, tenant_id=tenant_id)
result = await self._make_request(
"GET",
f"external/operations/school-calendars/{calendar_id}",
tenant_id=tenant_id,
timeout=5.0
)
if result:
logger.info("Successfully fetched school calendar", calendar_id=calendar_id)
return result
else:
logger.warning("School calendar not found", calendar_id=calendar_id)
return None
async def check_is_school_holiday(
self,
calendar_id: str,
check_date: str,
tenant_id: str
) -> Optional[Dict[str, Any]]:
"""
Check if a specific date is a school holiday
Args:
calendar_id: School calendar UUID
check_date: Date to check in ISO format (YYYY-MM-DD)
tenant_id: Tenant ID for auth
Returns:
Dict with is_holiday, holiday_name, etc.
"""
params = {"check_date": check_date}
logger.debug(
"Checking school holiday status",
calendar_id=calendar_id,
date=check_date,
tenant_id=tenant_id
)
result = await self._make_request(
"GET",
f"external/operations/school-calendars/{calendar_id}/is-holiday",
tenant_id=tenant_id,
params=params,
timeout=5.0
)
return result
async def get_city_school_calendars(
self,
city_id: str,
tenant_id: str,
school_type: Optional[str] = None,
academic_year: Optional[str] = None
) -> Optional[Dict[str, Any]]:
"""
Get all school calendars for a city with optional filters
Args:
city_id: City ID (e.g., "madrid")
tenant_id: Tenant ID for auth
school_type: Optional filter by school type
academic_year: Optional filter by academic year
Returns:
Dict with calendars list and total count
"""
params = {}
if school_type:
params["school_type"] = school_type
if academic_year:
params["academic_year"] = academic_year
logger.info(
"Fetching school calendars for city",
city_id=city_id,
tenant_id=tenant_id,
filters=params
)
result = await self._make_request(
"GET",
f"external/operations/cities/{city_id}/school-calendars",
tenant_id=tenant_id,
params=params if params else None,
timeout=5.0
)
if result:
logger.info(
"Successfully fetched school calendars",
city_id=city_id,
total=result.get("total", 0)
)
return result
else:
logger.warning("No school calendars found for city", city_id=city_id)
return None

View File

@@ -0,0 +1,83 @@
"""
Shared Pydantic schemas for audit log API responses.
Used across all services for consistent audit log retrieval.
"""
from datetime import datetime
from typing import Any, Dict, Optional
from uuid import UUID
from pydantic import BaseModel, Field
class AuditLogResponse(BaseModel):
"""Response schema for audit log entries"""
id: UUID
tenant_id: UUID
user_id: Optional[UUID] = None
service_name: str
action: str
resource_type: str
resource_id: Optional[str] = None
severity: str # low, medium, high, critical
description: str
changes: Optional[Dict[str, Any]] = None
audit_metadata: Optional[Dict[str, Any]] = None
endpoint: Optional[str] = None
method: Optional[str] = None # HTTP method
ip_address: Optional[str] = None
user_agent: Optional[str] = None
created_at: datetime
class Config:
from_attributes = True
json_encoders = {
datetime: lambda v: v.isoformat(),
UUID: lambda v: str(v)
}
class AuditLogFilters(BaseModel):
"""Query parameters for filtering audit logs"""
start_date: Optional[datetime] = Field(None, description="Filter logs from this date")
end_date: Optional[datetime] = Field(None, description="Filter logs until this date")
user_id: Optional[UUID] = Field(None, description="Filter by user ID")
action: Optional[str] = Field(None, description="Filter by action type")
resource_type: Optional[str] = Field(None, description="Filter by resource type")
severity: Optional[str] = Field(None, description="Filter by severity level")
search: Optional[str] = Field(None, description="Search in description field")
limit: int = Field(100, ge=1, le=1000, description="Number of records to return")
offset: int = Field(0, ge=0, description="Number of records to skip")
class AuditLogListResponse(BaseModel):
"""Paginated response for audit log listings"""
items: list[AuditLogResponse]
total: int
limit: int
offset: int
has_more: bool
class Config:
json_encoders = {
datetime: lambda v: v.isoformat(),
UUID: lambda v: str(v)
}
class AuditLogStatsResponse(BaseModel):
"""Statistics about audit logs"""
total_events: int
events_by_action: Dict[str, int]
events_by_severity: Dict[str, int]
events_by_resource_type: Dict[str, int]
date_range: Dict[str, Optional[datetime]]
class Config:
json_encoders = {
datetime: lambda v: v.isoformat()
}