feat(T5): editor web mapare operatii (hibrid + fuzzy + on-demand needs_mapping)
T5 reinterpretat: nu import DBF, ci editor web al maparii operatie ROAAUTO -> cod RAR, cu fuzzy lookup si validare de catre utilizator. - Contract hibrid: item prestatie accepta cod_prestatie (RAR direct, back-compat) SAU cod_op_service+denumire (mapat de gateway prin operations_mapping). - Ingestie: op intern necunoscut -> submission needs_mapping (nu pleaca la RAR); codul rezolvat se scrie inapoi in payload_json -> payload builder + worker neatinse. - Editor HTMX (_mapari.html + GET /_fragments/mapari, POST /mapari): listeaza op-urile nemapate, fuzzy preselecteaza codul RAR, save -> re-rezolvare automata (queued / needs_data). - Fuzzy: rapidfuzz.token_sort_ratio pe denumire normalizata (fara diacritice). - Nomenclator: seed fallback 18 coduri la boot (offline) + refresh live din worker. - Cont default id=1 cat timp auth API-key (CORE) nu exista (account_id NULL). - Endpointuri API: GET /v1/mapari/pending, POST /v1/mapari (respinge cod inexistent). - 15 teste noi (tests/test_mapping.py); 69 pass total. - Contract actualizat (docs/api-rar-contract.md), rapidfuzz==3.14.5 in requirements. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ obligatoriu, odometruInitial <= odometruFinal, normalizare strip/upper) este
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, Field, field_validator, model_validator
|
||||
|
||||
|
||||
class RarCredentials(BaseModel):
|
||||
@@ -19,12 +19,33 @@ class RarCredentials(BaseModel):
|
||||
|
||||
|
||||
class PrestatieItem(BaseModel):
|
||||
cod_prestatie: str = Field(..., description="cod din nomenclator RAR, ex. OE-1")
|
||||
"""O operatie de declarat. Contract hibrid (decis 2026-06-15):
|
||||
|
||||
ROAAUTO poate trimite FIE `cod_prestatie` (cod RAR direct, ex. OE-1), FIE
|
||||
`cod_op_service` (cod intern ROAAUTO) + `denumire` — pe care gateway-ul le
|
||||
mapeaza in cod RAR prin operations_mapping. Cel putin unul dintre
|
||||
cod_prestatie / cod_op_service e obligatoriu (shape -> 422 daca lipsesc ambele).
|
||||
"""
|
||||
|
||||
cod_prestatie: str | None = Field(None, description="cod din nomenclator RAR, ex. OE-1")
|
||||
cod_op_service: str | None = Field(None, description="cod intern operatie ROAAUTO (mapat -> cod RAR)")
|
||||
denumire: str | None = Field(None, description="denumirea operatiei ROAAUTO (pentru fuzzy lookup la mapare)")
|
||||
|
||||
@field_validator("cod_prestatie")
|
||||
@classmethod
|
||||
def _norm_cod(cls, v: str) -> str:
|
||||
return v.strip().upper()
|
||||
def _norm_cod(cls, v: str | None) -> str | None:
|
||||
return v.strip().upper() if v else None
|
||||
|
||||
@field_validator("cod_op_service", "denumire")
|
||||
@classmethod
|
||||
def _norm_op(cls, v: str | None) -> str | None:
|
||||
return v.strip() if v else None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _require_one(self) -> "PrestatieItem":
|
||||
if not self.cod_prestatie and not self.cod_op_service:
|
||||
raise ValueError("fiecare prestatie are nevoie de cod_prestatie sau cod_op_service")
|
||||
return self
|
||||
|
||||
|
||||
class PrezentareIn(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user