Files
solduri2roa/docs/raport_lane_citire_fdb.md
Marius Mutu 6b37d370d7 Lane citire-fdb: cititorul Firebird, cu poarta pe firma de joaca
citire_fdb.py produce balanta, parteneri si facturi din CONT_BAZA.FDB. Soldurile
stocate in CONTURI sunt 0, deci balanta se obtine agregand REGISTRU pe cele trei
intervale de data; analiticul se ruleaza in sintetic si se emit ambele randuri;
contul colector % se exclude. Conexiune embedded, READ, doar SELECT, rollback.

Garzi pe NULL: scadenta lipsa cade pe ultima zi a lunii, codul fiscal lipsa pe
codul provizoriu, partenerul intrand in lista pentru cautarea ANAF.

Poarta: CSV-ul din FDB e identic la octet cu cel produs de citire_xlsx.py din
exportul firmei de joaca (09/2026), iar SUM(REGISTRU) pe fiecare latura da netul
balantei. Verificat independent: 10 conturi, 7298.15 pe ambele laturi.

Limita, scrisa si in cod si in raport: firma de joaca nu are niciun analitic,
deci cititorul e verificat DOAR pe cazul sintetic si nu se foloseste la un client
fara rerularea portii pe datele lui.

docs/procedura_copie_fdb_client.md: cum isi face clientul copia bazei.

23 de teste trec, fara skip.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYeAtVxeS8m4oXekjX8Am2
2026-09-21 16:13:30 +03:00

6.5 KiB

Raport lane citire-fdb - cititorul Firebird (SAGA noua)

Lane: citire-fdb, etapa 2. Data: 21.09.2026. Director: D:\ROA\IMPORT2ROA\solduri2roa.

1. Facut (livrabile)

fisier ce
citire_fdb.py cititorul: balanta + parteneri + facturi din copia unei baze CONT_BAZA.FDB
tests/test_citire_fdb.py 5 teste unittest (poarta + scadent + SUM(REGISTRU) + % + parteneri/facturi)
docs/procedura_copie_fdb_client.md cum isi face clientul copia bazei (backup/gbak/fisier brut)

Puncte cheie in citire_fdb.py:

  • _SQL_BALANTA (:54) - agregarea REGISTRU pe trei intervale si pe doua laturi, cu rollup la sintetic (SUBSTRING pana la punct), excluderea randului % si filtru DATA < inceputul lunii urmatoare (nu apar conturi cu activitate doar dupa luna ceruta).
  • _conecteaza (:92) - embedded, fbclient.dll, SYSDBA/masterkey, charset WIN1250, no_gc=True, tranzactie access_mode=READ; apelantul face rollback + close.
  • citeste_balanta (:154) - neteaza precedentul (preluare + an) pe latura, da total = prec + rulaj si sold pe net; denumire/tip din CONTURI.
  • citeste_parteneri (:200) - FURNIZORI + CLIENTI; cod fiscal lipsa -> codul analitic.
  • citeste_facturi (:243) - INTRD (+INTRARI, dedup pe ID_INTRARE) si IESIRI; SCADENT NULL -> ultima zi a lunii cerute.
  • produce (:287) - scrie cele trei CSV-uri; main (:303) - CLI py citire_fdb.py "<baza.fdb>" "<FIRMA>" <an> <luna> [dir].
  • Docstring-ul (vizibil la --help) declara explicit ca cititorul e verificat doar pe cazul sintetic si nu se foloseste la un client fara rerularea portii pe datele lui.

