Files
roacont/docs/handoff_transa3_conditii.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

Handoff — TRANSA 3, verificare conditii de intrare (agent read-only)

Verificare pe cod + Oracle (schema MARIUSM_AUTO, alias ROA_CENTRAL), 27.07.2026. Referinta: docs\plan-anaf-tva-efactura-4-lucrari.md, sectiunea "TRANSA 3 — L3" (330-497) si "Ce ramane neverificat" (571-581). Niciun DDL/DML rulat, doar SELECT. Niciun commit.


A. Cotele 21%/11% in pack_contabINCHIS

Sursa exportata: docs\local\PACK_CONTAB.pck (ALL_SOURCE, MARIUSM_AUTO, PACKAGE + PACKAGE BODY, 451 linii).

  • defalca_tva_incasare (.pck:60-79) nu contine el insusi nicio lista de cote — deleaga integral la creeaza_note_tva_incasare (.pck:69).
  • creeaza_note_tva_incasare (.pck:121-415) foloseste DECODE(A.ID_JTVA_COLOANA, ...) cu id-urile 211/215 pentru JC (RO21NB/RO21NT, RO11NB/RO11NT, .pck:255-257, 288-289) si 38/42 pentru JV (.pck:270-272, 303-304), alaturi de 171/179/189/173 (24/20/19/9) si default 5%. Antetul pachetului are comentariul 08.08.2025 / creeaza_note_tva_incasare TVA 21%, 11% (.pck:56-58), care confirma data introducerii.
  • cauta_facturaTVAEx (.pck:417-448) filtreaza explicit RO21NT <> 0 OR RO11NT <> 0 OR RO19NT <> 0 OR RO9NT <> 0 OR RO5NT <> 0 (.pck:433, 446).

Observatie in afara scopului A (nu blocheaza conditia de intrare, dar de retinut): filtrul din cauta_facturaTVAEx omite RO24NT/RO20NT — o factura cu TVA neexigibil DOAR pe cota 24% sau 20% nu apare in lista cautata manual. E preexistent, nu introdus de suportul 21/11, si e alt buton (cauta_facturaTVAEx alimenteaza calea "Otherwise" din do_adauga_tva_exigibil, nu calea L3).

VERDICT: cotele 21%/11% sunt tratate integral in ambele proceduri. Conditia de intrare e inchisa.


B. Formula de sold neexigibil — INCHIS PARTIAL, CONTRAZICE PLANUL pe sursa datelor

Confirmat pe ALL_TAB_COLUMNS (MARIUSM_AUTO): toate cele 14 coloane din lista corecta (RO24NB/NT, RO20NB/NT, RO21NB/NT, RO11NB/NT, RO19NB/NT, RO9NB/NT, RO5NB/NT) exista, cu acelasi nume, in ambele JC2007 si JV2007 (NUMBER(18,4)). ID_FACT exista in ambele (NUMBER(20)).

CONTRAZICE PLANUL: coloana TVA_INCASARE nu exista in JC2007 nici in JV2007 — nu e "de confirmat", e absenta confirmata. TVA_INCASARE traieste pe DOCUMENTE (header-ul facturii, ID_DOC = id_fact, cf. pack_contab.creeaza_note_tva_incasare: select nract from documente where id_doc = tnIdFact), plus pe view-urile VJC2025/VJV2025 care deja o aduc alaturi de toate cele 14 coloane de cota (verificat pe ALL_TAB_COLUMNS) — acelasi view pe care cauta_facturaTVAEx il foloseste deja (vjv2025/vjc2025, .pck:430, 443).

O interogare literala "peste jc2007 + jv2007" cu filtru tva_incasare = 1, asa cum e formulat in plan la Pasul 3, ar da eroare Oracle (coloana inexistenta). Recomandare: interogarea sa foloseasca VJC2025/VJV2025 (deja au AN, LUNA, ID_FACT, toate cele 14 coloane, TVA_INCASARE) in loc de JC2007/JV2007 brute — consecvent cu precedentul din acelasi pachet (cauta_facturaTVAEx), sau alternativ un JOIN explicit jc2007/jv2007 -> documente pe id_doc = id_fact.

Interogare-draft testata pe date reale (VJC2025/VJV2025, fara restrictie an/luna, deci scanare completa ca sa vada volumul maxim):

select id_fact from vjc2025
 where tva_incasare = 1
   and (ro24nb+ro24nt+ro20nb+ro20nt+ro21nb+ro21nt+ro11nb+ro11nt+ro19nb+ro19nt+ro9nb+ro9nt+ro5nb+ro5nt) <> 0
