# 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.