Add more services

This commit is contained in:
Urtzi Alfaro
2025-08-21 20:28:14 +02:00
parent d6fd53e461
commit c6dd6fd1de
85 changed files with 17842 additions and 1828 deletions

View File

@@ -0,0 +1,250 @@
# ================================================================
# services/inventory/app/schemas/dashboard.py
# ================================================================
"""
Dashboard and analytics schemas for Inventory Service
"""
from datetime import datetime
from decimal import Decimal
from typing import List, Optional, Dict, Any
from uuid import UUID
from pydantic import BaseModel, Field
# ===== Dashboard Summary Schemas =====
class InventoryDashboardSummary(BaseModel):
"""Comprehensive dashboard summary for inventory management"""
# Current inventory metrics
total_ingredients: int
active_ingredients: int
total_stock_value: Decimal
total_stock_items: int
# Stock status breakdown
in_stock_items: int
low_stock_items: int
out_of_stock_items: int
expired_items: int
expiring_soon_items: int
# Food safety metrics
food_safety_alerts_active: int
temperature_violations_today: int
compliance_issues: int
certifications_expiring_soon: int
# Recent activity
recent_stock_movements: int
recent_purchases: int
recent_waste: int
recent_adjustments: int
# Business model context
business_model: Optional[str] = None # individual_bakery, central_bakery
business_model_confidence: Optional[Decimal] = None
# Category breakdown
stock_by_category: Dict[str, Any]
alerts_by_severity: Dict[str, int]
movements_by_type: Dict[str, int]
# Performance indicators
inventory_turnover_ratio: Optional[Decimal] = None
waste_percentage: Optional[Decimal] = None
compliance_score: Optional[Decimal] = None
cost_per_unit_avg: Optional[Decimal] = None
# Trending data
stock_value_trend: List[Dict[str, Any]] = []
alert_trend: List[Dict[str, Any]] = []
class Config:
from_attributes = True
class StockStatusSummary(BaseModel):
"""Summary of stock status by category"""
category: str
total_ingredients: int
in_stock: int
low_stock: int
out_of_stock: int
total_value: Decimal
percentage_of_total: Decimal
class AlertSummary(BaseModel):
"""Summary of alerts by type and severity"""
alert_type: str
severity: str
count: int
oldest_alert_age_hours: Optional[int] = None
average_resolution_time_hours: Optional[int] = None
class RecentActivity(BaseModel):
"""Recent activity item for dashboard"""
activity_type: str # stock_added, stock_consumed, alert_created, etc.
description: str
timestamp: datetime
user_name: Optional[str] = None
impact_level: str = Field(default="low") # low, medium, high
entity_id: Optional[UUID] = None
entity_type: Optional[str] = None
# ===== Food Safety Dashboard Schemas =====
class FoodSafetyDashboard(BaseModel):
"""Food safety specific dashboard metrics"""
# Compliance overview
total_compliance_items: int
compliant_items: int
non_compliant_items: int
pending_review_items: int
compliance_percentage: Decimal
# Temperature monitoring
temperature_sensors_online: int
temperature_sensors_total: int
temperature_violations_24h: int
current_temperature_status: str # all_good, warnings, violations
# Expiration tracking
items_expiring_today: int
items_expiring_this_week: int
expired_items_requiring_action: int
# Audit and certification status
upcoming_audits: int
overdue_audits: int
certifications_valid: int
certifications_expiring_soon: int
# Risk assessment
high_risk_items: int
critical_alerts: int
regulatory_notifications_pending: int
# Recent safety events
recent_safety_incidents: List[RecentActivity] = []
class Config:
from_attributes = True
class TemperatureMonitoringStatus(BaseModel):
"""Current temperature monitoring status"""
location: str
equipment_id: Optional[str] = None
current_temperature: Decimal
target_min: Decimal
target_max: Decimal
status: str # normal, warning, critical
last_reading: datetime
hours_since_last_reading: Decimal
alert_active: bool = False
class ComplianceStatusSummary(BaseModel):
"""Compliance status summary by standard"""
standard: str
standard_name: str
total_items: int
compliant: int
non_compliant: int
pending_review: int
expired: int
compliance_rate: Decimal
next_audit_date: Optional[datetime] = None
# ===== Analytics and Reporting Schemas =====
class InventoryAnalytics(BaseModel):
"""Advanced analytics for inventory management"""
# Turnover analysis
inventory_turnover_rate: Decimal
fast_moving_items: List[Dict[str, Any]]
slow_moving_items: List[Dict[str, Any]]
dead_stock_items: List[Dict[str, Any]]
# Cost analysis
total_inventory_cost: Decimal
cost_by_category: Dict[str, Decimal]
average_unit_cost_trend: List[Dict[str, Any]]
waste_cost_analysis: Dict[str, Any]
# Efficiency metrics
stockout_frequency: Dict[str, int]
overstock_frequency: Dict[str, int]
reorder_accuracy: Decimal
forecast_accuracy: Decimal
# Quality and safety metrics
quality_incidents_rate: Decimal
food_safety_score: Decimal
compliance_score_by_standard: Dict[str, Decimal]
temperature_compliance_rate: Decimal
# Supplier performance
supplier_performance: List[Dict[str, Any]]
delivery_reliability: Decimal
quality_consistency: Decimal
class Config:
from_attributes = True
class BusinessModelInsights(BaseModel):
"""Business model insights based on inventory patterns"""
detected_model: str # individual_bakery, central_bakery, mixed
confidence_score: Decimal
# Model characteristics
total_ingredient_types: int
average_stock_per_ingredient: Decimal
finished_product_ratio: Decimal
supplier_diversity: int
# Operational patterns
order_frequency_pattern: str
seasonal_variation: bool
bulk_purchasing_indicator: Decimal
production_scale_indicator: str
# Recommendations
model_specific_recommendations: List[str]
optimization_opportunities: List[str]
class Config:
from_attributes = True
# ===== Request/Filter Schemas =====
class DashboardFilter(BaseModel):
"""Filtering options for dashboard data"""
date_from: Optional[datetime] = None
date_to: Optional[datetime] = None
categories: Optional[List[str]] = None
severity_levels: Optional[List[str]] = None
alert_types: Optional[List[str]] = None
business_model: Optional[str] = None
include_inactive: bool = False
class AlertsFilter(BaseModel):
"""Filtering options for alerts dashboard"""
alert_types: Optional[List[str]] = None
severities: Optional[List[str]] = None
statuses: Optional[List[str]] = None
date_from: Optional[datetime] = None
date_to: Optional[datetime] = None
assigned_to: Optional[UUID] = None
unresolved_only: bool = True