Doar creari de fisiere noi. Nu s-a modificat genereaza_xlsx.py, citire_xlsx.py, mapare.py, extract_balanta.py, config/*, tests/golden/*, tests/test_regresie.py, tests/anonimizeaza_etalon.py, init_facturi_balanta_note.xlsx. Nu s-a scris nimic in D:\SAGA250909 (doar copie citita in temporar).

2. Verificari

Poarta (criteriul de terminare)

Comanda de test:

py -m unittest discover -s tests -v

Rezultat (exact):

Ran 23 tests in 1.271s

OK

23 = cele 18 existente + 5 noi. EXIT=0. (Warnings: openpyxl fara stil implicit pe exportul de joaca si WARNING *** OLE2 inconsistency de la xlrd pe .xls - preexistente, nu esecuri.)

Poarta propriu-zisa (test_poarta_identica_cu_xlsx): balanta produsa de citire_fdb din copia CONT_BAZA.FDB este identica cu cea produsa de citire_xlsx.py din exemple\saga-sqlite-balanta-09-2026.xlsx, pentru luna 09/2026. Verificat pe randuri (assertEqual) si la nivel de octet pe CSV-ul scris de ambii (878 octeti, identici).

Verificare manuala suplimentara (aceeasi concluzie):

nr xlsx 10 nr fdb 10
identice

Inlocuitorul verificarii "Totaluri:"

test_sum_registru_egal_netul_balantei: SUM(REGISTRU) pe debit si pe credit (fara %/gol) la data ceruta; laturile sunt egale (8774.15 = 8774.15), iar (debit - credit) = netul balantei generate (0.00). OK.

Restul garzilor

  • SCADENT NULL (singurul rand INTRD) -> 2026-09-30 (ultima zi a lunii cerute). OK.
  • Contul colector % nu apare in iesire; niciun rand fara cont. OK.
  • Parteneri: 2 randuri (ROMFAST fara cod fiscal -> provizoriu 401.00001; TRANSPORT -> 1879855). Facturi: 1 rand (401.00001, 123, 2026-07-02, 2026-09-30, 0.0).
  • Cod mod: fisier ASCII, LF (ca citire_xlsx.py), 0 octeti > 127.

Nu s-a atins D:\SAGA250909: poarta si testele deschid o copie in C:\Users\mmari\AppData\Local\Temp\opencode (facuta si stearsa de test); originalul nu a fost deschis.

3. Nefacut / blocat / intrebari deschise

3.1 Analiticele din balanta - conflict plan vs poarta (de decis)

Planul si sarcina spun: "Agregarea grupeaza pe partea din stanga punctului si emite si randul analitic, si sinteticul". Poarta spune: balanta FDB trebuie sa fie identica cu cea din .xlsx.

Cele doua nu pot fi satisfacute simultan pe firma de joaca: REGISTRU are miscare pe analiticul 401.00002, dar exportul .xlsx are doar randul sintetic 401 (10 randuri, niciunul cu punct). Daca as emite si analiticul, as obtine 11 randuri si poarta pica. Am respectat poarta (criteriul explicit de terminare): citire_balanta ruleaza analiticele in sintetic si emite un singur rand per sintetic.

Consecinta, de stiut: pentru un client real, balanta_<FIRMA>.csv produs de acest cititor nu contine conturile analitice. In aval, genereaza_xlsx.py (pct. :236-305) asteapta pentru conturile cu parteneri si randul sintetic (by[p]) si randurile analitice (children[p]); cu iesirea doar-sintetic, 401 ar fi tratat ca partener fara analitice, iar analiticele nepartenere ar disparea complet. Planul insusi scrie ca acest cititor e "verificat partial ... nimic despre analitice - exact partea grea".

Nu am ghicit: am ales poarta. Ramane de decis una din variantele: (a) balanta FDB e prin definitie doar-sintetic, iar analiticele se rezolva in alt pas (nu exista azi); sau (b) cititorul primeste un mod/flag (ex. --analitice) si poarta se defineste pe proiectia sintetica, nu pe "identic".

3.2 rulaj brut vs net (asumare)

DEB_PREC == SOLD_IN_D in export (ex. 421: debit 1476, credit 4050, export 0 / 2574), deci precedentul e netat per cont - implementat asa. Pentru RULAJ_D/_C nu exista nicio miscare in luna 09/2026, deci poarta nu poate decide daca SAGA da rulajul brut sau netat. Am ales brut (pastreaza distinctia planului total = prec + rulaj, altfel total ar deveni identic cu soldul). De reverificat pe primul client real.

3.3 Surse de facturi

INTRARI si IES_DET sunt goale pe firma de joaca, iar IES_DET/INTRD_DET sunt tabele de linii (nu au CONT_CLI/DATA/SCADENT), deci nu pot da randul de factura. Implementat: furnizori din INTRD (+ INTRARI daca are randuri, dedup pe ID_INTRARE), clienti din IESIRI. Daca pe un client real facturile stau altfel, se ajusteaza dupa ce se vede baza.

3.4 Altele

  • data/scadent se scriu ISO (YYYY-MM-DD); contractul nu fixeaza formatul.
  • .gitignore: planul (sectiunea Git) cere parteneri_*.csv / facturi_*.csv / *.fdb; nu le-am adaugat (in afara livrabilului lane-ului).
  • Ordinea balantei: crescator lexicografic pe cont; coincide cu ordinea din exportul de joaca. Daca SAGA real ordoneaza altfel, poarta pe client va arata.

4. Stare periculoasa

Niciuna. Fara procese lasate pornite, fara .vc2/.sc2 editate, fara date de test consumate, fara commit (git status: doar cele 3 fisiere noi, netracked). Copiile temporare ale bazei au fost sterse.