"""Modele Pydantic pentru suprafata API. ATENTIE: validarea completa (regex VIN ^[A-HJ-NPR-Z0-9]{17}$, nrInmatriculare, dataPrestatie ∈ [2024-12-01, azi] TZ Bucuresti, R-ODO/I-ODO -> odometruInitial obligatoriu, odometruInitial <= odometruFinal, normalizare strip/upper) este **T3** — aici sunt doar formele de baza. Vezi plan.md sect. 2 + roadmap T3. """ from __future__ import annotations from pydantic import BaseModel, Field, field_validator class RarCredentials(BaseModel): """Credentiale RAR per-cerere (vin de la ROAAUTO din Oracle). NU se stocheaza.""" email: str password: str class PrestatieItem(BaseModel): cod_prestatie: str = Field(..., description="cod din nomenclator RAR, ex. OE-1") @field_validator("cod_prestatie") @classmethod def _norm_cod(cls, v: str) -> str: return v.strip().upper() class PrezentareIn(BaseModel): """O prezentare de declarat la RAR. Pydantic doar NORMALIZEAZA aici (strip/upper pe vin/nrInm). Validarea de continut (regex VIN, interval data, R-ODO/I-ODO, odometru) e in app.validation.validate_prezentare si NU resping cererea — marcheaza `needs_data` (plan.md sect. 3). """ vin: str nr_inmatriculare: str data_prestatie: str # YYYY-MM-DD odometru_final: str # string per contract odometru_initial: str | None = None prestatii: list[PrestatieItem] sistem_reparat: str = "null" obs: str | None = None b64_image: str | None = None @field_validator("vin", "nr_inmatriculare") @classmethod def _norm_upper(cls, v: str) -> str: return v.strip().upper() @field_validator("data_prestatie", "odometru_final") @classmethod def _norm_strip(cls, v: str) -> str: return v.strip() class PrezentareRequest(BaseModel): """Body pentru POST /v1/prezentari — una sau mai multe prezentari + creds RAR.""" rar_credentials: RarCredentials prezentari: list[PrezentareIn] = Field(..., min_length=1) class SubmissionResult(BaseModel): submission_id: int status: str id_prezentare: int | None = None deduped: bool = False # True daca idempotency a intors un submission existent class PrezentariResponse(BaseModel): results: list[SubmissionResult]