View File

@@ -0,0 +1,283 @@
# ================================================================
# services/inventory/app/schemas/food_safety.py
# ================================================================
"""
Food safety schemas for Inventory Service
"""
from datetime import datetime
from decimal import Decimal
from typing import List, Optional, Dict, Any
from uuid import UUID
from pydantic import BaseModel, Field, validator
# ===== Food Safety Compliance Schemas =====
class FoodSafetyComplianceBase(BaseModel):
ingredient_id: UUID
standard: str
compliance_status: str = Field(default="pending_review")
certification_number: Optional[str] = None
certifying_body: Optional[str] = None
certification_date: Optional[datetime] = None
expiration_date: Optional[datetime] = None
requirements: Optional[Dict[str, Any]] = None
compliance_notes: Optional[str] = None
documentation_url: Optional[str] = None
last_audit_date: Optional[datetime] = None
next_audit_date: Optional[datetime] = None
auditor_name: Optional[str] = None
audit_score: Optional[float] = Field(None, ge=0, le=100)
risk_level: str = Field(default="medium")
risk_factors: Optional[List[str]] = None
mitigation_measures: Optional[List[str]] = None
requires_monitoring: bool = Field(default=True)
monitoring_frequency_days: Optional[int] = Field(None, gt=0)
class FoodSafetyComplianceCreate(FoodSafetyComplianceBase):
tenant_id: UUID
class FoodSafetyComplianceUpdate(BaseModel):
compliance_status: Optional[str] = None
certification_number: Optional[str] = None
certifying_body: Optional[str] = None
certification_date: Optional[datetime] = None
expiration_date: Optional[datetime] = None
requirements: Optional[Dict[str, Any]] = None
compliance_notes: Optional[str] = None
documentation_url: Optional[str] = None
last_audit_date: Optional[datetime] = None
next_audit_date: Optional[datetime] = None
auditor_name: Optional[str] = None
audit_score: Optional[float] = Field(None, ge=0, le=100)
risk_level: Optional[str] = None
risk_factors: Optional[List[str]] = None
mitigation_measures: Optional[List[str]] = None
requires_monitoring: Optional[bool] = None
monitoring_frequency_days: Optional[int] = Field(None, gt=0)
class FoodSafetyComplianceResponse(FoodSafetyComplianceBase):
id: UUID
tenant_id: UUID
is_active: bool
created_at: datetime
updated_at: datetime
created_by: Optional[UUID] = None
updated_by: Optional[UUID] = None
class Config:
from_attributes = True
# ===== Temperature Monitoring Schemas =====
class TemperatureLogBase(BaseModel):
storage_location: str = Field(..., min_length=1, max_length=100)
warehouse_zone: Optional[str] = Field(None, max_length=50)
equipment_id: Optional[str] = Field(None, max_length=100)
temperature_celsius: float
humidity_percentage: Optional[float] = Field(None, ge=0, le=100)
target_temperature_min: Optional[float] = None
target_temperature_max: Optional[float] = None
measurement_method: str = Field(default="manual")
device_id: Optional[str] = Field(None, max_length=100)
calibration_date: Optional[datetime] = None
class TemperatureLogCreate(TemperatureLogBase):
tenant_id: UUID
class TemperatureLogResponse(TemperatureLogBase):
id: UUID
tenant_id: UUID
is_within_range: bool
alert_triggered: bool
deviation_minutes: Optional[int] = None
recorded_at: datetime
created_at: datetime
recorded_by: Optional[UUID] = None
class Config:
from_attributes = True
# ===== Food Safety Alert Schemas =====
class FoodSafetyAlertBase(BaseModel):
alert_type: str
severity: str = Field(default="medium")
risk_level: str = Field(default="medium")
source_entity_type: str
source_entity_id: UUID
ingredient_id: Optional[UUID] = None
stock_id: Optional[UUID] = None
title: str = Field(..., min_length=1, max_length=200)
description: str = Field(..., min_length=1)
detailed_message: Optional[str] = None
regulatory_requirement: Optional[str] = Field(None, max_length=100)
compliance_standard: Optional[str] = None
regulatory_action_required: bool = Field(default=False)
trigger_condition: Optional[str] = Field(None, max_length=200)
threshold_value: Optional[Decimal] = None
actual_value: Optional[Decimal] = None
alert_data: Optional[Dict[str, Any]] = None
environmental_factors: Optional[Dict[str, Any]] = None
affected_products: Optional[List[UUID]] = None
public_health_risk: bool = Field(default=False)
business_impact: Optional[str] = None
estimated_loss: Optional[Decimal] = Field(None, ge=0)
class FoodSafetyAlertCreate(FoodSafetyAlertBase):
tenant_id: UUID
alert_code: str = Field(..., min_length=1, max_length=50)
class FoodSafetyAlertUpdate(BaseModel):
status: Optional[str] = None
alert_state: Optional[str] = None
immediate_actions_taken: Optional[List[str]] = None
investigation_notes: Optional[str] = None
resolution_action: Optional[str] = Field(None, max_length=200)
resolution_notes: Optional[str] = None
corrective_actions: Optional[List[str]] = None
preventive_measures: Optional[List[str]] = None
assigned_to: Optional[UUID] = None
assigned_role: Optional[str] = Field(None, max_length=50)
escalated_to: Optional[UUID] = None
escalation_deadline: Optional[datetime] = None
documentation: Optional[Dict[str, Any]] = None
class FoodSafetyAlertResponse(FoodSafetyAlertBase):
id: UUID
tenant_id: UUID
alert_code: str
status: str
alert_state: str
immediate_actions_taken: Optional[List[str]] = None
investigation_notes: Optional[str] = None
resolution_action: Optional[str] = None
resolution_notes: Optional[str] = None
corrective_actions: Optional[List[str]] = None
preventive_measures: Optional[List[str]] = None
first_occurred_at: datetime
last_occurred_at: datetime
acknowledged_at: Optional[datetime] = None
resolved_at: Optional[datetime] = None
escalation_deadline: Optional[datetime] = None
occurrence_count: int
is_recurring: bool
recurrence_pattern: Optional[str] = None
assigned_to: Optional[UUID] = None
assigned_role: Optional[str] = None
escalated_to: Optional[UUID] = None
escalation_level: int
notification_sent: bool
notification_methods: Optional[List[str]] = None
notification_recipients: Optional[List[str]] = None
regulatory_notification_required: bool
regulatory_notification_sent: bool
documentation: Optional[Dict[str, Any]] = None
audit_trail: Optional[List[Dict[str, Any]]] = None
external_reference: Optional[str] = None
detection_time: Optional[datetime] = None
response_time_minutes: Optional[int] = None
resolution_time_minutes: Optional[int] = None
alert_accuracy: Optional[bool] = None
false_positive: bool
feedback_notes: Optional[str] = None
created_at: datetime
updated_at: datetime
created_by: Optional[UUID] = None
updated_by: Optional[UUID] = None
class Config:
from_attributes = True
# ===== Bulk Operations Schemas =====
class BulkTemperatureLogCreate(BaseModel):
"""Schema for bulk temperature logging"""
tenant_id: UUID
readings: List[TemperatureLogBase] = Field(..., min_items=1, max_items=100)
class BulkComplianceUpdate(BaseModel):
"""Schema for bulk compliance updates"""
tenant_id: UUID
updates: List[Dict[str, Any]] = Field(..., min_items=1, max_items=50)
# ===== Filter and Query Schemas =====
class FoodSafetyFilter(BaseModel):
"""Filtering options for food safety data"""
compliance_standards: Optional[List[str]] = None
compliance_statuses: Optional[List[str]] = None
risk_levels: Optional[List[str]] = None
alert_types: Optional[List[str]] = None
severities: Optional[List[str]] = None
date_from: Optional[datetime] = None
date_to: Optional[datetime] = None
assigned_to: Optional[UUID] = None
include_resolved: bool = False
regulatory_action_required: Optional[bool] = None
class TemperatureMonitoringFilter(BaseModel):
"""Filtering options for temperature monitoring"""
storage_locations: Optional[List[str]] = None
equipment_ids: Optional[List[str]] = None
date_from: Optional[datetime] = None
date_to: Optional[datetime] = None
violations_only: bool = False
alerts_only: bool = False
# ===== Analytics Schemas =====
class FoodSafetyMetrics(BaseModel):
"""Food safety performance metrics"""
compliance_rate: Decimal = Field(..., ge=0, le=100)
temperature_compliance_rate: Decimal = Field(..., ge=0, le=100)
alert_response_time_avg: Optional[Decimal] = None
alert_resolution_time_avg: Optional[Decimal] = None
recurring_issues_count: int
regulatory_violations: int
certification_coverage: Decimal = Field(..., ge=0, le=100)
audit_score_avg: Optional[Decimal] = Field(None, ge=0, le=100)
risk_score: Decimal = Field(..., ge=0, le=10)
class TemperatureAnalytics(BaseModel):
"""Temperature monitoring analytics"""
total_readings: int
violations_count: int
violation_rate: Decimal = Field(..., ge=0, le=100)
average_temperature: Decimal
temperature_range: Dict[str, Decimal]
longest_violation_hours: Optional[int] = None
equipment_performance: List[Dict[str, Any]]
location_performance: List[Dict[str, Any]]
# ===== Notification Schemas =====
class AlertNotificationPreferences(BaseModel):
"""User preferences for alert notifications"""
email_enabled: bool = True
sms_enabled: bool = False
whatsapp_enabled: bool = False
dashboard_enabled: bool = True
severity_threshold: str = Field(default="medium") # Only notify for this severity and above
alert_types: Optional[List[str]] = None # Specific alert types to receive
quiet_hours_start: Optional[str] = Field(None, pattern=r"^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$")
quiet_hours_end: Optional[str] = Field(None, pattern=r"^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$")
weekend_notifications: bool = True