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
183 lines
11 KiB
Markdown
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.
|