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

1from typing import Optional, List 

2from pydantic import BaseModel, ConfigDict 

3from uuid import UUID 

4from datetime import datetime, date 

5from decimal import Decimal 

6 

7 

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 

22 

23 

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 

40 

41 model_config = ConfigDict(from_attributes=True) 

42 

43 

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 

60 

61 

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 

81 

82 model_config = ConfigDict(from_attributes=True) 

83 

84 

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 

94 

95 

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 

107 

108 model_config = ConfigDict(from_attributes=True) 

109 

110 

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 

123 

124 

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 

139 

140 model_config = ConfigDict(from_attributes=True) 

141 

142 

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 

155 

156 

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 

171 

172 model_config = ConfigDict(from_attributes=True) 

173 

174 

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 

191 

192 

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 

214 

215 model_config = ConfigDict(from_attributes=True) 

216 

217 

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 

239 

240 

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 

270 

271 model_config = ConfigDict(from_attributes=True) 

272 

273 

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