Initial commit - production deployment
This commit is contained in:
385
services/suppliers/app/schemas/performance.py
Normal file
385
services/suppliers/app/schemas/performance.py
Normal file
@@ -0,0 +1,385 @@
|
||||
# ================================================================
|
||||
# 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
|
||||
Reference in New Issue
Block a user