Files
2026-01-11 17:03:46 +01:00

489 lines
17 KiB
Python

# services/production/app/schemas/equipment.py
"""
Equipment schemas for Production Service
"""
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional, List
from datetime import datetime
from uuid import UUID
from app.models.production import EquipmentType, EquipmentStatus, IoTProtocol, IoTConnectionStatus
class IoTConnectionConfig(BaseModel):
"""Schema for IoT connection configuration"""
protocol: str = Field(..., description="IoT protocol (rest_api, opc_ua, mqtt, modbus, custom)")
endpoint: str = Field(..., description="Connection endpoint (URL or IP address)")
port: Optional[int] = Field(None, description="Connection port")
username: Optional[str] = Field(None, description="Username for authentication")
password: Optional[str] = Field(None, description="Password for authentication")
api_key: Optional[str] = Field(None, description="API key for authentication")
token: Optional[str] = Field(None, description="Authentication token")
additional_config: Optional[dict] = Field(None, description="Additional protocol-specific configuration")
model_config = ConfigDict(
json_schema_extra={
"example": {
"protocol": "rest_api",
"endpoint": "https://connectedcooking.com/api/v1",
"port": 443,
"api_key": "your-api-key-here",
"additional_config": {"poll_interval": 30}
}
}
)
class EquipmentCreate(BaseModel):
"""Schema for creating new equipment"""
name: str = Field(..., min_length=1, max_length=255, description="Equipment name")
type: EquipmentType = Field(..., description="Equipment type")
model: Optional[str] = Field(None, max_length=100, description="Equipment model")
serial_number: Optional[str] = Field(None, max_length=100, description="Serial number")
location: Optional[str] = Field(None, max_length=255, description="Physical location")
manufacturer: Optional[str] = Field(None, max_length=100, description="Manufacturer")
firmware_version: Optional[str] = Field(None, max_length=50, description="Firmware version")
status: EquipmentStatus = Field(default=EquipmentStatus.OPERATIONAL, description="Equipment status")
# Installation and maintenance
install_date: Optional[datetime] = Field(None, description="Installation date")
last_maintenance_date: Optional[datetime] = Field(None, description="Last maintenance date")
next_maintenance_date: Optional[datetime] = Field(None, description="Next scheduled maintenance date")
maintenance_interval_days: Optional[int] = Field(None, ge=1, description="Maintenance interval in days")
# Performance metrics
efficiency_percentage: Optional[float] = Field(None, ge=0, le=100, description="Current efficiency percentage")
uptime_percentage: Optional[float] = Field(None, ge=0, le=100, description="Overall uptime percentage")
energy_usage_kwh: Optional[float] = Field(None, ge=0, description="Current energy usage in kWh")
# Specifications
power_kw: Optional[float] = Field(None, ge=0, description="Power consumption in kilowatts")
capacity: Optional[float] = Field(None, ge=0, description="Equipment capacity")
weight_kg: Optional[float] = Field(None, ge=0, description="Weight in kilograms")
# Temperature monitoring
current_temperature: Optional[float] = Field(None, description="Current temperature")
target_temperature: Optional[float] = Field(None, description="Target temperature")
# IoT Connectivity
iot_enabled: bool = Field(default=False, description="Enable IoT connectivity")
iot_protocol: Optional[str] = Field(None, description="IoT protocol")
iot_endpoint: Optional[str] = Field(None, description="IoT endpoint URL or IP")
iot_port: Optional[int] = Field(None, description="IoT connection port")
iot_config: Optional[dict] = Field(None, description="IoT configuration")
# Real-time monitoring
supports_realtime: bool = Field(default=False, description="Supports real-time monitoring")
poll_interval_seconds: Optional[int] = Field(None, ge=1, description="Polling interval in seconds")
# Sensor capabilities
temperature_zones: Optional[int] = Field(None, ge=1, description="Number of temperature zones")
supports_humidity: bool = Field(default=False, description="Supports humidity monitoring")
supports_energy_monitoring: bool = Field(default=False, description="Supports energy monitoring")
supports_remote_control: bool = Field(default=False, description="Supports remote control")
# Notes
notes: Optional[str] = Field(None, description="Additional notes")
# Support contact information
support_contact: Optional[dict] = Field(
None,
description="Support contact information for equipment maintenance",
json_schema_extra={
"example": {
"email": "support@ovenfactory.com",
"phone": "+1-800-555-1234",
"company": "OvenTech Support",
"contract_number": "SUP-2023-001",
"response_time_sla": 24
}
}
)
model_config = ConfigDict(
json_schema_extra={
"example": {
"name": "Horno Principal #1",
"type": "oven",
"model": "Miwe Condo CO 4.1212",
"serial_number": "MCO-2021-001",
"location": "Área de Horneado - Zona A",
"status": "operational",
"install_date": "2021-03-15T00:00:00Z",
"maintenance_interval_days": 90,
"efficiency_percentage": 92.0,
"uptime_percentage": 98.5,
"power_kw": 45.0,
"capacity": 24.0
}
}
)
class EquipmentUpdate(BaseModel):
"""Schema for updating equipment"""
name: Optional[str] = Field(None, min_length=1, max_length=255)
type: Optional[EquipmentType] = None
model: Optional[str] = Field(None, max_length=100)
serial_number: Optional[str] = Field(None, max_length=100)
location: Optional[str] = Field(None, max_length=255)
manufacturer: Optional[str] = Field(None, max_length=100)
firmware_version: Optional[str] = Field(None, max_length=50)
status: Optional[EquipmentStatus] = None
# Installation and maintenance
install_date: Optional[datetime] = None
last_maintenance_date: Optional[datetime] = None
next_maintenance_date: Optional[datetime] = None
maintenance_interval_days: Optional[int] = Field(None, ge=1)
# Performance metrics
efficiency_percentage: Optional[float] = Field(None, ge=0, le=100)
uptime_percentage: Optional[float] = Field(None, ge=0, le=100)
energy_usage_kwh: Optional[float] = Field(None, ge=0)
# Specifications
power_kw: Optional[float] = Field(None, ge=0)
capacity: Optional[float] = Field(None, ge=0)
weight_kg: Optional[float] = Field(None, ge=0)
# Temperature monitoring
current_temperature: Optional[float] = None
target_temperature: Optional[float] = None
# IoT Connectivity
iot_enabled: Optional[bool] = None
iot_protocol: Optional[str] = None
iot_endpoint: Optional[str] = None
iot_port: Optional[int] = None
iot_config: Optional[dict] = None
# Real-time monitoring
supports_realtime: Optional[bool] = None
poll_interval_seconds: Optional[int] = Field(None, ge=1)
# Sensor capabilities
temperature_zones: Optional[int] = Field(None, ge=1)
supports_humidity: Optional[bool] = None
supports_energy_monitoring: Optional[bool] = None
supports_remote_control: Optional[bool] = None
# Notes
notes: Optional[str] = None
# Support contact information
support_contact: Optional[dict] = None
# Status flag
is_active: Optional[bool] = None
model_config = ConfigDict(
json_schema_extra={
"example": {
"status": "maintenance",
"last_maintenance_date": "2024-01-15T00:00:00Z",
"next_maintenance_date": "2024-04-15T00:00:00Z",
"efficiency_percentage": 88.0
}
}
)
class EquipmentResponse(BaseModel):
"""Schema for equipment response"""
id: UUID
tenant_id: UUID
name: str
type: EquipmentType
model: Optional[str] = None
serial_number: Optional[str] = None
location: Optional[str] = None
manufacturer: Optional[str] = None
firmware_version: Optional[str] = None
status: EquipmentStatus
# Installation and maintenance
install_date: Optional[datetime] = None
last_maintenance_date: Optional[datetime] = None
next_maintenance_date: Optional[datetime] = None
maintenance_interval_days: Optional[int] = None
# Performance metrics
efficiency_percentage: Optional[float] = None
uptime_percentage: Optional[float] = None
energy_usage_kwh: Optional[float] = None
# Specifications
power_kw: Optional[float] = None
capacity: Optional[float] = None
weight_kg: Optional[float] = None
# Temperature monitoring
current_temperature: Optional[float] = None
target_temperature: Optional[float] = None
# IoT Connectivity
iot_enabled: bool = False
iot_protocol: Optional[str] = None
iot_endpoint: Optional[str] = None
iot_port: Optional[int] = None
iot_connection_status: Optional[str] = None
iot_last_connected: Optional[datetime] = None
iot_config: Optional[dict] = None
# Real-time monitoring
supports_realtime: bool = False
poll_interval_seconds: Optional[int] = None
# Sensor capabilities
temperature_zones: Optional[int] = None
supports_humidity: bool = False
supports_energy_monitoring: bool = False
supports_remote_control: bool = False
# Status
is_active: bool
notes: Optional[str] = None
# Support contact information
support_contact: Optional[dict] = None
# Timestamps
created_at: datetime
updated_at: datetime
model_config = ConfigDict(from_attributes=True)
class EquipmentListResponse(BaseModel):
"""Schema for paginated equipment list response"""
equipment: List[EquipmentResponse]
total_count: int
page: int
page_size: int
model_config = ConfigDict(
json_schema_extra={
"example": {
"equipment": [],
"total_count": 10,
"page": 1,
"page_size": 50
}
}
)
class EquipmentDeletionSummary(BaseModel):
"""Schema for equipment deletion summary"""
can_delete: bool = Field(..., description="Whether the equipment can be deleted")
warnings: List[str] = Field(default_factory=list, description="List of warnings about deletion")
production_batches_count: int = Field(default=0, description="Number of production batches using this equipment")
maintenance_records_count: int = Field(default=0, description="Number of maintenance records")
temperature_logs_count: int = Field(default=0, description="Number of temperature logs")
equipment_name: Optional[str] = Field(None, description="Equipment name")
equipment_type: Optional[str] = Field(None, description="Equipment type")
equipment_location: Optional[str] = Field(None, description="Equipment location")
model_config = ConfigDict(
json_schema_extra={
"example": {
"can_delete": True,
"warnings": ["3 production batch(es) are using this equipment"],
"production_batches_count": 3,
"maintenance_records_count": 5,
"temperature_logs_count": 120,
"equipment_name": "Horno Principal #1",
"equipment_type": "oven",
"equipment_location": "Área de Horneado"
}
}
)
# ================================================================
# IoT-SPECIFIC SCHEMAS
# ================================================================
class EquipmentSensorReadingResponse(BaseModel):
"""Schema for equipment sensor reading response"""
id: UUID
tenant_id: UUID
equipment_id: UUID
batch_id: Optional[UUID] = None
reading_time: datetime
# Temperature readings
temperature: Optional[float] = None
temperature_zones: Optional[dict] = None
target_temperature: Optional[float] = None
# Humidity
humidity: Optional[float] = None
target_humidity: Optional[float] = None
# Energy monitoring
energy_consumption_kwh: Optional[float] = None
power_current_kw: Optional[float] = None
# Equipment status
operational_status: Optional[str] = None
cycle_stage: Optional[str] = None
cycle_progress_percentage: Optional[float] = None
time_remaining_minutes: Optional[int] = None
# Process parameters
motor_speed_rpm: Optional[float] = None
door_status: Optional[str] = None
steam_level: Optional[float] = None
# Quality indicators
product_weight_kg: Optional[float] = None
moisture_content: Optional[float] = None
# Additional sensor data
additional_sensors: Optional[dict] = None
# Data quality
data_quality_score: Optional[float] = None
is_anomaly: bool = False
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class EquipmentConnectionTestResponse(BaseModel):
"""Schema for IoT connection test response"""
success: bool = Field(..., description="Whether connection test succeeded")
status: str = Field(..., description="Connection status")
message: str = Field(..., description="Detailed message")
response_time_ms: Optional[int] = Field(None, description="Response time in milliseconds")
protocol_tested: str = Field(..., description="Protocol that was tested")
endpoint_tested: str = Field(..., description="Endpoint that was tested")
error_details: Optional[str] = Field(None, description="Error details if connection failed")
supported_features: Optional[List[str]] = Field(None, description="List of supported IoT features")
model_config = ConfigDict(
json_schema_extra={
"example": {
"success": True,
"status": "connected",
"message": "Successfully connected to equipment",
"response_time_ms": 145,
"protocol_tested": "rest_api",
"endpoint_tested": "https://connectedcooking.com/api/v1",
"supported_features": ["temperature", "humidity", "energy_monitoring"]
}
}
)
class RealTimeDataResponse(BaseModel):
"""Schema for real-time equipment data response"""
equipment_id: UUID
equipment_name: str
timestamp: datetime
connection_status: str
# Current readings
temperature: Optional[float] = None
temperature_zones: Optional[dict] = None
humidity: Optional[float] = None
energy_consumption_kwh: Optional[float] = None
power_current_kw: Optional[float] = None
# Status
operational_status: Optional[str] = None
cycle_stage: Optional[str] = None
cycle_progress_percentage: Optional[float] = None
time_remaining_minutes: Optional[int] = None
# Active batch
active_batch_id: Optional[UUID] = None
active_batch_name: Optional[str] = None
model_config = ConfigDict(
json_schema_extra={
"example": {
"equipment_id": "123e4567-e89b-12d3-a456-426614174000",
"equipment_name": "Horno Principal #1",
"timestamp": "2025-01-12T10:30:00Z",
"connection_status": "connected",
"temperature": 185.5,
"temperature_zones": {"zone1": 180, "zone2": 190, "zone3": 185},
"humidity": 65.0,
"operational_status": "running",
"cycle_stage": "baking",
"cycle_progress_percentage": 45.0,
"time_remaining_minutes": 12
}
}
)
class EquipmentIoTAlertResponse(BaseModel):
"""Schema for IoT alert response"""
id: UUID
tenant_id: UUID
equipment_id: UUID
batch_id: Optional[UUID] = None
# Alert information
alert_type: str
severity: str
alert_time: datetime
# Alert details
title: str
message: str
# Threshold information
threshold_value: Optional[float] = None
actual_value: Optional[float] = None
deviation_percentage: Optional[float] = None
# Status
is_active: bool
is_acknowledged: bool
acknowledged_by: Optional[UUID] = None
acknowledged_at: Optional[datetime] = None
is_resolved: bool
resolved_by: Optional[UUID] = None
resolved_at: Optional[datetime] = None
resolution_notes: Optional[str] = None
# Automated response
auto_resolved: bool
corrective_action_taken: Optional[str] = None
created_at: datetime
updated_at: datetime
model_config = ConfigDict(from_attributes=True)
class EquipmentSensorHistoryResponse(BaseModel):
"""Schema for sensor reading history response"""
equipment_id: UUID
equipment_name: str
start_time: datetime
end_time: datetime
total_readings: int
readings: List[EquipmentSensorReadingResponse]
model_config = ConfigDict(
json_schema_extra={
"example": {
"equipment_id": "123e4567-e89b-12d3-a456-426614174000",
"equipment_name": "Horno Principal #1",
"start_time": "2025-01-12T08:00:00Z",
"end_time": "2025-01-12T12:00:00Z",
"total_readings": 48,
"readings": []
}
}
)