Mechanic's work place
Some checks failed
ci / test (push) Has been cancelled

This commit is contained in:
VPN SaaS Dev
2026-05-16 10:04:56 +09:00
parent fec9635079
commit 83ad880b9d
39 changed files with 2951 additions and 74 deletions

View File

@@ -30,6 +30,8 @@ class ServiceCenterRead(ServiceCenterCreate):
name: str
verification_status: str
owner_user_id: int | None = None
employee_role: str | None = None
employee_status: str | None = None
created_at: datetime
verified_at: datetime | None = None
suspended_at: datetime | None = None
@@ -78,6 +80,7 @@ class ServiceEmployeeInvite(BaseModel):
telegram_id: int
role: str = "receptionist"
permissions: dict | None = None
expires_in_hours: int = Field(default=72, ge=0, le=720)
class ServiceEmployeeRead(BaseModel):
@@ -87,6 +90,10 @@ class ServiceEmployeeRead(BaseModel):
role: str
permissions: dict | None = None
status: str
invite_token: str | None = None
invite_expires_at: datetime | None = None
invite_revoked_at: datetime | None = None
activated_at: datetime | None = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
@@ -284,8 +291,27 @@ class ServiceVisitCreate(BaseModel):
class ServiceVisitRead(ServiceVisitCreate):
id: int
service_center_id: int
work_order_number: str | None = None
owner_id: int | None = None
created_by_employee_id: int | None = None
assigned_employee_id: int | None = None
status: str
customer_complaint: str | None = None
diagnosis: str | None = None
service_comment: str | None = None
owner_comment: str | None = None
recommendations_text: str | None = None
attachment_urls: list[str] | None = None
labor_total: Decimal = Decimal("0")
product_total: Decimal = Decimal("0")
discount_total: Decimal = Decimal("0")
final_total: Decimal = Decimal("0")
approval_required: bool = False
version: int = 1
completed_snapshot: dict | None = None
opened_at: datetime | None = None
approved_at: datetime | None = None
completed_at: datetime | None = None
owner_resolved_at: datetime | None = None
created_at: datetime
@@ -295,7 +321,12 @@ class ServiceVisitRead(ServiceVisitCreate):
class ServiceWorkItemCreate(BaseModel):
work_type: str = "other"
title: str
category: str | None = None
description: str | None = None
quantity: Decimal = Decimal("1")
unit: str = "pcs"
unit_price: Decimal | None = None
discount: Decimal = Decimal("0")
parts: list[dict] | None = None
oil_brand: str | None = None
oil_viscosity: str | None = None
@@ -303,11 +334,108 @@ class ServiceWorkItemCreate(BaseModel):
next_due_odometer: int | None = None
next_due_date: date | None = None
price: Decimal | None = None
warranty_days: int | None = None
warranty_odometer_km: int | None = None
@model_validator(mode="after")
def validate_item(self) -> "ServiceWorkItemCreate":
if self.quantity <= 0:
raise ValueError("quantity must be positive")
if self.discount < 0:
raise ValueError("discount must be non-negative")
if self.unit_price is not None and self.unit_price < 0:
raise ValueError("unit_price must be non-negative")
if self.price is not None and self.price < 0:
raise ValueError("price must be non-negative")
return self
class ServiceWorkItemRead(ServiceWorkItemCreate):
id: int
service_visit_id: int
total: Decimal | None = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class ServiceProductItemCreate(BaseModel):
title: str
category: str | None = None
product_type: str = "other"
brand: str | None = None
sku: str | None = None
quantity: Decimal = Decimal("1")
unit: str = "pcs"
unit_price: Decimal = Decimal("0")
discount: Decimal = Decimal("0")
volume: Decimal | None = None
viscosity: str | None = None
specification: str | None = None
used_volume: Decimal | None = None
@model_validator(mode="after")
def validate_product(self) -> "ServiceProductItemCreate":
if self.quantity <= 0:
raise ValueError("quantity must be positive")
if self.unit_price < 0 or self.discount < 0:
raise ValueError("price and discount must be non-negative")
return self
class ServiceProductItemRead(ServiceProductItemCreate):
id: int
service_visit_id: int
total: Decimal
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class WorkOrderUpdate(BaseModel):
odometer: int | None = None
assigned_employee_id: int | None = None
customer_complaint: str | None = None
diagnosis: str | None = None
notes: str | None = None
service_comment: str | None = None
owner_comment: str | None = None
recommendations_text: str | None = None
attachment_urls: list[str] | None = None
discount_total: Decimal | None = None
approval_required: bool | None = None
class WorkOrderDecision(BaseModel):
comment: str | None = None
confirm_lower_odometer: bool = False
class WorkOrderStatusHistoryRead(BaseModel):
id: int
service_visit_id: int
from_status: str | None = None
to_status: str
changed_by_user_id: int | None = None
comment: str | None = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class WorkOrderCorrectionCreate(BaseModel):
reason: str = Field(min_length=3, max_length=4000)
proposed_changes: dict | None = None
owner_approval_required: bool = True
class WorkOrderCorrectionRead(WorkOrderCorrectionCreate):
id: int
service_visit_id: int
requested_by_user_id: int | None = None
status: str
created_version: int
resolved_at: datetime | None = None
created_at: datetime
model_config = ConfigDict(from_attributes=True)