union
select id_fact from vjv2025
 where tva_incasare = 1
   and (ro24nb+ro24nt+ro20nb+ro20nt+ro21nb+ro21nt+ro11nb+ro11nt+ro19nb+ro19nt+ro9nb+ro9nt+ro5nb+ro5nt) <> 0;

Rezultate (fara filtrul de an/luna, deci acesta e volumul-plafon, nu volumul unei singure salvari): 5711 randuri in VJC2025, 15506 in VJV2025, care se filtreaza la interogarea reala pe an/luna curente plus intersectia locala cu tact. ID_FACT nu e niciodata null pe niciuna din cele doua (count(*) where tva_incasare=1 and id_fact is null = 0 pe amandoua).

VERDICT: coloanele de cota si id_fact sunt confirmate pe JC2007/JV2007 (lista corecta e completa acolo). tva_incasare NU e acolo — planul trebuie corectat sa citeasca din VJC2025/ VJV2025 (sau JOIN cu DOCUMENTE), altfel Pasul 3 pica la implementare cu eroare Oracle de coloana inexistenta.


C. defalca_tva_incasare poate intoarce zero randuri sau id_fact problematic — **INCHIS, cu

intarire fata de plan**

Din sursa (.pck:121-415): cursorul returnat de creeaza_note_tva_incasare seteaza mereu id_fact = tnIdFact (parametrul de intrare, literal — .pck:169) — deci id_fact NU poate fi NULL in cursor decat daca parametrul insusi era NULL, ceea ce VFP nu trimite (Str() pe un numeric). Zero randuri e insa posibil: filtrul final `WHERE A1.ID_JTVA_COLOANA IS NOT NULL AND SIGN(V_SUMA)

  • A1.totctva > SIGN(V_SUMA) * A1.DIF (.pck:412-413`) poate exclude toate liniile.

Codul VFP care insereaza din cursor (omodificari.vc2:12400-12422, Insert Into &tcCursorAct(...) ... FROM (lcCursorDefTVA) a) nu are protectie explicita pe 0 randuri — un INSERT INTO ... SELECT dintr-un cursor gol insereaza tacut 0 randuri, fara eroare. Confirma citatul din plan (oproceduri_inchidere.prg:843-848, alta cale de apel, meniu -> inchidere_tva_sold, care TRATEAZA explicit Reccount(lcCursorDefTVA) = 0).

Gasit in plus, mai relevant decat citatul din plan pentru drumul L3: pe drumul do_adauga_tva_exigibil (butonul chiar din spatele avertizarii L3), exista un caz concret si usor de reprodus in care tnIdFact trimis catre Oracle e santinela -5, nu id-ul real:

omodificari.vc2:12547-12552 (Case !Empty(perechec) And Left(scd,1)='5')
    loadd.id_fact = Iif(m.loadd.id_factc > 0, m.loadd.id_factc, -5)
    ...
    llCalculeazaNoteTVA = m.llCalculeazaTVAEx

si simetric la :12555-12561 pentru id_factd. Daca llCalculeazaNoteTVA e adevarat (bifat chkTVAEX), linia asta ajunge la Thisform.creeaza_note_tva_incasare('tact', m.loadd, m.lnSuma) (:12601), care citeste lnIdFact = toRec.id_fact (:12378) — posibil -5 — si il trimite direct la pack_contab.defalca_tva_incasare(-5, ...) (:12385-12389). Nicio factura nu are id_fact = -5, deci cursorul Oracle vine garantat gol pe acest drum, de fiecare data cand id_factc/id_factd nu era deja completat.

VERDICT: da, zero randuri e un caz real si reproductibil pe insusi drumul pe care il declanseaza butonul din dialogul L3 ("Adauga acum"), nu doar pe calea de meniu citata in plan. Flagul anti-bucla de la Pasul 5 e strict necesar — confirmarea e mai tare decat presupunea planul. id_fact NULL nu e posibil prin acest pachet (mereu = parametrul trimis); riscul real e parametrul insusi fiind santinela, nu NULL.


D. Kill-switch: unde se pune — CONTRAZICE PLANUL pe mecanism

