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

183 lines
11 KiB
Markdown

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