385 lines
12 KiB
Python
385 lines
12 KiB
Python
# ================================================================
|
|
# services/suppliers/app/schemas/performance.py
|
|
# ================================================================
|
|
"""
|
|
Performance Tracking and Alert Schemas for Suppliers Service
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import List, Optional, Dict, Any
|
|
from uuid import UUID
|
|
from pydantic import BaseModel, Field, validator
|
|
from decimal import Decimal
|
|
|
|
from app.models.performance import (
|
|
AlertSeverity, AlertType, AlertStatus, PerformanceMetricType,
|
|
PerformancePeriod
|
|
)
|
|
|
|
|
|
# ===== Base Schemas =====
|
|
|
|
class PerformanceMetricBase(BaseModel):
|
|
"""Base schema for performance metrics"""
|
|
metric_type: PerformanceMetricType
|
|
period: PerformancePeriod
|
|
period_start: datetime
|
|
period_end: datetime
|
|
metric_value: float = Field(ge=0, le=100)
|
|
target_value: Optional[float] = None
|
|
total_orders: int = Field(ge=0, default=0)
|
|
total_deliveries: int = Field(ge=0, default=0)
|
|
on_time_deliveries: int = Field(ge=0, default=0)
|
|
late_deliveries: int = Field(ge=0, default=0)
|
|
quality_issues: int = Field(ge=0, default=0)
|
|
total_amount: Decimal = Field(ge=0, default=0)
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class PerformanceMetricCreate(PerformanceMetricBase):
|
|
"""Schema for creating performance metrics"""
|
|
supplier_id: UUID
|
|
metrics_data: Optional[Dict[str, Any]] = None
|
|
external_factors: Optional[Dict[str, Any]] = None
|
|
|
|
|
|
class PerformanceMetricUpdate(BaseModel):
|
|
"""Schema for updating performance metrics"""
|
|
metric_value: Optional[float] = Field(None, ge=0, le=100)
|
|
target_value: Optional[float] = None
|
|
notes: Optional[str] = None
|
|
metrics_data: Optional[Dict[str, Any]] = None
|
|
external_factors: Optional[Dict[str, Any]] = None
|
|
|
|
|
|
class PerformanceMetric(PerformanceMetricBase):
|
|
"""Complete performance metric schema"""
|
|
id: UUID
|
|
tenant_id: UUID
|
|
supplier_id: UUID
|
|
previous_value: Optional[float] = None
|
|
trend_direction: Optional[str] = None
|
|
trend_percentage: Optional[float] = None
|
|
metrics_data: Optional[Dict[str, Any]] = None
|
|
external_factors: Optional[Dict[str, Any]] = None
|
|
calculated_at: datetime
|
|
|
|
class Config:
|
|
orm_mode = True
|
|
|
|
|
|
# ===== Alert Schemas =====
|
|
|
|
class AlertBase(BaseModel):
|
|
"""Base schema for alerts"""
|
|
alert_type: AlertType
|
|
severity: AlertSeverity
|
|
title: str = Field(max_length=255)
|
|
message: str
|
|
description: Optional[str] = None
|
|
trigger_value: Optional[float] = None
|
|
threshold_value: Optional[float] = None
|
|
metric_type: Optional[PerformanceMetricType] = None
|
|
recommended_actions: Optional[List[Dict[str, Any]]] = None
|
|
auto_resolve: bool = False
|
|
|
|
|
|
class AlertCreate(AlertBase):
|
|
"""Schema for creating alerts"""
|
|
supplier_id: UUID
|
|
purchase_order_id: Optional[UUID] = None
|
|
delivery_id: Optional[UUID] = None
|
|
performance_metric_id: Optional[UUID] = None
|
|
priority_score: int = Field(ge=1, le=100, default=50)
|
|
business_impact: Optional[str] = None
|
|
tags: Optional[List[str]] = None
|
|
|
|
|
|
class AlertUpdate(BaseModel):
|
|
"""Schema for updating alerts"""
|
|
status: Optional[AlertStatus] = None
|
|
actions_taken: Optional[List[Dict[str, Any]]] = None
|
|
resolution_notes: Optional[str] = None
|
|
escalated: Optional[bool] = None
|
|
|
|
|
|
class Alert(AlertBase):
|
|
"""Complete alert schema"""
|
|
id: UUID
|
|
tenant_id: UUID
|
|
supplier_id: UUID
|
|
status: AlertStatus
|
|
purchase_order_id: Optional[UUID] = None
|
|
delivery_id: Optional[UUID] = None
|
|
performance_metric_id: Optional[UUID] = None
|
|
triggered_at: datetime
|
|
acknowledged_at: Optional[datetime] = None
|
|
acknowledged_by: Optional[UUID] = None
|
|
resolved_at: Optional[datetime] = None
|
|
resolved_by: Optional[UUID] = None
|
|
actions_taken: Optional[List[Dict[str, Any]]] = None
|
|
resolution_notes: Optional[str] = None
|
|
escalated: bool = False
|
|
escalated_at: Optional[datetime] = None
|
|
notification_sent: bool = False
|
|
priority_score: int
|
|
business_impact: Optional[str] = None
|
|
tags: Optional[List[str]] = None
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
orm_mode = True
|
|
|
|
|
|
# ===== Scorecard Schemas =====
|
|
|
|
class ScorecardBase(BaseModel):
|
|
"""Base schema for supplier scorecards"""
|
|
scorecard_name: str = Field(max_length=255)
|
|
period: PerformancePeriod
|
|
period_start: datetime
|
|
period_end: datetime
|
|
overall_score: float = Field(ge=0, le=100)
|
|
quality_score: float = Field(ge=0, le=100)
|
|
delivery_score: float = Field(ge=0, le=100)
|
|
cost_score: float = Field(ge=0, le=100)
|
|
service_score: float = Field(ge=0, le=100)
|
|
on_time_delivery_rate: float = Field(ge=0, le=100)
|
|
quality_rejection_rate: float = Field(ge=0, le=100)
|
|
order_accuracy_rate: float = Field(ge=0, le=100)
|
|
response_time_hours: float = Field(ge=0)
|
|
cost_variance_percentage: float
|
|
total_orders_processed: int = Field(ge=0, default=0)
|
|
total_amount_processed: Decimal = Field(ge=0, default=0)
|
|
average_order_value: Decimal = Field(ge=0, default=0)
|
|
cost_savings_achieved: Decimal = Field(default=0)
|
|
|
|
|
|
class ScorecardCreate(ScorecardBase):
|
|
"""Schema for creating scorecards"""
|
|
supplier_id: UUID
|
|
strengths: Optional[List[str]] = None
|
|
improvement_areas: Optional[List[str]] = None
|
|
recommended_actions: Optional[List[Dict[str, Any]]] = None
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class ScorecardUpdate(BaseModel):
|
|
"""Schema for updating scorecards"""
|
|
overall_score: Optional[float] = Field(None, ge=0, le=100)
|
|
quality_score: Optional[float] = Field(None, ge=0, le=100)
|
|
delivery_score: Optional[float] = Field(None, ge=0, le=100)
|
|
cost_score: Optional[float] = Field(None, ge=0, le=100)
|
|
service_score: Optional[float] = Field(None, ge=0, le=100)
|
|
strengths: Optional[List[str]] = None
|
|
improvement_areas: Optional[List[str]] = None
|
|
recommended_actions: Optional[List[Dict[str, Any]]] = None
|
|
notes: Optional[str] = None
|
|
is_final: Optional[bool] = None
|
|
|
|
|
|
class Scorecard(ScorecardBase):
|
|
"""Complete scorecard schema"""
|
|
id: UUID
|
|
tenant_id: UUID
|
|
supplier_id: UUID
|
|
overall_rank: Optional[int] = None
|
|
category_rank: Optional[int] = None
|
|
total_suppliers_evaluated: Optional[int] = None
|
|
score_trend: Optional[str] = None
|
|
score_change_percentage: Optional[float] = None
|
|
strengths: Optional[List[str]] = None
|
|
improvement_areas: Optional[List[str]] = None
|
|
recommended_actions: Optional[List[Dict[str, Any]]] = None
|
|
is_final: bool = False
|
|
approved_by: Optional[UUID] = None
|
|
approved_at: Optional[datetime] = None
|
|
notes: Optional[str] = None
|
|
attachments: Optional[List[Dict[str, Any]]] = None
|
|
generated_at: datetime
|
|
generated_by: UUID
|
|
|
|
class Config:
|
|
orm_mode = True
|
|
|
|
|
|
# ===== Dashboard Schemas =====
|
|
|
|
class PerformanceDashboardSummary(BaseModel):
|
|
"""Performance dashboard summary schema"""
|
|
total_suppliers: int
|
|
active_suppliers: int
|
|
suppliers_above_threshold: int
|
|
suppliers_below_threshold: int
|
|
average_overall_score: float
|
|
average_delivery_rate: float
|
|
average_quality_rate: float
|
|
total_active_alerts: int
|
|
critical_alerts: int
|
|
high_priority_alerts: int
|
|
recent_scorecards_generated: int
|
|
cost_savings_this_month: Decimal
|
|
|
|
# Performance trends
|
|
performance_trend: str # improving, declining, stable
|
|
delivery_trend: str
|
|
quality_trend: str
|
|
|
|
# Business model insights
|
|
detected_business_model: str # individual_bakery, central_bakery, hybrid
|
|
model_confidence: float
|
|
business_model_metrics: Dict[str, Any]
|
|
|
|
|
|
class SupplierPerformanceInsights(BaseModel):
|
|
"""Supplier performance insights schema"""
|
|
supplier_id: UUID
|
|
supplier_name: str
|
|
current_overall_score: float
|
|
previous_score: Optional[float] = None
|
|
score_change_percentage: Optional[float] = None
|
|
performance_rank: Optional[int] = None
|
|
|
|
# Key performance indicators
|
|
delivery_performance: float
|
|
quality_performance: float
|
|
cost_performance: float
|
|
service_performance: float
|
|
|
|
# Recent metrics
|
|
orders_last_30_days: int
|
|
average_delivery_time: float
|
|
quality_issues_count: int
|
|
cost_variance: float
|
|
|
|
# Alert summary
|
|
active_alerts: int
|
|
resolved_alerts_last_30_days: int
|
|
alert_trend: str
|
|
|
|
# Performance categorization
|
|
performance_category: str # excellent, good, acceptable, needs_improvement, poor
|
|
risk_level: str # low, medium, high, critical
|
|
|
|
# Recommendations
|
|
top_strengths: List[str]
|
|
improvement_priorities: List[str]
|
|
recommended_actions: List[Dict[str, Any]]
|
|
|
|
|
|
class PerformanceAnalytics(BaseModel):
|
|
"""Advanced performance analytics schema"""
|
|
period_start: datetime
|
|
period_end: datetime
|
|
total_suppliers_analyzed: int
|
|
|
|
# Performance distribution
|
|
performance_distribution: Dict[str, int] # excellent, good, etc.
|
|
score_ranges: Dict[str, List[float]] # min, max, avg per range
|
|
|
|
# Trend analysis
|
|
overall_trend: Dict[str, float] # month-over-month changes
|
|
delivery_trends: Dict[str, float]
|
|
quality_trends: Dict[str, float]
|
|
cost_trends: Dict[str, float]
|
|
|
|
# Comparative analysis
|
|
top_performers: List[SupplierPerformanceInsights]
|
|
underperformers: List[SupplierPerformanceInsights]
|
|
most_improved: List[SupplierPerformanceInsights]
|
|
biggest_declines: List[SupplierPerformanceInsights]
|
|
|
|
# Risk analysis
|
|
high_risk_suppliers: List[Dict[str, Any]]
|
|
contract_renewals_due: List[Dict[str, Any]]
|
|
certification_expiries: List[Dict[str, Any]]
|
|
|
|
# Financial impact
|
|
total_procurement_value: Decimal
|
|
cost_savings_achieved: Decimal
|
|
cost_avoidance: Decimal
|
|
financial_risk_exposure: Decimal
|
|
|
|
|
|
class AlertSummary(BaseModel):
|
|
"""Alert summary schema"""
|
|
alert_type: AlertType
|
|
severity: AlertSeverity
|
|
count: int
|
|
avg_resolution_time_hours: Optional[float] = None
|
|
oldest_alert_age_hours: Optional[float] = None
|
|
trend_percentage: Optional[float] = None
|
|
|
|
|
|
class DashboardFilter(BaseModel):
|
|
"""Dashboard filter schema"""
|
|
supplier_ids: Optional[List[UUID]] = None
|
|
supplier_categories: Optional[List[str]] = None
|
|
performance_categories: Optional[List[str]] = None
|
|
date_from: Optional[datetime] = None
|
|
date_to: Optional[datetime] = None
|
|
include_inactive: bool = False
|
|
|
|
|
|
class AlertFilter(BaseModel):
|
|
"""Alert filter schema"""
|
|
alert_types: Optional[List[AlertType]] = None
|
|
severities: Optional[List[AlertSeverity]] = None
|
|
statuses: Optional[List[AlertStatus]] = None
|
|
supplier_ids: Optional[List[UUID]] = None
|
|
date_from: Optional[datetime] = None
|
|
date_to: Optional[datetime] = None
|
|
metric_types: Optional[List[PerformanceMetricType]] = None
|
|
|
|
|
|
# ===== Business Model Detection =====
|
|
|
|
class BusinessModelInsights(BaseModel):
|
|
"""Business model detection and insights schema"""
|
|
detected_model: str # individual_bakery, central_bakery, hybrid
|
|
confidence_score: float
|
|
model_characteristics: Dict[str, Any]
|
|
|
|
# Model-specific metrics
|
|
supplier_diversity_score: float
|
|
procurement_volume_patterns: Dict[str, Any]
|
|
delivery_frequency_patterns: Dict[str, Any]
|
|
order_size_patterns: Dict[str, Any]
|
|
|
|
# Recommendations
|
|
optimization_opportunities: List[Dict[str, Any]]
|
|
recommended_supplier_mix: Dict[str, Any]
|
|
cost_optimization_potential: Decimal
|
|
risk_mitigation_suggestions: List[str]
|
|
|
|
# Benchmarking
|
|
industry_comparison: Dict[str, float]
|
|
peer_comparison: Optional[Dict[str, float]] = None
|
|
|
|
|
|
# ===== Export and Reporting =====
|
|
|
|
class PerformanceReportRequest(BaseModel):
|
|
"""Performance report generation request"""
|
|
report_type: str # scorecard, analytics, alerts, comprehensive
|
|
format: str = Field(pattern="^(pdf|excel|csv|json)$")
|
|
period: PerformancePeriod
|
|
date_from: datetime
|
|
date_to: datetime
|
|
supplier_ids: Optional[List[UUID]] = None
|
|
include_charts: bool = True
|
|
include_recommendations: bool = True
|
|
include_benchmarks: bool = True
|
|
custom_metrics: Optional[List[str]] = None
|
|
|
|
|
|
class ExportDataResponse(BaseModel):
|
|
"""Export data response schema"""
|
|
export_id: UUID
|
|
format: str
|
|
file_url: Optional[str] = None
|
|
file_size_bytes: Optional[int] = None
|
|
generated_at: datetime
|
|
expires_at: datetime
|
|
status: str # generating, ready, expired, failed
|
|
error_message: Optional[str] = None |