feat(web): dashboard compact — import pe Acasa, status cu bife, Trimiteri lizibile, Mapari complete (3.5)
Acasa = ecran de import (tab Import scos, ?tab=import->Acasa). Bara status compacta pe 2 randuri cu bife accesibile (glife + text) + data formatata. 'Coada'->'Trimiteri': coloane RO, stare umana, detaliu la click in panou dedicat. Mapari pe 3 sectiuni (de rezolvat / op salvate / formate coloane), Cont doar cheie+creds. Filtrare Trimiteri, corectie inline needs_data cu re-enqueue + detectie coliziune idempotency, badge contoare pe tab-uri. Helper pur partajat payload_view.py (web + GET /v1/prezentari). Backend trimitere (worker/idempotenta/mapping/schema) neatins. 483 teste. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,8 @@ Functii pure: fara DB, fara request. Usor de testat unitar si de importat in tem
|
||||
Sursa de adevar pentru texte: tabelul din PRD 3.4 §3 US-001.
|
||||
"""
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from typing import Tuple
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -119,6 +121,80 @@ def eticheta_rar(stare: str) -> Eticheta:
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Format data RAR (US-001, PRD 3.5)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def format_data_rar(raw: object) -> str:
|
||||
"""Formateaza un timestamp ISO ca `dd.mm.yyyy hh24:mi:ss` (ora romaneasca).
|
||||
|
||||
- Valoare lipsa (None / "") -> "—".
|
||||
- ISO valid (cu sau fara timezone / 'Z' / microsecunde) -> data formatata,
|
||||
fara fractiuni de secunda.
|
||||
- Format invalid -> fallback grijuliu: intoarce stringul brut (nu arunca),
|
||||
ca operatorul sa vada totusi ceva, nu o pagina rupta.
|
||||
"""
|
||||
if raw is None:
|
||||
return "—"
|
||||
s = str(raw).strip()
|
||||
if not s:
|
||||
return "—"
|
||||
iso = s.replace("Z", "+00:00") if s.endswith("Z") else s
|
||||
try:
|
||||
dt = datetime.fromisoformat(iso)
|
||||
except (ValueError, TypeError):
|
||||
return s
|
||||
return dt.strftime("%d.%m.%Y %H:%M:%S")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Motiv uman din rar_error (US-004, PRD 3.5)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def motiv_uman(status: str, rar_error: object) -> str:
|
||||
"""Transforma `rar_error` (JSON tehnic) intr-un motiv lizibil pentru coloana Motiv.
|
||||
|
||||
Formele intalnite (vezi router.py / mapping.py):
|
||||
- validare continut: list[{field, message}] -> mesajele concatenate.
|
||||
- operatie nemapata: {"unmapped": [{cod_op_service, denumire}]}.
|
||||
- auto-send oprit: {"auto_send": "..."}.
|
||||
- eroare RAR: text simplu sau dict generic.
|
||||
Fara rar_error -> "". Nu arunca niciodata (degradeaza la text brut trunchiat).
|
||||
"""
|
||||
if not rar_error:
|
||||
return ""
|
||||
raw = rar_error if isinstance(rar_error, str) else str(rar_error)
|
||||
try:
|
||||
data = json.loads(raw)
|
||||
except (ValueError, TypeError):
|
||||
return raw[:160]
|
||||
|
||||
if isinstance(data, dict):
|
||||
if "unmapped" in data:
|
||||
ops = data.get("unmapped") or []
|
||||
nume = ", ".join(
|
||||
(o.get("cod_op_service") or "") for o in ops if isinstance(o, dict)
|
||||
).strip(", ")
|
||||
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)"
|
||||
parti = [f"{k}: {v}" for k, v in data.items()]
|
||||
return "; ".join(parti)[:200]
|
||||
|
||||
if isinstance(data, list):
|
||||
msgs: list[str] = []
|
||||
for e in data:
|
||||
if isinstance(e, dict):
|
||||
msgs.append(
|
||||
str(e.get("message") or e.get("msg") or "; ".join(str(v) for v in e.values()))
|
||||
)
|
||||
else:
|
||||
msgs.append(str(e))
|
||||
return "; ".join(m for m in msgs if m)[:200]
|
||||
|
||||
return str(data)[:160]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Constante auxiliare (microcopy fix, fara logica)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user