Files
roaauto/backend/app/vehicles/router.py
Marius Mutu 3a922a50e6 feat(backend): sync endpoints + all models + seed + order workflow
- All business models: Vehicle, Order, OrderLine, Invoice, Appointment,
  CatalogMarca/Model/Ansamblu/Norma/Pret/TipDeviz/TipMotor, Mecanic
- Sync endpoints: GET /sync/full, GET /sync/changes?since=, POST /sync/push
  with tenant isolation and last-write-wins conflict resolution
- Order CRUD with state machine: DRAFT -> VALIDAT -> FACTURAT
  Auto-recalculates totals (manopera + materiale)
- Vehicle CRUD: list, create, get, update
- Seed data: 24 marci, 11 ansamble, 6 tipuri deviz, 5 tipuri motoare, 3 preturi
- Alembic migration for all business models
- 13 passing tests (auth + sync + orders)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 17:31:02 +02:00

111 lines
3.1 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.base import uuid7
from app.db.models.vehicle import Vehicle
from app.db.session import get_db
from app.deps import get_tenant_id
from app.vehicles import schemas
router = APIRouter()
@router.get("")
async def list_vehicles(
tenant_id: str = Depends(get_tenant_id),
db: AsyncSession = Depends(get_db),
):
r = await db.execute(
select(Vehicle).where(Vehicle.tenant_id == tenant_id)
)
vehicles = r.scalars().all()
return [
{
"id": v.id,
"nr_auto": v.nr_inmatriculare,
"marca_id": v.marca_id,
"model_id": v.model_id,
"an": v.an_fabricatie,
"client_nume": v.client_nume,
}
for v in vehicles
]
@router.post("")
async def create_vehicle(
data: schemas.CreateVehicleRequest,
tenant_id: str = Depends(get_tenant_id),
db: AsyncSession = Depends(get_db),
):
vehicle = Vehicle(
id=uuid7(),
tenant_id=tenant_id,
nr_inmatriculare=data.nr_auto,
marca_id=data.marca_id,
model_id=data.model_id,
an_fabricatie=data.an_fabricatie,
vin=data.vin,
client_nume=data.proprietar_nume,
client_telefon=data.proprietar_telefon,
)
db.add(vehicle)
await db.commit()
return {"id": vehicle.id}
@router.get("/{vehicle_id}")
async def get_vehicle(
vehicle_id: str,
tenant_id: str = Depends(get_tenant_id),
db: AsyncSession = Depends(get_db),
):
r = await db.execute(
select(Vehicle).where(
Vehicle.id == vehicle_id, Vehicle.tenant_id == tenant_id
)
)
v = r.scalar_one_or_none()
if not v:
raise HTTPException(status_code=404, detail="Vehicle not found")
return {
"id": v.id,
"nr_auto": v.nr_inmatriculare,
"marca_id": v.marca_id,
"model_id": v.model_id,
"an": v.an_fabricatie,
"vin": v.vin,
"client_nume": v.client_nume,
"client_telefon": v.client_telefon,
"client_email": v.client_email,
}
@router.put("/{vehicle_id}")
async def update_vehicle(
vehicle_id: str,
data: schemas.UpdateVehicleRequest,
tenant_id: str = Depends(get_tenant_id),
db: AsyncSession = Depends(get_db),
):
r = await db.execute(
select(Vehicle).where(
Vehicle.id == vehicle_id, Vehicle.tenant_id == tenant_id
)
)
v = r.scalar_one_or_none()
if not v:
raise HTTPException(status_code=404, detail="Vehicle not found")
update_data = data.model_dump(exclude_unset=True)
if "nr_auto" in update_data:
update_data["nr_inmatriculare"] = update_data.pop("nr_auto")
if "proprietar_nume" in update_data:
update_data["client_nume"] = update_data.pop("proprietar_nume")
if "proprietar_telefon" in update_data:
update_data["client_telefon"] = update_data.pop("proprietar_telefon")
for key, value in update_data.items():
setattr(v, key, value)
await db.commit()
return {"ok": True}