Files
roacont/docs/handoff_transa3_deschise.md
Marius Mutu 7cd7d57708 Transa 1 ANAF TVA: changelog 2.11.67, plan corectat pe date, handoff-uri de verificare
Plan corectat in patru puncte confirmate pe Oracle:
- lista de coloane de taxare inversa are 13 termeni, nu 10 (TI19T/TI09T nu exista pe jc2007;
  expresia din oproceduri_decont.prg:8670 e scrisa peste view-ul VJC2025, cu aliasuri calculate)
- tva_incasare nu exista pe jc2007/jv2007; interogarea transei 3 merge pe VJC2025/VJV2025
- kill-switch-ul nu se face in Optiuni_FIRMA/PROGRAM.dbf, ci pe modelul RC_ANAF_VERIF_SELECTIE
  (INI + optiuni Oracle + intrare de meniu)
- oExecute deschide dialog de reconectare cu QUIT pe conexiune cazuta; apelul din transa 3 trebuie
  sa dezactiveze explicit reconectarea

SVN r17910/r17911.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhJwsrFFe1ZNAAtS8Twuti
2026-07-28 00:50:26 +03:00

11 KiB

TRANSA 3 (L3) — cele doua puncte ramase din "Ce ramane neverificat"

Data: 27.07.2026. Read-only (Oracle: doar SELECT; cod: doar citire). Nimic modificat, nimic comis. Nu ating docs\handoff_transa3_conditii.md (al colegului T3-cond).

VERDICT GENERAL

  • Punctul 1 (goExecutor la timeout/conexiune cazuta) — CONTRAZICE PLANUL. Comportamentul implicit NU e "se sare, cu linie in goLog": pe conexiune cazuta apare mereu un dialog modal blocant, care la Cancel face QUIT (inchide toata aplicatia). Pattern-ul defensiv cerut de plan nu are niciun precedent azi in codebase — trebuie construit, nu copiat.
  • Punctul 2 (linii pe decont) — RAMAS DESCHIS pe cifra exacta, dar decizia arhitecturala a planului (fara lista IN(...)) ramane intemeiata independent de cifra. Schema dev nu are volum reprezentativ pentru batch-uri reale de extras/decont.

Punctul 1 — comportamentul goExecutor la timeout / conexiune cazuta

Sursa reala (cautata cu rg --no-ignore... de fapt Grep a gasit-o direct, COMUN nu era exclus in aceasta sesiune): clasa oexecutor e definita in COMUN\programe\oproceduri_comune.prg:69-547 (NU in anaf_efactura.vc2 — de acolo doar se apeleaza). Instantiata o singura data: goExecutor = Createobject("oExecutor"), Programe\roacont.prg:588.

Ce intoarce oExecute() la esec

Functie normala, nu arunca eroare VFP. SQLExec() esuat intoarce direct < 0, prins de codul existent — niciun THROW/ERROR() implicat. Return: CT_INSUCCES (= -1, COMUN\include\comun.h:10) daca lnSucces < 1, altfel CT_SUCCES (= 1) (oproceduri_comune.prg:496, Return Iif(lnSucces >= 1, CT_SUCCES, CT_INSUCCES)). Cursorul de iesire nu se creeaza pe esec (Use-ul din urma nu ruleaza).

oExecuta() (wrapper cu litera mica, folosit in ~jumatate din apeluri) doar impacheteaza oExecute() si adauga necontitionat amessagebox(This.oPrelucrareEroare(), 16, "Eroare") pe orice esec (:149-152) — indiferent de parametri. Diferenta fata de oExecute() (raw) e semnificativa pentru L3.

Urca eroarea la ErrorHandler global? NU, direct — DAR

Nu urca la ON ERROR (nu e o exceptie VFP). Insa exista un dialog modal necontitionat de tlShowError, la eroare ODBC (lnEroare1 = 1526) cu cod de eroare in lista 12152, 3113, 3114, 12560, 4068, 28, 12 (oproceduri_comune.prg:383) — exact codurile de conexiune cazuta/protocol (3114 = NOT CONNECTED TO ORACLE, 3113 = end-of-file on communication channel, 12560 = protocol adapter error):

lnRaspuns = amessagebox('Eroare de conectare.' + ... + 'Doriti reconectare?', 4 + 32, 'Eroare')

(:390) — apare mereu cand llReconnect = .T., chiar daca apelantul a lasat toti parametrii default. Daca utilizatorul raspunde "Nu" (lnRaspuns <> 6): Quit + Retry (:412-413) — inchide toata aplicatia, nu doar sare peste verificare.

