Dovezile masurate pentru propunerile de directie (09.2026)

Backtest read-only pe productie: recunoasterea articolului la importul de
eFactura, contarea pe istoric de furnizor, identificarea partenerului la
importul de extrase, plafonul potrivirii facturii din textul bancii.
Include harta codului de import extrase, testul care confirma eroarea de
parsare BT si scripturile SQL reproductibile.

Propunerile care se sprijina pe ele:
COMUN/docs/cercetare/rec_directie_roacont_2026_09.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T8jmGHs29e9eyLgoMiLBHW
This commit is contained in:
2026-09-03 14:19:16 +03:00
parent d4a9c800ff
commit f9af574877
12 changed files with 2088 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
# Backtest: identificarea partenerului la importul de extrase
Masurat 03.09.2026 pe serverul `10.0.20.36` (`ROA_ROMFAST`), conectat ca `ROMFAST`, citire
incrucisata pe schemele cabinetului. Doar `SELECT`. Datele extrase (denumiri de parteneri, IBAN-uri)
au ramas in directorul temporar al sesiunii, **nu sunt in repo**.
## Ce s-a masurat si de ce altfel decat prima data
Masuratoarea din `BACKTEST_VENDING.md` sectiunea 8 numara doar daca `ID_FACTD/ID_FACTC` e completat, si
a dat 100%. Cifra e reala, dar nu spune nimic: imperecherea o face operatorul, manual sau confirmand
propunerea importului. Nu exista tabel de audit - corectiile din `frm_modific2024` se fac inainte de
scrierea in `ACT` (`Programe\ocont2003.prg:1245-1257`).
Ce se poate face totusi: liniile venite din import sunt identificabile (`ID_SET = 90023`), iar textul
bancii se pastreaza in `ACT.EXPLICATIA`. Se ia fiecare linie in ordine cronologica, se aplica pe ea
regula (fara sa vada viitorul) si se compara cu partenerul care e efectiv inregistrat pe linie - adica
adevarul confirmat de operator. Asta e un backtest onest, nu o estimare.
Populatia: liniile de banca cu contrapartida 401/411 si partener completat, ultimele 12 luni incheiate.
**3.490 de linii, 7 firme.** Celelalte 14 firme ale cabinetului nu folosesc deloc importul de extras
(zero linii cu `ID_SET = 90023`).
## Rezultatul
| | linii pre-completate corect | acoperire | precizie |
|---|---|---|---|
| **Azi** (denumire de pe pozitie fixa, potrivire exacta) | 161 din 3.490 | **4,6%** | - |
| **Cheie invatata din istoric**, cu garda de unicitate | 974 din 3.490 | **28,5%** | **97,9%** |
Pe firme, varianta propusa:
| Firma | linii/an | gasite | precizie |
|---|---|---|---|
| ROMFAST (export Banca Transilvania) | 400 | 79,5% | 99,4% |
| COTOFANACONCEPT | 85 | 50,6% | 97,7% |
| PASS | 1.486 | 29,1% | 99,3% |
| INTERIOR | 187 | 16,6% | 83,9% |
| TURQUOISE | 1.176 | 13,2% | 96,1% |
| CERAMOTERM | 153 | 10,5% | 75,0% |
| CUX | 3 | 0% | - |
## Cum arata regula masurata
Pentru fiecare linie se construiesc doua chei: IBAN-ul, daca descrierea contine unul, si textul
descrierii normalizat (se taie tipul tranzactiei de la inceput, se sterg datele calendaristice si
toate cifrele, se pastreaza primele 24 de caractere). Se propune partenerul doar daca acea cheie a
aparut in istoricul firmei **si a dus de fiecare data la acelasi partener**. Daca cheia a fost
ambigua macar o data, nu se propune nimic.
Garda de unicitate nu e un detaliu: fara ea, aceeasi masuratoare da 58,3% acoperire dar **56,4%
precizie** - adica aproape jumatate din propuneri gresite, ceea ce ar face functia inutilizabila.
## De ce difera atat de mult intre firme
Nu tine de firma, tine de ce trimite banca in descriere.
- La ROMFAST (export Banca Transilvania) descrierea contine denumirea comerciantului sau a
partenerului: `INCASARE OP;FF 2026161;<DENUMIRE FURNIZOR> SRL;<IBAN>;...`. Cheia e stabila si
se invata dupa prima aparitie.
- La TURQUOISE si CERAMOTERM banca trimite doar numere de referinta:
`CV FACT NR 4463/02.12.2025 REFERINTA INSTANT: 1764758837752667950764`. Dupa stergerea cifrelor
ramane `CV FACT NR REFERINTA INS` - un text generic pe care il au 611 linii cu 76 de parteneri
diferiti. Garda de unicitate observa asta si **refuza sa propuna**, ceea ce e comportamentul corect.
Concluzia practica: regula se auto-regleaza dupa format. Acolo unde banca da informatie, propune mult
si bine; acolo unde nu da, tace. Nu are nevoie de configurare per banca.
## Doua constatari colaterale
**IBAN-ul extras de parser nu ajunge niciodata in baza.** Din 879 de linii importate la ROMFAST,
`EXPLICATIA4` (unde `Programe\oproceduri_import.prg:902` scrie IBAN-ul) e goala la 878. Iar in
nomenclator doar 174 din 3.880 de parteneri activi (4,5%) au `CONT_BANCA` completat. Deci cheia de
cautare dupa IBAN, care ar fi cea mai sigura, nu are azi de unde sa functioneze. Daca importul ar
salva IBAN-ul pe partener atunci cand operatorul confirma potrivirea, nomenclatorul s-ar umple singur
si cheia ar deveni utilizabila in cateva luni.
**Platile la POS sunt cazul cel mai prost tratat azi.** La ROMFAST sunt 115 linii pe an catre 33 de
comercianti distincti (abonamente software, magazine online, telecom). Parserul pune pe pozitia denumirii numele
**propriei firme** (`ROMFAST SRL`), deci cautarea de partener nu are cum sa reuseasca; denumirea reala
a comerciantului e in textul EPOS, care azi nu e folosit. Aceleasi linii, cu regula invatata: 70,4%
gasite la 95,1% precizie.
## Reproducere
Scripturile de extragere sunt in sesiune, nu in repo (contin denumiri de parteneri). Interogarea de
baza, per schema:
```sql
select to_char(a.dataact,'yyyy-mm-dd'),
case when substr(a.scd,1,3) in ('401','411') then pd.denumire else pc.denumire end,
a.explicatia
from <SCHEMA>.act a
left join <SCHEMA>.nom_parteneri pd on pd.id_part = a.id_partd
left join <SCHEMA>.nom_parteneri pc on pc.id_part = a.id_partc
where nvl(a.sters,0)=0 and nvl(a.id_set,0)=90023
and a.dataact >= add_months(trunc(sysdate,'MM'),-12) and a.dataact < trunc(sysdate,'MM')
and (substr(a.scd,1,3)='512' or substr(a.scc,1,3)='512')
and (substr(a.scd,1,3) in ('401','411') or substr(a.scc,1,3) in ('401','411'))
and (case when substr(a.scd,1,3) in ('401','411') then a.id_partd else a.id_partc end) > 0
order by a.dataact;
```
Capcana in care am cazut si eu: partenerul trebuie luat **de pe latura contului 401/411**, nu cu
`nvl(id_partd, id_partc)` - pe latura contului de banca partenerul e contul bancar al firmei, si
masuratoarea iese fals de buna.
---
## Limitele impuse de formate si de ce scriu bancile (masurat 03.09.2026)
Trei obiectii reale, verificate pe date, nu admise pe cuvant.
### 1. Bancile nu au acelasi format
Adevarat, si codul o arata: `ExtrasBanca_General::Parse` (`Programe\oproceduri_import.prg:1417`)
recunoaste dupa antet ~25 de formate CSV (Stripe, PayU, Intesa, Garanti, OTP, Raiffeisen, Unicredit,
ING, BT, PayPal, BRD, BCR, First Bank, CEC, MobilPay, Idea, CreditEurope, Alpha ...), plus MT940 si
doua formate XML.
Tocmai de asta cheia invatata din istoric e raspunsul potrivit: **nu depinde de format.** Cele 7 firme
masurate folosesc banci si formate diferite, iar aceeasi regula, fara nicio configurare per banca, a dat
79,5% la ROMFAST, 50,6% la COTOFANACONCEPT, 29,1% la PASS si 10-17% acolo unde banca nu trimite nimic
util. Nu trebuie scris cod pentru fiecare banca; regula invata ce trimite banca fiecarei firme.
### 2. Nu toate bancile completeaza codul fiscal al platitorului
Adevarat si masurabil in cod: din locurile unde parserele scriu in cursorul de import
(`oproceduri_import.prg`), o parte scriu doar denumirea (`Replace tert With ...`, ex. liniile 3579,
3944, 4131), altele scriu si IBAN, si doar unele scriu si codul fiscal (liniile 1618, 2080, 2746, 2824,
3244, 3908, 3984, 4047). La Banca Transilvania codul fiscal e fixat gol neconditionat
(`oproceduri_import.prg:3015`).
Consecinta: cheia cea mai sigura - codul fiscal - nu e disponibila la majoritatea formatelor, iar cheia
de rezerva - IBAN-ul - nu are pe ce lucra pentru ca nomenclatorul are IBAN doar la 4,5% dintre
parteneri. Ramane textul, si de aceea el trebuie invatat, nu citit de pe o pozitie fixa.
### 3. Nu toti scriu numarul documentului platit, si explicatiile sunt libere
**Aceasta e obiectia care schimba o concluzie.** Masurat pe 3.074 de linii de banca pe care operatorul
le-a legat de o factura, la cele 7 firme: numarul acelei facturi apare in textul bancii doar in **25,0%**
din cazuri. In 73,9% din cazuri textul contine numere, dar altele - referinte, numere de OP, coduri de
tranzactie.
| Firma | linii legate de factura | numarul facturii chiar e in text |
|---|---|---|
| TURQUOISE | 784 | 56,6% |
| ROMFAST | 317 | 46,4% |
| INTERIOR | 123 | 17,1% |
| CERAMOTERM | 113 | 15,0% |
| COTOFANACONCEPT | 87 | 11,5% |
| PASS | 1.462 | 8,8% |
| CUX | 188 | 0% |
Deci **plafonul teoretic** al oricarei imbunatatiri care cauta factura dupa numarul din explicatie este
25%, si la unele firme aproape zero. Operatorul nu citeste numarul din text - el stie din suma, din
partener si din soldul deschis care factura se achita.
Alternativa masurata: dupa ce partenerul e cunoscut, cat de des suma platii identifica singura un
document?
| | linii | suma identifica exact un document | din care corect |
|---|---|---|---|
| toate cele 7 firme | 3.490 | **21,2%** | **89,9%** |
Si aici precizia e prea mica pentru completare automata (aproape una din zece gresita), iar in 7,0% din
linii suma se potriveste pe mai multe documente deodata.
**Concluzia care se schimba:** partea de factura a importului de extrase nu are un castig mare de
automatizare, indiferent cat de bine se scrie algoritmul - informatia lipseste din fisier in trei
sferturi din cazuri. Efortul merita mutat de la "gaseste factura singur" la "arata-i operatorului
lista scurta a documentelor deschise ale partenerului, ordonate dupa cat de bine se potriveste suma",
ca sa aleaga dintr-o lista in loc sa caute. Ceea ce face utila si aici imbunatatirea de la partener:
fara partener nu exista lista scurta.