M1: implement operational core
Demo auth, seed import/reset, dashboard, vehicle/booking list+detail, audit trail. Backend: 19 tests passing, ruff clean. Frontend: React Router shell, typed API client, responsive pages. Verified end-to-end via curl and browser.
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
Role = Literal["operations_manager", "rental_employee"]
|
||||
|
||||
|
||||
class DemoLoginRequest(BaseModel):
|
||||
role: Role
|
||||
|
||||
|
||||
class CurrentUser(BaseModel):
|
||||
public_ref: str
|
||||
display_name: str
|
||||
role: Role
|
||||
|
||||
|
||||
class VehicleOut(BaseModel):
|
||||
public_ref: str
|
||||
make: str
|
||||
model: str
|
||||
model_year: int
|
||||
registration_number: str
|
||||
location: str
|
||||
operational_status: str
|
||||
odometer_km: int
|
||||
next_service_km: int
|
||||
active: bool
|
||||
attention: bool = False
|
||||
|
||||
|
||||
class BookingSummaryOut(BaseModel):
|
||||
public_ref: str
|
||||
customer_ref: str
|
||||
vehicle_ref: str
|
||||
starts_at: datetime
|
||||
ends_at: datetime
|
||||
status: str
|
||||
|
||||
|
||||
class BookingOut(BookingSummaryOut):
|
||||
start_odometer_km: int | None
|
||||
end_odometer_km: int | None
|
||||
requirements_complete: bool
|
||||
customer_name: str
|
||||
|
||||
|
||||
class InspectionOut(BaseModel):
|
||||
public_ref: str
|
||||
booking_ref: str
|
||||
type: str
|
||||
fuel_level_percent: int
|
||||
cleanliness_ok: bool
|
||||
damage_reported: bool
|
||||
technical_warning: bool
|
||||
odometer_km: int
|
||||
completed_at: datetime
|
||||
|
||||
|
||||
class MaintenanceOut(BaseModel):
|
||||
public_ref: str
|
||||
occurred_at: datetime
|
||||
odometer_km: int
|
||||
category: str
|
||||
summary: str
|
||||
|
||||
|
||||
class DataQualityIssueOut(BaseModel):
|
||||
public_ref: str
|
||||
rule_type: str
|
||||
entity_type: str
|
||||
entity_ref: str
|
||||
severity: str
|
||||
status: str
|
||||
evidence: dict[str, Any]
|
||||
detected_at: datetime
|
||||
resolved_at: datetime | None = None
|
||||
|
||||
|
||||
class VehicleDetailOut(VehicleOut):
|
||||
bookings: list[BookingSummaryOut] = Field(default_factory=list)
|
||||
inspections: list[InspectionOut] = Field(default_factory=list)
|
||||
maintenance: list[MaintenanceOut] = Field(default_factory=list)
|
||||
quality_issues: list[DataQualityIssueOut] = Field(default_factory=list)
|
||||
|
||||
|
||||
class DashboardMetrics(BaseModel):
|
||||
available: int
|
||||
rented: int
|
||||
cleaning: int
|
||||
maintenance: int
|
||||
blocked: int
|
||||
open_quality_issues: int
|
||||
pending_or_failed_workflows: int
|
||||
|
||||
|
||||
class AttentionItem(BaseModel):
|
||||
kind: Literal["quality_issue", "vehicle"]
|
||||
severity: str
|
||||
title: str
|
||||
detail: str
|
||||
link_type: Literal["vehicle", "booking", "customer"]
|
||||
link_ref: str
|
||||
|
||||
|
||||
class TodayItem(BaseModel):
|
||||
kind: Literal["departure", "return"]
|
||||
booking_ref: str
|
||||
vehicle_ref: str
|
||||
scheduled_at: datetime
|
||||
|
||||
|
||||
class AutomationRunOut(BaseModel):
|
||||
event_id: str
|
||||
event_type: str
|
||||
aggregate_ref: str
|
||||
status: str
|
||||
attempts: int
|
||||
last_error: str | None
|
||||
occurred_at: datetime
|
||||
|
||||
|
||||
class DashboardOut(BaseModel):
|
||||
metrics: DashboardMetrics
|
||||
attention_items: list[AttentionItem]
|
||||
today: list[TodayItem]
|
||||
recent_automation: list[AutomationRunOut]
|
||||
|
||||
|
||||
class AuditEventOut(BaseModel):
|
||||
id: str
|
||||
actor_type: str
|
||||
actor_label: str
|
||||
action: str
|
||||
entity_type: str
|
||||
entity_id: str | None
|
||||
correlation_id: str
|
||||
occurred_at: datetime
|
||||
metadata: dict[str, Any] | None = None
|
||||
Reference in New Issue
Block a user