Coverage for modules\trucking\schemas.py: 100%
236 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-06 17:01 +0800
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-06 17:01 +0800
1from typing import Optional, List
2from pydantic import BaseModel, ConfigDict
3from uuid import UUID
4from datetime import datetime, date
5from decimal import Decimal
8# ── Vehicle ────────────────────────────────────────────────────────────────────
9class VehicleIn(BaseModel):
10 plate_number: str
11 vin: Optional[str] = None
12 vehicle_type: str = "TRUCK"
13 make: Optional[str] = None
14 model: Optional[str] = None
15 year: Optional[int] = None
16 capacity_tons: Decimal = Decimal("0.00")
17 fuel_type: Optional[str] = None
18 status: str = "ACTIVE"
19 current_odometer: int = 0
20 image_url: Optional[str] = None
21 notes: Optional[str] = None
24class VehicleOut(BaseModel):
25 id: UUID
26 plate_number: str
27 vin: Optional[str] = None
28 vehicle_type: str
29 make: Optional[str] = None
30 model: Optional[str] = None
31 year: Optional[int] = None
32 capacity_tons: Decimal
33 fuel_type: Optional[str] = None
34 status: str
35 current_odometer: int
36 image_url: Optional[str] = None
37 notes: Optional[str] = None
38 created_at: datetime
39 updated_at: datetime
41 model_config = ConfigDict(from_attributes=True)
44# ── Driver ─────────────────────────────────────────────────────────────────────
45class DriverIn(BaseModel):
46 first_name: str
47 last_name: str
48 email: Optional[str] = None
49 phone: Optional[str] = None
50 license_number: Optional[str] = None
51 license_type: Optional[str] = None
52 license_expiry: Optional[date] = None
53 date_of_birth: Optional[date] = None
54 hire_date: Optional[date] = None
55 status: str = "ACTIVE"
56 address: Optional[str] = None
57 emergency_contact: Optional[str] = None
58 emergency_phone: Optional[str] = None
59 notes: Optional[str] = None
62class DriverOut(BaseModel):
63 id: UUID
64 first_name: str
65 last_name: str
66 full_name: str
67 email: Optional[str] = None
68 phone: Optional[str] = None
69 license_number: Optional[str] = None
70 license_type: Optional[str] = None
71 license_expiry: Optional[date] = None
72 date_of_birth: Optional[date] = None
73 hire_date: Optional[date] = None
74 status: str
75 address: Optional[str] = None
76 emergency_contact: Optional[str] = None
77 emergency_phone: Optional[str] = None
78 notes: Optional[str] = None
79 created_at: datetime
80 updated_at: datetime
82 model_config = ConfigDict(from_attributes=True)
85# ── Fuel Card ──────────────────────────────────────────────────────────────────
86class FuelCardIn(BaseModel):
87 card_number: str
88 vehicle_id: Optional[UUID] = None
89 driver_id: Optional[UUID] = None
90 pin: Optional[str] = None
91 daily_limit: Decimal = Decimal("0.00")
92 is_active: bool = True
93 expiry_date: Optional[date] = None
96class FuelCardOut(BaseModel):
97 id: UUID
98 card_number: str
99 vehicle_id: Optional[UUID] = None
100 driver_id: Optional[UUID] = None
101 pin: Optional[str] = None
102 daily_limit: Decimal
103 is_active: bool
104 expiry_date: Optional[date] = None
105 created_at: datetime
106 updated_at: datetime
108 model_config = ConfigDict(from_attributes=True)
111# ── Fuel Log ───────────────────────────────────────────────────────────────────
112class FuelLogIn(BaseModel):
113 vehicle_id: UUID
114 driver_id: Optional[UUID] = None
115 fuel_card_id: Optional[UUID] = None
116 odometer: int
117 liters: Decimal
118 price_per_liter: Decimal
119 total_cost: Decimal
120 location: Optional[str] = None
121 invoice_number: Optional[str] = None
122 notes: Optional[str] = None
125class FuelLogOut(BaseModel):
126 id: UUID
127 vehicle_id: UUID
128 driver_id: Optional[UUID] = None
129 fuel_card_id: Optional[UUID] = None
130 odometer: int
131 liters: Decimal
132 price_per_liter: Decimal
133 total_cost: Decimal
134 location: Optional[str] = None
135 invoice_number: Optional[str] = None
136 notes: Optional[str] = None
137 created_at: datetime
138 updated_at: datetime
140 model_config = ConfigDict(from_attributes=True)
143# ── Maintenance Log ────────────────────────────────────────────────────────────
144class MaintenanceLogIn(BaseModel):
145 vehicle_id: UUID
146 maintenance_type: str = "SCHEDULED"
147 description: str
148 cost: Decimal = Decimal("0.00")
149 vendor: Optional[str] = None
150 invoice_number: Optional[str] = None
151 next_service_odometer: Optional[int] = None
152 next_service_date: Optional[date] = None
153 completed_at: Optional[datetime] = None
154 is_completed: bool = False
157class MaintenanceLogOut(BaseModel):
158 id: UUID
159 vehicle_id: UUID
160 maintenance_type: str
161 description: str
162 cost: Decimal
163 vendor: Optional[str] = None
164 invoice_number: Optional[str] = None
165 next_service_odometer: Optional[int] = None
166 next_service_date: Optional[date] = None
167 completed_at: Optional[datetime] = None
168 is_completed: bool
169 created_at: datetime
170 updated_at: datetime
172 model_config = ConfigDict(from_attributes=True)
175# ── Trip ───────────────────────────────────────────────────────────────────────
176class TripIn(BaseModel):
177 vehicle_id: UUID
178 driver_id: UUID
179 origin: str
180 destination: str
181 distance_km: Decimal = Decimal("0.00")
182 cargo_description: Optional[str] = None
183 cargo_weight_tons: Decimal = Decimal("0.00")
184 status: str = "PLANNED"
185 planned_departure: Optional[datetime] = None
186 planned_arrival: Optional[datetime] = None
187 fuel_cost: Decimal = Decimal("0.00")
188 tolls_cost: Decimal = Decimal("0.00")
189 other_costs: Decimal = Decimal("0.00")
190 notes: Optional[str] = None
193class TripOut(BaseModel):
194 id: UUID
195 vehicle_id: UUID
196 driver_id: UUID
197 origin: str
198 destination: str
199 distance_km: Decimal
200 cargo_description: Optional[str] = None
201 cargo_weight_tons: Decimal
202 status: str
203 planned_departure: Optional[datetime] = None
204 actual_departure: Optional[datetime] = None
205 planned_arrival: Optional[datetime] = None
206 actual_arrival: Optional[datetime] = None
207 fuel_cost: Decimal
208 tolls_cost: Decimal
209 other_costs: Decimal
210 total_cost: Decimal
211 notes: Optional[str] = None
212 created_at: datetime
213 updated_at: datetime
215 model_config = ConfigDict(from_attributes=True)
218# ── Delivery ───────────────────────────────────────────────────────────────────
219class DeliveryIn(BaseModel):
220 trip_id: Optional[UUID] = None
221 tracking_number: str
222 recipient_name: str
223 recipient_phone: Optional[str] = None
224 recipient_email: Optional[str] = None
225 delivery_address: str
226 city: str
227 province: Optional[str] = None
228 postal_code: Optional[str] = None
229 country: str = "Philippines"
230 package_description: Optional[str] = None
231 package_weight_kg: Decimal = Decimal("0.00")
232 number_of_packages: int = 1
233 status: str = "PENDING"
234 priority: str = "NORMAL"
235 scheduled_date: Optional[date] = None
236 scheduled_time_window_start: Optional[datetime] = None
237 scheduled_time_window_end: Optional[datetime] = None
238 reference_number: Optional[str] = None
241class DeliveryOut(BaseModel):
242 id: UUID
243 trip_id: Optional[UUID] = None
244 tracking_number: str
245 recipient_name: str
246 recipient_phone: Optional[str] = None
247 recipient_email: Optional[str] = None
248 delivery_address: str
249 city: str
250 province: Optional[str] = None
251 postal_code: Optional[str] = None
252 country: str
253 package_description: Optional[str] = None
254 package_weight_kg: Decimal
255 number_of_packages: int
256 status: str
257 priority: str
258 scheduled_date: Optional[date] = None
259 scheduled_time_window_start: Optional[datetime] = None
260 scheduled_time_window_end: Optional[datetime] = None
261 actual_delivery_time: Optional[datetime] = None
262 signature_url: Optional[str] = None
263 photo_urls: List[str] = []
264 delivery_notes: Optional[str] = None
265 recipient_signature_name: Optional[str] = None
266 reference_number: Optional[str] = None
267 proof_of_delivery_received: bool
268 created_at: datetime
269 updated_at: datetime
271 model_config = ConfigDict(from_attributes=True)
274class DeliveryUpdateProof(BaseModel):
275 """Schema for updating proof of delivery."""
276 signature_url: Optional[str] = None
277 photo_urls: Optional[List[str]] = None
278 delivery_notes: Optional[str] = None
279 recipient_signature_name: Optional[str] = None
280 actual_delivery_time: Optional[datetime] = None
281 proof_of_delivery_received: bool = True