feat(anaf-dedup): ANAF partner dedup + address fix + UI enrichment
Prevent partner duplicates via ANAF CUI verification and dual PL/SQL search. Fix address matching with street-level comparison and diacritics normalization. Show partner/address comparison in order detail modal. - New anaf_service.py: batch ANAF API client with chunking, retry, cache - PL/SQL: dual CUI search (bare/RO+bare/RO space+bare), 3-tier address search (street+city+id_loc → city+id_loc → create), strip_diacritics at storage for addresses and partner names - SQLite: anaf_cache table, 12 new order columns for partner/address data - import_service: cod_fiscal_override param, return partner/address from Oracle - sync_service: ANAF batch integration, denomination mismatch detection, cache pre-population trigger - Router: enriched order_detail with partner_info + addresses JSON - UI: collapsible Detalii Partener + Adrese Comparativ sections in modal, auto-expand on mismatch, ANAF badges, mobile address cards - Dashboard: address quality attention indicator - New scan_duplicate_partners.py script for one-time duplicate audit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1095,3 +1095,93 @@ tr.mapping-deleted td {
|
||||
color: var(--info);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ── Partner/Address section headers (ANAF dedup) ── */
|
||||
.detail-section-header {
|
||||
font-family: var(--font-display);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--text-secondary);
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.detail-section-header:hover { color: var(--text-primary); }
|
||||
.detail-section-header .bi-chevron-right {
|
||||
transition: transform 150ms ease-out;
|
||||
font-size: 10px;
|
||||
}
|
||||
.detail-section-header[aria-expanded="true"] .bi-chevron-right {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.detail-section-header .alert-count {
|
||||
font-family: var(--font-body);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
background: var(--error-light);
|
||||
color: var(--error-text);
|
||||
padding: 2px 8px;
|
||||
border-radius: 9999px;
|
||||
margin-left: auto;
|
||||
}
|
||||
.detail-section-body { padding: 12px 0; }
|
||||
.partner-row { display: flex; gap: 24px; flex-wrap: wrap; margin-bottom: 8px; }
|
||||
.partner-field { min-width: 140px; }
|
||||
.partner-label {
|
||||
font-family: var(--font-display);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.partner-value {
|
||||
font-family: var(--font-data);
|
||||
font-size: 13px;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.anaf-badge {
|
||||
display: inline-block;
|
||||
font-family: var(--font-body);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
padding: 2px 8px;
|
||||
border-radius: 9999px;
|
||||
}
|
||||
.anaf-badge-ok { background: var(--success-light); color: var(--success-text); }
|
||||
.anaf-badge-warn { background: var(--warning-light); color: var(--warning-text); }
|
||||
.anaf-badge-gray { background: var(--cancelled-light); color: var(--text-muted); }
|
||||
.addr-table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
||||
.addr-table th {
|
||||
font-family: var(--font-display);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-muted);
|
||||
padding: 6px 8px;
|
||||
text-align: left;
|
||||
}
|
||||
.addr-table td { padding: 8px; vertical-align: top; font-family: var(--font-body); }
|
||||
.addr-mismatch { background: var(--warning-light) !important; }
|
||||
.addr-efactura-risk { background: var(--error-light) !important; }
|
||||
.addr-label {
|
||||
font-family: var(--font-display);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
/* Mobile address cards */
|
||||
.addr-card { border: 1px solid var(--border); border-radius: var(--card-radius); margin-bottom: 8px; overflow: hidden; }
|
||||
.addr-card-header { padding: 6px 10px; font-family: var(--font-display); font-size: 11px; font-weight: 500; text-transform: uppercase; color: var(--text-secondary); background: var(--surface-raised); }
|
||||
.addr-card-row { padding: 8px 10px; }
|
||||
.addr-card-row + .addr-card-row { border-top: 1px dashed var(--border-subtle); }
|
||||
.addr-card-source { font-size: 11px; font-weight: 500; color: var(--text-muted); margin-bottom: 2px; }
|
||||
.addr-card-text { font-family: var(--font-body); font-size: 13px; }
|
||||
.addr-card.mismatch { border-left: 3px solid var(--warning); }
|
||||
.addr-card.match .addr-match-label { font-size: 11px; color: var(--success-text); }
|
||||
|
||||
Reference in New Issue
Block a user