feat(errors): erori pe 3 niveluri (problema+cauza+fix) pe API si UI (PRD 5.4)
Catalog central pur app/errors.py ca sursa unica cod->{problema,fix},
consumat de API+UI+worker. Aditiv (field/message pastrate la octet) +
rar_error stocat superset. Scope: fluxul de declarare; login/signup/CSRF
neatinse. labels.parse_erori degradeaza gratios; UI progresiv AA light+dark.
631 teste.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -178,6 +178,8 @@ def motiv_uman(status: str, rar_error: object) -> str:
|
||||
return f"Cod RAR lipsa pentru: {nume}" if nume else "Cod RAR lipsa"
|
||||
if "auto_send" in data:
|
||||
return "Necesita confirmare manuala (auto-send oprit pentru cod)"
|
||||
if "problema" in data:
|
||||
return str(data.get("problema") or "")[:200]
|
||||
parti = [f"{k}: {v}" for k, v in data.items()]
|
||||
return "; ".join(parti)[:200]
|
||||
|
||||
@@ -195,6 +197,102 @@ def motiv_uman(status: str, rar_error: object) -> str:
|
||||
return str(data)[:160]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# parse_erori — transforma rar_error in lista 3-niveluri (US-006, PRD 5.4)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def parse_erori(rar_error: object) -> list[dict]:
|
||||
"""Transforma `rar_error` (JSON stocat) intr-o lista de erori 3-niveluri.
|
||||
|
||||
Fiecare element al listei are cheile: problema, cauza, fix, field (sau None).
|
||||
Functie PURA — nu arunca niciodata exceptii; degradeaza gratios pe orice forma.
|
||||
|
||||
Forme recunoscute:
|
||||
- None / "" / falsy -> lista goala []
|
||||
- array imbogatit (au cod sau problema) -> un element per eroare
|
||||
- dict cu cod specific -> 1 element cu cele 3 niveluri din dict
|
||||
- dict fara cod (forma veche: unmapped / auto_send) -> 1 element cu problema din context
|
||||
- lista cu {field, message} fara cod -> degradare: problema=message, cauza/fix=""
|
||||
- string plain -> 1 element cu problema=text, cauza/fix=""
|
||||
- JSON corupt -> 1 element cu problema=text brut, cauza/fix=""
|
||||
"""
|
||||
if not rar_error:
|
||||
return []
|
||||
|
||||
raw = rar_error if isinstance(rar_error, str) else str(rar_error)
|
||||
|
||||
# Incercare parsare JSON
|
||||
try:
|
||||
data = json.loads(raw)
|
||||
except (ValueError, TypeError):
|
||||
# String plain sau JSON corupt: degradare gratuoasa
|
||||
return [{"problema": raw[:200], "cauza": "", "fix": "", "field": None}]
|
||||
|
||||
# --- Forma: array de erori ---
|
||||
if isinstance(data, list):
|
||||
rezultat = []
|
||||
for e in data:
|
||||
if not isinstance(e, dict):
|
||||
rezultat.append({"problema": str(e)[:200], "cauza": "", "fix": "", "field": None})
|
||||
continue
|
||||
# Eroare imbogatita (are cod sau problema)
|
||||
if e.get("cod") or e.get("problema"):
|
||||
rezultat.append({
|
||||
"problema": e.get("problema") or e.get("cod") or "",
|
||||
"cauza": e.get("cauza") or e.get("message") or "",
|
||||
"fix": e.get("fix") or "",
|
||||
"field": e.get("field"),
|
||||
})
|
||||
else:
|
||||
# Forma veche: {field, message} fara cod
|
||||
msg = str(e.get("message") or e.get("msg") or "; ".join(str(v) for v in e.values()))
|
||||
elem = {
|
||||
"problema": msg[:200],
|
||||
"cauza": "",
|
||||
"fix": "",
|
||||
"field": e.get("field"),
|
||||
}
|
||||
# Filtreaza elementele complet goale (problema/cauza/fix toate vide)
|
||||
if not (
|
||||
elem["problema"].strip() == ""
|
||||
and elem["cauza"].strip() == ""
|
||||
and elem["fix"].strip() == ""
|
||||
):
|
||||
rezultat.append(elem)
|
||||
return rezultat
|
||||
|
||||
# --- Forma: dict ---
|
||||
if isinstance(data, dict):
|
||||
# Dict imbogatit cu cod explicit
|
||||
if data.get("cod") or data.get("problema"):
|
||||
return [{
|
||||
"problema": data.get("problema") or data.get("cod") or "",
|
||||
"cauza": data.get("cauza") or "",
|
||||
"fix": data.get("fix") or "",
|
||||
"field": data.get("field"),
|
||||
}]
|
||||
# Dict vechi: unmapped
|
||||
if "unmapped" in data:
|
||||
ops = data.get("unmapped") or []
|
||||
coduri = ", ".join(
|
||||
(o.get("cod_op_service") or "") for o in ops if isinstance(o, dict)
|
||||
).strip(", ")
|
||||
problema = f"Cod RAR lipsa pentru: {coduri}" if coduri else "Cod RAR lipsa"
|
||||
return [{"problema": problema, "cauza": "", "fix": "", "field": None}]
|
||||
# Dict vechi: auto_send
|
||||
if "auto_send" in data:
|
||||
return [{"problema": "Necesita confirmare manuala (auto-send oprit pentru cod)",
|
||||
"cauza": "", "fix": "", "field": None}]
|
||||
# Dict generic necunoscut
|
||||
parti = "; ".join(f"{k}: {v}" for k, v in data.items())
|
||||
if not parti.strip():
|
||||
return []
|
||||
return [{"problema": parti[:200], "cauza": "", "fix": "", "field": None}]
|
||||
|
||||
# Scalar (nr, bool, etc.)
|
||||
return [{"problema": str(data)[:200], "cauza": "", "fix": "", "field": None}]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Constante auxiliare (microcopy fix, fara logica)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user