# Reconciliere facturi manuale ROA ↔ comenzi GoMag **Script:** [`scripts/relink_manual_invoices.py`](../scripts/relink_manual_invoices.py) **Launcher Windows:** [`scripts/relink_manual_invoices.bat`](../scripts/relink_manual_invoices.bat) ## Cand se foloseste Cand Oracle pool / sync-ul **a fost cazut** (ex. dupa o pana de curent la VENDING) si operatorul a emis **facturi manual direct in ROA** in acel interval. Dupa ce aplicatia revine, importeaza aceleasi comenzi web in `COMENZI`, **dar** factura manuala nu se leaga de comanda → comanda ramane **nefacturata** in ROA si in dashboard, desi factura exista. Semnal: in dashboard apar comenzi „nefacturate" pentru clienti care au fost de fapt facturati, iar in `VANZARI` exista facturi cu `ID_COMANDA IS NULL`. ## Cauza tehnica | Flux | `VANZARI.ID_COMANDA` | `COMENZI.COMANDA_EXTERNA` | |------|----------------------|----------------------------| | Normal (app) | setat (leaga factura de comanda) | nr comanda GoMag | | Manual (operator, in downtime) | **NULL** | — | Dashboard-ul / cache-ul SQLite marcheaza o comanda „Facturat" doar daca exista `VANZARI ... WHERE id_comanda = AND sters = 0` (vezi `invoice_service.check_invoices_for_orders`). Factura manuala cu `ID_COMANDA NULL` nu e niciodata gasita → comanda apare nefacturata. `ID_FACT` (documentul fiscal) si `COMENZI.COMANDA_EXTERNA` sunt deja completate; **singura piesa lipsa e legatura `VANZARI → COMANDA`.** ## ⚠️ Facturi de depozit (walk-in) — NU se ating Operatorul emite zilnic si **facturi manuale legitime din depozit** (~20+/zi), fara nicio comanda online in spate. Acestea au tot `ID_COMANDA NULL`, dar **nu** trebuie legate de nimic. De aceea matching-ul e **conservator**: orice nu e o potrivire 1:1 sigura e raportat, niciodata legat automat. ## Cum potriveste Pentru fiecare factura orfana (`VANZARI.ID_COMANDA NULL`, `sters=0`, in fereastra `--days`) cauta o comanda GoMag nefacturata (in SQLite, cu `id_comanda` setat) cu: 1. **Total identic** (`TOTAL_CU_TVA` ≈ `order_total`, toleranta 0.01 lei), apoi 2. **acelasi partener** (`ID_PART` = `id_partener`) **SAU** 3. **nume potrivit** (token-overlap, tolereaza SRL/SC si ordinea cuvintelor) — acopera cazul in care operatorul a creat un **partener duplicat** la facturare. Verifica si ca acea comanda e activa in ROA (`sters=0`) si **nu** are deja factura (anti-dubla-facturare). ### Clasificare (in raport) | Eticheta | Ce inseamna | Actiune | |----------|-------------|---------| | `LINK` | potrivire 1:1 sigura | leaga (la `--apply`) | | `SKIP_NOMATCH` | nicio comanda online cu acel total | **factura de depozit — lasata neatinsa** | | `SKIP_AMBIGUOUS` | mai multe comenzi plauzibile, sau total potrivit dar partener+nume diferit | raportat pentru verificare manuala | | `SKIP_ALREADY` | comanda nu mai e activa / are deja factura | sarit | La aplicare: `UPDATE VANZARI SET ID_COMANDA = ` + populeaza `orders.factura_*` in SQLite, exact ca aplicatia (`update_order_invoice`). ## Utilizare Ruleaza **pe serverul de productie VENDING** (are nevoie de Oracle prod + `api/data/import.db` prod). Foloseste `app.config.settings` (deci `.env`-ul prod). ```bat REM din C:\gomag-vending\scripts relink_manual_invoices.bat REM dry-run, ultimele 3 zile (NU modifica) relink_manual_invoices.bat --apply REM aplica, cu confirmare relink_manual_invoices.bat --apply --yes REM aplica fara confirmare relink_manual_invoices.bat --days 7 REM alta fereastra ``` Dublu-click pe `.bat` = dry-run. `.bat`-ul seteaza mediul Oracle thick-mode (`TNS_ADMIN` + PATH instant client) ca `start.bat`. Direct cu Python (echivalent): ```bat set TNS_ADMIN=C:\roa\instantclient_11_2_0_2 set PATH=C:\app\Server\product\18.0.0\dbhomeXE\bin;%PATH% C:\gomag-vending\venv\Scripts\python.exe scripts\relink_manual_invoices.py --apply ``` Din containerul de dev, peste SSH: ```bash scp -P 22122 scripts/relink_manual_invoices.* gomag@79.119.86.134:C:/gomag-vending/scripts/ ssh -p 22122 gomag@79.119.86.134 'cmd /c "C:\gomag-vending\scripts\relink_manual_invoices.bat --days 3 < nul"' ``` **Workflow recomandat:** intai dry-run → verifica lista `LINK` si `SKIP_AMBIGUOUS` → apoi `--apply`. Cazurile `SKIP_AMBIGUOUS` se rezolva manual in ROA. ## Istoric Codifica reconcilierea din **2026-06-26** (pana de curent la VENDING): pool cazut ~09:07–10:25; 12 facturi manuale `TIP=1` (IDV 138191–138203 → comenzi 5419–5430) legate; 3 facturi de depozit corect excluse (CRISS VENDING, COFEE SEVEN TO GO, PANDELE MIOARA); 2 parteneri duplicati semnalati (CERBU, MILITARU). Vezi si: [oracle-schema-notes.md](oracle-schema-notes.md) (tabele `COMENZI`/`VANZARI`), sectiunea „Facturi & Cache" din [README](../README.md).