325 lines
7.3 KiB
Python
325 lines
7.3 KiB
Python
from pydantic import BaseModel, EmailStr, Field
|
|
from typing import Optional, List
|
|
from datetime import datetime
|
|
|
|
# User Schemas
|
|
class UserBase(BaseModel):
|
|
username: str
|
|
email: Optional[EmailStr] = None
|
|
full_name: Optional[str] = None
|
|
role: str = "mechanic"
|
|
|
|
class UserCreate(UserBase):
|
|
password: str
|
|
|
|
class UserUpdate(BaseModel):
|
|
username: Optional[str] = None
|
|
email: Optional[EmailStr] = None
|
|
full_name: Optional[str] = None
|
|
role: Optional[str] = None
|
|
|
|
class UserPasswordUpdate(BaseModel):
|
|
current_password: str
|
|
new_password: str
|
|
|
|
class AdminPasswordUpdate(BaseModel):
|
|
new_password: str
|
|
|
|
class UserLogin(BaseModel):
|
|
username: str
|
|
password: str
|
|
|
|
class User(UserBase):
|
|
id: int
|
|
is_active: bool
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class Token(BaseModel):
|
|
access_token: str
|
|
token_type: str
|
|
user: User
|
|
|
|
|
|
# API Token Schemas
|
|
class APITokenCreate(BaseModel):
|
|
description: Optional[str] = None
|
|
|
|
class APIToken(BaseModel):
|
|
id: int
|
|
description: Optional[str] = None
|
|
is_active: bool
|
|
last_used_at: Optional[datetime] = None
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class APITokenWithValue(APIToken):
|
|
token: str
|
|
|
|
|
|
# Checklist Schemas
|
|
class ChecklistBase(BaseModel):
|
|
name: str
|
|
description: Optional[str] = None
|
|
ai_mode: str = "off"
|
|
scoring_enabled: bool = True
|
|
logo_url: Optional[str] = None
|
|
|
|
class ChecklistCreate(ChecklistBase):
|
|
mechanic_ids: Optional[List[int]] = [] # IDs de mecánicos autorizados
|
|
|
|
class ChecklistUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
description: Optional[str] = None
|
|
ai_mode: Optional[str] = None
|
|
scoring_enabled: Optional[bool] = None
|
|
logo_url: Optional[str] = None
|
|
is_active: Optional[bool] = None
|
|
mechanic_ids: Optional[List[int]] = None # IDs de mecánicos autorizados
|
|
|
|
class Checklist(ChecklistBase):
|
|
id: int
|
|
max_score: int
|
|
is_active: bool
|
|
created_by: int
|
|
created_at: datetime
|
|
allowed_mechanics: Optional[List[int]] = [] # IDs de mecánicos permitidos
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Question Schemas
|
|
class QuestionBase(BaseModel):
|
|
section: Optional[str] = None
|
|
text: str
|
|
type: str
|
|
points: int = 1
|
|
options: Optional[dict] = None
|
|
order: int = 0
|
|
allow_photos: bool = True
|
|
max_photos: int = 3
|
|
requires_comment_on_fail: bool = False
|
|
send_notification: bool = False
|
|
parent_question_id: Optional[int] = None
|
|
show_if_answer: Optional[str] = None
|
|
ai_prompt: Optional[str] = None
|
|
|
|
class QuestionCreate(QuestionBase):
|
|
checklist_id: int
|
|
|
|
class QuestionUpdate(QuestionBase):
|
|
pass
|
|
|
|
class Question(QuestionBase):
|
|
id: int
|
|
checklist_id: int
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
|
|
# Inspection Schemas
|
|
class InspectionBase(BaseModel):
|
|
or_number: Optional[str] = None
|
|
work_order_number: Optional[str] = None
|
|
vehicle_plate: str
|
|
vehicle_brand: Optional[str] = None
|
|
vehicle_model: Optional[str] = None
|
|
vehicle_km: Optional[int] = None
|
|
client_name: Optional[str] = None
|
|
|
|
class InspectionCreate(InspectionBase):
|
|
checklist_id: int
|
|
|
|
class InspectionUpdate(BaseModel):
|
|
vehicle_brand: Optional[str] = None
|
|
vehicle_model: Optional[str] = None
|
|
vehicle_km: Optional[int] = None
|
|
signature_data: Optional[str] = None
|
|
status: Optional[str] = None
|
|
|
|
class Inspection(InspectionBase):
|
|
id: int
|
|
checklist_id: int
|
|
mechanic_id: int
|
|
score: int
|
|
max_score: int
|
|
percentage: float
|
|
flagged_items_count: int
|
|
status: str
|
|
started_at: datetime
|
|
completed_at: Optional[datetime] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Answer Schemas
|
|
class AnswerBase(BaseModel):
|
|
answer_value: str
|
|
status: str = "ok"
|
|
comment: Optional[str] = None
|
|
is_flagged: bool = False
|
|
|
|
class AnswerCreate(AnswerBase):
|
|
inspection_id: int
|
|
question_id: int
|
|
|
|
class AnswerUpdate(AnswerBase):
|
|
pass
|
|
|
|
class Answer(AnswerBase):
|
|
id: int
|
|
inspection_id: int
|
|
question_id: int
|
|
points_earned: int
|
|
ai_analysis: Optional[dict] = None
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# MediaFile Schemas
|
|
class MediaFileBase(BaseModel):
|
|
caption: Optional[str] = None
|
|
order: int = 0
|
|
|
|
class MediaFileCreate(MediaFileBase):
|
|
file_type: str = "image"
|
|
|
|
class MediaFile(MediaFileBase):
|
|
id: int
|
|
answer_id: int
|
|
file_path: str
|
|
file_type: str
|
|
uploaded_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Response Schemas
|
|
class ChecklistWithQuestions(Checklist):
|
|
questions: List[Question] = []
|
|
|
|
class AnswerWithMedia(Answer):
|
|
media_files: List[MediaFile] = []
|
|
question: Question
|
|
|
|
class InspectionDetail(Inspection):
|
|
checklist: ChecklistWithQuestions
|
|
mechanic: User
|
|
answers: List[AnswerWithMedia] = []
|
|
|
|
|
|
# AI Configuration Schemas
|
|
class AIConfigurationBase(BaseModel):
|
|
provider: str # openai, gemini
|
|
api_key: str
|
|
model_name: Optional[str] = None
|
|
|
|
class AIConfigurationCreate(AIConfigurationBase):
|
|
pass
|
|
|
|
class AIConfigurationUpdate(BaseModel):
|
|
provider: Optional[str] = None
|
|
api_key: Optional[str] = None
|
|
model_name: Optional[str] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
class AIConfiguration(AIConfigurationBase):
|
|
id: int
|
|
is_active: bool
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class AIModelInfo(BaseModel):
|
|
id: str
|
|
name: str
|
|
provider: str
|
|
description: Optional[str] = None
|
|
|
|
# Reports Schemas
|
|
class InspectionStats(BaseModel):
|
|
total_inspections: int
|
|
completed_inspections: int
|
|
pending_inspections: int
|
|
completion_rate: float
|
|
avg_score: float
|
|
total_flagged_items: int
|
|
|
|
class MechanicRanking(BaseModel):
|
|
mechanic_id: int
|
|
mechanic_name: str
|
|
total_inspections: int
|
|
avg_score: float
|
|
completion_rate: float
|
|
|
|
class ChecklistStats(BaseModel):
|
|
checklist_id: int
|
|
checklist_name: str
|
|
total_inspections: int
|
|
avg_score: float
|
|
|
|
class DashboardData(BaseModel):
|
|
stats: InspectionStats
|
|
mechanic_ranking: List[MechanicRanking]
|
|
checklist_stats: List[ChecklistStats]
|
|
inspections_by_date: dict
|
|
pass_fail_ratio: dict
|
|
|
|
class InspectionListItem(BaseModel):
|
|
id: int
|
|
vehicle_plate: str
|
|
checklist_name: str
|
|
mechanic_name: str
|
|
status: str
|
|
score: Optional[int]
|
|
max_score: Optional[int]
|
|
flagged_items: int
|
|
started_at: Optional[datetime]
|
|
completed_at: Optional[datetime]
|
|
|
|
|
|
# Audit Log Schemas
|
|
class AuditLogBase(BaseModel):
|
|
action: str
|
|
entity_type: str
|
|
field_name: Optional[str] = None
|
|
old_value: Optional[str] = None
|
|
new_value: Optional[str] = None
|
|
comment: Optional[str] = None
|
|
|
|
class AuditLog(AuditLogBase):
|
|
id: int
|
|
inspection_id: int
|
|
answer_id: Optional[int] = None
|
|
user_id: int
|
|
user_name: Optional[str] = None
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
class AnswerEdit(BaseModel):
|
|
answer_value: Optional[str] = None
|
|
status: Optional[str] = None
|
|
comment: Optional[str] = None
|
|
is_flagged: Optional[bool] = None
|
|
edit_comment: Optional[str] = None # Comentario del admin sobre por qué editó
|
|
|
|
max_score: Optional[int]
|
|
flagged_items: int
|
|
started_at: Optional[datetime]
|
|
completed_at: Optional[datetime]
|