Planul (Pasul 0.5) presupune "Optiune in Optiuni_FIRMA/Optiuni_PROGRAM" — DBF-urile locale din D:\ROA\ROACONT\DATE\ (Optiuni_FIRMA.dbf, Optiuni_PROGRAM.dbf, Optiuni_LOCAL.dbf — exista pe disc, confirmat). RC_ANAF_VERIF_SELECTIE NU foloseste aceste DBF-uri. Mecanismul real, verificat in cod:

  • Functia care citeste nivelul: ANAF_NivelVerificare (COMUN\programe\ocautare.prg:242-276).
  • Kill-switch propriu-zis, verificat PRIMUL: fisier .ini, nu DBF — getini(gcGeneralIniFile, 'anaf', 'verificare_selectie'); doar valoarea explicita '0' opreste (ocautare.prg:247-249). Absenta cheii NU opreste nimic (cascada continua).
  • Optiune per-utilizator/per-firma: cursoarele crsOptiuniUtilizator/crsOptiuni, incarcate din Oracle la pornire — tabelele Oracle optiuni_util / optiuni (actualizeaza_optiuni_utilizator / actualizeaza_optiuni, oinit_optiuni.prg:709-722, 784-798), citite prin citeste_optiune_utilizator / citeste_optiune (oinit_optiuni.prg:725-742, 802-823; apel efectiv la ocautare.prg:264-266). Cache pe sesiune intr-o Collection (goCacheANAF_Nivel, ocautare.prg:253-259), cheia fiind schema + utilizator.
  • Scriere: scrie_optiune_utilizator cheama PACK_SESIUNE.SetOptiuneUtilizator (oinit_optiuni.prg: 764) — deci store-ul de adevar e Oracle, nu DBF local.
  • Aparitia in UI: intrare de meniu, nu ecran de optiuni cu DBF — ON SELECTION BAR 3 OF optiuniuti DO ANAF_ComutaVerificare IN ocautare.prg (Meniuri\CONT2000.MPR:210), care cheama ANAF_ComutaVerificare (ocautare.prg:324-382) — un toggle interactiv (citeste valoarea curenta, cere valoarea noua), nu un formular cu campuri DBF.

VERDICT: modelul real de urmat pentru kill-switch-ul L3 e Oracle (optiuni/optiuni_util + citeste_optiune/citeste_optiune_utilizator + cache in Collection) plus, daca se vrea si oprire per-masina, INI-ul (getini(gcGeneralIniFile, ...)) — NU Optiuni_FIRMA/Optiuni_PROGRAM.dbf din DATE\. Planul trebuie corectat inainte de Pasul 0.5.


E. Acoperirea drumurilor de instantiere — INCHIS, lista din plan e completa

Cautare rg --no-ignore in tot D:\ROA\ROACONT (inclusiv COMUN\) dupa Createobject([frm_modific2007]...) / Createobject([frm_modific2024]...). Rezultat (excluzand .BAK, fisiere de test, si documentul de plan insusi): exact aceleasi 14 situri din listă: ocont2003.prg:416,1230,1679,2141; oproceduri_incasari.prg:299; frm_import_extrase_banca.sc2:1652; anaf_efactura.vc2:12733,12940; frm_initializare_facturi_balanta.sc2:1803; comun.vc2:2436; oproceduri_inchidere.prg:719,902,1007,1438; frm_import_note_a4200.sc2:1651; frm_import_note_facturi_clienti.sc2:895; ooperatii_comune.prg:1137. Nimic lipsa.

(Gasit in plus, dar nu conteaza pentru acoperirea de productie: COMUN\utile\Teste\ achizitie_import\test_repro_cnrcrt_footer.prg:82 — harness de test, nu drum de productie.)

Verificare bucla (subagent, citire directa a codului din jurul fiecarui Createobject): din cele 14 situri, niciunul altul nu instantiaza formularul intr-o bucla activa — toate SCAN/FOR din procedurile respective se incheie inainte de linia cu Createobject. Singura exceptie sintactica: oproceduri_inchidere.prg:719 e in interiorul unui Do While, dar urmat imediat de un Exit necondiționat dupa loForm.Show(1) — functional tot instantiere unica, nu bucla reala.

VERDICT: candidatii pentru flagul de lot (Pasul 0.6) raman exact cei trei numiti in plan — anaf_efactura.vc2:12733, :12940, comun.vc2:2436. Nu mai sunt altii.


Ce ramane neverificat (in afara scopului A-E, de mentionat)

  • Comportamentul goExecutor la timeout/conexiune cazuta — nu a fost testat (ar necesita simularea unei conexiuni cazute); contractul de cod (lnSucces < 0 la esec, in toate apelurile vazute) e vizibil, dar nu a fost validat prin scenariu de esec real.
  • Volumul real de linii pe un decont de curier/procesator la clienti — nu exista date de productie disponibile in schema de dev (MARIUSM_AUTO) ca sa fie masurat; ramane pe baza estimarii din plan.

Fisiere generate

  • docs\local\PACK_CONTAB.pck — export sursa pack_contab (PACKAGE + PACKAGE BODY), 451 linii, ALL_SOURCE din MARIUSM_AUTO.