llReconnect e recalculat la fiecare apel, ignorand orice setare anterioara pe obiect (:220-224):

If SQLGetprop(lnHandle, "Transactions") = 2  && TRANZACTIE MANUALA
    This.lReconnect = .F.
Else
    This.lReconnect = .T.      && cazul normal, in afara unei tranzactii manuale
Endif

si apoi, daca apelul are sub 8 parametri (cazul general in tot codebase-ul), llReconnect preia This.lReconnect — deci .T. implicit pentru orice verificare in afara unei tranzactii manuale. Singurul mod de a opri acest modal e sa dai explicit al 8-lea parametru (tlReconnect = .F.) la apel — vezi mai jos, nu exista niciun apel asa in tot codebase-ul.

CONTRAZICE PLANUL: cerinta "orice esec (... conexiune cazuta ...) -> se sare, cu linie in goLog. Niciodata tacut... Esecul nu blocheaza salvarea" (plan, :445-448) nu e comportamentul implicit pentru exact acest caz (conexiune cazuta). E opusul: un dialog modal blocant, care poate opri toata aplicatia. Pentru orice ALTA eroare (SQL gresit, tabela inexistenta — ORA-00942, coloana lipsa — ORA-00904), comportamentul implicit CHIAR e "se sare, log, fara dialog" — llShowError e .F. implicit si acel dialog nu e conditionat decat de el. Deci planul are dreptate pentru clasa generala de erori, dar nu pentru "conexiune cazuta" — exact cazul numit explicit in text.

goLog.Log(...) SE cheama pe toate drumurile de esec (:368-370, :384-387, :422-424) — de partea asta planul are dreptate necontitionat, indiferent de tipul erorii.

In plus, pe orice esec (lnSucces < 0), independent de parametri, codul posteaza automat eroarea la endpoint-ul de erori (goMyXMLHTTP.postError(...), :463-471) — un apel HTTP sincron in plus pe drumul de salvare, la fiecare esec, inclusiv la cele care ar trebui "sarite silentios".

Timeout configurat?

Nu exista niciun SQLSETPROP cu QueryTimeout/ConnectTimeout/WaitTime pe handle-ul Oracle, nicaieri in oExecutor/oConn (oproceduri_comune.prg:662-731, Connect foloseste doar Sqlstringconnect(lcString) cu dsn=...;Uid=...;Pwd=..., fara parametri de timeout). Singurul ConnectTimeout gasit in tot fisierul (:4105-4118) e pentru verificarea HTTP de update-uri, fara legatura cu conexiunea Oracle. Concluzie: un query care ramane agatat (nu eroare, ci hang) nu are niciun timeout care sa-l intrerupa — ar bloca formularul la nesfarsit, ceva ce nici planul, nici codul actual nu adreseaza. De consemnat separat, dincolo de "esec" (eroare) — un hang nu e un esec, e o blocare fara iesire.

Tiparul de apel defensiv "corect" deja folosit in codebase — NU EXISTA

