Etapa 2: plan v3, rapoarte de cercetare si etalonul de regresie

Cercetare: ambele formate SAGA (VFP xls/xlsx si Firebird .FDB), cu dovezi
fisier:linie in docs/raport_sursa_saga_xlsx.md si raport_exporturi_saga_noua.md.

Plan v3 dupa review de strategie si arhitectura: contract intern + trei
cititoare, mapare in doua fisiere cu proprietari diferiti, lane-uri.

Etalon de regresie anonimizat in tests/golden/ (sume si structura neatinse,
zero IBAN si zero cod fiscal real). Tabela de corespondenta ramane ignorata.

Iesirile de productie ies din git (raman pe disc); .gitignore acopera si
copiile de baze de client si iesirile intermediare ale convertorului.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYeAtVxeS8m4oXekjX8Am2
This commit is contained in:
2026-09-21 15:44:57 +03:00
parent ceab089281
commit 15bb26ac15
23 changed files with 2085 additions and 191 deletions

395
docs/review_eng_etapa2.md Normal file
View File

@@ -0,0 +1,395 @@
# Review eng - plan etapa 2 (`docs/plan_etapa2_convertor.md`, PROPUNERE v2)
Lane: `review-eng`. Analiza statica, read-only. Nu am modificat planul, nu am scris cod, nu am dat commit.
Am aplicat skill-ul `plan-eng-review` (SKILL.md + `sections/review-sections.md`) ca analiza: unde skill-ul
cere AskUserQuestion, am scris DECIZII DE LUAT (sectiunea 3). Sursa de adevar pentru fiecare afirmatie
de mai jos este un fisier citit; unde am presupus, scrie explicit "presupunere".
Fisiere citite: planul; `raport_sursa_saga_xlsx.md`; `raport_exporturi_saga_noua.md`; `decizii_import.md`;
`plan_solduri2roa.md`; `config_cont_ireg.md`; `raport_form_init_balanta.md`; `conturi_cu_analitice.md`;
`extract_balanta.py`; `genereaza_xlsx.py`; `.gitignore`; CLAUDE.md; git status/log.
---
## 0. Step 0 - Scope challenge (rezultat)
- **Ce exista deja si e refolosit corect**: `extract_balanta.py` (PDF, nemodificat - bine),
`genereaza_xlsx.py` (constructia BALANTA/FACTURA, ramane), sablonul `init_facturi_balanta_note.xlsx`,
conventiile `.TOATE`/`.RESTUL` din `conturi_roa.dbf` (`raport_sursa_saga_xlsx.md` 2.1-2.3), regulile
validate `decizii_import.md`. Planul nu reconstruieste ce exista - punct bun.
- **Minimum set**: planul e rezonabil de minimal (3 cititoare + mapare + integrare + regresie).
Nu am gasit scope creep mare. Etapa 3 (baza reala, gbak, Firebird pe retea) e corect lasata afara
(`plan_etapa2_convertor.md:172-180`).
- **Complexity check** (skill: 8+ fisiere / 2+ clase noi = smell): planul atinge ~6-8 module noi
(`citire_xlsx`, `citire_fdb`, `mapare`, `extrage`, `genereaza`, test) - la limita, nu peste.
Nu declanshez reducere de scope pe acest motiv.
- **Completeness check**: planul propune varianta completa pe hartie (poarta de identitate CSV,
regresie pe productie) - dar doua dintre porti nu sunt executabile cu artefactele actuale
(vezi C2, C3). Deci "complet" e declarat, nu livrabil.
- **Distribution check**: unealta interna, rulata de Marius pe masina lui. Nu necesita pipeline de
publicare. Corect lasat afara.
---
## 1. Scoruri pe dimensiunile skill-ului
| Dimensiune (din skill) | Nota | Ce ar aduce-o la maxim |
|---|---|---|
| Scope challenge | 8/10 | Sa declare explicit ce se pierde cand "un singur CSV" nu e suficient (parteneri, totaluri, rollup) - vezi C5, C11 |
| Architecture / data flow | 5/10 | Contract intern real (balanta + parteneri + facturi), nu un singur CSV; regula de rollup FDB specificata (C2, C11) |
| Code quality / DRY | 6/10 | Clarifica cine detine cont/acont (mapare vs `genereaza`), evita re-encodarea pct. 16 in doua locuri (C4, C9) |
| Test coverage | 4/10 | Golden fixtures comise in git + framework de test; altfel poarta de regresie si poarta FDB nu ruleaza (C3, C5, sec. 2.5) |
| Performance | 7/10 | Agregare in SQL (GROUP BY pe 3 intervale de data), nu `SELECT *` in Python; charset WIN1250 (C15) |
| Failure modes / esecuri tacute | 5/10 | Trateaza explicit: verificarea Totaluri care dispare tacut, SCADENT NULL, cod fiscal gol (C5, C6) |
| Diagrame | 8/10 | Diagrama de pipeline exista (`:35-39`); lipseste diagrama de forma a datelor per cititor (ce coloane intra/ies) |
| Outside voice (cross-model) | n/a | Nu am putut rula Codex/subagent in acest lane; nu e o nota, e o limita de mediu |
Verdict de ansamblu: **plan bun ca intentie, cu 3 gauri de executie care il opresc sa fie "gata"**
(poarta FDB fara regula, poarta de regresie fara fixture, sursa partenerilor care contrazice productia).
---
## 2. Constatari
Format: `[Px] (confidence N/10) ce e in plan / ce e in neregula / ce propun`.
### C1 [P1] (confidence 9/10) - `CONFIG_CONT_IREG` nu reproduce setul de parteneri validat
- **In plan**: `:119-122` - "Ce NU se configureaza aici: care conturi merg pe parteneri. Ramane
`CONFIG_CONT_IREG` din Oracle ... e sursa de adevar a ROACONT".
- **In neregula**: codul validat in productie foloseste alt set. `genereaza_xlsx.py:47-53`:
`PARTENER_BANCA={5121,5124}`, `PARTENER_SINTETIC={401,4092,4111,461,462,4551}`,
`PARTENER_FARA_ANALITICE={5311}`. In `config_cont_ireg.md:89-91` (CU_INREGISTRARI=1) **nu apar
5121, 5124, 5311**, iar in lista Oracle apar 404,408,4091-4094,418,419 etc. pe care `genereaza`
NU le trateaza ca parteneri. Deci: daca unealta decide partenerii doar din Oracle, 5121/5124/5311
(decisiuni validate, `decizii_import.md` pct. 14-15) devin conturi obisnuite -> regresie tacuta pe
MASTER (`5121.01 PIRAEUS`).
- **Propun**: sursa de adevar operationala = o lista in repo, derivata din setul validat + reconciliata
explicit cu `CONFIG_CONT_IREG`; Oracle ramane consultativ. Documenteaza divergenta (Oracle listeaza
trezoreriile ca `CU_INREGISTRARI=0`, dar `decizii_import.md:52-55` arata ca formularul are liste
hardcodate separate `:1104`/`:1107`).
### C2 [P1] (confidence 9/10) - agregarea REGISTRU pentru balanta e sub-specificata; poarta de identitate nu e demonstrabila
- **In plan**: `:62-64` - "balanta: agregare pe `REGISTRU` la data ceruta" si `:75` - "cititorul 3 (FDB)
si cititorul 2 (xlsx) trebuie sa produca acelasi CSV".
- **In neregula**: (a) balanta exportului are 4 marimi, nu una: `DEB_INIT/CRED_INIT` (inceput de an),
`DEB_PREC/CRED_PREC` (inceput de perioada), `RULAJ_*` (perioada), `FIN_*` (sold) - deci sunt necesare
**doua praguri de data**, nu unul (`raport_exporturi_saga_noua.md` C.4:288-297 o arata pe cazul
`641` din 2025-11-30 -> `DEB_INIT`). (b) exportul **ruleaza analiticul in sintetic**: `REGISTRU` are
`401.00002`, exportul are `401` (`C.4:294,298-301`), iar `C.5:303-304` spune explicit ca "regula exacta
de includere sintetic/analitic nu se poate stabili". Fara regula de rollup, agregarea din
`CONT_D/CONT_C` produce `401.00002`, iar CSV-ul nu e identic - testul pica din cauza regulii lipsa,
nu a unui bug de cititor.
- **Propun**: specifica algoritmul in plan (nu in cod): grupare pe sintetic (`stanga punctului`),
3 intervale de data (an, perioada, in perioada) + `FIN=PREC+RULAJ`; declara explicit ca testul pe
firma de joaca dovedeste doar cazul sintetic (`:80-82`). Adauga in plan un al doilea prag (`an`).
### C3 [P1] (confidence 9/10) - poarta `regresie` nu are fixture comis in git
- **In plan**: `:167` - "xlsx-urile noi **identice** cu cele importate deja in productie";
`:154-156` - `.gitignore` ignora `init_*.xlsx` si "fisierele de productie au fost scoase cu
`git rm --cached`".
- **In neregula**: `git status` arata `D init_FUNDATIA_2025_12.xlsx`, `D init_MASTER_2025_12.xlsx`, iar
`.gitignore:6` ignora `init_*.xlsx`. Criteriul de terminare al lane-ului de regresie compara cu
fisiere care nu sunt in repo -> pe alt checkout/masina poarta nu se poate rula, iar rezultatul nu e
reproductibil nici de autor peste o luna.
- **Propun**: comite o copie golden sub `tests/golden/` (exceptie in `.gitignore`), sau un manifest de
hash-uri + regulile de numarare; atunci "identice" devine verificabil automat. PDF-urile sunt deja in
git (bine), dar output-ul-tinta lipseste.
### C4 [P1] (confidence 8/10) - "genereaza ia cont/acont din mapare" se bate cap in cap cu logica pastrata in cod
- **In plan**: `:143-146` - "singura schimbare de fond este ca ia `cont`/`acont` din mapare in loc sa le
calculeze"; `:103-104` - pre-completarea e generica ("primele max 4 caractere" + "cifrele
analiticului concatenate, max 4").
- **In neregula**: (a) randurile de diferenta NU exista in balanta, deci nu pot veni din mapare;
sunt calculate (`genereaza_xlsx.py:204-212,243-249`) - planul nu spune cine le mai emite. (b) forma
`acont` depinde de categorie: `401` -> acont gol, `5121` -> acont completat identic pe BALANTA si
FACTURA (`decizii_import.md` pct. 16; `genereaza_xlsx.py:219-249,252-283`). Regula generica de
pre-completare ar pune acont pe `401` -> chei diferite -> dublare tacuta (pct. 16).
- **Propun**: decide cine detine `acont`: ori pre-completarea din mapare e constienta de categorie
(partener -> pct. 16, analitic -> regula generica), ori `genereaza` ramane singurul care decide
forma pentru parteneri, iar maparea doar suprascrie. A doua e mai putin riscanta (codul deja validat).
### C5 [P2] (confidence 8/10) - verificarea "Totaluri" dispare tacut pe drumurile xlsx/FDB
- **In plan**: `:54` - `este_total = gol` pe exportul de foaie de calcul; `:56` - xls/xlsx nu au rand de
totaluri.
- **In neregula**: `genereaza_xlsx.py:89-94` cauta randul "Totaluri" si `:330,381-390` face cross-check-ul
net xlsx vs net Totaluri doar daca il gaseste. Pe drumurile noi `citeste_totaluri` intoarce `None`,
deci cea mai puternica verificare cap-la-cap se **omite silentios** - exact tiparul de esec tacut pe
care planul il interzice in alta parte.
- **Propun**: inlocuieste verificarea pierduta cu una echivalenta: pe FDB, `SUM(REGISTRU)` pe latura la
data ceruta = netul balantei (cifra de control reala); pe xlsx, re-calculeaza netul din coloanele
citite. Daca nu exista echivalent, scrie explicit in `verificare_<firma>.md` "verificare indisponibila",
nu o sari.
### C6 [P2] (confidence 8/10) - "cod fiscal real" si "scadenta reala" nu sunt garantate de baza
- **In plan**: `:65-66` - "Codul fiscal real vine de aici" si `:134` - FDB da "cod fiscal real si
scadenta reala ... nimic lipseste".
- **In neregula**: in baza de joaca, `FURNIZORI` are `***('00001','ROMFAST','','401.00001')***` - cod
fiscal **gol** (`raport_exporturi_saga_noua.md` C.3:264), iar singurul `INTRD` are `SCADENT=NULL`
(C.3:274). Deci "real" poate insemna gol/NULL pe date reale.
- **Propun**: pastreaza fallback-urile de azi (cod provizoriu `<cont>.<analitic>`, scadenta = ultima zi
a lunii) ca default cand FDB da NULL/gol, si raporteaza cate randuri au cazut pe fallback.
### C7 [P2] (confidence 7/10) - semantica `MANUAL` in merge e nedeclarata
- **In plan**: `:100` `stare` e "nu" (need editabila); `:114-117` - "randurile `MANUAL` raman intacte".
- **In neregula**: nu se spune **cine** si **cum** face trecerea `AUTO -> MANUAL`. Daca utilizatorul
editeaza `cont`/`acont`, cine observa? Cum se distinge o editare de o re-preluare a aceleiasi valori?
La a doua rulare, daca regula auto ar produce exact valoarea editata, randul ramane AUTO si poate fi
suprascris mai tarziu. De asemenea: un MANUAL care devine `DISPARUT` si reapare - ce stare are?
- **Propun**: defineste regula (ex.: orice modificare a `cont`/`acont`/`exclus` fata de valoarea
pre-completata marcheaza `MANUAL`; `stare` devine `READONLY`), si trateaza revenirea `DISPARUT -> MANUAL`.
### C8 [P2] (confidence 8/10) - regula de coliziune se bate cu `.TOATE`/`.RESTUL`
- **In plan**: `:148-150` - opreste cu eroare daca "doua randuri produc acelasi `(cont, acont)` fara sa
fie acelasi cont SAGA"; `:106-109` - `<sintetic>.TOATE` = toate analiticele merg pe acelasi `(cont,
acont)` ROA.
- **In neregula**: `.TOATE`/`.RESTUL` sunt **agregare intentionata** a mai multor conturi SAGA pe aceeasi
cheie ROA, exact ce regula de mai sus declara eroare. Asa cum e scris, tool-ul se opreste pe cazul
suportat. In plus, pentru conturile-partener `acont` e irelevant (pct. 16) - nu trebuie sa intre in
verificarea de coliziune.
- **Propun**: scuteste agregarea intentionata (acelasi `cont_saga` de baza sub `.TOATE`/`.RESTUL`) si
exclude partenerii din verificarea de coliziune; raporteaza doar coliziunile neintentionate.
### C9 [P2] (confidence 7/10) - redenumirea sinteticului (`409 -> 4091`) nu vine din noul mapare
- **In plan**: `:106-112` preia doar `.TOATE`/`.RESTUL` din `conturi_roa.dbf`; pre-completarea `:103-104`
copiaza sinteticul SAGA.
- **In neregula**: `raport_sursa_saga_xlsx.md` 2.1/2.3 arata ca `conturi_roa.dbf` face si redenumire de
sintetic (`409 -> 4091`, `431 -> 4311`, `4374 -> 4371`). Regula de pre-completare nu o produce, deci
o firma cu `409` iese cu `cont=409` in loc de `4091`. Ramane corectabila manual, dar planul pretinde
reutilizare.
- **Propun**: semeneaza maparea din `conturi_roa.dbf` cand exista (CONT2/ACONT2), sau adauga tabela de
redenumire explicita.
### C10 [P2] (confidence 8/10) - selectia foii nu e specificata si difera intre surse
- **In plan**: `:48-56` (cititorul 2) nu spune cum alege foaia; `raport_sursa_saga_xlsx.md` spune ca
foaia VFP se numeste `balanta`, iar `raport_exporturi_saga_noua.md` A.2:110 spune `xl` (xls) vs
`Sheet1` (xlsx).
- **In neregula**: un cititor care cauta fix `Sheet1` pica pe exportul VFP; unul care ia `active` pica
pe fisiere cu foi ascunse.
- **Propun**: alege prima foaie, sau cauta dupa nume in lista cunoscuta, cu eroare clara daca nu exista.
### C11 [P2] (confidence 7/10) - "un singur CSV intern" nu e suficient pentru nivelul 3-4 de FACTURA
- **In plan**: `:41-42` - "Restul lantului nu stie din ce sursa vine"; dar `:136` parametri
`--furnizori/--clienti/--facturi/--fdb` intra in **generator**, nu in cititor.
- **In neregula**: numele partenerului, codul fiscal real si detaliul de factura nu stau in CSV-ul de
balanta; sunt intrari separate. Diagrama `:35-39` sugereaza un singur flux, iar contractul real are
3 intrari. Nu e fatal, dar planul se contrazice si ascunde o dependenta.
- **Propun**: scrie contractul real: `balanta_<FIRMA>.csv` + optional `parteneri_<FIRMA>.csv` +
optional `facturi_<FIRMA>.csv`; `genereaza` accepta cele doua optionale si degradeaza la nivelul
corespunzator (`:124-134`).
### C12 [P3] (confidence 7/10) - coloana `TIP` (a 13-a) nu are consumator
- **In plan**: `:55` - "Coloana `TIP` (A/P) se duce in CSV ca a 13-a coloana, optionala".
- **In neregula**: `genereaza_xlsx.py` nu citeste niciodata `TIP`; natura D/C vine din latura hardcodata
(`:43`) si din net. Deci coloana e greutate moarta sau scop nedeclarat.
- **Propun**: fie o lasi afara, fie ii dai un consumator concret (ex. validare latura/cont de partener).
### C13 [P3] (confidence 6/10) - facturile de clienti din FDB sunt speculativ specificate
- **In plan**: `:67-68` - `IESIRI`/`IES_DET` -> facturi clienti.
- **In neregula**: `raport_exporturi_saga_noua.md` C.3:280 da `IESIRI` (0 randuri) si `IES_DET` cu
structura "-" (necunoscuta); firma are 0 clienti. Deci SQL-ul de facturi clienti e presupunere.
- **Propun**: marcheaza partea de clienti ca neverificata si nu o promite ca livrabil pana nu ai o baza
reala (Etapa 3, `:175`).
### C14 [P3] (confidence 6/10) - Oracle (retea + credentiale) intr-un flux de fisiere offline
- **In plan**: `:119-122` - partenerii vin din `CONFIG_CONT_IREG` (Oracle local).
- **In neregula**: aduce o dependenta de DSN/VPN/tnsnames si de parola din
`D:\ROA\ROACONT\docs\oracle_parola_standard.secret` (`config_cont_ireg.md:7,17`) intr-o unealta care
altfel lucreaza doar pe fisiere. Esti pe acelasi LAN (`10.0.20.121`), deci e fezabil, dar adauga
moduri de esec (DNS, cont SQL*Plus, parola expirata) pentru un pas care se schimba rar.
- **Propun**: instantaneu versionat (`config/cont_ireg.csv`) regenerat de un script mic cand Oracle se
schimba; unealta citeste instantaneul offline. Vezi si C1.
### C15 [P3] (confidence 6/10) - performanta FDB si charset
- **In plan**: `:58-64` nu spune cum se agrega.
- **In neregula**: la clienti cu `REGISTRU` mare, `SELECT *` + agregare in Python e lent si consuma
memorie; iar `CONT_D/CONT_C` si denumirile au diacritice/CP1250.
- **Propun**: agregare in SQL (`GROUP BY cont, CASE pe intervale de data`), `charset=WIN1250`
(`raport_exporturi_saga_noua.md` C.2:230 foloseste deja WIN1250).
### C16 [P3] (confidence 5/10) - potrivirea numelor de coloane trebuie exacta, nu substring
- **In plan**: `:51-53` compara antetul case-insensitive.
- **In neregula**: exportul are si `DEB_PREC` si `DEB_PREC_1` (setul `_1`, `raport_sursa_saga_xlsx.md`
1.1). O potrivire prin `in`/startswith poate alege coloana gresita tacut.
- **Propun**: normalizeaza si compara egalitate exacta dupa nume; ignora explicit coloanele `_1`.
---
## 2.5 Test review (per lane - ce test automat lasa fiecare)
Azi nu exista niciun test (`tests/` lipseste; `pytest` neinstalat, verificat). Skill-ul cere 100%
acoperire; propun concret pentru fiecare lane:
| Lane | Test lasat in urma | Observatie |
|---|---|---|
| `citire-xlsx` | `tests/test_citire_xlsx.py`: CSV produs din `exemple/saga-sqlite-balanta-09-2026.xlsx` == CSV golden comis; + relatiile `total=prec+rulaj`, `sold=total` pe toate randurile | Fixture e deja in git (`exemple/`) |
| `mapare` | `tests/test_mapare.py` pe functia de merge: MANUAL supravietuieste, analitic nou -> `NOU`, disparut -> `DISPARUT`, coliziune neintentionata -> Stop, `.TOATE` NU e coliziune | Pur logic, fara dependinte |
| `citire-fdb` | `tests/test_citire_fdb.py`: CSV produs din `D:\SAGA250909\0001\CONT_BAZA.FDB` == CSV golden comis (inghetat o data). Live, doar daca baza exista (skip motivat) | Baza nu e in repo -> testul depinde de mediu; de aceea ingheata CSV-ul |
| `integrare` | rulare cap-la-cap pe firma de joaca, comparatie cu xlsx golden | Necesita C3 |
| `regresie` | `tests/test_regresie.py`: `init_FUNDATIA_2025_12.xlsx` si `init_MASTER_2025_12.xlsx` regenerate == golden comis | Necesita C3 (altfel nu ruleaza) |
Problema transversala: **fara fixture comis (C3), 2 din 5 lane-uri nu pot demonstra criteriul de
terminare**. Recomand `unittest` din stdlib ca sa nu adaugi dependinte (CLAUDE.md: doar pdfplumber,
openpyxl, xlrd, firebird-driver), sau `pytest` acceptat explicit ca dependinta dev-only.
Acoperire estimata azi: 0%. Dupa cele 5 testuri de mai sus, portile reale ale planului devin
automate. Cazurile pe care planul insusi le declara neacoperite (`:80-83`: 0 analitice, 2 furnizori,
0 clienti, 1 factura) raman neacoperite pana la o baza reala (Etapa 3) - corect de raportat, nu de ascuns.
---
## 2.6 Failure modes (esec + test + eroare vizibila?) - cele fara test SI fara mesaj = critical gap
| Failure mode | Test? | Eroare clara? | Verdict |
|---|---|---|---|
| Rollup FDB analitic->sintetic gresit (C2) | Nu (poarta nu are regula) | Nu, iese un CSV diferit | **CRITICAL GAP** |
| Verificarea Totaluri dispare tacut (C5) | Nu | Nu | **CRITICAL GAP** |
| Regresie fara golden -> cineva crede ca a trecut (C3) | Nu | Nu | **CRITICAL GAP** |
| Editare MANUAL suprascrisa la a 2-a rulare (C7) | Nu | Nu | **CRITICAL GAP** |
| Coliziune `.TOATE` oprita ca eroare / coliziune reala ratata (C8) | Nu | Da (Stop) / Nu | Risc mediu |
| `fbclient.dll` lipsa / cale gresita | Nu | Da (exceptie driver) | Risc mic |
| Foaie gresita aleasa (C10) | Nu | Depinde | Risc mediu |
| Cod fiscal gol / SCADENT NULL din FDB (C6) | Nu | Nu (valoare proasta) | Risc mediu |
| Facturi clienti FDB pe structura necunoscuta (C13) | Nu | Nu | Risc mediu, amanat |
---
## 2.7 Required outputs (cerute de skill)
**NOT in scope** (plan `:16-17`, `:172-180`): import registru jurnal; balante lunare; nomenclator
parteneri lunar; baza `.FDB` reala; procedura `gbak` pentru client; Firebird prin retea. Corect
delimitat. De adaugat explicit: pipeline de distributie (nu exista, unealta interna) si testarea pe
analitice reale (amanata la Etapa 3).
**What already exists** (reutilizat): `extract_balanta.py` (nemodificat), `genereaza_xlsx.py`
(constructie + verificari), sablonul, `decizii_import.md`, `conturi_roa.dbf` (conventii), baza de joaca
+ exporturile din `exemple/`. Planul reutilizeaza bine; singurul lucru reconstruit inutil ar fi
`TIP` (C12) si, potential, setul de parteneri (C1).
**Diagrams**: exista diagrama de pipeline (`:35-39`). Lipseste o diagrama de forma a datelor: pentru
fiecare cititor, ce coloane intra si ce iese in CSV (utila exact pentru C5/C10/C11/C16).
**Worktree parallelization**:
| Step | Module | Depinde de |
|---|---|---|
| citire-xlsx | `citire_xlsx` | - |
| mapare | `mapare` | - |
| citire-fdb | `citire_fdb` | citire-xlsx (contract CSV comun) |
| integrare | `extrage`, `genereaza` | toate |
| regresie | `tests`, golden | integrare |
Lane A: citire-xlsx -> citire-fdb (secvential, contract comun). Lane B: mapare (independent).
Apoi integrare, apoi regresie. Fara conflict de module intre A si B. Planul are deja dependenta
`citire-fdb -> citire-xlsx` (`:165`), corect.
**Implementation Tasks** (sinteza):
- T1 (P1) - scrie regula de agregare/rollup FDB in plan (C2).
- T2 (P1) - comite golden fixtures pentru regresie (C3).
- T3 (P1) - reconciliaza setul de parteneri cu productia (C1).
- T4 (P1) - decide proprietarul `cont/acont` si trata diferentele (C4).
- T5 (P2) - inlocuieste verificarea Totaluri pe drumurile noi (C5).
- T6 (P2) - specifica merge-ul `MANUAL`/coliziuni/.TOATE (C7, C8).
- T7 (P2) - selectie foaie + fallback cod fiscal/scadenta (C6, C10).
---
## 3. DECIZII DE LUAT DE MARIUS
### D1 - Sursa setului de conturi cu parteneri
- **A)** Interogare Oracle `CONFIG_CONT_IREG` la fiecare rulare (retea + credentiale).
- **B)** Instantaneu versionat in repo (`config/cont_ireg.csv`), regenerat de un script mic; setul
operational (5121/5124/5311 etc.) adaugat explicit langa el. (recomandat)
- **C)** Hardcodeaza setul validat in `genereaza_xlsx.py`.
- **Recomandare: B** - offline pentru flux, dar totusi auditat si actualizabil; A aduce esecuri de
retea intr-un pas care se schimba rar; C e exact "lista hardcodata in `.prg`" pe care planul (`:121`)
vrea sa o evite. Motiv: explicitudine + portabilitate.
### D2 - Regula de agregare FDB (ca sa treaca poarta de identitate)
- **A)** Rollup la sintetic (stanga punctului) + 3 intervale de data; test pe firma de joaca dovedeste
doar sinteticul. (recomandat)
- **B)** Pastreaza analiticul ca atare si cere exportul SAGA tot la nivel analitic.
- **C)** Amaneaza FDB pana ai o baza reala cu analitice.
- **Recomandare: A** - e singurul mod in care poarta `:75` poate pica/trece pe datele existente;
C amana tot lane-ul, B muta problema la client.
### D3 - Fixture pentru poarta de regresie
- **A)** Comite copiile `init_FUNDATIA_2025_12.xlsx` / `init_MASTER_2025_12.xlsx` sub `tests/golden/`
(exceptie in `.gitignore`). (recomandat)
- **B)** Manifest de hash-uri + un CSV golden al continutului.
- **C)** Renunta la poarta de regresie.
- **Recomandare: A** - e poarta finala a planului (`:167-170`); fara fixture nu exista; continutul e
date de test validate in productie, nu secrete.
### D4 - Cine detine `cont`/`acont` si randurile de diferenta
- **A)** Maparea pre-completeaza constient de categorie (partener pct. 16 vs analitic), `genereaza` doar
citeste. (planul de azi)
- **B)** `genereaza` ramane singurul care decide forma pentru parteneri; maparea doar suprascrie;
randurile de diferenta raman calculate in cod. (recomandat)
- **C)** Reescrie `genereaza` complet pe mapare, inclusiv diferentele (rescriere mai mare).
- **Recomandare: B** - codul de parteneri e deja validat in productie (`decizii_import.md` pct. 16,
`genereaza_xlsx.py:219-303`); re-encodarea lui in generatorul de mapare dubleaza regula (DRY) si
risca regresia pe MASTER.
### D5 - Verificarea echivalenta "Totaluri" pe drumurile xlsx/FDB
- **A)** Adauga un check real: `SUM(REGISTRU)` pe latura la data ceruta = netul balantei generate. (recomandat)
- **B)** Doar avertizare explicita in raport ca verificarea nu e disponibila.
- **C)** Ignora.
- **Recomandare: A** - planul declara ca nu ajusteaza cifre ca sa treaca verificari (`CLAUDE.md`);
verificarea trebuie inlocuita cu una reala, nu doar scoasa.
### D6 - Framework de test
- **A)** `unittest` stdlib (fara dependinte noi). (recomandat)
- **B)** `pytest` (dependinta dev-only).
- **C)** Scripturi shell/py ad-hoc, fara framework.
- **Recomandare: A** - respecta "fara alte dependinte"; C nu da raportare de totaluri/esecuri.
---
## 4. Ce am verificat si ce NU am putut verifica
**Verificat (dovada in fisier):**
- `genereaza_xlsx.py` citeste din CSV doar `cont/denumire/total_d/total_c/este_total`;
nu citeste `sold_*`, nu citeste `TIP`, iar cross-check-ul Totaluri depinde de un rand care exista
doar in PDF (`:65-94,196-304,321-390`).
- `extract_balanta.py` scrie 12 coloane; `pagina`/`este_total` sunt coloanele care nu au echivalent
in export (`:232-237`, plan `:54`).
- Setul de parteneri din cod (5121/5124/5311) contrazice `CU_INREGISTRARI` din Oracle
(`genereaza_xlsx.py:47-53` vs `config_cont_ireg.md:89-91`).
- Baza de joaca: 0 analitice in export, `FURNIZORI.COD_FISCAL` gol pentru `ROMFAST`,
`INTRD.SCADENT=NULL`, regulile de rollup analitic->sintetic declarate necunoscute
(`raport_exporturi_saga_noua.md` A.1, C.3, C.4, C.5).
- `.gitignore` ignora `init_*.xlsx`; `git status` arata xlsx-urile de productie scoase din index.
- Mediu: `xlrd 2.0.2` si `firebird-driver` instalate; `pytest` NU; `tests/` NU.
**Nu am putut verifica (si nu am inventat):**
- Daca `409 -> 4091` sau alte redenumiri sunt necesare pe firmele viitoare (nu apar in FUNDATIA/MASTER).
- Structura `IES_DET` din Firebird (raportul o da ca necunoscuta) - partea de facturi clienti e
presupunere pana la o baza reala.
- Daca `CONFIG_CONT_IREG` s-a schimbat fata de dump-ul din `config_cont_ireg.md` (nu am interogat Oracle).
- Regula exacta de includere sintetic/analitic in exportul SAGA (`C.5` o declara nedeterminabila).
- Comportamentul real al formularului pe combinatia "acont gol pe FACTURA + acont completat pe BALANTA"
pe alte conturi decat cele deja tratate (am luat de bun `decizii_import.md` pct. 16).
**Nu am rulat** Codex/outside voice (mediu de subagent, fara Codex) si nici testul real de identitate
CSV (nu am voie sa rulez VFP/cod in acest lane; oricum planul nu are inca cititoarele).
---
Stare: niciun fisier modificat in afara acestui raport; fara commit; fara procese pornite;
fara date de test consumate.