Am cautat toate apelurile oExecute(/oExecuta( din COMUN si Programe (peste 150) — niciunul nu trece de 2 parametri (tcSql, tcCursor). Nimeni nu foloseste vreodata parametrii 6-8 (tlShowError, tlQuitOnError, tlReconnect) explicit. Deci pattern-ul "cheama cu tlReconnect = .F. ca sa eviti dialogul de reconectare" nu are niciun precedent — L3 ar fi PRIMUL loc din codebase care il foloseste.

Cel mai apropiat precedent (nu perfect, dar cel mai aproape de "se sare fara dialog"):

  • oproceduri_inchidere.prg:1297: goExecutor.oExecuta(lcSql, "imob_conturi") urmat doar de If m.llSucces ... Endif — la esec nu se face nimic in plus (dar oExecuta tot arata singura amessagebox interna, deci nu e cu adevarat silentios).
  • Pattern mai bun de citat ca baza (foloseste oExecute, nu wrapper-ul oExecuta): COMUN\clase\baza.vc2:1807, lnSucces = goExecutor.oExecute(lcSql,lcCursor), fara parametri suplimentari — la 2 parametri, llShowError/llQuitOnError raman .F. (fara dialog pe erori generice), dar llReconnect tot devine .T. implicit, deci tot apare dialogul de reconectare pe conexiune cazuta.

Recomandare pentru L3 (nu e sarcina mea sa implementez, doar de raportat ca gasire): interogarea noua trebuie sa apeleze goExecutor.oExecute(...) (NU oExecuta, care are mesaj propriu necontitionat), cu toti cei 8 parametri, ultimul (tlReconnect) explicit .F., si verificarea proprie a rezultatului fara niciun amessagebox propriu — un tipar care azi nu exista nicaieri in cod si trebuie scris de la zero, nu copiat.


Punctul 2 — numarul real de linii pe un decont de curier/procesator

Ce s-a verificat despre sursa datelor

Confirmat din cod (Programe\oproceduri_import.prg:100-264): importul de extrase/deconturi e strict pe fisier local (Getfile() la :138, parsat client-side in cursoare VFP C_IMPORT_TEMP -> cActTemp). Oracle NU pastreaza niciun tabel de staging cu "lot de import" si numar de linii — abia dupa validare, liniile devin note (ACT/ACTACTAN) si se salveaza individual. Deci nu exista in Oracle o coloana/tabela care sa raspunda direct la intrebare — a trebuit reconstruita indirect.

nom_fdoc: id_fdoc = 40 = EXTRAS CON (extras cont), id_fdoc = 33 = DECONT (decont curier/procesator).

Reconstructie indirecta (proxy, nu masuratoare directa)

ACT nu are o coloana de "id lot" — am grupat notele salvate prin apropierea DATAORA (momentul efectiv al salvarii, cu ora), pe acelasi id_util, cu prag de 10 minute intre randuri consecutive ca limita de lot. E o aproximare (poate sparge/uni loturi reale), nu o masuratoare exacta din aplicatie.

Rezultate (schema MARIUSM_AUTO, dev):

  • DECONT (id_fdoc=33): doar 2 randuri in toata baza, un singur lot de 2 linii (25.06.2026). Date insuficiente pentru orice concluzie.
  • EXTRAS CON (id_fdoc=40): 222 randuri, pe 32 zile distincte, din 19.01.2008 pana in 29.05.2026 — 40 loturi estimate. min 1, max 70, medie 5.6, percentila 95 ≈ 10 linii/lot.

CONTRAZICE PLANUL, cu rezerva explicita de mai jos: cifra afirmata in plan ("un extras obisnuit are 300-2000 linii/luna") e cu un ordin de marime peste orice lot gasit in aceasta schema (maximul absolut observat e 70).

De ce nu extrapolez asta la "planul gresit pe cifra": MARIUSM_AUTO e schema de dezvoltare a lui Marius (confirmat in COMUN\docs\oracle_export.md), nu un client real cu volum de productie. Loturile gasite arata a teste punctuale facute de-a lungul anilor (o inserare la cateva luni sau ani), nu activitate de contabilitate lunara reala pe un cont bancar activ. Schema dev NU are date reprezentative pentru volumul real al unui client — nu pot confirma sau infirma cifra 300-2000 pe aceasta baza. Ramane RAMAS DESCHIS strict pe cifra exacta.

Corroborare slaba, doar indicativa: fisierul-sablon real din Alte\Extras_de_cont_11634808MT 940.txt (extras MT940 pentru o singura zi, un singur cont) are 11 linii de tranzactie (:61:) pentru acea zi. Extrapolat naiv la ~20-22 zile lucratoare/luna ar da ~220-240 linii/luna pentru un cont de activitate medie — aproape de capatul de jos al intervalului din plan (300), dar e un singur esantion de o zi, pentru o singura firma, nu o distributie.

Ce ramane solid, indiferent de cifra exacta

Decizia arhitecturala a planului de la Pasul 3 ("fara lista IN(...)", :421-431) nu depinde de cifra 300-2000 ca sa fie corecta: o interogare unica, de lungime fixa, cu intersectia facuta local in VFP, elimina o clasa intreaga de eroare (ORA-01795, prag 1000) indiferent daca lotul real are 10 sau 2000 de linii — nu exista un prag sub care revenirea la IN(...) ar fi de preferat, pentru ca varianta cu interogare unica nu are dezavantaj de cost fata de o lista IN mica. Deci verdictul practic: decizia ramane intemeiata, chiar daca premisa numerica citata in text nu e verificata (si, pe aceasta schema, pare supraestimata).


Alte observatii utile

  • oExecuta() (wrapper) vs oExecute() (raw): distinctia conteaza mult pentru L3 si nu era evidenta din plan. oExecuta are propriul amessagebox necontitionat pe esec — pentru cerinta "niciodata dialog, doar log", trebuie folosit oExecute, nu oExecuta.
  • oPrelucrareEroare() (folosit de mesajele proprii de eroare) nu a fost citit in detaliu — nu era necesar pentru cele doua puncte cerute.