Registre 2025: cotele 24/20 la soldul neexigibil; exigibilizare TVA reparata
frm_regcump2025 / frm_regvanz2025 au fost derivate din clasele 2010 INLOCUIND cotele 24/20 cu 11/21, in loc sa le adauge. Consecinta: filtrul "Diferenta sold" si lista TVA-ului exigibilizat din plati pierdeau facturile cu TVA neexigibil la 24% sau 20% - adica exact facturile vechi cu TVA la incasare, cele carate din perioade anterioare, care sunt rostul filtrului. Corectate 6 filtre, formula de sold din frm_regvanz2025 (care omitea complet RO20/RO24, spre deosebire de geamana ei de la cumparari) si lista de coloane selectate. Clasele frm_regcump2010 / frm_regvanz2010 raman neatinse: enumera 24/20/19/9/5 si e corect asa - se folosesc doar pe perioade dinainte de cotele 21/11, iar cursorul lor actcv nici nu are coloanele ro11*/ro21*. inchidere_tva_sold: - soldn21/soldn11 si ro21nt/ro11nt se citesc doar daca exista in cursor. Registrele de dinainte de 2025 nu le emit, de unde eroarea VFP la apasarea butonului de exigibilizare pe orice perioada anterioara. - cota 21 nu era luata in calcul: `Iif(m.lnCota = 21, ...)` intr-o bucla For 1 To 7, deci lnSuma21 era cod mort, iar la cota 6 se lua soldul de 11% cu 1.21. Linia imediat urmatoare folosea deja corect `= 6`. - 8 variabile adaugate in Local; deveneau PRIVATE si se scurgeau in stiva de apel. Scoase 37 `SET STEP ON` ramase in cod (35 in ovanzcump.vc2, 2 in oproceduri_inchidere.prg); deschideau depanatorul la fiecare rulare din IDE. Changelog 2.11.66. Sterse handoff-urile, planurile si patch-urile de review ale lucrarii ANAF/TVA/eFactura; .gitignore acopera acum docs/diff_*.patch, nu doar docs/diff_runda*.patch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DhJwsrFFe1ZNAAtS8Twuti
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -104,6 +104,6 @@ roacont_ref.FPT
|
||||
# --- COMUN este gestionat separat, prin propriul sau git (romfast/comun.git) ---
|
||||
COMUN/
|
||||
|
||||
docs/diff_runda*.patch
|
||||
docs/diff_*.patch
|
||||
.gstack/
|
||||
docs/local/
|
||||
|
||||
@@ -20865,7 +20865,6 @@ DEFINE CLASS frm_deconttva AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
SET STEP ON
|
||||
lcNumePrenumeDeclarant = Alltrim(NVL(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -21063,7 +21062,6 @@ DEFINE CLASS frm_deconttva AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -21274,7 +21272,6 @@ DEFINE CLASS frm_deconttva AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -21485,7 +21482,6 @@ DEFINE CLASS frm_deconttva AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -22921,7 +22917,6 @@ DEFINE CLASS frm_deconttva_201601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
SET STEP ON
|
||||
lcNumePrenumeDeclarant = Alltrim(NVL(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -23119,7 +23114,6 @@ DEFINE CLASS frm_deconttva_201601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -23330,7 +23324,6 @@ DEFINE CLASS frm_deconttva_201601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -23541,7 +23534,6 @@ DEFINE CLASS frm_deconttva_201601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -25155,7 +25147,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
SET STEP ON
|
||||
lcNumePrenumeDeclarant = Alltrim(NVL(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -25353,7 +25344,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -25564,7 +25554,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -25775,7 +25764,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -25997,7 +25985,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -26221,7 +26208,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -26425,7 +26411,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -26631,7 +26616,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -26835,7 +26819,6 @@ DEFINE CLASS frm_deconttva_201701 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -28466,7 +28449,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
SET STEP ON
|
||||
lcNumePrenumeDeclarant = Alltrim(NVL(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -28664,7 +28646,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -28875,7 +28856,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -29086,7 +29066,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -29308,7 +29287,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -29532,7 +29510,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -29736,7 +29713,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -29942,7 +29918,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -30146,7 +30121,6 @@ DEFINE CLASS frm_deconttva_202601 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
Set Date To Ymd
|
||||
Set Mark To '-'
|
||||
Set Step On
|
||||
lcNumePrenumeDeclarant = Alltrim(Nvl(gofirma.declarant,''))
|
||||
lcNumeDeclarant = lcNumePrenumeDeclarant
|
||||
lcPrenumeDeclarant = ""
|
||||
@@ -38862,7 +38836,6 @@ DEFINE CLASS frm_regcump2010 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
*!* Delete From cListRCTemp Where Padl(nract,14,'0') + '|' + Dtos(dataact) + '|' + Padr(denumire,100,' ') Not In ;
|
||||
*!* (Select Padl(nract,14,'0') + '|' + Dtos(dataact) + '|' + Padr(denumire,100,' ') From cListRC WHERE !EMPTY(NVL(denumire,'')) )
|
||||
*!* Endif
|
||||
SET STEP ON
|
||||
WAIT WINDOW 'TVA exigibilizat din plati facturi cu TVA Incasare' NOWAIT
|
||||
*** ADAUG TVA INCASARE (DIN INCASARI/PLATI, TVA 4427 LA 90 ZILE)
|
||||
TEXT to m.lcSql textmerge noshow
|
||||
@@ -42642,14 +42615,14 @@ DEFINE CLASS frm_regcump2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
from vjc2010
|
||||
where an = <<m.gnAn>>
|
||||
and luna = <<m.gnLuna>>
|
||||
and (RO11nt <> 0 or RO21nt <> 0 or ro19nt <> 0 or ro9nt <> 0 or ro5nt <> 0)
|
||||
and (RO11nt <> 0 or RO21nt <> 0 or ro20nt <> 0 or ro24nt <> 0 or ro19nt <> 0 or ro9nt <> 0 or ro5nt <> 0)
|
||||
and tva_incasare = 1)
|
||||
group by id_fact, cont) ip
|
||||
on jc.id_fact = ip.id_fact
|
||||
where jc.an = <<m.gnAn>>
|
||||
and jc.luna = <<m.gnLuna>>
|
||||
and jc.tva_incasare = 1
|
||||
and (jc.RO11nt <> 0 or jc.RO21nt <> 0 or jc.ro19nt <> 0 or jc.ro9nt <> 0 or jc.ro5nt <> 0)
|
||||
and (jc.RO11nt <> 0 or jc.RO21nt <> 0 or jc.ro20nt <> 0 or jc.ro24nt <> 0 or jc.ro19nt <> 0 or jc.ro9nt <> 0 or jc.ro5nt <> 0)
|
||||
and nvl(ip.sold, 0) - (RO11nb + RO11nt + RO21nb + RO21nt + RO20nb + RO20nt + RO24nb + RO24nt + ro19nb + ro19nt + ro9nb + ro9nt + ro5nb + ro5nt) <> 0
|
||||
ENDTEXT
|
||||
|
||||
@@ -43155,7 +43128,6 @@ DEFINE CLASS frm_regcump2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
lcWhere = Alltrim(Substr(m.lcWhere, m.lnPos + 11))
|
||||
Endif
|
||||
Endif
|
||||
SET STEP ON
|
||||
Do Case
|
||||
Case m.lnTipJurnal = 1
|
||||
pcSubtitlu = "Achizitii de bunuri si prestari de sevicii taxabile din tara"
|
||||
@@ -43452,7 +43424,6 @@ DEFINE CLASS frm_regcump2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
*!* Delete From cListRCTemp Where Padl(nract,14,'0') + '|' + Dtos(dataact) + '|' + Padr(denumire,100,' ') Not In ;
|
||||
*!* (Select Padl(nract,14,'0') + '|' + Dtos(dataact) + '|' + Padr(denumire,100,' ') From cListRC WHERE !EMPTY(NVL(denumire,'')) )
|
||||
*!* Endif
|
||||
SET STEP ON
|
||||
WAIT WINDOW 'TVA exigibilizat din plati facturi cu TVA Incasare' NOWAIT
|
||||
*** ADAUG TVA INCASARE (DIN INCASARI/PLATI, TVA 4427 LA 90 ZILE)
|
||||
TEXT to m.lcSql textmerge noshow
|
||||
@@ -43467,7 +43438,7 @@ DEFINE CLASS frm_regcump2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
LEFT Join JTVA_COLOANE J2 On J.id_jtva_coloana = J2.id_tva
|
||||
left join nom_fdoc fdoc on a.id_fdoc = fdoc.id_fdoc
|
||||
where a.an = ?m.gnAn and a.luna = ?m.gnLuna and a.sters = 0 and a.scd = '4426' And a.scc = '4428' And Nvl(a.id_jtva_coloana, 0) <> 0
|
||||
and jc.an = ?m.gnAn and jc.luna = ?m.gnLuna and (jc.RO11nt <> 0 or jc.RO21nt <> 0 or jc.ro19nt <> 0 or jc.ro9nt <> 0 or jc.ro5nt <> 0)
|
||||
and jc.an = ?m.gnAn and jc.luna = ?m.gnLuna and (jc.RO11nt <> 0 or jc.RO21nt <> 0 or jc.ro20nt <> 0 or jc.ro24nt <> 0 or jc.ro19nt <> 0 or jc.ro9nt <> 0 or jc.ro5nt <> 0)
|
||||
ORDER BY a.cod, J2.COLOANA_JC
|
||||
ENDTEXT
|
||||
|
||||
@@ -44214,7 +44185,6 @@ DEFINE CLASS frm_regcump2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
*!* 25.08.2014
|
||||
*!* marius.mutu
|
||||
*!* se transmit si soldurile pe cote de TVA 24,9,5 pentru cazul in care soldul total este 0
|
||||
SET STEP ON
|
||||
Local lcXMLFacturi
|
||||
If !(luna_inchisa Or m.glEMama)
|
||||
Select *, (RO11NB+RO21NB+RO24NB+RO20NB+RO19NB+RO09NB+RO05NB + RO11NT+RO21NT+RO24NT+RO20NT+RO19NT+RO09NT+RO05NT) as soldn, ;
|
||||
@@ -50170,7 +50140,6 @@ DEFINE CLASS frm_regvanz2010 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_excel
|
||||
SET STEP ON
|
||||
do export_excel_grid WITH thisform._grdbase1,"dataact, nract", "", this.lb_titlu_alb_b121.caption IN proceduri_excel.prg
|
||||
|
||||
return
|
||||
@@ -50521,7 +50490,6 @@ DEFINE CLASS frm_regvanz2010 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
|
||||
update_jtva_coloane('JV')
|
||||
*** SELECTEZ FACTURILE CU TVA_INCASARE CU TOTAL BAZA, TVA, BAZAN, TVAN
|
||||
SET STEP ON
|
||||
Select r.cod, r.id_fact, r.tip, r.denumire, r.nract, r.SERIE_ACT, r.dataact, r.COD_FISCAL, Space(10) As COD_TVA, Space(100) As EXPLICATIE_TVA, r.TOTCTVA, r.TOTFTVATAX, r.TOTTVATAX, TVA_INCASARE, ;
|
||||
(RO24B + RO20B + RO19B + RO9B + RO5B + CESCDD1 + CESCDD2 + CEOPTR + FODD + FOFDD + CESVDD + CESVFDD + CESVFS + ROTI + WRN + WRSCDD + WRSCFDD) As BAZA, ;
|
||||
(RO24T + RO20T + RO19T + RO9T + RO5T) As TVA, ;
|
||||
@@ -51396,7 +51364,6 @@ DEFINE CLASS frm_regvanz2010 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
*!* 25.08.2014
|
||||
*!* marius.mutu
|
||||
*!* se transmit si soldurile pe cote de TVA 24,9,5 pentru cazul in care soldul total este 0
|
||||
SET STEP ON
|
||||
Local lcXMLFacturi
|
||||
If !(luna_inchisa Or m.glEMama)
|
||||
Select *, (RO24NB+RO20NB+RO19NB+RO9NB+RO5NB + RO24NT+RO20NT+RO19NT+RO9NT+RO5NT) as soldn, ;
|
||||
@@ -53816,8 +53783,8 @@ DEFINE CLASS frm_regvanz2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
select jv.id_fact,
|
||||
ip.cont,
|
||||
nvl(ip.sold, 0) as soldf,
|
||||
(RO11nb + RO11nt + RO21nb + RO21nt + ro19nb + ro19nt + ro9nb + ro9nt + ro5nb + ro5nt) as soldn,
|
||||
nvl(ip.sold, 0) - (RO11nb + RO11nt + RO21nb + RO21nt + ro19nb + ro19nt + ro9nb + ro9nt + ro5nb + ro5nt) as solddif,
|
||||
(RO11nb + RO11nt + RO21nb + RO21nt + RO20nb + RO20nt + RO24nb + RO24nt + ro19nb + ro19nt + ro9nb + ro9nt + ro5nb + ro5nt) as soldn,
|
||||
nvl(ip.sold, 0) - (RO11nb + RO11nt + RO21nb + RO21nt + RO20nb + RO20nt + RO24nb + RO24nt + ro19nb + ro19nt + ro9nb + ro9nt + ro5nb + ro5nt) as solddif,
|
||||
jv.denumire,
|
||||
jv.nract,
|
||||
jv.serie_act,
|
||||
@@ -53830,6 +53797,10 @@ DEFINE CLASS frm_regvanz2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
jv.RO11nt,
|
||||
jv.RO21nb,
|
||||
jv.RO21nt,
|
||||
jv.RO20nb,
|
||||
jv.RO20nt,
|
||||
jv.RO24nb,
|
||||
jv.RO24nt,
|
||||
jv.ro19nb,
|
||||
jv.ro19nt,
|
||||
jv.ro9nb,
|
||||
@@ -53849,15 +53820,15 @@ DEFINE CLASS frm_regvanz2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
from vjv2010
|
||||
where an = <<m.gnAn>>
|
||||
and luna = <<m.gnLuna>>
|
||||
and (RO11nt <> 0 or RO21nt <> 0 or ro19nt <> 0 or ro9nt <> 0 or ro5nt <> 0)
|
||||
and (RO11nt <> 0 or RO21nt <> 0 or ro20nt <> 0 or ro24nt <> 0 or ro19nt <> 0 or ro9nt <> 0 or ro5nt <> 0)
|
||||
and tva_incasare = 1)
|
||||
group by id_fact, cont) ip
|
||||
on jv.id_fact = ip.id_fact
|
||||
where jv.an = <<m.gnAn>>
|
||||
and jv.luna = <<m.gnLuna>>
|
||||
and jv.tva_incasare = 1
|
||||
and (jv.RO11nt <> 0 or jv.RO21nt <> 0 or jv.ro19nt <> 0 or jv.ro9nt <> 0 or jv.ro5nt <> 0)
|
||||
and nvl(ip.sold, 0) - (RO11nb + RO11nt + RO21nb + RO21nt + ro19nb + ro19nt + ro9nb + ro9nt + ro5nb + ro5nt) <> 0
|
||||
and (jv.RO11nt <> 0 or jv.RO21nt <> 0 or jv.ro20nt <> 0 or jv.ro24nt <> 0 or jv.ro19nt <> 0 or jv.ro9nt <> 0 or jv.ro5nt <> 0)
|
||||
and nvl(ip.sold, 0) - (RO11nb + RO11nt + RO21nb + RO21nt + RO20nb + RO20nt + RO24nb + RO24nt + ro19nb + ro19nt + ro9nb + ro9nt + ro5nb + ro5nt) <> 0
|
||||
ENDTEXT
|
||||
|
||||
llSucces = goExecutor.oExecuta(m.lcSql, "crsSoldDif")
|
||||
@@ -53888,7 +53859,6 @@ DEFINE CLASS frm_regvanz2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_excel
|
||||
SET STEP ON
|
||||
do export_excel_grid WITH thisform._grdbase1,"dataact, nract", "", this.lb_titlu_alb_b121.caption IN proceduri_excel.prg
|
||||
|
||||
return
|
||||
@@ -54377,7 +54347,7 @@ DEFINE CLASS frm_regvanz2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
LEFT Join JTVA_COLOANE J2 On J.id_jtva_coloana = J2.id_tva
|
||||
left join nom_fdoc fdoc on a.id_fdoc = fdoc.id_fdoc
|
||||
where a.an = ?m.gnAn and a.luna = ?m.gnLuna and a.sters = 0 and a.scd = '4428' And a.scc = '4427' And Nvl(a.id_jtva_coloana, 0) <> 0
|
||||
and jv.an = ?m.gnAn and jv.luna = ?m.gnLuna and (jv.RO11nt <> 0 or jv.RO21nt <> 0 or jv.ro19nt <> 0 or jv.ro9nt <> 0 or jv.ro5nt <> 0)
|
||||
and jv.an = ?m.gnAn and jv.luna = ?m.gnLuna and (jv.RO11nt <> 0 or jv.RO21nt <> 0 or jv.ro20nt <> 0 or jv.ro24nt <> 0 or jv.ro19nt <> 0 or jv.ro9nt <> 0 or jv.ro5nt <> 0)
|
||||
order by a.cod, J2.COLOANA_JC
|
||||
ENDTEXT
|
||||
|
||||
@@ -55063,7 +55033,6 @@ DEFINE CLASS frm_regvanz2025 AS _frmbase OF "..\comun\clase\_frm_base.vcx"
|
||||
*!* 25.08.2014
|
||||
*!* marius.mutu
|
||||
*!* se transmit si soldurile pe cote de TVA 24,9,5 pentru cazul in care soldul total este 0
|
||||
SET STEP ON
|
||||
Local lcXMLFacturi
|
||||
If !(luna_inchisa Or m.glEMama)
|
||||
Select *, (RO11NB+RO21NB+RO24NB+RO20NB+RO19NB+RO9NB+RO5NB + RO11NT+RO21NT+RO24NT+RO20NT+RO19NT+RO9NT+RO5NT) as soldn, ;
|
||||
|
||||
@@ -771,7 +771,7 @@ Procedure inchidere_tva_sold
|
||||
Local lnIdSet, lnNrAct, lnProcTVA, lnRecords, lnSucces, lnSuma, loAct
|
||||
Local lnCota, lnCotaTVA, lnSuma24, lnSuma5, lnSuma9, lnSumaT
|
||||
Local lnSuma24T, lnSuma5T, lnSuma9T, lnSumaNT, lcMesaj
|
||||
SET STEP ON
|
||||
Local lnSuma11, lnSuma19, lnSuma20, lnSuma21, lnSuma11T, lnSuma19T, lnSuma20T, lnSuma21T
|
||||
lcJurnal = Upper(Alltrim(m.tcJurnal)) && JC/JV
|
||||
If m.lcJurnal = 'JC' && Jurnal Cumparari
|
||||
lcSCD = '4426'
|
||||
@@ -788,7 +788,6 @@ SET STEP ON
|
||||
lcMesaj = ''
|
||||
lnIdSet = 99999 && nota fara predefinire
|
||||
lnBut = lans(m.lnIdSet)
|
||||
Set Step On
|
||||
If m.lnBut = 1
|
||||
Select actactan
|
||||
Scatter Name loAct
|
||||
@@ -799,8 +798,18 @@ SET STEP ON
|
||||
lnNrAct = crsTVAIncasareTemp.nract
|
||||
lnIdFact = crsTVAIncasareTemp.id_fact
|
||||
lnSumaT = soldn
|
||||
lnSuma21 = soldn21
|
||||
lnSuma11 = soldn11
|
||||
lnSuma21 = 0
|
||||
lnSuma11 = 0
|
||||
lnSuma21T = 0
|
||||
lnSuma11T = 0
|
||||
If Type('crsTVAIncasareTemp.soldn21') = 'N'
|
||||
lnSuma21 = crsTVAIncasareTemp.soldn21
|
||||
lnSuma11 = crsTVAIncasareTemp.soldn11
|
||||
Endif
|
||||
If Type('crsTVAIncasareTemp.ro21nt') = 'N'
|
||||
lnSuma21T = crsTVAIncasareTemp.ro21nt
|
||||
lnSuma11T = crsTVAIncasareTemp.ro11nt
|
||||
Endif
|
||||
|
||||
lnSuma24 = soldn24
|
||||
lnSuma20 = soldn20
|
||||
@@ -809,16 +818,12 @@ SET STEP ON
|
||||
lnSuma5 = soldn5
|
||||
|
||||
If m.lcJurnal = 'JC' && Jurnal Cumparari
|
||||
lnSuma21T = ro21nt
|
||||
lnSuma11T = ro11nt
|
||||
lnSuma24T = ro24nt
|
||||
lnSuma20T = ro20nt
|
||||
lnSuma19T = ro19nt
|
||||
lnSuma9T = ro09nt
|
||||
lnSuma5T = ro05nt
|
||||
ELSE
|
||||
lnSuma21T = ro21nt
|
||||
lnSuma11T = ro11nt
|
||||
lnSuma24T = ro24nt
|
||||
lnSuma20T = ro20nt
|
||||
lnSuma19T = ro19nt
|
||||
@@ -830,7 +835,7 @@ SET STEP ON
|
||||
lnSuma = m.lnSumaT
|
||||
lnCotaTVA = 0.00
|
||||
If m.lnSumaT = 0
|
||||
lnSuma = Iif(m.lnCota = 1, m.lnSuma24, Iif(m.lnCota = 2, m.lnSuma20, Iif(m.lnCota = 3, m.lnSuma19, Iif(m.lnCota = 4, m.lnSuma9, Iif(m.lnCota = 5, m.lnSuma5, Iif(m.lnCota = 21, m.lnSuma21, m.lnSuma11))))))
|
||||
lnSuma = Iif(m.lnCota = 1, m.lnSuma24, Iif(m.lnCota = 2, m.lnSuma20, Iif(m.lnCota = 3, m.lnSuma19, Iif(m.lnCota = 4, m.lnSuma9, Iif(m.lnCota = 5, m.lnSuma5, Iif(m.lnCota = 6, m.lnSuma21, m.lnSuma11))))))
|
||||
lnCotaTVA = Iif(m.lnCota = 1, 1.24, Iif(m.lnCota = 2, 1.20, Iif(m.lnCota = 3, 1.19, Iif(m.lnCota = 4, 1.09, Iif(m.lnCota = 5, 1.05, Iif(m.lnCota = 6, 1.21, 1.11))))))
|
||||
Endif
|
||||
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
<!--
|
||||
28/07/2026
|
||||
ROACONT - 2.11.68
|
||||
ROACONT - 2.11.66
|
||||
|
||||
:modificare:
|
||||
Borderou eFactura, facturi primite. Facturile cu taxare inversa nu mai apar colorate ca avand diferenta fata de contabilitate. In eFactura taxarea inversa are TVA zero, dar in contabilitate se inregistreaza 4426 = 4427, iar diferenta afisata tine cont acum de acest TVA. Necesita actualizarea bazei de date.
|
||||
-->
|
||||
|
||||
<!--
|
||||
28/07/2026
|
||||
ROACONT - 2.11.67
|
||||
:nou:
|
||||
Note contabile. La salvarea notei, programul verifica incasarile si platile care au factura pereche completata si avertizeaza daca pentru vreuna dintre facturile cu TVA la incasare nu s-a adaugat nota de TVA exigibilizat. Notele de TVA exigibilizat se pot adauga pe loc. Verificarea poate fi oprita din settings.ini, sectiunea [tva], avertizare_exigibilizare=0.
|
||||
|
||||
:modificare:
|
||||
Alegere partener. Starea de TVA de la ANAF arata si de cand este valabila: data de la care partenerul este platitor sau neplatitor de TVA, data incetarii inregistrarii sau data anularii din oficiu. In lista, data apare doar cand starea difera de nomenclator, partenerul este inactiv sau perioada s-a incheiat deja; tasta F4 arata intotdeauna perioada completa si mesajul primit de la ANAF.
|
||||
Alegere partener. Starea de TVA de la ANAF arata si de cand este valabila, cu eticheta care spune ce reprezinta perioada: inregistrat TVA de la o data pana la alta, sau cod TVA anulat din data. In lista, perioada apare doar cand starea difera de nomenclator, partenerul este inactiv sau perioada s-a incheiat deja; tasta F4 arata intotdeauna perioada completa si mesajul primit de la ANAF, inclusiv atunci cand nu exista niciun partener cu codul fiscal corect.
|
||||
|
||||
:modificare:
|
||||
Initializari > Optiuni utilizator > "Verificare ANAF la alegerea partenerului". Mesajul cu setarea curenta intreaba acum daca doriti sa o modificati, iar la raspunsul Nu setarea ramane neschimbata. Cand verificarea este oprita de pe calculatorul curent, se propune tot oprirea locala, nu valoarea care ar fi oprit verificarea pentru utilizator pe orice calculator.
|
||||
|
||||
:eroare:
|
||||
Registrele de cumparari si vanzari, incepand cu 01.08.2025. Filtrul "Diferenta sold" si lista TVA-ului exigibilizat din plati nu luau in calcul facturile cu TVA neexigibil la 24% sau 20%, deci facturile mai vechi cu TVA la incasare lipseau din rezultate.
|
||||
|
||||
:eroare:
|
||||
Exigibilizare TVA la incasare din Registrul de cumparari/vanzari. Butonul dadea eroare pe perioadele anterioare anului 2025, iar cota de 21% nu era luata in calcul la impartirea soldului pe cote.
|
||||
|
||||
:eroare:
|
||||
Alegere partener. La codurile numerice de 13 cifre (CNP) si la codurile fiscale invalide, detaliile verificarii (F4) spuneau gresit "ANAF nu a raspuns - verificarea a fost sarita". Acum se afiseaza "Persoana fizica - CNP corect", respectiv "Cod fiscal invalid - nu s-a interogat ANAF".
|
||||
-->
|
||||
|
||||
<!--
|
||||
27/07/2026
|
||||
ROACONT - 2.11.66
|
||||
|
||||
:nou:
|
||||
D406 SAF-T. La validarea cu erori se deschide si un fisier de erori pe intelesul utilizatorului: pentru fiecare eroare - pagina, pozitia, partenerul sau contul in cauza si cum se rezolva. Erorile fictive "Cod taxa nu se afla in lista" (bug al validatorului ANAF) sunt separate la sfarsit si se pot ignora.
|
||||
|
||||
@@ -1,941 +0,0 @@
|
||||
<!-- /autoplan restore point: /c/Users/mmari/.gstack/projects/ROACONT/claude-partener-anaf-autoplan-restore-20260726-165226.md -->
|
||||
# Design: Asistenta alegere partener corect la introducere (verificare ANAF automata)
|
||||
|
||||
Generat de /office-hours pe 24.07.2026
|
||||
Branch: main (implementarea va merge pe claude/<subiect>)
|
||||
Repo: romfast/roacont (mirror git al SVN ^/ROACONT/Trunk)
|
||||
Status: APPROVED (24.07.2026, D7)
|
||||
Mode: Startup (intraprenoriat — produs intern ROA)
|
||||
|
||||
## Problema
|
||||
|
||||
La introducerea facturilor de achizitie/vanzare (si la incasari/plati) utilizatorul
|
||||
alege partenerul dintr-un dialog de cautare. Cand un partener isi schimba calitatea
|
||||
de platitor TVA, conventia ROA cere ALT partener (alt `nom_parteneri.id_par`) cu
|
||||
acelasi nume si cod fiscal cu/fara RO; cel vechi se marcheaza de regula INACTIV.
|
||||
Probleme concrete:
|
||||
|
||||
1. Utilizatorul nu are nicio informatie, la selectie, despre situatia ANAF curenta
|
||||
a partenerului (platitor TVA sau nu, activ/radiat) — statutul se poate schimba
|
||||
oricand, chiar daca partenerul nu are inca o "pereche".
|
||||
2. Perechea inactiva e complet invizibila (filtru hardcodat `STERS=0 AND INACTIV=0`),
|
||||
deci la o noua schimbare de calitate utilizatorul creeaza al TREILEA duplicat in
|
||||
loc sa reactiveze partenerul vechi.
|
||||
3. Alegerea gresita din pereche rupe imperecherea plati/incasari cu facturi
|
||||
(aceeasi cheie `id_part`), producand solduri fantoma pe doi parteneri.
|
||||
4. Importurile (eFactura, extrase) compara codul fiscal doar cu UPPER+ALLTRIM,
|
||||
deci `RO12345` si `12345` sunt terti diferiti — fabrica de duplicate noi.
|
||||
|
||||
## Evidenta cererii
|
||||
|
||||
- Situatie recurenta la clientii ROACONT: parteneri care comuta calitatea de
|
||||
platitor TVA de mai multe ori; utilizatori care aleg din greseala membrul gresit
|
||||
al perechii; corectii manuale costisitoare la imperecherea plati-facturi.
|
||||
- Butonul de verificare ANAF exista deja in nomenclator si e folosit — dar e in alt
|
||||
flux decat introducerea, unde se ia de fapt decizia.
|
||||
|
||||
## Status quo (fluxul actual, mapat in cod)
|
||||
|
||||
- Nucleu selectie: `CautPartenerContabilitate()` — `COMUN\programe\ocautare.prg:56`
|
||||
(SELECT `ID_PART, DENUMIRE, COD_FISCAL` din `NOM_PARTENERI`, filtru inactivi
|
||||
`:117-121`), varianta casa/banca `caut_parteneri()` `:161` (param `tlInactiv`
|
||||
`:175-177`), selectie multipla `caut_parteneri_xml()` `:199`.
|
||||
- Dialog: `cauta_alfa_form(_plus)` — `COMUN\clase\cauta_alfa_forms.vc2` (do_cauta,
|
||||
do_alege, do_adauga/buton Nou).
|
||||
- Puncte de apel: note contabile/facturi (`Clase\ointroduceri_cont.vc2`,
|
||||
`verific_partener` :1542/:4769 → `do_cauta_partener` :921/:3848), casa/banca
|
||||
(`COMUN\clase\ocasabanca.vc2:1788,1823`), stornare
|
||||
(`Ferestre\frm_stornare_plinc.sc2:368`), importuri
|
||||
(`frm_import_extrase_banca.sc2`, `frm_import_note_a4200.sc2`,
|
||||
`oproceduri_import.prg:364/:746`).
|
||||
- Verificare ANAF existenta: clasa `VerificareANAF` cu
|
||||
`ANAF_SincronWebService_PlatitorTva` — `COMUN\programe\validare.prg:1552,1603`
|
||||
(endpoint v9 `PlatitorTvaRest`, loturi max 100 CUI, pauza 1s; intoarce `scpTVA`,
|
||||
`statusInactivi`, `statusTvaIncasare`, denumire/adresa); buton `but_verifica`
|
||||
(`COMUN\clase\cmd_butoane.vc2:427`) doar pe nomenclator/formular verificare.
|
||||
- Statutul TVA NU e stocat pe partener: se deduce din prefixul `RO` al
|
||||
`COD_FISCAL` (ex. `saft_d406.prg:1066`). Rezultatele verificarii merg doar in
|
||||
istoric (`pack_parteneri.save_istoric_cod_fiscal`, `validare.prg:757`).
|
||||
|
||||
## Utilizator tinta si pana cea mai ingusta
|
||||
|
||||
Operatorul de contabilitate care introduce zilnic facturi si incasari/plati.
|
||||
Pana cea mai ingusta: in momentul alegerii partenerului, sa i se spuna automat
|
||||
"ANAF zice altceva decat codul fiscal al partenerului ales" si sa i se ofere
|
||||
perechea corecta (inclusiv cea inactiva) sau crearea unui partener nou.
|
||||
|
||||
## Constrangeri
|
||||
|
||||
- 80/20: modificari minime cu efect maxim; fara refactorizari; fara schimbare de
|
||||
schema Oracle (fara coloana "platitor TVA" pe `nom_parteneri`).
|
||||
- VFP9 legacy, fara teste automate; comentarii in cod max o linie `*!*`.
|
||||
- Conventia ROA ramane: partener nou la schimbare de calitate TVA; regula se
|
||||
documenteaza (nu era scrisa nicaieri pana la acest document).
|
||||
- Fara commit (git/SVN) fara review pe diff in `docs/`.
|
||||
|
||||
## Premise agreate
|
||||
|
||||
1. Modelul de date ramane neschimbat; statutul TVA se deduce din prefixul RO.
|
||||
2. (revizuita) Durerea are DOUA surse: lipsa de vizibilitate la selectie SI
|
||||
duplicatele nascute la import din compararea nenormalizata a codului fiscal.
|
||||
3. Punctul de interventie cu efect maxim e nucleul de selectie din `ocautare.prg`
|
||||
(+ dialogul `cauta_alfa_form`), mostenit de toate punctele de apel.
|
||||
4. (decizie utilizator, D5) Verificarea ANAF se face AUTOMAT la fiecare alegere de
|
||||
partener, nu doar cand exista pereche — statutul se poate schimba intre timp.
|
||||
|
||||
## Perspectiva cross-model (subagent independent)
|
||||
|
||||
- Steelman: dialogul de selectie devine "ghid de decizie" — o singura interventie
|
||||
in nucleu, mostenita de toate formularele, fara schimbare de model de date.
|
||||
- Insight-cheie: criteriul de "partener corect" nu e doar ANAF, ci SI "pe ce
|
||||
id_part sunt documentele existente" → fereastra de decizie afiseaza data
|
||||
ultimului document per membru al perechii.
|
||||
- Premisa contestata (acceptata): duplicatele se nasc si la import → fixul de
|
||||
potrivire normalizata intra in pachet.
|
||||
- Idee laterala retinuta ca transa viitoare: raport pasiv de discordante
|
||||
"prefix RO vs ultimul istoric ANAF" peste datele deja colectate.
|
||||
|
||||
## Abordari considerate
|
||||
|
||||
### A: Doar buton manual "Verificare ANAF" in dialogul de selectie
|
||||
Refolosire `but_verifica`; zero latenta automata. Respinsa ca insuficienta:
|
||||
protectia depinde de disciplina utilizatorului.
|
||||
|
||||
### B (ALEASA): Verificare ANAF automata la alegere + fereastra de decizie + fix import
|
||||
Detalii mai jos. Completeness 9/10 pe durerea descrisa.
|
||||
|
||||
### C: B + raport pasiv discordante ANAF din istoric
|
||||
Amanata ca transa separata (depinde de cat de des ruleaza clientii verificarea in
|
||||
lot; decuplata de hot path — se poate adauga oricand).
|
||||
|
||||
## Abordarea recomandata (aprobata: B)
|
||||
|
||||
Interventie intr-un singur punct comun + doua completari mici:
|
||||
|
||||
1. **Functie noua** `VerificaPartenerLaSelectie(toPartener)` in
|
||||
`COMUN\programe\ocautare.prg`, apelata din `CautPartenerContabilitate()`
|
||||
**inainte de blocul `ADAUGA_CORESP_TIP_PART` (`ocautare.prg:148-150`)** — daca
|
||||
utilizatorul comuta pe pereche, corespondentele tip-partener se adauga pe
|
||||
id_part-ul FINAL, nu pe cel initial. Acopera note/facturi, stornare, importuri
|
||||
fara sa atinga cele ~10 puncte de apel.
|
||||
- **Contract**: functia primeste si poate REESCRIE obiectul de retur
|
||||
(`id_part`, `nume/denumire`, `cod_fiscal`, `tip`); daca `loCauta` e NULL/gol
|
||||
(utilizatorul a renuntat la cautare), verificarea se sare complet.
|
||||
- **Politica de activare (decizie eng review D1, apelanti triati in cod)**:
|
||||
hibrid explicit. `CautPartenerContabilitate`: hook ON implicit (apelantii
|
||||
sunt fluxuri de introducere), cu opt-out DOAR la `orap_terti.prg:1019`
|
||||
(raport). `caut_parteneri`: hook OFF implicit, activat EXPLICIT (parametru
|
||||
nou `tlVerificaANAF`) la cele 4 puncte de introducere: `ocasabanca.vc2`
|
||||
(:1823), `frm_import_extrase_banca.sc2` (:2211, :2616),
|
||||
`ointroduceri_cont.vc2` (:9665, :9704). Fluxurile de consultare (fisa
|
||||
cont `fisa_cont_noua.sc2:459`, `orap_trezorerie.prg:31/:229`,
|
||||
`orap_terti.prg:826/:1794/:1986`) raman NEATINSE, fara nicio modificare.
|
||||
- Apel ANAF pentru CUI-ul partenerului ales: **wrapper nou single-CUI** peste
|
||||
`VerificareANAF` (functia de lot `ANAF_SincronWebService_PlatitorTva` e
|
||||
construita pentru loturi de 100 cu logging intens — nu se cheama direct in
|
||||
hot path); timeout-ul se seteaza pe obiectul WinHTTP cu `SetTimeouts`.
|
||||
- **Cache pe sesiune** — proprietate pe un obiect global existent (ex.
|
||||
`goApp`) sau colectie publica declarata in `roacont.prg`, cheie = CUI
|
||||
normalizat (fara RO), valoare = rezultat+timestamp; se goleste la
|
||||
schimbarea firmei. Un CUI verificat o data pe sesiune nu mai genereaza
|
||||
apel — limiteaza si presiunea pe serviciul ANAF (mai multi operatori
|
||||
simultan raman fiecare cu 1 apel/CUI/sesiune).
|
||||
- **Degradare tacuta**: fara internet / ANAF cazut / timeout ⇒ comportament
|
||||
identic cu azi (fara mesaje de eroare in hot path).
|
||||
- **Guard obligatoriu de mediu partajat**: `ocautare.prg` e inclus si de alte
|
||||
produse ROA — hook-ul verifica intai existenta clasei
|
||||
(`TYPE("goApp")`/`ALINES`+`SET("PROCEDURE")` sau `try CREATEOBJECT` cu
|
||||
fallback) si degradeaza tacut daca `validare.prg`/`VerificareANAF` nu sunt
|
||||
incarcate in acel produs. Fara guard, orice selectie de partener din
|
||||
produsele-frate ar crapa la runtime.
|
||||
- **Excluderi**: persoane fizice (TIP_PERSOANA=2 / CNP 13 cifre), coduri
|
||||
nenumerice dupa eliminarea RO, parteneri externi (COD_TARA<>RO).
|
||||
2. **La discordanta** (ANAF `scpTVA` ≠ prefixul RO al partenerului ales, sau
|
||||
`statusInactivi` = inactiv/radiat) — fereastra compacta de decizie
|
||||
(**forma noua mica in `COMUN\ferestre\`**, pe stilul dialogurilor existente;
|
||||
nu AMESSAGEBOX — are grid cu membrii perechii si 3-4 butoane):
|
||||
- Cauta perechea dupa CUI normalizat (fara RO), **INCLUSIV INACTIV=1**
|
||||
(interogare Oracle ieftina; filtrul gridului principal NU se schimba).
|
||||
- Afiseaza toti membrii: ID, denumire, cod fiscal, activ/inactiv,
|
||||
**data ultimului document** per `id_part` (MAX peste jurnal cumparari,
|
||||
jurnal vanzari si casa/banca — lista exacta a tabelelor se confirma la
|
||||
implementare; atentie la lipsa indexului pe `id_part` pe baze mari — se
|
||||
ruleaza DOAR in fereastra de discordanta, nu in hot path).
|
||||
- Actiuni: (a) alege perechea concordanta cu ANAF; (b) **swap ghidat** cu
|
||||
confirmare: reactiveaza perechea + inactiveaza partenerul curent (evita al
|
||||
treilea duplicat); dupa swap se face **refresh pe cursorul de selectie**
|
||||
(cel vechi dispare, cel reactivat apare); (c) fara pereche: propune buton
|
||||
"Nou" cu CUI-ul corect precompletat; (d) continua oricum (utilizatorul
|
||||
decide, nimic blocant).
|
||||
- **Guvernarea swap-ului (decizie CEO review D2)**: swap-ul se executa prin
|
||||
calea EXISTENTA de modificare nomenclator (`nom_parteneri_modifica` /
|
||||
pachetul Oracle aferent), NU prin UPDATE ad-hoc in ocautare.prg — o
|
||||
singura cale de scriere in nom_parteneri. Gating cu dreptul EXISTENT de
|
||||
modificare nomenclator parteneri (`verifica_drepturi`): fara drept,
|
||||
butonul de swap e dezactivat cu tooltip explicativ, dar perechea poate fi
|
||||
in continuare ALEASA.
|
||||
- **Kill-switch (decizie CEO review D4)**: optiune noua in `settings.ini`,
|
||||
sectiunea `[anaf]`, `verificare_selectie=1` implicit (citita cu `getini`).
|
||||
Cu 0, verificarea automata la selectie e oprita complet (comportament
|
||||
identic cu azi) — rollback chirurgical per statie/client fara downgrade
|
||||
de exe.
|
||||
- Concordanta ⇒ nicio fereastra, flux identic cu azi.
|
||||
3. **Fix import** (`Programe\oproceduri_import.prg`, potrivirea
|
||||
`GetPartenerByCodFiscal` :449 / dedup :4479-4495, citare verificata): cand
|
||||
potrivirea exacta esueaza, se incearca potrivirea pe CUI normalizat (fara
|
||||
RO); la gasire NU se alege automat — se cere confirmare ("exista partener cu
|
||||
acelasi CUI fara/cu RO — folosesti acela sau creezi unul nou?").
|
||||
**Pe loturi** (zip eFactura): confirmarile NU se pun una cate una in mijlocul
|
||||
importului — discordantele se colecteaza si se prezinta o singura data, la
|
||||
final, intr-o lista cu optiune per rand + "aplica la toate". Opreste fabrica
|
||||
de duplicate fara sa blocheze importul.
|
||||
4. **Optional** (redundant partial cu verificarea automata — se taie daca
|
||||
diff-ul creste): buton `but_verifica` si in `cauta_alfa_form`, pentru
|
||||
verificare manuala INAINTE de alegere.
|
||||
|
||||
### Ce NU facem (explicit)
|
||||
- Nu adaugam coloana TVA / data verificare pe `nom_parteneri`.
|
||||
- Nu facem merge/reasignare de documente intre id_part-uri.
|
||||
- Nu schimbam filtrul `STERS=0 AND INACTIV=0` al gridului de selectie.
|
||||
- Nu blocam alegerea: toate avertismentele sunt informative, cu "continua oricum".
|
||||
|
||||
## Intrebari deschise
|
||||
|
||||
1. ~~Drepturile swap~~ — REZOLVAT (CEO review D2): dreptul existent de
|
||||
modificare nomenclator parteneri; executie prin calea existenta de
|
||||
modificare, nu UPDATE ad-hoc.
|
||||
2. TTL cache: pe sesiune (propus) sau pe zi (persistat)? Propunerea: sesiune.
|
||||
3. `caut_parteneri_xml` (selectie multipla) intra in scope sau ramane pe fluxul
|
||||
vechi? Propunerea: ramane pe fluxul vechi (volum mare de CUI-uri per apel).
|
||||
4. Latenta reala ANAF in orele de varf — de masurat inainte de a decide timeout-ul.
|
||||
5. ~~Sursa `tip` la comutare~~ — REZOLVAT (eng review D2): la comutarea pe
|
||||
pereche, `tip` se recalculeaza pentru id-ul perechii cu acelasi criteriu ca
|
||||
in SELECT-ul gridului (apartenenta la `coresp_tip_part` pentru tipurile
|
||||
contului); hook-ul fiind inainte de blocul `ocautare.prg:148-150`, blocul
|
||||
existent adauga natural corespondenta lipsa pe id-ul FINAL. Nota de
|
||||
implementare: wrapper-ul single-CUI sta in `validare.prg`, langa clasa
|
||||
`VerificareANAF` (coeziune).
|
||||
|
||||
## Criterii de succes
|
||||
|
||||
- La alegerea unui partener discordant cu ANAF, utilizatorul vede fereastra de
|
||||
decizie intr-un timp acceptabil (tinta orientativa <3s; pragul final se
|
||||
fixeaza dupa masuratorile de latenta din Tema) si poate ajunge la perechea
|
||||
inactiva fara sa iasa din fluxul de introducere.
|
||||
- Zero regresie de viteza cand ANAF nu raspunde (degradare tacuta).
|
||||
- Importul eFactura nu mai creeaza partener nou fara confirmare cand exista
|
||||
pereche pe CUI normalizat.
|
||||
- Niciun duplicat nou "al treilea" la clientii-pilot dupa o luna de folosire.
|
||||
|
||||
## Plan de distributie
|
||||
|
||||
Livrare in `roacont.exe` prin fluxul existent: build din VFP IDE (`roacont.PJX`),
|
||||
revizie in `pj2`, intrare in `changelog_roacont.txt` (tag `:nou:`), commit SVN de
|
||||
catre Marius dupa aprobarea diff-ului. Nu necesita migrare Oracle (fara DDL).
|
||||
|
||||
## Dependinte
|
||||
|
||||
- Serviciul ANAF `PlatitorTvaRest v9` (deja folosit in verificarea din nomenclator).
|
||||
- `COMUN\programe\validare.prg` si `ocautare.prg` sunt partajate cu alte produse
|
||||
ROA care le includ — de verificat la implementare cine mai apeleaza
|
||||
`caut_parteneri`/`CautPartenerContabilitate` din alte produse (blast radius
|
||||
COMUN vs COMUNROA).
|
||||
|
||||
## Anexa: harta erorilor, edge-case-uri si teste (CEO review D3)
|
||||
|
||||
### Harta erorilor (regula-cheie: verificarea esueaza TACUT, swap-ul esueaza ZGOMOTOS)
|
||||
|
||||
| Cale | Ce poate merge prost | Actiune | Utilizatorul vede |
|
||||
|---|---|---|---|
|
||||
| Apel ANAF (wrapper) | timeout / DNS / HTTP 5xx / 429 | degradare tacuta + UN log pe sesiune (nu per apel) | ~~nimic (flux ca azi)~~ — REVIZUIT REVIZIA 5: banda gri "ANAF nu a raspuns - verificare sarita" in toate cazurile (timeout/DNS/conexiune refuzata SI HTTP 5xx/429); doar timeout/DNS/conexiune refuzata (`FARA_RASPUNS`) deschide intrerupatorul, vezi REVIZIA 5 pt. 5 |
|
||||
| Raspuns ANAF | JSON malformat / ~~CUI negasit~~ / refuz | tratat ca "fara informatie" → degradare tacuta | nimic — REVIZUIT REVIZIA 5: 404 cu `notFound` continand chiar CUI-ul cerut nu mai e "fara informatie", da verdict rosu "Cod fiscal inexistent la ANAF" (vezi REVIZIA 5 pt. 4) |
|
||||
| Query pereche Oracle | eroare goExecutor | degradare tacuta + log | nimic |
|
||||
| MAX(data doc) per id_part | lent / eroare | fereastra se deschide FARA coloana "ultim doc" | fereastra fara acea coloana |
|
||||
| Swap (via nom_parteneri_modifica) | eroare Oracle / lock / drept lipsa | mesaj de EROARE vizibil; partenerul ramane neschimbat | AMESSAGEBOX cu cauza |
|
||||
| Anulare fereastra (ESC/inchidere) | — | selectia ORIGINALA ramane valabila | revine in formular cu partenerul ales initial |
|
||||
| Dublu-click / reintrare | apel dublu in curs | guard de reintrare (flag "verificare in curs") — implementat REVIZIA 5 (`lVerificareInCurs`, vezi REVIZIA 5 pt. 8), nu doar cerut | un singur apel, o singura fereastra |
|
||||
|
||||
### Ordinea operatiilor (performanta)
|
||||
1. Alege partener → 2. cache lookup CUI → 3. apel ANAF (doar daca nu e in
|
||||
cache) → 4. concordant ⇒ STOP (zero query suplimentar pe selectiile normale)
|
||||
→ 5. DOAR la discordanta: query pereche pe CUI normalizat (inclusiv inactivi)
|
||||
+ MAX(data doc) per membru → 6. fereastra de decizie.
|
||||
|
||||
### Reguli de implementare
|
||||
- **`NormalizeazaCUI()`** — functie UNICA in COMUN (strip RO doar daca restul
|
||||
e numeric, UPPER, fara spatii), folosita de wrapper, de query-ul de pereche
|
||||
si de fixul de import. Fara logica duplicata in 3 locuri.
|
||||
- **Indicator vizual**: wait cursor + text scurt "Verificare ANAF..." pe durata
|
||||
apelului (hot path-ul devine perceptibil doar cand chiar se apeleaza ANAF).
|
||||
- **Logging**: fiecare discordanta gasita se logheaza in `goLog` (CUI, id_part
|
||||
ales, ce a zis ANAF, ce a decis utilizatorul) — diagnosticabil ulterior.
|
||||
- **Kill-switch**: `settings.ini [anaf] verificare_selectie=0` dezactiveaza
|
||||
complet hook-ul (verificat la intrare in functie, inainte de orice).
|
||||
|
||||
### Lista de teste (manual / harness headless — test_init_env_auto)
|
||||
1. Partener concordant (RO + ANAF platitor) → niciun mesaj, flux identic.
|
||||
2. Discordant cu pereche ACTIVA → fereastra, alegerea perechii scrie id-ul corect.
|
||||
3. Discordant cu pereche INACTIVA → fereastra o arata; swap reactiveaza/inactiveaza
|
||||
+ refresh cursor; fara drept de nomenclator → buton dezactivat, alegerea merge.
|
||||
4. Discordant FARA pereche → propunere "Nou" cu CUI precompletat.
|
||||
5. ~~Fara internet / ANAF cazut → zero mesaje, flux identic cu azi, un log.~~
|
||||
REVIZUIT REVIZIA 5: Fara internet / ANAF cazut → banda gri "ANAF nu a
|
||||
raspuns - verificare sarita" (nu zero mesaje), niciun dialog modal, flux
|
||||
fara blocare; log pe tranzitie de stare, nu per apel (vezi REVIZIA 5 pt. 1-2).
|
||||
6. Persoana fizica (CNP) / partener extern (COD_TARA<>RO) / CUI gol → skip total.
|
||||
7. Import lot eFactura cu discordante → confirmarile apar O DATA la final,
|
||||
"aplica la toate" functioneaza, niciun partener creat fara confirmare.
|
||||
8. Dublu-click rapid pe rand → un singur apel ANAF, o singura fereastra.
|
||||
9. Kill-switch 0 → comportament identic cu versiunea anterioara.
|
||||
10. Cache: al doilea document pe acelasi partener in aceeasi sesiune → zero
|
||||
apel ANAF nou.
|
||||
11. REGRESIE (eng review D1): fisa de cont si rapoartele terti/trezorerie NU
|
||||
declanseaza verificarea ANAF — comportament identic cu versiunea anterioara.
|
||||
|
||||
## Specificatia vizuala a ferestrei de decizie (design review D2-D3)
|
||||
|
||||
```
|
||||
+--- Verificare partener ANAF ------------------------------------+
|
||||
| ANAF: NEPLATITOR TVA (din 01.03.2026). Partenerul ales are |
|
||||
| codul fiscal RO12345678 — nu corespunde. | <- verdictul, PRIMUL
|
||||
+------------------------------------------------------------------+
|
||||
| ID | Denumire | Cod fiscal | Stare | Ultim document |
|
||||
| 1234 | FIRMA SRL | RO12345678 | Activ | 15.06.2026 | <- alegerea initiala
|
||||
|>5678 | FIRMA SRL | 12345678 | INACTIV | 20.02.2026 | <- PERECHEA, preselectata
|
||||
+------------------------------------------------------------------+
|
||||
| [Alege selectat] [Reactiveaza+inactiveaza] [Nou] [Continua] |
|
||||
+------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
- **Ierarhie**: 1) verdictul intr-o propozitie (status ANAF + data + de ce nu
|
||||
corespunde), 2) gridul cu toti membrii, randul CONCORDANT cu ANAF preselectat,
|
||||
3) butoanele. Ton utilitar, fara alarmism — o singura decizie pe ecran.
|
||||
- **Tastatura (decizie D2)**: Enter = alege randul selectat (preselectat:
|
||||
perechea concordanta); sageti = schimba selectia; ESC = pastreaza alegerea
|
||||
originala (inchide fara nicio actiune); swap DOAR pe butonul dedicat, cu
|
||||
confirmare suplimentara — niciodata pe Enter. Hotkey-uri pe butoane (VFP \<).
|
||||
- **Conventii existente refolosite**: randul INACTIV colorat gri
|
||||
RGB(225,225,225) + tooltip — aceeasi conventie pe care utilizatorii o stiu
|
||||
din cauta_alfa_form ("partenerii de alt tip sunt colorati gri",
|
||||
ocautare.prg:136-137); butoane din cmd_butoane.vcx; erori prin AMESSAGEBOX;
|
||||
fereastra pe clasele de baza cont2000 (stil identic cu dialogurile existente).
|
||||
- **Starea "fara pereche"**: fereastra FARA grid — doar verdictul + butoanele
|
||||
[Nou (CUI precompletat)] si [Continua]; Enter = Continua (aici NU exista
|
||||
alternativa corecta de preselectat, deci implicitul ramane conservator).
|
||||
- **Butonul de swap fara drept de nomenclator**: dezactivat (nu ascuns), cu
|
||||
tooltip "Necesita drept de modificare nomenclator parteneri".
|
||||
- **Indicator in dialogul de selectie**: pe durata apelului ANAF — wait cursor
|
||||
+ WAIT WINDOW "Verificare ANAF..." NOWAIT, sters imediat dupa raspuns;
|
||||
vizibil doar cand apelul chiar are loc (cache miss).
|
||||
|
||||
## Regula de lucru documentata (nota ceruta — nu era scrisa nicaieri)
|
||||
|
||||
**Conventie ROA — schimbarea calitatii de platitor TVA a unui partener:**
|
||||
1. NU se modifica codul fiscal al partenerului existent (istoricul documentelor
|
||||
ramane legat de `id_part`-ul vechi si de statutul TVA de la acea data).
|
||||
2. Se foloseste ALT partener cu acelasi nume si codul fiscal cu/fara RO dupa noua
|
||||
calitate. Daca perechea EXISTA deja (chiar inactiva), se REACTIVEAZA aceea —
|
||||
nu se creeaza al treilea duplicat.
|
||||
3. De regula, membrul care nu mai corespunde se marcheaza INACTIV ca sa nu mai
|
||||
apara la introducere. Daca ambii raman activi (situatii tranzitorii),
|
||||
utilizatorul alege dupa situatia ANAF si dupa documentul introdus.
|
||||
4. La incasari/plati se alege ACELASI `id_part` ca pe facturile pe care le
|
||||
stinge — altfel imperecherea plati-facturi se rupe.
|
||||
|
||||
(La implementare, acest text se muta/copiaza si in `COMUN\docs\` daca vrem sa fie
|
||||
vizibil si celorlalte produse ROA.)
|
||||
|
||||
## Tema (assignment)
|
||||
|
||||
Inainte de implementare, ruleaza pe o baza reala de client doua masuratori:
|
||||
1. `SELECT` de numarare: cate grupuri de CUI normalizat (fara RO) au >1 partener
|
||||
si cati dintre ei au membri inactivi — dimensioneaza problema reala.
|
||||
2. 10 apeluri ANAF `PlatitorTvaRest` la ore diferite — masoara latenta reala
|
||||
pentru alegerea timeout-ului.
|
||||
Rezultatele decid timeout-ul si daca fereastra de decizie are nevoie de
|
||||
pre-incarcare asincrona.
|
||||
|
||||
## Ce am observat la felul in care gandesti
|
||||
|
||||
- Ai respins ambele extreme si ai corectat exact pe mecanism: "chiar daca nu
|
||||
exista o pereche, tot trebuie facuta verificarea automata pe ANAF, pentru ca
|
||||
intre timp partenerul isi poate fi schimbat calitatea" — ai vazut ca riscul e
|
||||
in timp, nu in structura datelor.
|
||||
- Ai adus singur cazul-limita care omoara solutiile naive: "partenerul anterior
|
||||
este marcat inactiv... si exista situatii in care isi schimba calitatea de mai
|
||||
multe ori" — perechea invizibila din cauza filtrului INACTIV=0.
|
||||
- "80/20 minim de modificari cu maxim de efecte" — ai cerut explicit constrangerea
|
||||
de cost inainte de solutii, nu dupa.
|
||||
|
||||
## GSTACK REVIEW REPORT
|
||||
|
||||
| Review | Trigger | Why | Runs | Status | Findings |
|
||||
|--------|---------|-----|------|--------|----------|
|
||||
| CEO Review | `/plan-ceo-review` | Scope & strategy | 1 | CLEAR | mode: HOLD_SCOPE, 3 constatari decise (swap guvernat, anexa spec, kill-switch), 0 critical gaps |
|
||||
| Codex Review | `/codex review` | Independent 2nd opinion | 0 | — | sarit (2 verificari independente rulate azi la office-hours) |
|
||||
| Eng Review | `/plan-eng-review` | Architecture & tests (required) | 1 | CLEAR | 2 issues (politica hook hibrid D1, recalc tip D2), 13/13 cai cu test, 0 critical gaps |
|
||||
| Design Review | `/plan-design-review` | UI/UX gaps | 1 | CLEAR | score: 5/10 → 9/10, 3 decizii (focus, Enter=perechea, spec vizuala) |
|
||||
| DX Review | `/plan-devex-review` | Developer experience gaps | 0 | — | n/a (nu e produs developer-facing) |
|
||||
|
||||
- **UNRESOLVED:** 0 — toate deciziile CEO (D1-D6), eng (D1-D2) si design (D1-D3) au raspuns.
|
||||
- **VERDICT:** CEO + ENG + DESIGN CLEARED — planul e complet, gata de implementare pe branch claude/partener-anaf.
|
||||
|
||||
---
|
||||
|
||||
## REVIZIA 2 (25.07.2026) — V2': verdict ANAF in formularul de cautare
|
||||
|
||||
Status: APPROVED (25.07.2026, feedback live Marius + D1a/D2 confirmate).
|
||||
Aceasta revizie INLOCUIESTE sectiunile "fereastra de decizie" si "Specificatia
|
||||
vizuala a ferestrei de decizie" din designul initial. Restul (hook, wrapper
|
||||
single-CUI, NormalizeazaCUI, cache, kill-switch, excluderi, degradare tacuta,
|
||||
fix import, politica de activare pe apelanti) RAMANE VALABIL.
|
||||
|
||||
### Motivatia (test live 25.07, ROMFAST 1879855)
|
||||
|
||||
Fereastra de decizie implementata in rundele 1-8 s-a dovedit confuza in uz real:
|
||||
1. Utilizatorul nu intelege de ce a aparut fereastra; mesajul de sus e insuficient
|
||||
(fara numele partenerului, fara ce inseamna verdictul, fara ce are de facut).
|
||||
2. Gridul arata TOT grupul de CUI, inclusiv membrii cu aceeasi problema — nu ghideaza.
|
||||
3. Butonul Inactiveaza/Activeaza cere o operatiune de nomenclator ambigua (pe care
|
||||
rand? in pereche cu cine?) in mijlocul fluxului de introducere.
|
||||
4. Verificarea ANAF e invizibila cand totul corespunde (WAIT WINDOW NOWAIT dispare
|
||||
la orice miscare de mouse) — utilizatorul nu stie ca protectia exista.
|
||||
5. Butonul "Nou" din fereastra dubleaza butonul Nou al cautarii.
|
||||
|
||||
### Solutia revizuita
|
||||
|
||||
**1. Label ANAF in `cauta_alfa_form` (COMUN\clase\cauta_alfa_forms.vc2)** —
|
||||
verdictul pentru RANDUL CURENT din grid, vizibil INAINTE de alegere:
|
||||
|
||||
```
|
||||
+--- Cautare partener --------------------------------------------+
|
||||
| Cautare: ROMFAST_ [Nou] |
|
||||
| | Denumire | Cod fiscal | ... ||
|
||||
| |>ROMFAST CONSTANTA SRL | 1879855 | ||
|
||||
| ANAF: PLATITOR TVA — codul 1879855 (fara RO) NU corespunde. | <- label
|
||||
+------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
Starile labelului (texte finale, spec Marius 25.07):
|
||||
- gol — persoana fizica / partener extern / CUI nenumeric / kill-switch 0;
|
||||
- ~~eroare-timeout ANAF (degradare tacuta)~~ — REVIZUIT REVIZIA 5: la lipsa
|
||||
raspunsului HTTP labelul nu mai ramane gol, arata gri "ANAF nu a raspuns -
|
||||
verificare sarita" (vezi REVIZIA 5 pt. 1);
|
||||
- "Verificare ANAF..." — pe durata apelului (persistent, nu WAIT WINDOW);
|
||||
- concordant (VERDE): "ANAF: Platitor TVA (RO1879855 FAGA SRL)" — cod fiscal +
|
||||
denumirea ANAF;
|
||||
- discordant (ROSU, bold): "(!) ANAF: Platitor TVA (1879855 ROMFAST CONSTANTA
|
||||
SRL) » detalii" — marcaj (!) si sageata » (chr 187, cp1252) care indica
|
||||
apasarea pentru detalii; cursor mana pe label (clickabil).
|
||||
|
||||
Declansare: `AfterRowColChange` reporneste un timer debounce (~400ms); apelul se
|
||||
face doar daca utilizatorul ramane pe rand (cache per CUI pe sesiune → un singur
|
||||
apel real per partener). Navigarea rapida nu declanseaza nimic.
|
||||
|
||||
Blast radius: label + timer + proprietate de activare intra in clasa comuna, dar
|
||||
INERTE implicit (proprietate .F.); se activeaza doar din cautarile de parteneri
|
||||
cu verificare ANAF (tlVerificaANAF / CautPartenerContabilitate), cu guard-urile
|
||||
existente pentru produsele-frate. Celelalte nomenclatoare nu vad nicio diferenta.
|
||||
|
||||
**2. Dublu-click pe label** → AMESSAGEBOX cu detaliile complete: nume + cod ales,
|
||||
verdict ANAF, codul fiscal corect, perechea existenta (cautata pe CUI normalizat,
|
||||
INCLUSIV inactiva) sau indrumarea catre butonul Nou al cautarii daca nu exista.
|
||||
|
||||
**3. La alegerea unui partener discordant (D1a)** — plasa de siguranta: apare
|
||||
automat dialogul de decizie (formularul de cautare ramane deschis). Format
|
||||
final (spec Marius, 25.07) — lista numerotata + butoane care spun exact ce aleg:
|
||||
|
||||
```
|
||||
1. ROMFAST CONSTANTA SRL (CUI: 1879855, ID: 108) ANAF: PLATITOR TVA
|
||||
2. FAGA SRL (CUI: RO1879855, ID: 200140) inactiv
|
||||
|
||||
[Alege FAGA SRL] [Alege ROMFAST CONSTANTA SRL] [Renunta]
|
||||
```
|
||||
|
||||
- Butonul perechii alege perechea; butonul alesului pastreaza alegerea;
|
||||
Renunta (si ESC) = ramai in cautare. Fara linie de mapare Da/Nu.
|
||||
- Fara pereche: randul 1 + "Nu exista partener cu CUI RO1879855 (il puteti
|
||||
crea cu butonul Nou)." — butoane [Continua] [Renunta].
|
||||
- Mai multi candidati: lista numerotata a candidatilor + "Alegeti manual." —
|
||||
buton unic, ramai in cautare.
|
||||
- Implementare: AMESSAGEBOX nu suporta etichete custom pe butoane — dialogul e
|
||||
o clasa mica `DEFINE CLASS ... AS Form` definita IN COD in ocautare.prg
|
||||
(fara .scx, fara binar), 2-3 butoane cu Caption dinamic (denumiri trunchiate
|
||||
rezonabil). Detaliile de la dublu-click pe label folosesc acelasi format
|
||||
numerotat, pur informativ.
|
||||
|
||||
**FARA activare/reactivare (decizie Marius, 25.07)**: alegerea unei perechi
|
||||
inactive doar FOLOSESTE acel id_part pe document — partenerul ramane inactiv,
|
||||
"inactiv" apare pur informativ. Motivatie: pe incasari/plati utilizatorul vrea
|
||||
partenerul cu facturile/soldul, indiferent de TVA; nu toti utilizatorii au
|
||||
drepturi de modificare nomenclator; orice operatiune de nomenclator in fluxul
|
||||
de introducere incurca. Activarea/inactivarea raman exclusiv operatiuni
|
||||
manuale in nomenclatorul de parteneri.
|
||||
|
||||
**4. Alegere rapida (D2)**: daca utilizatorul alege inainte ca timerul sa fi
|
||||
verificat randul, verificarea se face PE LOC la selectie (alegerile rapide nu
|
||||
ocolesc protectia).
|
||||
|
||||
### Ce se ELIMINA din implementarea rundelor 1-8
|
||||
|
||||
- `COMUN\ferestre\frm_verif_partener_anaf` (.sc2/.scx/.sct) — fereastra dispare.
|
||||
- But_swap / ActualizeazaCaptionSwap / apelul `PACK_PARTENERI.MODIFICA_INACTIV`.
|
||||
- Migrarea `ff_2026_07_24_01_COMUN_PACK_PARTENERI.sql` — NU se mai ruleaza pe
|
||||
productie; `versiune_db.txt` revine la valoarea anterioara. (Procedura ramane
|
||||
aplicata pe schema de test — inofensiva, se poate drop-ui separat.)
|
||||
- Deschiderea ferestrei din hook (`Do Form ... frm_verif_partener_anaf`).
|
||||
|
||||
### Ce se PASTREAZA neschimbat
|
||||
|
||||
`NormalizeazaCUI`, wrapper single-CUI `ANAF_VerificaCuiSingle`, cache-ul pe
|
||||
sesiune + golirea la schimbarea firmei, kill-switch `[anaf] verificare_selectie`,
|
||||
excluderile (PF/extern/nenumeric), degradarea tacuta, fixul de import
|
||||
(oproceduri_import.prg), politica de activare pe apelanti (tlVerificaANAF,
|
||||
opt-out orap_terti), regula de lucru documentata, harta erorilor (mai putin
|
||||
randul de swap — eliminat).
|
||||
|
||||
### Teste afectate
|
||||
|
||||
Suita `COMUN\utile\Teste\partener_anaf\` se rescrie pe noul flux: label (stari,
|
||||
debounce, dublu-click), D1a (cele 3 butoane), D2 (alegere rapida), reactivare
|
||||
single-row, regresie nomenclatoare non-partener (label inert).
|
||||
|
||||
---
|
||||
|
||||
## REVIZIA 3 (25.07.2026) — verdict la data documentului + texte finale
|
||||
|
||||
Status: APPROVED (25.07.2026, feedback live Marius pe screenshot-ul din productie).
|
||||
Aceasta revizie ajusteaza doar textele si adauga data documentului; restul REVIZIEI 2
|
||||
ramane valabil.
|
||||
|
||||
### 1. Textul labelului
|
||||
|
||||
Denumirea si codul fiscal afisate sunt cele de la ANAF (nu cele ale randului ales),
|
||||
in ordinea NUME apoi COD, plus data la care s-a cerut starea:
|
||||
|
||||
- concordant (verde): `ANAF: Platitor TVA (ROMFAST SRL RO1879855) la 15.06.2026`
|
||||
- discordant (rosu, bold): `(!) ANAF: Platitor TVA (ROMFAST SRL RO1879855) la 15.06.2026 >> click detalii`
|
||||
|
||||
Sageata `»` (Chr(187)) se inlocuieste cu `>>` ASCII (fara risc de encoding cp1252),
|
||||
iar textul devine `click detalii`. Marcajul `(!)` se pastreaza la discordanta.
|
||||
|
||||
### 2. Dialogurile (detalii la dublu-click + confirmarea la alegere)
|
||||
|
||||
Format aerisit, cu antet comun (metodele `AntetDialog` / `ListaCorecti` din
|
||||
`anaf_verif_cautare`):
|
||||
|
||||
```
|
||||
ROMFAST CONSTANTA SRL (CUI: 1879855, ID: 108)
|
||||
|
||||
! ANAF: Platitor TVA (ROMFAST SRL, RO1879855) la 15.06.2026
|
||||
|
||||
Parteneri ROA cu CUI RO1879855:
|
||||
1. ABSOLUT SRL (ID: 598) inactiv
|
||||
2. ROMFAST S.R.L. (ID: 614)
|
||||
```
|
||||
|
||||
- lista contine DOAR partenerii cu codul fiscal corect (fara cel deja ales),
|
||||
ordonati alfabetic (`ORDER BY UPPER(DENUMIRE)` in `ANAF_CautaPereche`);
|
||||
- fara candidati: `Nu exista partener cu CUI RO1879855 (il puteti crea cu butonul Nou).`;
|
||||
- la alegere, ultimul rand ramane maparea butoanelor:
|
||||
`Da = alege 1. <denumire> Nu = pastreaza selectia Abandon = inapoi la cautare`.
|
||||
|
||||
### 3. Starea ANAF la data documentului
|
||||
|
||||
Serviciul `PlatitorTvaRest v9` primea deja o data (era `Date()`); acum primeste data
|
||||
documentului, cand exista:
|
||||
|
||||
- `ANAF_VerificaCuiSingle(tcCui, tdData)` si `ANAF_StarePartener(tcCodFiscal, tdData)`;
|
||||
data goala/lipsa => data curenta (comportament identic cu inainte);
|
||||
- cheia de cache pe sesiune devine `CUI + data` (acelasi CUI la doua date = doua apeluri);
|
||||
- transport: cheia de hash `dDataDoc` pentru `CautPartenerContabilitate`, parametrul 7
|
||||
`tdDataDoc` pentru `caut_parteneri`; proprietatea `dDataDoc` pe `anaf_verif_cautare`;
|
||||
- sursele datei in apelanti: `poAct.dataact` (introduceri note/facturi,
|
||||
`ointroduceri_cont.vc2`: `do_cauta_partener` x2, gridurile de partener din
|
||||
`frm_note`/`frm_note2007`, `frm_plati_impozite`) si `poDate.dataact` (facturare,
|
||||
`ofacturare.vc2`: `do_cauta_client`, `do_cauta_furnizor`); toate cu guard `Type(...)='D'`.
|
||||
|
||||
### 4. Casa/banca — verificare scoasa
|
||||
|
||||
Punctul activat in runda 1 (`ocasabanca.vc2`, `Ck_bancasa.InteractiveChange`) NU e
|
||||
introducere de document: e checkbox-ul de filtrare care alege casa/banca proprie
|
||||
(`filtru = ' AND id_bancasa = ...'`), fara data de document. Verificarea ANAF se
|
||||
dezactiveaza acolo (revenire la apelul fara `tlVerificaANAF`).
|
||||
|
||||
### 5. Comentarii in cod
|
||||
|
||||
Regula de lucru confirmata de Marius (25.07): fara comentarii in corpul codului; o
|
||||
singura linie scurta in antetul fisierului, fara autor "claude". Comentariile inline
|
||||
adaugate in rundele 1-11 pentru aceasta functionalitate se elimina.
|
||||
|
||||
### 6. Import din extras de cont — corectie de abordare (decizie Marius, 25.07)
|
||||
|
||||
La importul din extras e vorba de PLATI/INCASARI, nu de facturi: statutul ANAF
|
||||
(platitor/neplatitor) nu ajuta cu nimic acolo. Singurul criteriu care conteaza e
|
||||
"partenerul pe care stau facturile", pentru ca `GetDocumentByContPartenerAct`
|
||||
(`COMUN\programe\oproceduri_comune.prg:6942`) cauta documentul strict pe `id_part`
|
||||
(`ireg_parteneri`, an/luna curente), iar `GetPartenerByCodFiscal` (`:6557`)
|
||||
normalizeaza CUI-ul si ia orbeste `MAX(id_part)` din grup.
|
||||
|
||||
Prin urmare:
|
||||
- verificarea ANAF se scoate din formularul de import extrase (cele doua pickere
|
||||
manuale de partener din configurari);
|
||||
- confirmarea pe loturi pentru discordantele de CUI (adaugata in runda 1) se
|
||||
ELIMINA — importul nu mai intreaba nimic;
|
||||
- cand exista mai multi parteneri cu acelasi CUI normalizat, alegerea se face
|
||||
dupa documente, nu dupa `MAX(id_part)`:
|
||||
1. daca linia de extras are numar de document si optiunea "Asociaza facturi" e
|
||||
bifata, documentul se cauta pe TOTI membrii grupului, iar nota merge pe
|
||||
partenerul pe care s-a gasit factura (se muta si `id_partd`/`id_partc`);
|
||||
2. altfel, se alege membrul cu documente in perioada curenta (`ireg_parteneri`,
|
||||
numar de randuri, la egalitate soldul cel mai mare in modul);
|
||||
3. daca niciun membru nu are documente, ramane alegerea de azi.
|
||||
- la initializare facturi din balanta (`CompleteazaParteneriROA`) confirmarea per
|
||||
partener se elimina: se foloseste tacut partenerul existent cu acelasi CUI
|
||||
normalizat, iar cursorul de parteneri primeste coloana normalizata calculata o
|
||||
singura data (fara `Locate` cu apel de functie per partener).
|
||||
|
||||
---
|
||||
|
||||
## REVIZIA 4 (26.07.2026) — verificare neintruziva la alegerea partenerului
|
||||
|
||||
Status: APROBATA CU MODIFICARI dupa review /autoplan (26.07.2026, 3 lentile:
|
||||
CEO / design / inginerie, Codex indisponibil pe masina). Aceasta revizie
|
||||
inlocuieste punctul 3 al REVIZIEI 2 ("La alegerea unui partener discordant")
|
||||
si punctul 2 al REVIZIEI 3 (maparea butoanelor la alegere).
|
||||
|
||||
Motivatia (Marius, 26.07): formularul de avertizare de la alegerea partenerului
|
||||
e intruziv si confuz, mai ales pe incasari/plati, unde partenerul NU e o alegere
|
||||
libera — e determinat de facturile de imperecheat, iar o propunere de schimbare
|
||||
a partenerului exact in acel punct sparge imperecherea (`GetDocumentByContPartenerAct`
|
||||
cauta documentul strict pe `id_part`).
|
||||
|
||||
### Decizii de poarta (review /autoplan, 26.07)
|
||||
|
||||
| # | Decizie | Continut |
|
||||
|---|---|---|
|
||||
| D1 / UC1 | **Marcajul colorat pe toate randurile NU intra in aceasta transa** | Implicit ramane nivelul 1 (verdict pe randul curent). Ghidarea o preia, in Detalii, semnul "are documente in perioada" pe fiecare candidat. Marcajul in grid devine transa separata, dupa masuratori (vezi "Transa viitoare") |
|
||||
| UC2 | **Polaritate inversata** | `CautPartenerContabilitate` devine OFF implicit + opt-in explicit `lVerificaANAF=>1` pe 8 apeluri. Simetric cu `caut_parteneri` |
|
||||
| UC3 | **Detalii ramane AMESSAGEBOX** | Fara formular nou definit in cod. Optiunea per utilizator se comuta dintr-un punct de meniu, dupa modelul `RC_REGCUMP_LISTARE_BUG` |
|
||||
|
||||
### 1. Ce se scoate din calea de alegere
|
||||
|
||||
`VerificaAlegere` (`ocautare.prg:428`) nu mai deschide nimic pe comportamentul
|
||||
implicit: cand nivelul de confirmare e 0 face `Return .T.` imediat, fara apel
|
||||
sincron la ANAF.
|
||||
|
||||
La nivelul 3 (opt-in) comportamentul ramane exact cel de azi: verificare sincrona
|
||||
+ `Amessagebox(...,3+48)` cu lista numerotata + `aInputBox` pentru varianta.
|
||||
ATENTIE (eroare factuala corectata): clasa `anaf_dialog` **nu exista** — a fost
|
||||
eliminata la runda 11, iar confirmarea de azi e AMESSAGEBOX. Nicio parte a acestei
|
||||
revizii nu se sprijina pe ea.
|
||||
|
||||
Chiar cand nu se afiseaza nimic, alegerea unui partener discordant **se logheaza**
|
||||
in `goLog` (CUI, `id_part` ales, verdict) — e singura sursa de date despre
|
||||
frecventa reala a problemei, si conditia de intrare pentru transa viitoare.
|
||||
|
||||
### 2. Detalii (click pe label) — decizia, la cererea utilizatorului
|
||||
|
||||
Ramane `AMESSAGEBOX`, cu formatul din REVIZIA 3, plus doua schimbari:
|
||||
|
||||
1. **Discriminatorul pe documente** langa fiecare candidat — criteriul care conteaza
|
||||
efectiv la imperechere, nu statutul TVA:
|
||||
```
|
||||
ROMFAST CONSTANTA SRL (CUI: 1879855, ID: 108)
|
||||
|
||||
! ANAF: Platitor TVA (ROMFAST SRL, RO1879855) la 15.06.2026
|
||||
|
||||
Parteneri ROA cu CUI RO1879855:
|
||||
1. ABSOLUT SRL (ID: 598) inactiv
|
||||
2. ROMFAST S.R.L. (ID: 614) are documente in perioada
|
||||
```
|
||||
Sursa: `ireg_parteneri` pe anul/luna curente, un singur SELECT, **doar la
|
||||
deschiderea Detalii** (niciodata in calea de navigare prin grid).
|
||||
2. **Alegerea variantei se face de aici** (butoanele AMESSAGEBOX + `aInputBox`
|
||||
cand sunt mai multi candidati), adica exact mecanismul existent, mutat de pe
|
||||
calea impusa pe calea ceruta de utilizator. Foloseste `poANAFInlocuire` +
|
||||
`AplicaInlocuirePartenerANAF`, cu guardul obligatoriu de la punctul 5 (C2).
|
||||
|
||||
Detalii se deschide si cand `oStare` e `.Null.` (ANAF picat, cod fiscal invalid):
|
||||
afiseaza antetul si o linie explicita ("ANAF nu a raspuns — verificarea a fost
|
||||
sarita"), nu returneaza mut ca azi (`ocautare.prg:411`).
|
||||
|
||||
Labelul devine clickabil pe ambele stari (verde si rosu) si primeste **F4** ca
|
||||
echivalent de tastatura (utilizatorii lucreaza fara mouse); textul labelului spune
|
||||
`F4 = detalii`. Codul de tasta pentru F4 se confirma la implementare — ramura
|
||||
`OTHERWISE` din `cauta_alfa_forms.vc2:715` nu intra in conflict cu redirectarea
|
||||
literelor catre caseta de cautare.
|
||||
|
||||
### 3. Cascada de optiuni — o singura scara
|
||||
|
||||
O singura optiune, `RC_ANAF_VERIF_SELECTIE`, cu valori cumulative:
|
||||
|
||||
| Valoare | Comportament |
|
||||
|---|---|
|
||||
| 0 | oprit (nicio verificare) |
|
||||
| **1** | **verdict pe randul curent (implicit)** |
|
||||
| 2 | rezervat pentru marcajul in grid (transa viitoare) |
|
||||
| 3 | verdict + confirmare la alegerea unui partener discordant (opt-in) |
|
||||
|
||||
Rezolvare, prima valoare gasita castiga:
|
||||
1. `settings.ini [anaf] verificare_selectie` — **doar kill-switch pe valoarea 0**,
|
||||
nu sursa de nivel (altfel bifa/optiunea utilizatorului devine silentios
|
||||
inoperanta si nimeni nu poate explica de ce);
|
||||
2. `citeste_optiune_utilizator('RC_ANAF_VERIF_SELECTIE')` — per utilizator;
|
||||
3. `citeste_optiune('RC_ANAF_VERIF_SELECTIE')` — per firma;
|
||||
4. hardcodat: 1.
|
||||
|
||||
Comutarea per utilizator: punct de meniu, dupa modelul `RC_REGCUMP_LISTARE_BUG`
|
||||
(citeste valoarea, arata starea, scrie noua valoare cu `scrie_optiune_utilizator`).
|
||||
Etichete fara ambiguitate: `Arata starea ANAF in cautarea de partener` /
|
||||
`Intreaba la alegerea unui partener discordant`.
|
||||
|
||||
Seed-ul per firma se amana: cascada cade oricum pe implicitul hardcodat, iar un
|
||||
INSERT in `optiuni` e citit de COMUN in toate produsele — nu e "discoverabilitate",
|
||||
e comutator suite-wide.
|
||||
|
||||
### 4. Politica de activare (inversata, UC2)
|
||||
|
||||
`CautPartenerContabilitate` (`ocautare.prg:507`) devine **OFF implicit**, cu opt-in
|
||||
explicit `lVerificaANAF=>1`. Motivul, verificat: exista ~68 de apelanti, dintre care
|
||||
lista de opt-out acoperea ~20, toti din ROACONT; ar fi ramas ON prin omisiune
|
||||
`COMUN\clase\baza.vc2:10400` (clasa de baza UI, deci toate produsele),
|
||||
`orapoarte_cont.vc2:3843` (filtru de raport), `ofacturare.vc2:20946` ("Alegeti Banca"),
|
||||
`:20957` ("casa in lei"), `:19441` (Agenti), `:7160/:7997/:9257` (Responsabili),
|
||||
`:13793/:17826` (Partener rezervare), plus `oinventar`, `omodificari`,
|
||||
`onomenclatoare`, `ferestre_cere_date`, `ooperatii_comune.prg`. `ROAGEST` si
|
||||
`ROAAUTO` incarca `validare.prg` (`roagest.prg:234`, `roaauto.prg:198`), deci toate
|
||||
guardurile existente trec si la ele.
|
||||
|
||||
**Lista ON (singurele locuri cu `lVerificaANAF=>1`):**
|
||||
- `Clase\ointroduceri_cont.vc2` — `do_cauta_partener` (x2, `:921`, `:3850`);
|
||||
- `Clase\ointroduceri_cont.vc2` — gridurile de partener din `frm_note` (`:7096`, `:7120`)
|
||||
si `frm_note2007` (`:8943`, `:8984`);
|
||||
- `COMUN\clase\ofacturare.vc2` — `do_cauta_client`, `do_cauta_furnizor`.
|
||||
|
||||
Parametrul `lNuVerificaANAF` dispare. Consecinta de curatat: dupa inversare, niciun
|
||||
apelant nu mai trimite `tlVerificaANAF` la `caut_parteneri` — se decide explicit daca
|
||||
parametrii `tlVerificaANAF`/`tdDataDoc` si ramura ANAF din `caut_parteneri`
|
||||
(`ocautare.prg:625`) raman sau se scot ca ei cod mort.
|
||||
|
||||
### 5. Reguli obligatorii de implementare (constatari verificate in cod)
|
||||
|
||||
| # | Regula | Ancoraj |
|
||||
|---|---|---|
|
||||
| C2 | `AplicaInlocuirePartenerANAF` se apeleaza **doar cand `gnButon = 1`**; `poANAFInlocuire` se reseteaza la intrarea in Detalii si pe ramura de abandon. Altfel: utilizatorul alege varianta in Detalii, apoi anuleaza cautarea, iar `Scatter ... Blank` (`cauta_alfa.prg:243`) + guardul slab `Type('toPartener.id_part')='N'` fac ca apelantul sa primeasca totusi partenerul — pe incasari rupe imperecherea | `ocautare.prg:165`, `:609`, `:666` |
|
||||
| C3 | `do_termin` pe formularul de cautare se apeleaza **dupa** ce AMESSAGEBOX-ul a returnat, niciodata din interiorul unui dialog modal copil (`do_termin` face `this.Release`) | `_frm_base.vc2:363-371` |
|
||||
| H2 | Eroarea de SELECT din `ANAF_CautaPereche` nu mai are voie sa apara ca "Nu exista partener cu CUI ... (il puteti crea cu butonul Nou)" — asta indruma activ spre al treilea duplicat. `ListaCorecti` primeste un parametru de eroare; la eroare mesajul devine "Nu s-a putut citi lista de parteneri" si sugestia "Nou" dispare. Cursorul se inchide si pe ramura de eroare | `ocautare.prg:154-157`, `:389-405`, `:423`, `:455` |
|
||||
| H6 | Cascada se citeste **o singura data**, la intrarea in `CautPartenerContabilitate`/`caut_parteneri`, cu `lcSel = Select()` / `Select(m.lcSel)` in jur. Niciodata din `Activeaza`, `VerificaRand` sau dintr-un handler de UI. `citeste_optiune_utilizator` **nu restaureaza** zona de lucru, iar `scrie_optiune_utilizator` da AMESSAGEBOX la eroare si face `TABLEUPDATE` in afara ramurii de succes | `oinit_optiuni.prg:731-740`, `:770-778` |
|
||||
| H7 | Cascada testeaza `!Empty(Alltrim(valoare))` pe fiecare nivel. Patternul existent `Int(Val(Nvl(citeste_optiune_utilizator(...), '0')))` mapeaza absent -> 0 = OPRIT si ar opri verificarea la primul nivel gol | `Clase\ovanzcump.vc2` (pattern), `oinit_optiuni.prg:730`, `:808` |
|
||||
| M9 | Citirea `getini` iese de pe calea per-rand: azi `ANAF_StarePartener` o face la fiecare verificare, cu `FOPEN`/scan/`FCLOSE` pe `DIRGEN\settings.ini`, care e de regula pe share de retea. Kill-switch-ul se citeste odata cu cascada | `ocautare.prg:59`, `ini.prg:288`, `roacont.prg:441` |
|
||||
| M2 | Se foloseste `This.oForm.crs_cursor`, nu `_GRID1.RecordSource`: `SAVE_GRID` goleste `RecordSource` pe toata durata repopularii, care include un round-trip Oracle | `oproceduri_comune.prg:1387`, `ocautare.prg:303`, `:414`, `:443` |
|
||||
| M5 | Valorile de cascada cache-uite pe sesiune se invalideaza la schimbarea firmei sau a utilizatorului (ca si cache-ul ANAF) | — |
|
||||
| A2 | Guard suplimentar `'OINIT_OPTIUNI' $ Upper(Set('Procedure'))` inainte de orice apel la cascada: `ROACASA` incarca `ocautare` fara `oinit_optiuni` | `ocautare.prg:63` (modelul existent) |
|
||||
| B1 | Bug in codul de azi: `VerificaRand` iese pe `Reccount = 0` fara sa goleasca labelul, deci verdictul precedent ramane pe ecran atribuit unei liste goale | `ocautare.prg:304-306` |
|
||||
| B2 | Spec vs implementare: `SeteazaLabel` forteaza `FontBold = .F.`, desi REVIZIA 2/3 cere discordanta in rosu **bold**. Se aliniaza (bold la discordanta) | `ocautare.prg:353` |
|
||||
| B3 | `Anchor` al labelului devine 14 (Left+Bottom+Right) — cu 6 textul se taie la redimensionare; labelul urca deasupra `cmd_select` (invizibil pe fluxul de partener), fara sa mai creasca inaltimea formei | `cauta_alfa_forms.vc2:47`, `:269-279`, `ocautare.prg:245-257` |
|
||||
| B4 | Denumirea ANAF se trunchiaza la ~24 caractere in label (cea completa apare in Detalii): textul discordant la lungime maxima depaseste 2 randuri de Arial 10 in ~487x30px si se taie fara elipsa | `ocautare.prg:367` |
|
||||
| B5 | `SET STEP ON` viu la `validare.prg:1841` (preexistent, nu din aceasta lucrare) — in IDE deschide debuggerul. De scos | `validare.prg:1841` |
|
||||
|
||||
Wrapperul batch ANAF **nu se scrie** in aceasta transa: fara marcaj in grid nu are
|
||||
consumator (YAGNI).
|
||||
|
||||
### 6. Ce se pastreaza neschimbat
|
||||
|
||||
Textele si culorile labelului (REVIZIA 3 pt. 1, cu corectia B2), starea la data
|
||||
documentului (REVIZIA 3 pt. 3), `dDataDoc`/`tdDataDoc`, `NormalizeazaCUI`,
|
||||
`ANAF_VerificaCuiSingle`, cache-ul pe sesiune + golirea la schimbarea firmei,
|
||||
excluderile (PF/extern/nenumeric), degradarea tacuta, `ANAF_CautaPereche`,
|
||||
`AplicaInlocuirePartenerANAF`, fixul de import (REVIZIA 3 pt. 6), regula "fara
|
||||
comentarii in corpul codului" (REVIZIA 3 pt. 5), hook-ul generic din `cauta_alfa.prg`
|
||||
si cele 8 linii din `cauta_alfa_forms.vc2`.
|
||||
|
||||
### 7. Teste (toate fezabile in harnessul headless)
|
||||
|
||||
1. Cascada: ini `0` bate tot; utilizator bate firma; firma bate hardcodatul;
|
||||
**absent != 0** (H7); lipsa `crsOptiuni`/`crsOptiuniUtilizator`/`goExecutor`.
|
||||
2. Nivel 1 (implicit): label prezent; `VerificaAlegere` nu deschide nimic si **nu
|
||||
face niciun apel HTTP** la alegere (contorul de apeluri exista deja in suita).
|
||||
3. Nivel 0: `poVerifAlegere` neinstantiat, zero apeluri, label absent.
|
||||
4. Nivel 3: dialogul existent, cele 3 rezultate — testele actuale, rulate cu
|
||||
optiunea pe 3.
|
||||
5. **C2 (testul cel mai important, lipsa azi):** `poANAFInlocuire` setat + `gnButon = 2`
|
||||
(Renunta) => obiectul returnat ramane blank, `id_part = 0`.
|
||||
6. H2: `ANAF_CautaPereche` esuat (mock pe `goExecutor`) => mesaj de eroare, fara
|
||||
sugestia "Nou".
|
||||
7. Detalii cu `oStare` `.Null.` => se deschide, cu linia explicativa.
|
||||
8. Discriminatorul "are documente in perioada" (mock pe `goExecutor`, cu si fara randuri).
|
||||
9. Bug-ul B1: cautare fara rezultate => labelul se goleste.
|
||||
10. Zona de lucru: `Alias()` identic inainte si dupa citirea/scrierea optiunilor (H6).
|
||||
11. Punctul de meniu scrie valoarea corecta si are efect imediat (`M6`: la trecerea
|
||||
pe 0 se opreste si timerul si se goleste labelul pe cautarea deschisa).
|
||||
12. Regresie: apelantii care NU au `lVerificaANAF=>1` nu instantiaza `poVerifAlegere`.
|
||||
|
||||
### 8. Transa viitoare — marcaj in grid (nivelul 2), cu conditii de intrare
|
||||
|
||||
Nu se implementeaza pana nu exista, in aceasta ordine:
|
||||
1. **Masuratori** (Tema din planul initial, inca nefacuta): latenta reala a unui apel
|
||||
ANAF la ore diferite; comportamentul la rafale (30 loturi de 20 CUI la interval
|
||||
scurt — de la al catelea vine 429); numarul real de perechi de CUI duplicat la un
|
||||
client real.
|
||||
2. **Date din loguri**: cate discordante apar efectiv la pilot si in ce flux.
|
||||
|
||||
Cerinte tehnice de respectat atunci (toate verificate acum, ca sa nu se piarda):
|
||||
|
||||
| # | Cerinta |
|
||||
|---|---|
|
||||
| UC1 | Criteriul de colorare corect pe trezorerie e "are documente in perioada" (SELECT local), nu statutul ANAF: pe o incasare, verdele dupa ANAF indruma spre partenerul fara facturi |
|
||||
| D-F2 | `DynamicForeColor` e **invizibil pe randul selectat** (`_baza.vc2:200-201`: highlight bleumarin cu text alb). Semnalul are nevoie de al doilea canal: `DynamicFontBold`, care supravietuieste highlight-ului. Verde+bold pentru randul confirmat, restul normal; rosul dispare de pe randuri (are 3 sensuri distincte: prefix gresit, radiat la ANAF, CIF invalid) |
|
||||
| C4 | Un singur `anaf_timer` cu doua consumatoare = nedeterminism: `do_cauta` face `Go Top` + `SetFocus` dupa `actualizeaza_grid1`, deci `AfterRowColChange` rearmeaza acelasi timer. Necesar: doua flag-uri (sau doua timere) + flag de suprimare `lInBatch`, `GO` pe `Recno()` salvat, colectarea CUI-urilor fara `SELECT-SQL` pe cursorul legat de grid |
|
||||
| H1 | CUI-urile din `notfound` sunt inserate ca randuri blank (`scpTVA = .F.`, denumire goala) — fara filtru `!Empty(denumire)` orice partener cu prefix RO negasit la ANAF ar aparea marcat gresit | `validare.prg:1984-1996` |
|
||||
| H4 | `Collection.GetKey` e supraincarcat: cu argument numeric intoarce cheia de la index, nu indexul. Cheile se construiesc string: `'P' + Transform(id_part)`, si `Item()` doar dupa `GetKey(...) <> 0` |
|
||||
| H5 | Expresia `Dynamic*` se evalueaza in context de pictare: referinta necalificata (`ANAF_CuloareRand(id_part)`), corp intreg in `TRY/CATCH` cu `Return Rgb(0,0,0)`, `Nvl(id_part,0)` (randul `<TOATE INREGISTRARILE>` de pe ramura `lAllInList` are `id_part` blank), zero apeluri care schimba zona de lucru. O eroare aici se repeta la fiecare repaint |
|
||||
| H8 | Curatarea binding-ului pe metoda: `Unbindevents(form, 'actualizeaza_grid1', This, 'DupaGrid')` cu 4 argumente — varianta cu 1 argument sterge si `BINDEVENT(Thisform,"lAles",...)` din `Init` si rupe selectia multipla |
|
||||
| H9 | Codul ROA impune >= 1s intre interogarile ANAF (`validare.prg:1777`, `INKEY(1)`); un debounce de 400ms il incalca. Necesare: interval minim global pe sesiune + circuit-breaker la 3 esecuri + log per cod HTTP distinct (azi `gvANAF_EroareLogataSesiune` amuteste toata sesiunea dupa prima eroare, iar 429/5xx sunt indistinguibile de "fara informatie"). Nota REVIZIA 5: intrerupatorul livrat acolo e pe timp (10 minute dupa un singur esec FARA_RASPUNS), mecanism diferit — contorul de 3 esecuri si logul per cod HTTP raman cerinta deschisa, neacoperita, pentru nivelul 2 |
|
||||
| M1 | Delegatul `DupaGrid` trebuie sa aiba semnatura metodei delegate (`Lparameters pcFiltru`), altfel eroare 1229 |
|
||||
| M7 | Codul fiscal invalid nu are stare in schema de culori — se decide explicit sau se documenteaza omisiunea |
|
||||
| Test | Partile netestabile in harnessul actual: ordinea actiunilor sub timer, reentranta pe cursorul gridului, culorile efectiv randate. Daca intra, intra cu risc de regresie permanent |
|
||||
| Invariant | Intreg mecanismul depinde de `PRIVATE poVerifAlegere`/`poANAFInlocuire` vizibile prin domeniu dinamic, ceea ce functioneaza doar pentru ca formularul de cautare e `WindowType = 1` (modal). Orice trecere la modeless rupe atribuirea **fara eroare** |
|
||||
|
||||
---
|
||||
|
||||
## REVIZIA 5 (27.07.2026) — reparatie 404 + intrerupator de disponibilitate ANAF
|
||||
|
||||
Status: APROBATA (27.07.2026, plan `docs\plan-reparatie-anaf-404-breaker.md`, T1-T8).
|
||||
Aceasta revizie nu schimba fereastra sau textele labelului (raman cele din REVIZIA 3,
|
||||
cu corectia B2 din REVIZIA 4); corecteaza contractul dintre wrapper-ul ANAF
|
||||
(`COMUN\programe\validare.prg`) si consumatorul lui (`COMUN\programe\ocautare.prg`)
|
||||
si adauga o a treia stare de banda pentru cand serviciul ANAF nu raspunde.
|
||||
|
||||
### Motivatia
|
||||
|
||||
Doua simptome constatate pe ecran: (1) `RO123456789` — cod valid ca cifra de
|
||||
control dar inexistent la ANAF, banda arata promptul gri generic in loc de
|
||||
"inexistent la ANAF"; (2) `FANALEX OIL MARKET S.R.L.` scris in campul cod fiscal —
|
||||
banda tace complet. Plus un al treilea defect gasit la analiza: serviciul cazut sau
|
||||
supraincarcat poate bloca interfata pana la cateva zeci de secunde per rand, pentru
|
||||
ca garda existenta din jurul `SetTimeouts` nu se aplica pe obiectul COM folosit.
|
||||
|
||||
### 1. Regula "esec tacit" revizuita pentru banda
|
||||
|
||||
Regula veche (REVIZIA 2, "Starile labelului"): orice eroare/timeout ANAF lasa
|
||||
labelul gol, identic cu starea "nimic de verificat". Regula noua: "esec tacit"
|
||||
ramane valabila pentru dialogurile modale (fara AMESSAGEBOX la esec, ca azi), dar
|
||||
banda de stare VORBESTE:
|
||||
|
||||
- lipsa de raspuns HTTP (`FARA_RASPUNS`), raspuns HTTP primit dar neinteles
|
||||
(`RASPUNS_NEINTELES`, punctul 5) sau apel sarit fiindca serviciul e deja in
|
||||
starea CAZUT/SE TESTEAZA (punctul 3) → acelasi text de banda gri, in toate
|
||||
trei situatiile: **"ANAF nu a raspuns - verificare sarita"**, distincta de
|
||||
promptul gri generic (persoana fizica / partener extern / CUI nenumeric /
|
||||
kill-switch 0);
|
||||
- ce difera intre `FARA_RASPUNS` si `RASPUNS_NEINTELES` e DOAR intrerupatorul:
|
||||
`FARA_RASPUNS` il deschide (stare CAZUT); `RASPUNS_NEINTELES` schimba banda la
|
||||
fel, dar nu deschide intrerupatorul si nu intra in cache;
|
||||
- 404 cu `notFound` continand chiar CUI-ul cerut → verdict rosu "Cod fiscal
|
||||
inexistent la ANAF" (punctul 4), nu mai e tratat ca "fara informatie".
|
||||
|
||||
### 2. Testul 5 actualizat
|
||||
|
||||
Testul 5 din "Lista de teste" (mai sus) trece de la "zero mesaje" la banda care
|
||||
vorbeste explicit la lipsa raspunsului; vezi textul revizuit la pozitia lui in
|
||||
lista. Regresiile de pastrat verzi: celelalte 10 teste ale listei plus cele 30 de
|
||||
scenarii existente in suita headless (`test_verif_partener_anaf_v2_ui.ps1`).
|
||||
|
||||
### 3. Starea serviciului ANAF pe sesiune
|
||||
|
||||
Patru stari, tinute pe sesiune (nu per CUI), cu intrerupator de 10 minute:
|
||||
|
||||
```
|
||||
+-------------+
|
||||
pornire sesiune ---->| NECUNOSCUT |
|
||||
+------+------+
|
||||
deschidere formular | (sonda pleaca asincron)
|
||||
v
|
||||
+-------------+ sonda / verificare reala OK
|
||||
| SE TESTEAZA+-------------------------------> +-----+
|
||||
+------+------+ | VIU |
|
||||
| sonda esuata +--+--+
|
||||
v |
|
||||
+-------------+ <--------------------------------+
|
||||
| CAZUT (10') | apel real esuat (FARA_RASPUNS)
|
||||
+------+------+
|
||||
| au trecut 10 minute + se deschide un formular
|
||||
+--> SE TESTEAZA (sonda noua, tot asincron)
|
||||
```
|
||||
|
||||
- **NECUNOSCUT / CAZUT expirat** → la deschiderea formularului de cautare pleaca o
|
||||
sonda asincrona (acelasi constructor de cerere ca verificarea normala), fara sa
|
||||
blocheze interfata.
|
||||
- **SE TESTEAZA** → randul care cere verdict NU face apel propriu; asteapta
|
||||
raspunsul sondei (banda: "ANAF: se verifica <cod>..."), interogat neblocant de
|
||||
timerul de debounce existent (400ms). Sonda are propriul termen de viata; daca
|
||||
expira fara raspuns, starea trece direct pe CAZUT.
|
||||
- **VIU** → verificari sincrone normale, fara sonda.
|
||||
- **CAZUT** → zero apeluri catre ANAF pentru randul curent, banda gri "ANAF nu a
|
||||
raspuns - verificare sarita".
|
||||
- La tranzitia CAZUT/NECUNOSCUT → VIU, `nIdPart` se invalideaza, ca sa se
|
||||
re-evalueze randul curent (altfel ramane pe verdictul dinaintea revenirii).
|
||||
- La nivelul 3 (confirmare la alegere, opt-in): in starile CAZUT si SE TESTEAZA
|
||||
verificarea sincrona de la alegere se sare, iar alegerea trece fara blocare.
|
||||
|
||||
### 4. Contractul 404
|
||||
|
||||
Corpul raspunsului ANAF se citeste si pe status 404, nu doar pe 200. Verdictul
|
||||
"Cod fiscal inexistent la ANAF" se da **doar** cand `notFound` din raspuns contine
|
||||
chiar CUI-ul cerut — niciun alt corp neinteles nu mai produce acest verdict; ramura
|
||||
veche care trata orice corp diferit de "gasit" ca "inexistent" se elimina.
|
||||
|
||||
### 5. Clasa de esec a wrapper-ului
|
||||
|
||||
`ANAF_VerificaCuiSingle` primeste un parametru suplimentar, prin referinta, cu
|
||||
clasa esecului. `ANAF_StarePartener` o preia si o expune mai departe apelantului,
|
||||
tot prin referinta:
|
||||
|
||||
| Valoare | Cand | Banda | Intrerupator |
|
||||
|---|---|---|---|
|
||||
| `''` | apel reusit (obiect intors) sau verdict "inexistent" valid | verdict normal (verde/rosu) | nimic |
|
||||
| `FARA_RASPUNS` | niciun raspuns HTTP: exceptie la deschiderea/trimiterea cererii, timeout, DNS, conexiune refuzata | gri "ANAF nu a raspuns - verificare sarita" | **singura** valoare care il deschide (stare CAZUT) |
|
||||
| `RASPUNS_NEINTELES` | raspuns HTTP primit dar corpul nu se poate interpreta: status neasteptat, corp gol, JSON neparsabil, `notFound` fara CUI-ul cerut, 429, 500 | acelasi gri "ANAF nu a raspuns - verificare sarita" | nu il deschide, nu intra in cache |
|
||||
|
||||
Apelul fara acest parametru ramane valabil (parametru optional) — apelantii
|
||||
existenti nu se schimba.
|
||||
|
||||
### 6. Cache doar pe verdicte pozitive
|
||||
|
||||
Verdictul `'NEGASIT'` si esecurile nu se mai tin in cache toata sesiunea. Cache-ul
|
||||
pe sesiune (cheie CUI+data, vezi REVIZIA 3 pt. 3) ramane doar pentru verdicte
|
||||
pozitive (platitor/neplatitor gasit la ANAF). Rolul de "nu bate ANAF de doua ori
|
||||
pentru acelasi caz esuat" il preia intrerupatorul de la punctul 3, nu cache-ul —
|
||||
altfel un verdict negativ dintr-un serviciu picat sau degenerat ar ramane lipit pe
|
||||
CUI pana la schimbarea firmei.
|
||||
|
||||
### 7. Cod normalizat cu litere in campul cod fiscal
|
||||
|
||||
Cand codul din campul cod fiscal contine litere dupa normalizare (cazul
|
||||
`FANALEX OIL MARKET S.R.L.` scris acolo din greseala) → banda gri "nu se poate
|
||||
verifica la ANAF", nu tacere ca azi. `VALIDARE_CIF` nu se modifica in aceasta
|
||||
transa (ramane folosita neschimbata in restul suitei — D406, import, facturare);
|
||||
tara partenerului nu intra in aceasta transa — punctul D (`cod_tara` in cursorul
|
||||
de cautare) ramane amanat, ca in "Ce NU facem" mai sus.
|
||||
|
||||
### 8. Guard de reintrare implementat
|
||||
|
||||
Guard-ul de reintrare (flag "verificare in curs") cerut deja in harta erorilor de
|
||||
mai sus e implementat in aceasta transa ca `lVerificareInCurs`, nu doar specificat:
|
||||
fara el, timerele VFP care trag si in timpul unui `AMESSAGEBOX`/`WaitForResponse`
|
||||
pot intrerupe secventa "verifica cheia → apel → adauga in cache" si arunca eroare
|
||||
la a doua inserare pe aceeasi cheie.
|
||||
|
||||
### 9. Ce se pastreaza neschimbat
|
||||
|
||||
Textele si culorile labelului (REVIZIA 3 pt. 1, cu corectia B2), starea la data
|
||||
documentului (REVIZIA 3 pt. 3), `NormalizeazaCUI`, cache-ul pe sesiune + golirea la
|
||||
schimbarea firmei (cu restrangerea de la pct. 6), excluderile (PF/extern/
|
||||
nenumeric — extinse acum cu banda gri de la pct. 7 in loc de tacere),
|
||||
degradarea tacuta pentru `RASPUNS_NEINTELES` (niciun AMESSAGEBOX, nicio acuzatie,
|
||||
nicio scriere in cache, intrerupatorul neatins — dar banda vorbeste, ca la pct. 1),
|
||||
`ANAF_CautaPereche`,
|
||||
`AplicaInlocuirePartenerANAF`, fixul de import, cascada de optiuni
|
||||
`RC_ANAF_VERIF_SELECTIE` (REVIZIA 4 pt. 3), politica de activare pe apelanti
|
||||
(REVIZIA 4 pt. 4).
|
||||
@@ -1,87 +0,0 @@
|
||||
# Handoff Transa 1 (L1 + L2) — ocautare.prg + validare.prg
|
||||
|
||||
Data: 27.07.2026. Patch: `docs/diff_runda1_transa1.patch`. Backup-uri: `*.pre_runda1.bak`
|
||||
in `COMUN/programe/`. Fara comit (git/svn), fara `git add`.
|
||||
|
||||
## L1 — perioada TVA
|
||||
|
||||
- `validare.prg` header (dupa ultima intrare 27.07.2026): intrare noua cumulativa.
|
||||
- `validare.prg:1663 ANAF_VerdictDinCursor`: 4 proprietati noi pe `loResult`
|
||||
(`dInceputScpTVA`, `dSfarsitScpTVA`, `dAnulareScpTVA`, `cMesajScpTVA`), citite din
|
||||
cursor INAINTE de `Use In` — linii neschimbate fata de plan (1657→1663 dupa insertia
|
||||
headerului, offset normal).
|
||||
- `validare.prg` `ParseJsonANAFv8` (~2074-2086): log explicit (nu in CATCH) pentru fiecare
|
||||
din cele 3 campuri de data, cand sirul sursa e nevid dar `CTOD` a intors gol.
|
||||
- `ocautare.prg` header: intrare noua cumulativa (L1; L2 nu are comentariu, e corectie).
|
||||
- `ocautare.prg:145-153 ANAF_StarePartener`: propaga cele 4 proprietati in `loOut`, citire
|
||||
garda cu `Pemstatus(loRezANAF, '<prop>', 5)`; daca lipsesc (validare.prg vechi la alte
|
||||
produse ROA), `loOut` primeste oricum proprietatea cu valoare goala — asa TextAnaf/Detalii
|
||||
n-au nevoie de Pemstatus la randul lor.
|
||||
- `TextStare` (nou parametru `tcPerioada`) + `SufixPerioadaTVA` (functie noua) + `TextAnaf`
|
||||
(foloseste cele doua) — implementeaza tabelul de conditii si formele exacte din plan
|
||||
(precedenta pe `dAnulareScpTVA`, apoi range daca ambele date, apoi `din data`; sufixul
|
||||
`' la data documentului'` dispare cand perioada apare).
|
||||
- `TextPerioadaTVA` (functie noua) + `Detalii`: bloc cu perioada completa (etichete distincte)
|
||||
+ mesajul ANAF integral, inserat dupa `AntetDialog(...)` in AMBELE ramuri unde `oStare`
|
||||
nu e null (cazul concordant si cel discordant/lista de candidati) — deci apare si in cazul
|
||||
concordant, cum cere planul.
|
||||
|
||||
## L2 — CNP la 13 cifre
|
||||
|
||||
- `EvalueazaRand:600(vechi)`: `This.cClasaEsec = ''` → `'COD_INVALID'` (fara comentariu).
|
||||
- `ANAF_StarePartener`: parametru nou `tnTipPersoana` (adaugat la finalul listei, ca sa nu
|
||||
mut pozitiile parametrilor `@`); conditia de la `:82` devine
|
||||
`Len(m.lcCui) = 13 And !(Vartype(m.tnTipPersoana) = 'N' And m.tnTipPersoana = 1)`, seteaza
|
||||
`tcClasaEsec = 'CNP'` inainte de `Return .Null.`. Singurul apel din tot codul e in
|
||||
`EvalueazaRand` (verificat cu grep in D:\ROA\ROACONT) — actualizat sa paseze
|
||||
`m.lnTipPersoana` (deja calculat la linia anterioara, nimic nou de calculat).
|
||||
**Corectie runda 2** (semnalata de team-lead la review): forma initiala
|
||||
`m.tnTipPersoana <> 1` compara direct cu 1, ceea ce arunca eroare VFP 107
|
||||
("Operator/operand type mismatch") daca `ANAF_StarePartener` e chemata cu vechea
|
||||
semnatura de 6 parametri (`tnTipPersoana` nepasat = `.F.` logic, `.F. <> 1` = mismatch
|
||||
tip) — risc real, pentru ca fisierul e cod partajat COMUN si alte produse ROA il pot
|
||||
chema fara noul parametru. Forma cu `Vartype(...) = 'N' And ... = 1` e sigura indiferent
|
||||
daca parametrul e pasat sau nu si pastreaza compatibilitatea inapoi (apelant vechi -> se
|
||||
comporta ca azi, sare ANAF pe 13 cifre).
|
||||
- `EvalueazaRand`: ramura noua `Case Isnull(m.loStare) And m.lcClasaEsec == 'CNP'` inaintea
|
||||
lui `Case Isnull(m.loStare)`, banda neutra `'Persoana fizica - CNP corect'`.
|
||||
- `Detalii`, Iif imbricat: doua ramuri noi, `CNP` si `COD_INVALID`, exact textul din plan.
|
||||
- Ramurile marcate INACCESIBILE in plan (CNP invalid sub clasa noua, CUI valid/invalid sub
|
||||
FARA_RASPUNS) NU au fost implementate, cum cere planul.
|
||||
|
||||
## Verificari facute
|
||||
|
||||
- cp1252: toate editarile au fost facute INTAI, verificare byte-level DUPA. `ocautare.prg`
|
||||
a avut 3 linii corupte (`0xBA` → `EF BF BD`) dupa editari (caracterul `ș` din
|
||||
"mașina"/"și"/"tranșa", niciuna dintre ele atinsa intentionat) — reparate cu
|
||||
`s/\xEF\xBF\xBD/\xBA/g` (sigur, pentru ca toate cele 3 corupte erau confirmat `0xBA` in
|
||||
backup si in `svn cat`, verificat byte-cu-byte cu `xxd`+`md5sum`, nu doar vizual — atentie,
|
||||
terminalul afiseaza `0xBA` si `EF BF BD` identic vizual, verificarea trebuie facuta pe
|
||||
octeti, nu pe ce se vede). Dupa reparare: 0 aparitii `EF BF BD` in ambele fisiere, numar de
|
||||
linii cu octeti >=0x80 identic intre fisierul curent si `svn cat` (3 in ocautare.prg, 0 in
|
||||
validare.prg), continut confirmat identic prin md5sum pe liniile respective.
|
||||
- Comentarii: doar in antet, cate o intrare cumulativa per fisier (L1); L2 fara comentariu.
|
||||
- Patch (`docs/diff_runda1_transa1.patch`) recitit — contine doar modificarile de mai sus,
|
||||
fara cele 3 linii cu diacritice (au disparut din diff dupa reparare, semn ca sunt
|
||||
byte-identice cu baseline-ul).
|
||||
|
||||
## Ce n-am putut verifica
|
||||
|
||||
- Nu am rulat headless VFP (`vfp9.exe -A -T`) pe aceste functii — modificarile ating clase
|
||||
UI (`anaf_verif_cautare`, mesaje `Amessagebox`) greu de testat fara IDE/formular; recomand
|
||||
testare manuala in VFP conform planului de test insotitor.
|
||||
- N-am gasit alti apelanti ai `ANAF_StarePartener` in afara de `ocautare.prg` insusi (grep pe
|
||||
tot `D:\ROA\ROACONT`), deci parametrul nou `tnTipPersoana` nu are alti calleri de actualizat
|
||||
— dar n-am verificat si in `D:\ROA\COMUNROA` sau alte produse ROA in afara acestui working
|
||||
copy.
|
||||
|
||||
## Capcane intalnite
|
||||
|
||||
- Editarea cu Edit tool a corupt caractere cp1252 in TOT fisierul `ocautare.prg` la fiecare
|
||||
scriere, exact cum avertizeaza `conventie_encoding_cp1252.md` — dar comparatia vizuala in
|
||||
terminal ("liniile arata la fel") a fost INSELATOARE: `0xBA` si `EF BF BD` (3 octeti) se
|
||||
afiseaza identic ca `<60>` in terminal. Un prim test cu `perl -ne 'print "$." if /[\x80-\xFF]/'`
|
||||
a raportat "acelasi numar de linii, acelasi continut vizual" si a fost gresit interpretat ca
|
||||
"nicio corupere" — abia comparatia cu `xxd`+`md5sum` a scos la iveala diferenta reala.
|
||||
Concluzie pentru viitor: verificarea corecta e strict pe secventa de octeti `EF BF BD`
|
||||
(`perl -ne 'print "$." if /\xEF\xBF\xBD/'`), nu pe prezenta oricarui octet >=0x80.
|
||||
@@ -1,51 +0,0 @@
|
||||
# Handoff TRANSA 2 (L4) — borderou eFactura, taxare inversa
|
||||
|
||||
Data: 28.07.2026. Status: implementat si validat pe schema dev, NEAPLICAT pe view-urile reale.
|
||||
|
||||
## Ce am scris
|
||||
|
||||
1. `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\07\ff_2026_07_28_01_COMUN_EFACTURA.sql` (nou, CRLF):
|
||||
`create or replace view` pentru `anaf_vefactura_primit` (coloana `jtva_ti` = suma celor 13
|
||||
termeni `TI*`/`XX*TIT` de pe `jc2007`, printr-un singur `CROSS APPLY` care intoarce si
|
||||
`jtotctva` si `jtva_ti` odata — un singur scan, nu doi subselecti) si `anaf_vefactura_trimis`
|
||||
(`jtva_ti` = `0` constant, `jtotctva` neschimbat). La final: `alter view ... compile` pe cele
|
||||
doua DETALIU + verificare `user_objects.status='INVALID'` care arunca eroare daca ramane ceva
|
||||
invalid. `versiune_db.txt`: `2026_07_26_02` -> `2026_07_28_01`.
|
||||
2. `COMUN\programe\import_efactura.prg`: sonda `user_tab_columns` pe `lcTabel` (`goExecutor.oExecuta`,
|
||||
tipar deja folosit in fisier la `cGestiuni`/`cUMISO`/`cUM`) inainte de a construi `lcSelect`;
|
||||
`lcExprDiferenta` ia una din doua forme (cu/fara `jtva_ti`), injectata prin `<<m.lcExprDiferenta>>`
|
||||
in `TEXTMERGE`. `lcSchema` neatins (numar de coloane identic). Antet actualizat cu intrare noua
|
||||
`*!* 28.07.2026 / marius.mutu`.
|
||||
|
||||
## Ce am validat pe baza (`MARIUSM_AUTO@ROA_CENTRAL`, doar SELECT + view-uri temporare)
|
||||
|
||||
Am creat `zz_test_jtva_primit`/`zz_test_jtva_trimis` cu EXACT corpul din script, verificat, apoi
|
||||
`DROP VIEW` pe amandoua (confirmat: `no rows selected` la interogarea finala pe `user_objects`).
|
||||
|
||||
- Ambele compileaza (`STATUS = VALID`).
|
||||
- `zz_test_jtva_primit`: 487 randuri (coincide cu ce raporta handoff-ul conditiilor); 459 pe trimis.
|
||||
- Cele 8 randuri cu `id_fact` completat: `jtotctva` neschimbat fata de azi, `jtva_ti = 0` pe toate
|
||||
(niciuna nu e taxare inversa — coincide cu constatarea din `handoff_transa2_conditii.md`).
|
||||
- Pe trimis: `jtva_ti` e `0` pe toate randurile, niciodata NULL.
|
||||
- Testul aritmetic direct pe cazul sintetic din handoff (`jc2007.id_fact=8007136`,
|
||||
`an=2022 luna=4 dataact=30-APR-22 nract=222 id_part=614`): `totctva=119`, `jtva_ti_expr=19` —
|
||||
exact valorile asteptate (confirma ca `diferenta` ar deveni `100-(119-19)=0`).
|
||||
- Sonda `user_tab_columns` gaseste `JTVA_TI` pe ambele view-uri de test — confirma ca tehnica
|
||||
folosita in `import_efactura.prg` functioneaza identic pe view ca pe tabela.
|
||||
|
||||
NU am rulat `create or replace view` pe view-urile reale si nu am atins `jc2007`/`jv2007`.
|
||||
|
||||
## Ce ramane de facut de om
|
||||
|
||||
- Aplicarea scriptului pe schema clientului, INAINTE de deploy-ul exe-ului (ordinea ceruta de plan).
|
||||
- Verificarea finala pe o factura REALA de taxare inversa importata din eFactura — schema dev nu are
|
||||
niciuna (confirmat deja in `handoff_transa2_conditii.md`); mecanismul e demonstrat doar numeric.
|
||||
- Review + aprobare `docs\diff_runda1_transa2.patch` inainte de orice commit (SVN sau git).
|
||||
- Curatenie dupa aprobare: `import_efactura.prg.pre_runda1.bak` si patch-ul se sterg (nu se comit).
|
||||
|
||||
## Fisiere
|
||||
|
||||
- Backup: `D:\ROA\ROACONT\COMUN\programe\import_efactura.prg.pre_runda1.bak`
|
||||
- Patch: `D:\ROA\ROACONT\docs\diff_runda1_transa2.patch`
|
||||
- Script nou: `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\07\ff_2026_07_28_01_COMUN_EFACTURA.sql`
|
||||
- `D:\ROA\ROACONT\versiune_db.txt`: `2026_07_28_01`
|
||||
@@ -1,189 +0,0 @@
|
||||
# TRANSA 2 (L4) — inchidere conditii de intrare — verificare Oracle
|
||||
|
||||
Data: 27.07.2026. Conexiune: `MARIUSM_AUTO@ROA_CENTRAL` (schema dev), read-only, doar SELECT.
|
||||
Fisiere sursa salvate: `docs/local/view_anaf_vefactura_primit.sql`, `docs/local/view_anaf_vefactura_trimis.sql`.
|
||||
|
||||
## VERDICT GENERAL
|
||||
|
||||
- **A — INCHISA.** Definitiile curente extrase din `USER_VIEWS.TEXT`.
|
||||
- **B — INCHISA PARTIAL.** Mecanismul e confirmat pe date, dar NU dintr-o factura venita real din import eFactura (nu exista in schema dev). Demonstrat pe cel mai apropiat caz din `jc2007`.
|
||||
- **C — INCHISA, cu recomandare concreta.** Forma subselectului unic e mai jos.
|
||||
- **D — INCHISA.** Sonda recomandata: `user_tab_columns`.
|
||||
|
||||
**CONTRAZICE PLANUL (cel mai important gasit):** lista canonica de 10 coloane din plan
|
||||
(`TI21T, TI11T, TI19T, TI09T, TI24T, TI20T, XX21TIT, XX11TIT, XX19TIT, XX9TIT`) **nu compileaza
|
||||
direct pe `JC2007`**. `TI19T` si `TI09T` NU exista ca si coloane pe tabela — vezi B mai jos.
|
||||
|
||||
---
|
||||
|
||||
## A. Definitiile curente ale view-urilor
|
||||
|
||||
Extrase din `USER_VIEWS.TEXT` (nu din arhiva CLAR), salvate integral in:
|
||||
- `docs/local/view_anaf_vefactura_primit.sql`
|
||||
- `docs/local/view_anaf_vefactura_trimis.sql`
|
||||
|
||||
Confirmari:
|
||||
- `anaf_vefactura_primit.jtotctva` = subselect corelat pe `jc2007 j` + `left join nom_parteneri p`,
|
||||
cheie de potrivire an/luna/dataact + `REGEXP_SUBSTR(a.xnumar_act, '\d+[^[:digit:]]*$') LIKE '%'||TO_CHAR(j.nract)||'%'`
|
||||
+ `REGEXP_REPLACE(p.cod_fiscal,'[^[:digit:]]','') = a.cod_fiscal_emitent`. Exact cum descrie planul.
|
||||
- `anaf_vefactura_trimis.jtotctva` = acelasi tipar dar pe **`jv2007`** (nu `jc2007`), cheie pe
|
||||
`cod_fiscal_beneficiar`, filtru `a.factura_emisa = 1`. Confirma ca planul are dreptate sa puna
|
||||
`jtva_ti = 0` constant la trimis: la vanzari nu exista familia `TI*`/`XX*TIT` (verificat — acele
|
||||
coloane sunt specifice achizitiilor, nu apar in `jv2007`, nu a fost nevoie sa fie recalculate).
|
||||
|
||||
**Views DETALIU** — exista amandoua, construite peste view-urile de baza prin `id_efactura`/`id`:
|
||||
- `ANAF_VEFACTURA_PRIMIT_DETALIU` (VALID) — `SELECT f.* (coloane specifice), d.* FROM anaf_vefactura_primit f JOIN anaf_efactura_detalii d ON f.id = d.id_efactura`.
|
||||
- `ANAF_VEFACTURA_TRIMIS_DETALIU` (VALID) — identic, pe `anaf_vefactura_trimis`.
|
||||
- Bonus gasit: exista si `ANAF_VEFACTURA_EMIS_DETALIU`, dar e **INVALID** azi (preexistent, nelegat
|
||||
de L4 — de semnalat, nu de reparat aici).
|
||||
|
||||
Important pentru scriptul de migrare: niciuna din cele doua DETALIU nu selecteaza `jtotctva` sau
|
||||
orice coloana noua din view-ul de baza (`f.*` explicit enumerat, fara `jtotctva`/`jtva_ti`) — deci
|
||||
adaugarea `jtva_ti` in view-urile de baza **nu le afecteaza structural**, doar le invalideaza
|
||||
temporar (dependinta VFP) pana la recompilare automata pe urmatoarea referire. Se pastreaza
|
||||
verificarea de obiecte invalide ceruta de plan la finalul scriptului.
|
||||
|
||||
---
|
||||
|
||||
## B. Trasare cap-coada — CONTRAZICE PLANUL pe lista de coloane
|
||||
|
||||
### Ce s-a confirmat
|
||||
|
||||
- `ProcentTva2IdJtva` (gasita real in `COMUN\programe\oproceduri_comune.prg:5836`, NU in
|
||||
`anaf_efactura.vc2` cum spune planul — functia e apelata acolo la `:12093`/`:12636`, dar
|
||||
**definita** in `oproceduri_comune.prg`) confirma exact id-urile din plan pentru taxare inversa
|
||||
pe JC: 21%->216, 11%->218, 19%->141, 9%->145 (`:5864-5871`).
|
||||
- `oproceduri_decont.prg:8670` (citat corect de plan) e o expresie SQL, dar **din view-ul
|
||||
`VJC2025`**, nu direct pe `jc2007`. Am extras `USER_VIEWS.TEXT` pentru `VJC2025`: acolo
|
||||
`ti19t` si `ti09t` sunt ALIASURI calculate — `SUM(a.ti19bct + a.ti19bvt + a.ti19bft) as ti19t`,
|
||||
`SUM(a.ti09bvt + a.ti09bft) as ti09t` — NU coloane fizice.
|
||||
|
||||
### Verificare directa pe `JC2007` (`USER_TAB_COLUMNS`)
|
||||
|
||||
Din cele 10 coloane canonice din plan, gasite pe tabela **8/10**:
|
||||
|
||||
| Coloana plan | Exista pe JC2007? |
|
||||
|---|---|
|
||||
| TI21T, TI11T, TI24T, TI20T | DA (coloane simple) |
|
||||
| XX21TIT, XX11TIT, XX19TIT, XX9TIT | DA (coloane simple) |
|
||||
| **TI19T** | **NU** — pe tabela exista in schimb `TI19BCT`, `TI19BVT`, `TI19BFT` (3 subcoloane) |
|
||||
| **TI09T** | **NU** — pe tabela exista in schimb `TI09BVT`, `TI09BFT` (2 subcoloane, fara varianta `BC`) |
|
||||
|
||||
Un `create or replace view` care scrie `nvl(j.TI19T,0)+nvl(j.TI09T,0)` direct pe `jc2007 j` **nu
|
||||
compileaza** — `ORA-00904`. Lista corecta de termeni pentru `jc2007` (13 termeni, nu 10):
|
||||
|
||||
```
|
||||
NVL(j.TI21T,0)+NVL(j.TI11T,0)+NVL(j.TI24T,0)+NVL(j.TI20T,0)
|
||||
+ NVL(j.TI19BCT,0)+NVL(j.TI19BVT,0)+NVL(j.TI19BFT,0)
|
||||
+ NVL(j.TI09BVT,0)+NVL(j.TI09BFT,0)
|
||||
+ NVL(j.XX21TIT,0)+NVL(j.XX11TIT,0)+NVL(j.XX19TIT,0)+NVL(j.XX9TIT,0)
|
||||
```
|
||||
|
||||
### Factura reala cu taxare inversa — NU exista una venita din import eFactura in schema dev
|
||||
|
||||
- `anaf_efactura` (schema `MARIUSM_AUTO`): 487 randuri primite, doar **8** au `id_fact` completat
|
||||
(legatura catre `jc2007`/`act`). Niciunul dintre acele 8 `id_fact` se suprapune cu vreun rand din
|
||||
`jc2007` care are coloane `TI*`/`XX*TIT` nenule (31 randuri in toata schema, toate din test/demo,
|
||||
ani 2007-2022, fara `id_fact` legat de `anaf_efactura`). Interogarea de join explicit
|
||||
(`jc2007 j JOIN anaf_efactura a ON a.id_fact = j.id_fact WHERE a.factura_emisa=0 AND <TI nenul>`)
|
||||
a intors **0 randuri**.
|
||||
- Cele 6 randuri din `anaf_vefactura_primit` cu `id_fact` legat au `total_cu_tva = jtotctva`
|
||||
(diferenta 0) — niciuna dintre ele nu e taxare inversa, deci nu demonstreaza mecanismul.
|
||||
|
||||
**Cel mai apropiat caz gasit** (nu vine din eFactura, e din `jc2007` direct — demonstreaza doar
|
||||
aritmetica pe care view-ul o va aplica):
|
||||
|
||||
```
|
||||
an=2022 luna=4 dataact=30-APR-22 nract=222 id_part=614 id_fact=8007136
|
||||
ti19bft=19 totctva=119
|
||||
```
|
||||
|
||||
Daca acest rand ar fi venit dintr-un import eFactura cu linie `AE` (TVA XML = 0), XML-ul ar fi
|
||||
avut `total_cu_tva = 100` (119 - 19 taxare inversa), in timp ce `jtotctva` (= `SUM(totctva)`) tot
|
||||
ar da `119`. Cu view-ul curent: `diferenta = total_cu_tva - jtotctva = 100 - 119 = -19` (fals
|
||||
pozitiv, exact cat e TVA de taxare inversa). Cu `jtva_ti` adaugat: `diferenta = total_cu_tva -
|
||||
(jtotctva - jtva_ti) = 100 - (119 - 19) = 0`. Mecanismul se confirma numeric, dar **pe un caz
|
||||
sintetic, nu pe o factura reala din import eFactura** — schema dev nu are asa ceva. De consemnat
|
||||
in nota de release: verificare finala pe date reale ramane de facut la prima factura de taxare
|
||||
inversa importata dupa aplicarea scriptului (sau pe schema de productie/testare cu date reale,
|
||||
daca exista acces).
|
||||
|
||||
---
|
||||
|
||||
## C. Verdict performanta — forma subselectului unic
|
||||
|
||||
Confirmat: `jtotctva` e deja un subselect scalar corelat cu `REGEXP_SUBSTR`/`REGEXP_REPLACE` in
|
||||
`WHERE`, neindexabil. Recomandare: `CROSS APPLY` (Oracle 12c+, disponibil pe 19c) in loc de doi
|
||||
subselecti scalari separati — un singur scan per rand din urma, ambele sume calculate odata:
|
||||
|
||||
```sql
|
||||
SELECT ...,
|
||||
jt.jtotctva,
|
||||
jt.jtva_ti
|
||||
FROM anaf_efactura a
|
||||
CROSS APPLY (
|
||||
SELECT SUM(j.totctva) AS jtotctva,
|
||||
SUM(NVL(j.TI21T,0)+NVL(j.TI11T,0)+NVL(j.TI24T,0)+NVL(j.TI20T,0)
|
||||
+NVL(j.TI19BCT,0)+NVL(j.TI19BVT,0)+NVL(j.TI19BFT,0)
|
||||
+NVL(j.TI09BVT,0)+NVL(j.TI09BFT,0)
|
||||
+NVL(j.XX21TIT,0)+NVL(j.XX11TIT,0)+NVL(j.XX19TIT,0)+NVL(j.XX9TIT,0)) AS jtva_ti
|
||||
FROM jc2007 j
|
||||
LEFT JOIN nom_parteneri p ON j.id_part = p.id_part
|
||||
WHERE j.an = EXTRACT(YEAR FROM a.xdata_act)
|
||||
AND j.luna = EXTRACT(MONTH FROM a.xdata_act)
|
||||
AND j.dataact = a.xdata_act
|
||||
AND REGEXP_SUBSTR(a.xnumar_act, '\d+[^[:digit:]]*$') LIKE '%' || TO_CHAR(j.nract) || '%'
|
||||
AND REGEXP_REPLACE(p.cod_fiscal, '[^[:digit:]]', '') = a.cod_fiscal_emitent
|
||||
) jt
|
||||
WHERE a.factura_emisa = 0
|
||||
```
|
||||
|
||||
Motiv pentru `CROSS APPLY` (nu doi subselecti separati): pastreaza exact semantica actuala — fiind
|
||||
un `SUM(...)` fara `GROUP BY`, subquery-ul `APPLY` intoarce mereu exact un rand (NULL pe ambele
|
||||
sume cand nu exista potrivire), identic cu comportamentul scalar-subquery de azi. Nu necesita
|
||||
restructurarea restului view-ului (multe coloane scalare + `detalii` tip `M`/CLOB, imposibil de
|
||||
pus curat intr-un `GROUP BY` la nivel de view fara alte modificari). Nu e scriptul de migrare final
|
||||
— doar forma recomandata, de validat de cine scrie scriptul.
|
||||
|
||||
Pe `anaf_vefactura_trimis`: `jtva_ti` ramane `0` constant (fara subselect), deci nu exista cost
|
||||
suplimentar acolo — planul are dreptate aici, nimic de schimbat.
|
||||
|
||||
---
|
||||
|
||||
## D. Sonda de coloana
|
||||
|
||||
Confirmat azi (inainte de migrare):
|
||||
```sql
|
||||
SELECT jtva_ti FROM anaf_vefactura_primit WHERE 1=2;
|
||||
-- ORA-00904: "JTVA_TI": invalid identifier
|
||||
```
|
||||
|
||||
**Recomandare: `USER_TAB_COLUMNS`**, nu `TRY` pe `SELECT`:
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) FROM user_tab_columns
|
||||
WHERE table_name = 'ANAF_VEFACTURA_PRIMIT' AND column_name = 'JTVA_TI';
|
||||
```
|
||||
|
||||
Motive:
|
||||
- Confirmat ca views apar normal in `USER_TAB_COLUMNS` (40 coloane gasite pentru
|
||||
`ANAF_VEFACTURA_PRIMIT`), deci interogarea functioneaza identic pe view ca pe tabela.
|
||||
- E o interogare de dictionar, fara sa declanseze parsarea/executia interogarii principale — in VFP
|
||||
nu necesita un bloc `TRY/CATCH` in jurul unui `SELECT` care ar putea arunca o eroare ANAF pe
|
||||
conexiunea Oracle reala (goExecutor), doar un `SELECT ... FROM user_tab_columns`, mai usor de
|
||||
facut robust si de logat separat daca lipseste catalogul.
|
||||
- Cost neglijabil (interogare pe dictionar, nu pe date), rulata o singura data la deschiderea
|
||||
ferestrei, nu per rand.
|
||||
|
||||
---
|
||||
|
||||
## Alte observatii utile pentru cine scrie scriptul de migrare
|
||||
|
||||
- `TI09` nu are deloc varianta `BC` (doar `BV`/`BF`) — asimetric fata de `TI19` care are toate 3
|
||||
(`BC`/`BV`/`BF`). Nu e o eroare, tabela chiar arata asa; scriptul trebuie sa scrie exact
|
||||
`TI09BVT + TI09BFT` (2 termeni), nu 3.
|
||||
- `XX9TIT`/`XX9TIB` (fara zero la 9) sunt corecte, exista pe tabela — confirmat, la fel cum zice
|
||||
planul.
|
||||
- `ANAF_VEFACTURA_EMIS_DETALIU` e INVALID in schema dev azi, independent de L4 — de mentionat catre
|
||||
echipa daca cineva verifica obiecte invalide global, ca sa nu fie confundat cu o stricare produsa
|
||||
de scriptul L4.
|
||||
@@ -1,185 +0,0 @@
|
||||
# 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_contab` — **INCHIS**
|
||||
|
||||
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):
|
||||
|
||||
```sql
|
||||
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`.
|
||||
@@ -1,182 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,714 +0,0 @@
|
||||
# Plan: 4 lucrari ROACONT (ANAF perioada TVA, validare CNP, avertizare exigibilizare, borderou eFactura)
|
||||
|
||||
Data: 27.07.2026. Autor livrare: marius.mutu.
|
||||
Versiune consolidata dupa runda 2 de review si poarta de decizie. **Aceasta e versiunea de
|
||||
executat** — incorporeaza toate deciziile. Istoricul review-ului e in Anexa, la final, si nu
|
||||
contine nimic de implementat.
|
||||
|
||||
Plan de test insotitor:
|
||||
`~/.gstack/projects/ROACONT/mmari-main-eng-review-test-plan-20260727-194744.md`
|
||||
|
||||
## Livrare in TREI TRANSE separate
|
||||
|
||||
Cele 4 lucrari nu au nicio dependenta functionala intre ele, dar au clase de risc si povesti de
|
||||
retragere incompatibile. Impachetate impreuna, o retragere pentru L3 ar lua cu ea si view-ul deja
|
||||
aplicat in schema clientului.
|
||||
|
||||
| Transa | Continut | Blast radius | Retragere | Blocata de |
|
||||
|---|---|---|---|---|
|
||||
| 1 | L1 + L2 | 2 fisiere `.prg` in COMUN | un pas | nimic — se poate incepe |
|
||||
| 2 | L4 | script DB + o expresie in client | doi pasi coordonati | 2 conditii de intrare |
|
||||
| 3 | L3 | drumul de salvare al notelor, toata suita ROA | un pas, dar afecteaza tot | 1 conditie de intrare |
|
||||
|
||||
Fiecare transa se inchide in SVN inainte de a incepe urmatoarea.
|
||||
|
||||
---
|
||||
|
||||
# TRANSA 1 — L1 + L2
|
||||
|
||||
Ambele in `COMUN\programe\ocautare.prg` + `COMUN\programe\validare.prg`. Lane secvential: L1 apoi L2.
|
||||
Fara DB, fara drum de salvare. Reversibil prin revenire la binarul anterior.
|
||||
|
||||
## L1 — de cand este platitor / neplatitor de TVA
|
||||
|
||||
### Problema
|
||||
|
||||
Verificarea ANAF de la alegerea partenerului spune doar starea la data documentului
|
||||
("ANAF: platitor TVA la 27.07.2026"). Pentru un cod fiscal care si-a schimbat atributul,
|
||||
utilizatorul nu vede DE CAND s-a schimbat.
|
||||
|
||||
### Ce exista deja (verificat, nu se construieste)
|
||||
|
||||
- `ParseJsonANAFv8` (`validare.prg:2001-2114`) pune DEJA in cursor toate campurile necesare:
|
||||
`data_inceput_ScpTVA`, `data_sfarsit_ScpTVA`, `data_anul_imp_ScpTVA`, `mesaj_ScpTVA`
|
||||
(citite din `inregistrare_scop_tva.perioade_tva[1]`, liniile 2060-2072).
|
||||
- Cele trei coloane de data sunt DEJA de tip `D` in `CREATE CURSOR` (`validare.prg:2012`).
|
||||
Nu e nevoie de normalizare, doar de garda pe gol.
|
||||
- Informatia se pierde in `ANAF_VerdictDinCursor` (`validare.prg:1657-1689`), care ia din cursor
|
||||
doar `cui`, `scpTVA`, `statusInactivi`, `denumire`, `mesaj` (`:1670-1675`).
|
||||
- Cache-ul de sesiune `goCacheANAF_Sesiune` pastreaza **obiectul intreg** (`ocautare.prg:127`
|
||||
`.Add(m.loRezANAF, ...)`, `:130` `.Item(...)`). Proprietatile noi supravietuiesc. Nu se modifica.
|
||||
- `lDiscordanta` exista deja: `ocautare.prg:143`,
|
||||
`(loRezANAF.scpTVA <> loOut.lAreRO) Or loRezANAF.statusInactivi`. Banda se ramifica deja pe ea
|
||||
la `:651`. Nu se scrie detectie noua.
|
||||
|
||||
Lucrarea e strict propagare + afisare. Nu se schimba apelul HTTP, nu se face al doilea apel.
|
||||
|
||||
### Modificari
|
||||
|
||||
**1. `validare.prg`, `ANAF_VerdictDinCursor` (~1657-1689)**
|
||||
|
||||
Pe obiectul rezultat se adauga patru proprietati, toate citite din cursorul deja parsat:
|
||||
|
||||
- `dInceputScpTVA`, `dSfarsitScpTVA`, `dAnulareScpTVA` — din coloanele de tip `D`, cu `Nvl` si
|
||||
garda pe gol.
|
||||
- `cMesajScpTVA` — din coloana **`mesaj_ScpTVA`** (`C(244)`), NU din `mesaj`.
|
||||
|
||||
Motiv: `validare.prg:2012` declara `mesaj_ScpTVA C(244)` dar `mesaj V(100)`, iar `:2109` face
|
||||
`loDate.mesaj = loDate.mesaj_ScpTVA` urmat de `Insert Into` la `:2112` — VFP taie tacut la 100
|
||||
din 244 de caractere. Proprietatea `mesaj` deja expusa contine mesajul ANAF trunchiat la 41%.
|
||||
|
||||
Toate patru se citesc **aici**: cursorul se inchide la `:1683` si nu mai exista alta ocazie.
|
||||
|
||||
**2. `ocautare.prg`, `ANAF_StarePartener`, blocul de verdict (`136-145`)**
|
||||
|
||||
Propaga cele patru proprietati in `loOut`.
|
||||
|
||||
Citirea se face cu `Pemstatus(loRezANAF, 'dInceputScpTVA', 5)` **aici, la `:140-145`** — nu in
|
||||
`TextAnaf`. `ocautare.prg` e incarcat si de produse ROA care pot avea un `validare.prg` mai vechi
|
||||
(garda existenta la `:63-66`); citirea neprotejata ar arunca eroare in acest bloc, inainte sa se
|
||||
ajunga vreodata la `TextAnaf`.
|
||||
|
||||
**3. `ocautare.prg`, `TextAnaf` (`683-695`) — cand si unde apare data**
|
||||
|
||||
Data de perioada apare in banda **doar pe trei conditii**. In rest banda ramane identica cu azi,
|
||||
iar perioada completa se vede in F4.
|
||||
|
||||
| Conditie | Data in banda |
|
||||
|---|---|
|
||||
| `lDiscordanta` = .T. (ROA difera de ANAF, sau partener inactiv) | DA |
|
||||
| `dAnulareScpTVA` nevid (anulare din oficiu) | DA |
|
||||
| `dSfarsitScpTVA` < `Date()` (perioada s-a incheiat deja) | DA |
|
||||
| rest (cazul normal, concordant) | NU |
|
||||
|
||||
**Regula de pozitionare, obligatorie:** data se lipeste **imediat dupa starea de TVA, inaintea
|
||||
oricarui segment `, Inactiv`**.
|
||||
|
||||
`TextStare` (`ocautare.prg:680`) produce `Platitor TVA, Inactiv`. Forma gresita
|
||||
`ANAF: Platitor TVA, Inactiv din 01.03.2019` afirma ca partenerul e inactiv din 2019, cand de fapt
|
||||
aceea e data de inceput a perioadei de TVA. Cum `lDiscordanta` include `statusInactivi`, cazul
|
||||
inactiv e chiar unul dintre cele aduse in banda — deci regula nu e optionala.
|
||||
|
||||
Forme corecte:
|
||||
|
||||
```
|
||||
ANAF: Platitor TVA din 01.03.2019, Inactiv (DENUMIRE... RO12345678) (F4 = detalii)
|
||||
ANAF: Platitor TVA din 01.03.2019 (DENUMIRE... RO12345678) (F4 = detalii)
|
||||
ANAF: Platitor TVA 01.03.2019 - 31.03.2026 (DENUMIRE... RO12345678) (F4 = detalii)
|
||||
ANAF: Neplatitor TVA din 12.03.2026 (DENUMIRE... 12345678) (F4 = detalii)
|
||||
ANAF: Neplatitor TVA, anulat din 12.03.2026 (DENUMIRE... 12345678) (F4 = detalii)
|
||||
```
|
||||
|
||||
Precedenta cand ambele date sunt nevide: pe `dAnulareScpTVA` — anularea din oficiu e informatia
|
||||
mai grava, iar `anulat` e cuvantul pe care contabilul il cauta. Cele doua date NU se contopesc:
|
||||
`data_sfarsit_ScpTVA` (incetarea inregistrarii) si `data_anul_imp_ScpTVA` (anulare din oficiu) au
|
||||
consecinte diferite asupra dreptului de deducere.
|
||||
|
||||
Cand perioada apare in banda, data documentului redundanta (`' la ' + Dtoc(toStare.dData)`) se
|
||||
scoate din text, ca sa nu rezulte doua date cu doua prepozitii alaturate.
|
||||
|
||||
Banda are voie 2-3 randuri: `lb_anaf` are `WordWrap = .T.`, `Height = 46`,
|
||||
`Width = toForm.Width - 20` (`ocautare.prg:472-476`). Riscul real nu e latimea, ci ca un sufix de
|
||||
lungime variabila muta punctul de wrap si `(F4 = detalii)` sare intre randuri la derularea cu
|
||||
sagetile. Regula de mai sus il reduce mult: ~95% din randuri pastreaza banda de azi.
|
||||
|
||||
**4. `ocautare.prg`, `Detalii` (`787-873`)**
|
||||
|
||||
Bloc nou in dialog, dupa starea curenta: perioada de inregistrare in scopuri de TVA (inceput /
|
||||
sfarsit / anulare, cele nevide, cu etichete distincte) si, daca `cMesajScpTVA` e nevid, mesajul
|
||||
textual primit de la ANAF, **integral**.
|
||||
|
||||
Perioada apare in F4 **intotdeauna** cand ANAF a trimis-o, inclusiv in cazul concordant in care
|
||||
banda nu o arata.
|
||||
|
||||
**5. `validare.prg` (`2064-2072`) — logul pe parsare esuata**
|
||||
|
||||
Se logheaza cazul in care `perioade_tva[1]` exista, sirul sursa e nevid, dar data parsata e goala.
|
||||
|
||||
Conditia se scrie **explicit**, NU in `CATCH`: `CTOD` nu arunca exceptie pe format necunoscut, ci
|
||||
intoarce data goala. `CATCH`-ul de la `:2070` prinde doar erori de acces la `perioade_tva[1]`, deci
|
||||
un log pus acolo nu s-ar declansa niciodata pe cazul pentru care a fost cerut.
|
||||
|
||||
(Parsarea e corecta cat timp ANAF trimite `YYYY-MM-DD`, sub `Set Date To YMD` de la `:2023`,
|
||||
restaurat in `Finally` la `:2131`.)
|
||||
|
||||
### Limita de acceptat
|
||||
|
||||
ANAF v9 intoarce O SINGURA perioada — cea care acopera data interogata. Textul afisat descrie
|
||||
perioada relevanta pentru data documentului, nu tot istoricul.
|
||||
|
||||
---
|
||||
|
||||
## L2 — validare CNP la codurile de 13 cifre
|
||||
|
||||
### Problema (bug raportat)
|
||||
|
||||
`ARGHIR MARIA (CUI: 2540324131210, ID: 149) ANAF nu a raspuns - verificarea a fost sarita.`
|
||||
|
||||
Mesajul e fals. `ANAF_StarePartener` (`ocautare.prg:82-84`) intoarce `.Null.` pentru codurile de
|
||||
13 cifre FARA a seta `tcClasaEsec`. CNP-ul din exemplu este VALID.
|
||||
|
||||
Localizarea exacta a defectului:
|
||||
- BANDA nu acuza ANAF: `.Null.` cu clasa goala cade pe `Case Isnull(m.loStare)` (`:648-650`) ->
|
||||
promptul neutru. Nu e gresit, dar nu spune nimic.
|
||||
- DIALOGUL F4 e singurul care minte: `Detalii`, `:799-804`, ultima ramura a `Iif`-ului imbricat
|
||||
(`:803`) -> 'ANAF nu a raspuns - verificarea a fost sarita.'
|
||||
- `VerificaAlegere` (`:875+`) intoarce `.T.` tacut pe `oStare` nul — acolo nu e nimic de reparat.
|
||||
|
||||
Defectul e mai larg decat cazul raportat: `EvalueazaRand` sterge explicit clasa de esec cand codul
|
||||
e invalid (`:600`, `This.cClasaEsec = ''`). Deci pentru ORICE cod fiscal invalid, banda spune corect
|
||||
"CNP invalid" / "CIF invalid", dar F4 afiseaza tot 'ANAF nu a raspuns'. Cazul raportat e una din
|
||||
doua instante ale aceluiasi defect.
|
||||
|
||||
### Ce exista deja (verificat)
|
||||
|
||||
- Validarea locala RULEAZA DEJA: `EvalueazaRand` apeleaza `ANAF_ValidareCod` la `:594` si iese
|
||||
devreme pe orice rezultat nevid (`595-604`), INAINTE de apelul ANAF. Deci "CNP invalid (...)" si
|
||||
"CIF invalid (...)" se afiseaza deja azi. Nu se scrie validare noua.
|
||||
- Consecinta: un cod care pica validarea nu ajunge niciodata pe drumul ANAF. Ramurile
|
||||
"CNP invalid" sub clasa noua si "CUI valid/invalid" sub `FARA_RASPUNS` sunt INACCESIBILE prin
|
||||
constructie si NU se implementeaza.
|
||||
- `ANAF_ValidareCod` (`:208-227`) decide CNP vs CIF cu prioritate pe `tip_persoana`, altfel lungime 13.
|
||||
- `VALIDARE_CNP` (`validare.prg:1296-1312`), `VALIDARE_CIF` (`validare.prg:1225-1294`).
|
||||
- Clasa noua `COD_INVALID` urmeaza tiparul existent `COD_NENUMERIC` de la `ocautare.prg:643-646`.
|
||||
|
||||
### Modificari
|
||||
|
||||
1. `ocautare.prg`, `EvalueazaRand` (`:600`): `This.cClasaEsec = 'COD_INVALID'` in loc de `''`.
|
||||
2. `ocautare.prg`, `ANAF_StarePartener` (`82-84`): seteaza `tcClasaEsec = 'CNP'` inainte de
|
||||
`Return .Null.`
|
||||
3. `ocautare.prg`, `ANAF_StarePartener`: primeste in plus `tnTipPersoana`, iar conditia de la `:82`
|
||||
devine `Len(m.lcCui) = 13 And m.lnTipPersoana <> 1`.
|
||||
|
||||
Motiv: `:82` decide "persoana fizica" doar pe lungime, ignorand `tip_persoana`, in timp ce
|
||||
`ANAF_ValidareCod` (`:222`) decide invers, cu prioritate pe `tip_persoana`. Divergenta e mascata
|
||||
azi pentru ca banda cade pe promptul neutru si nu afirma nimic. L2 pune acolo
|
||||
"Persoana fizica - CNP corect", deci pentru un partener extern cu cod numeric de 13 cifre
|
||||
aplicatia ar **afirma pe ecran** ceva fals, unde azi tace. Cauza e preexistenta, consecinta
|
||||
vizibila ar fi introdusa de L2.
|
||||
4. `ocautare.prg`, `EvalueazaRand` (`636-657`): ramura noua inaintea lui `Case Isnull(m.loStare)`,
|
||||
pe clasa `'CNP'` — banda arata `Persoana fizica - CNP corect`, culoare NEUTRA
|
||||
(`SeteazaLabel(..., .F., .T.)`), nu verde.
|
||||
|
||||
De ce nu verde: verdele si formularea scurta stau in acelasi loc si in aceeasi culoare cu
|
||||
confirmarea reala de la ANAF. O cifra de control nu este o verificare la ANAF.
|
||||
5. `ocautare.prg`, `Detalii` (`799-804`): doua ramuri noi in `Iif`-ul imbricat:
|
||||
- `'CNP'` -> `Persoana fizica - CNP corect.`
|
||||
- `'COD_INVALID'` -> `Cod fiscal invalid - nu s-a interogat ANAF. Corectati codul in fisa partenerului.`
|
||||
|
||||
Informativ, fara blocare si fara dialog de confirmare — cascada `RC_ANAF_VERIF_SELECTIE` ramane
|
||||
neatinsa.
|
||||
|
||||
---
|
||||
|
||||
# TRANSA 2 — L4: borderou eFactura, taxare inversa
|
||||
|
||||
Nu se incepe inainte ca transa 1 sa fie in SVN.
|
||||
|
||||
### Problema
|
||||
|
||||
In borderoul eFactura, facturile primite cu taxare inversa apar gri (diferenta fata de registrul de
|
||||
cumparari). In XML-ul eFactura taxarea inversa are TVA 0 (`ClassifiedTaxCategory/ID = 'AE'`), dar in
|
||||
contabilitate se inregistreaza `4426 = 4427`, deci `jc2007.totctva` contine si acest TVA. Diferenta
|
||||
rezultata e exact TVA-ul de taxare inversa si nu e o eroare reala.
|
||||
|
||||
Importul face deja corectia inversa la generarea notelor (`anaf_efactura.vc2:12096-12106`), dar
|
||||
numai `IF thisform.lPrimite`.
|
||||
|
||||
### Decizie
|
||||
|
||||
Corectia se face din datele contabile REALE, prin view-ul Oracle — nu prin recalcul cu cota
|
||||
standard (care ar da gresit pe facturi mai vechi la 19%). Scope: DOAR facturi primite.
|
||||
|
||||
**Coloana vizibila in grid NU se face.** Se livreaza doar corectia interna a expresiei `diferenta`.
|
||||
|
||||
### Conditii de intrare (ambele obligatorii inainte de a scrie scriptul)
|
||||
|
||||
1. **Trasare cap-coada** a unei facturi reale: linie XML cu `ClassifiedTaxCategory/ID = 'AE'` ->
|
||||
`id_jtva_coloana` -> coloana din `jc2007`. Se confirma pe date ca acolo sta suma.
|
||||
2. **Definitia curenta a lui `anaf_vefactura_trimis` se ia din `USER_VIEWS.TEXT` din schema tinta**,
|
||||
nu din arhiva CLAR.
|
||||
|
||||
Motiv: scriptul-model `2025\06\ff_2025_06_16_02_COMUN_EFACTURA.sql` redefineste NUMAI
|
||||
`anaf_vefactura_primit` (`:3-53`). Corpul lui `anaf_vefactura_trimis` e in alt fisier, mai vechi
|
||||
(`2024\08\ff_2024_08_22_01_COMUN_EFACTURA.sql:63-112`); cele doua au divergat cu ~10 luni si
|
||||
exista 10 scripturi in arhiva care il redefinesc. Cine il rescrie "dupa model" luand fisierul
|
||||
gresit revine tacut la o versiune veche a view-ului.
|
||||
|
||||
### Modificari
|
||||
|
||||
**1. Script de migrare nou**, in `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\07\`
|
||||
|
||||
`create or replace view` pentru AMBELE view-uri, cu o coloana noua `jtva_ti`:
|
||||
|
||||
- `anaf_vefactura_primit`: `jtva_ti` = suma coloanelor de TVA de taxare inversa din `jc2007`, cu
|
||||
EXACT aceeasi potrivire ca cea folosita azi pentru `jtotctva` (an/luna/dataact/regexp pe numar act
|
||||
si cod fiscal emitent).
|
||||
- `anaf_vefactura_trimis`: `jtva_ti` = constanta `0`. La facturi emise nu se inregistreaza nota
|
||||
contabila de TVA pentru taxare inversa, deci `diferenta` de acolo ramane identica cu azi.
|
||||
|
||||
Coloana e obligatorie in AMBELE: `import_efactura.prg:40` foloseste `FROM <<m.lcTabel>>`, un
|
||||
singur SELECT pentru ambele view-uri (`lcTabel` setat la `:27`). Fara ea, borderoul de facturi
|
||||
TRIMISE crapa cu ORA-00904.
|
||||
|
||||
**Lista de coloane** — CORECTATA 28.07.2026, verificata pe `USER_TAB_COLUMNS`.
|
||||
|
||||
Expresia din `Programe\oproceduri_decont.prg:8670` NU se poate copia: e scrisa peste view-ul
|
||||
`VJC2025` (`FROM VJC2025 J`, `:8677`), nu peste tabela. In acel view `ti19t` si `ti09t` sunt
|
||||
ALIASURI calculate (`SUM(ti19bct+ti19bvt+ti19bft) as ti19t`, `SUM(ti09bvt+ti09bft) as ti09t`).
|
||||
**Pe `jc2007` coloanele `TI19T` si `TI09T` nu exista.** Un `create or replace view` care le
|
||||
foloseste direct pica cu `ORA-00904` — si, cum acelasi script redefineste si
|
||||
`anaf_vefactura_trimis`, ar rupe borderoul pe AMBELE sensuri.
|
||||
|
||||
Lista corecta pe `jc2007` are **13 termeni**, nu 10 (`TI09` nu are varianta `BC`, asimetric fata
|
||||
de `TI19`):
|
||||
|
||||
```
|
||||
NVL(j.TI21T,0)+NVL(j.TI11T,0)+NVL(j.TI24T,0)+NVL(j.TI20T,0)
|
||||
+ NVL(j.TI19BCT,0)+NVL(j.TI19BVT,0)+NVL(j.TI19BFT,0)
|
||||
+ NVL(j.TI09BVT,0)+NVL(j.TI09BFT,0)
|
||||
+ NVL(j.XX21TIT,0)+NVL(j.XX11TIT,0)+NVL(j.XX19TIT,0)+NVL(j.XX9TIT,0)
|
||||
```
|
||||
|
||||
Familia NU este `XX*TI*` singura. Importul eFactura trece prin `ProcentTva2IdJtva`
|
||||
(definita in `COMUN\programe\oproceduri_comune.prg:5836`, doar apelata din
|
||||
`anaf_efactura.vc2:12093`), care pentru cumparari cu taxare inversa da id-urile 216/218/141/145;
|
||||
in `jtva_coloane`, 216 = 'TX. INV. 21%' -> `TI21B` (pereche 217 = `TI21T`), 218 = 'TX. INV. 11%' ->
|
||||
`TI11B` (219 = `TI11T`). Coloanele `XX*TIT` sunt achizitii NON-CE, pe care importul eFactura nu le
|
||||
scrie. Toate confirmate ca existente in `jc2007`: `TI21T`=217, `TI11T`=219
|
||||
(`2026\03\ff_2026_03_09_02_COMUN_PACK_CONTAFIN_10G_ROMCONSTRUCT.pck:4991-4993`), `XX19TIB`=192,
|
||||
`XX19TIT`=193 (`2026\01\PACK_CONTAFIN_ROMCONSTRUCT...pck:4891-4892`).
|
||||
|
||||
**Performanta:** `jtotctva` e deja un subselect corelat peste `jc2007` cu `REGEXP_SUBSTR` +
|
||||
`REGEXP_REPLACE` in `WHERE` — neindexabil, scanare per rand. Un al doilea subselect identic pentru
|
||||
`jtva_ti` ar dubla exact acest cost. Se scrie **un singur subselect care intoarce ambele sume**.
|
||||
|
||||
Se pastreaza `EXEC pack_migrare.UpdateVersiune(...)` + `COMMIT`. Fisierul se scrie cu **CRLF**.
|
||||
Se bumpeaza `versiune_db.txt`. Scriptul se incheie cu o verificare de obiecte invalide: view-urile
|
||||
`anaf_vefactura_primit_detaliu` si `anaf_vefactura_trimis_detaliu`
|
||||
(`2024\08\ff_2024_08_28_02_COMUN_EFACTURA.sql:84`, `:122`) sunt construite peste cele doua si se
|
||||
recompileaza automat, dar invaliditatea trebuie sa nu treaca neobservata.
|
||||
|
||||
**2. `COMUN\programe\import_efactura.prg` — o singura expresie**
|
||||
|
||||
Linia `:36`:
|
||||
|
||||
```
|
||||
NVL(total_cu_tva,0.00) - (NVL(jtotctva,0.00) - NVL(jtva_ti,0.00)) as diferenta
|
||||
```
|
||||
|
||||
**`lcSchema` (`:31-33`) NU se modifica.** `jtva_ti` apare doar ca termen intr-o expresie, nu ca
|
||||
coloana de iesire, deci numarul de coloane al cursorului ramane acelasi. `lcSchema` e o schema
|
||||
**pozitionala** imperecheata cu `lcSelect` in `gencursor` (`:50`); orice coloana noua de iesire ar
|
||||
cere modificarea ambelor, iar modificarea uneia singure ar strica intreg borderoul.
|
||||
|
||||
**3. Degradare gratioasa la lipsa coloanei**
|
||||
|
||||
Inainte de a construi `lcSelect`, se testeaza o data existenta coloanei (`SELECT jtva_ti FROM ...
|
||||
WHERE 1=2` intr-un `TRY`, sau interogare pe `user_tab_columns`) si se construieste `lcSelect` cu sau
|
||||
fara termenul `jtva_ti`.
|
||||
|
||||
Motiv: exe-ul ajunge la client prin update automat, iar migrarea CLAR ruleaza pe alta cadenta. Fara
|
||||
sonda, prima combinatie gresita da ORA-00904 si borderoul nu se deschide deloc, nici primite nici
|
||||
trimise. Cu sonda, ordinea de livrare devine optimizare, nu conditie de functionare.
|
||||
|
||||
Ordinea recomandata ramane: **scriptul se aplica INAINTE de build** — de scris in nota de release.
|
||||
|
||||
**4. Ce NU se atinge**
|
||||
|
||||
Colorarea ramane pe `diferenta <> 0` (`anaf_efactura.vc2:6020-6041` Page2 si `12790-12817`
|
||||
`frm_import_efactura`) — se corecteaza doar sursa numarului. NU se inventeaza o a treia culoare:
|
||||
randurile cu taxare inversa nu sunt de investigat, sunt corecte prin constructie, iar falsurile
|
||||
pozitive omoara marcajul de exceptie. NU se ating Page1 / Page3 si filtrul `chkDiferente`
|
||||
(`anaf_efactura.vc2:5347-5349`) — sunt facturi emise. Nu se editeaza niciun binar `.vcx`.
|
||||
|
||||
### Limita cunoscuta, de consemnat
|
||||
|
||||
O taxare inversa inregistrata la cota GRESITA face ca diferenta sa se anuleze reciproc si randul sa
|
||||
devina alb. Fara coloana in grid nu mai exista nicio parghie vizuala pentru acest caz. E pretul
|
||||
deciziei de a nu adauga coloana si trebuie sa fie scris, nu descoperit.
|
||||
|
||||
---
|
||||
|
||||
# TRANSA 3 — L3: avertizare de exigibilizare TVA la salvarea notelor
|
||||
|
||||
Ultima, singura. Nu se incepe inainte ca transele 1 si 2 sa fie in SVN.
|
||||
|
||||
### Scopul lucrarii — ca sa nu se citeasca gresit
|
||||
|
||||
Singura modificare de cod e in `COMUN\clase\omodificari.vc2`, in `inainte_de_do_termin` al celor
|
||||
doua clase de formular de note: `frm_modific2007` (`:5001`) si `frm_modific2024` (`:13131`).
|
||||
|
||||
**NU** se modifica `oproceduri_inchidere.prg`. **NU** se modifica `do_adauga_tva_exigibil`.
|
||||
**NU** se genereaza nimic automat in afara butonului din dialog.
|
||||
|
||||
`oproceduri_inchidere.prg` apare mai jos doar ca drum de test: exigibilizarea din meniu deschide
|
||||
chiar `frm_modific2007` (`:902`, `Createobject([frm_modific2007], ...)`, cu titlul
|
||||
'Exigibilizare TVA Incasare'), deci avertizarea se declanseaza si acolo fara ca cineva sa fi atins
|
||||
acel fisier.
|
||||
|
||||
### Conditie de intrare
|
||||
|
||||
Cotele 21% si 11% in `pack_contab.defalca_tva_incasare` si `pack_contab.cauta_facturaTVAEx`.
|
||||
Partial inchisa: exista suport 21%/11% in `2025\08\ff_2025_08_08_02_COMUN__PACK_CONTAB.sql`
|
||||
(comentariu "creeaza_note_tva_incasare TVA 21%, 11%"). De confirmat pe date.
|
||||
|
||||
### Ce exista deja (verificat)
|
||||
|
||||
- `Command5` -> `Thisform.do_adauga_tva_exigibil()` (`omodificari.vc2:13776-13778`).
|
||||
Captionul DIFERA intre clase: `:2643` = "Adauga nota TVA devenit exigibil" (`frm_modific2007`),
|
||||
`:6923` = "Adauga TVA exigibilizat" (`frm_modific2024`).
|
||||
- `do_adauga_tva_exigibil` (`:12483+`) lucreaza pe conditia
|
||||
`ales and (scc = '4428' or scd = '4428' or id_factd > 0 or id_factc > 0)` (`:12509`).
|
||||
**Nu contine nicio lista de cote** — lucreaza pe liniile notei si pe `proc_tva`, si deleaga
|
||||
defalcarea Oracle-ului. Deci e agnostic la cota si functioneaza la 21%.
|
||||
- `cmdSelect.Click` = "Selecteaza tot" (`:13640-13658`) — face doar `Replace All ales With .T.`
|
||||
- Precedent identic ca forma in acelasi hook: avertizarea 4426-4428 (`:13165-13176`), cu
|
||||
`amessagebox(..., 4+32, ...)` si `Return .F.`
|
||||
- `tact` poarta `tipnota`, `id_fact`, `id_factd`, `id_factc`, `ales`, `id_act`. Cursorul e construit
|
||||
de fiecare apelant, nu de `omodificari.vc2`. Codul insusi nu are incredere ca `tipnota` exista:
|
||||
`:4752` si `:12847` folosesc `If TYPE('tact.tipnota') = 'N' AND ...`
|
||||
- `Return .F.` din `inainte_de_do_termin` opreste salvarea: apelantul din `_frm_base.vc2`
|
||||
(`PROCEDURE do_termin`) nu face Release/Hide si **nu seteaza `buton`/`gnButon`**, iar toti
|
||||
apelantii testeaza `If buton = 1` inainte de a scrie. Nicio subclasa a celor doua clase nu exista
|
||||
in arbore, deci niciun override nu poate sari peste hook.
|
||||
|
||||
### Modificari — algoritm
|
||||
|
||||
**Pasul 0 — pozitionare in hook.** Verificarea se aseaza sub acelasi `IF m.llRet` ca avertizarea
|
||||
existenta (`:13165`) si **dupa** `SELECT tact` / `SET FILTER TO` de la inceputul procedurii
|
||||
(`:5001-5005`, `:13131-13135`). Altfel apare peste dialogul de eroare de la
|
||||
`verificare_note_contabile`, sau filtrul gridului ii ascunde randuri.
|
||||
|
||||
Ordinea dialogurilor la o singura apasare de Salvare: `verificare_note_contabile` -> avertizarea
|
||||
4426-4428 -> avertizarea noua. Prima semnaleaza o greseala facuta, a doua o omisiune.
|
||||
|
||||
**Pasul 0.5 — kill-switch.** Optiune implicit pornita. Daca e oprita: nicio avertizare, nicio
|
||||
interogare, in tot produsul. L1/L2 stau deja in spatele `RC_ANAF_VERIF_SELECTIE`; L3 intra pe drumul
|
||||
de salvare al intregii suite si nu are voie sa fie fara oprire.
|
||||
|
||||
**Mecanismul — CORECTAT 28.07.2026.** NU se folosesc `Optiuni_FIRMA`/`Optiuni_PROGRAM.dbf` din
|
||||
`DATE\`: acele tabele exista pe disc, dar nu sunt calea folosita si nu apar deloc in cod. Modelul de
|
||||
urmat este chiar `RC_ANAF_VERIF_SELECTIE`, care are trei straturi (`ocautare.prg:255-285`, `:341-381`):
|
||||
|
||||
1. kill-switch INI: `getini(gcGeneralIniFile, 'anaf', 'verificare_selectie')`, doar `'0'` opreste;
|
||||
2. optiuni Oracle (`optiuni` / `optiuni_util`), citite cu `citeste_optiune` /
|
||||
`citeste_optiune_utilizator` din `oinit_optiuni.prg`, cu cache intr-o `Collection`;
|
||||
3. UI = intrare de meniu (`Meniuri\CONT2000.MPR:210`, `ON SELECTION BAR ... DO ANAF_ComutaVerificare`),
|
||||
nu ecran cu campuri DBF.
|
||||
|
||||
**Pasul 0.6 — flag de lot.** Apelantii care instantiaza formularul in bucla seteaza un flag public
|
||||
"rulez in lot", iar verificarea se sare. `anaf_efactura.vc2:12733` instantiaza `frm_modific2024`
|
||||
**per factura importata**: un import de 150 de facturi ar insemna 150 de `AMESSAGEBOX` succesive
|
||||
plus 150 de interogari Oracle sincrone. Acelasi lucru la `:12940` si `comun.vc2:2436`.
|
||||
|
||||
**Pasul 1 — colectare.** Din `tact`, id-urile `id_factd` / `id_factc` > 0. Daca nu exista niciunul:
|
||||
nimic, cost zero, fara interogare Oracle.
|
||||
|
||||
**Pasul 2 — suprimarea platilor deja acoperite.**
|
||||
|
||||
Regula: exista in `tact` o linie cu `tipnota = 1` SI `id_fact = <id>`.
|
||||
|
||||
Citirea lui `tipnota` se face prin `TYPE('tact.tipnota') = 'N'`, ca la `:4752` si `:12847` —
|
||||
`tact` e construit de apelant, posibil din alt produs ROA.
|
||||
|
||||
**Santinela `-5` NU intra in regula.** `do_adauga_tva_exigibil` scrie `-5` numai cand id-ul
|
||||
facturii nu se poate rezolva (`:12531`, `:12542`, `:12551`, `:12559`), iar comentariul din cod spune
|
||||
ce inseamna: "pun -5 ... ca sa-i completez id_fact la scrie_in_act" — adica **"de completat la
|
||||
scriere"**, nu "rezolvat". Pentru liniile colectate la pasul 1 (`id_factd`/`id_factc` > 0) codul
|
||||
scrie intotdeauna id-ul real, deci `-5` e imposibil prin constructie pe multimea urmarita. In
|
||||
schimb, o disjunctie `SAU id_fact = -5` nu ar fi conditionata de id: o singura linie cu `-5`
|
||||
oriunde in `tact` ar stinge avertizarea pentru TOATE platile din lot, tacut.
|
||||
|
||||
Calificarea pe `tipnota = 1` se pastreaza: fara ea, excluderea ar prinde si notele MANUALE
|
||||
`4426=4428` — exact cele despre care avertizarea existenta de la `:13165` spune ca sunt probabil
|
||||
gresite.
|
||||
|
||||
> Nota de reconciliere: o decizie intermediara a review-ului (D23) ceruse mutarea cheii de pe
|
||||
> `tipnota` pe perechea de conturi, pe motiv ca notele generate de `inchidere_tva_sold` au
|
||||
> `tipnota = 0` (`oproceduri_inchidere.prg:884`). Motivul a cazut: acel drum nu ajunge niciodata la
|
||||
> regula, pentru ca `INSERT INTO actactan` (`:848-854`) nu completeaza `id_factd`/`id_factc`, deci
|
||||
> pasul 1 nu colecteaza nimic. Cheia ramane pe `tipnota`, fara `-5`.
|
||||
|
||||
**Pasul 3 — interogarea, fara lista IN.**
|
||||
|
||||
O singura interogare `goExecutor`, care intoarce `id_fact`-urile cu `tva_incasare = 1` si sold
|
||||
neexigibil `<> 0`. **Intersectia cu `tact` se face local, in VFP.**
|
||||
|
||||
**Sursa — CORECTATA 28.07.2026.** Interogarea NU se poate scrie peste `jc2007` + `jv2007`:
|
||||
**coloana `tva_incasare` nu exista pe cele doua tabele** (verificat pe `USER_TAB_COLUMNS`). Ea sta pe
|
||||
`DOCUMENTE` (`id_doc = id_fact`) si pe view-urile `VJC2025` / `VJV2025`. Se interogheaza view-urile:
|
||||
au deja tot ce trebuie (cotele, `tva_incasare`, `an`/`luna`, `id_fact`) si sunt exact ce foloseste
|
||||
deja `pack_contab.cauta_facturaTVAEx`. Cele 14 coloane de cota de mai jos exista, in schimb, si pe
|
||||
`jc2007`/`jv2007` — verificat.
|
||||
|
||||
Nu se construieste lista `IN (...)`. Pragul Oracle de 1000 (ORA-01795) se atinge la utilizare
|
||||
normala, nu la 10x: acelasi formular deserveste, dupa propriul caption, "Import extrase bancare,
|
||||
deconturi curieri, procesatori plati" (`anaf_efactura.vc2:12941`), iar imperecherea se face linie cu
|
||||
linie (`oproceduri_import.prg:729, 755, 782, 808`). Un extras obisnuit are 300-2000 linii/luna; un
|
||||
decont de procesator, mult mai mult. Un singur SQL de lungime fixa elimina o clasa intreaga de esec
|
||||
de pe drumul de salvare al intregii suite.
|
||||
|
||||
**Formula de sold neexigibil** — NU se copiaza din registru. Filtrul existent la
|
||||
`Clase\ovanzcump.vc2:38011` foloseste
|
||||
`ro24nb+ro24nt+ro20nb+ro20nt+ro19nb+ro19nt+ro9nb+ro9nt+ro5nb+ro5nt`, care OMITE cotele 21% si 11%,
|
||||
in vigoare din august 2025 (`RO21NB/RO21NT/RO11NB/RO11NT`, id-uri 214/215,
|
||||
`2025\07\ff_2025_07_21_01_COMUN_TVA21.sql:134-140`). Cu formula copiata, avertizarea nu s-ar
|
||||
declansa NICIODATA pe o factura din 2025 incoace — exact pe facturile pentru care a fost ceruta.
|
||||
|
||||
Lista corecta:
|
||||
```
|
||||
ro24nb+ro24nt+ro20nb+ro20nt+ro21nb+ro21nt+ro11nb+ro11nt+ro19nb+ro19nt+ro9nb+ro9nt+ro5nb+ro5nt
|
||||
```
|
||||
|
||||
**Robustete.** Verificarea ruleaza doar dupa ce `verificare_note_contabile` a trecut si doar cu
|
||||
conexiune valida. Orice esec (tabela inexistenta in alt produs ROA, conexiune cazuta, timeout) ->
|
||||
**se sare, cu linie in `goLog`**. Niciodata tacut: o verificare care moare invizibil e mai rea decat
|
||||
una absenta, pentru ca nimeni nu afla ca nu mai merge. Esecul nu blocheaza salvarea.
|
||||
|
||||
**Cum se obtine asta — PRECIZAT 28.07.2026, dupa citirea clasei.** `oexecutor` e in
|
||||
`COMUN\programe\oproceduri_comune.prg:69-547`. Comportamentul real:
|
||||
|
||||
- `oExecute()` NU arunca eroare VFP pe SQL esuat: intoarce `CT_INSUCCES` (-1). Deci nu urca la
|
||||
`ON ERROR` global. `goLog.Log` se apeleaza pe toate drumurile de esec. Pana aici, cerinta e
|
||||
indeplinita din oficiu.
|
||||
- **DAR** pe eroare ODBC de conexiune cazuta (cod 1526 cu subcod 12152/3113/3114/12560/4068/28/12 —
|
||||
exact cazul numit mai sus) se deschide un `amessagebox` "Doriti reconectare?"
|
||||
(`oproceduri_comune.prg:390`) NECONDITIONAT de `tlShowError`, iar raspunsul "Nu" duce la `QUIT` —
|
||||
**inchide aplicatia**, in mijlocul salvarii. Exact opusul cerintei.
|
||||
- Deci apelul TREBUIE facut cu reconectarea dezactivata explicit. **Nu exista precedent**: din 150+
|
||||
apeluri `oExecute`/`oExecuta` din codebase, niciunul nu trece de 2 parametri. Tiparul se scrie
|
||||
aici prima oara.
|
||||
- Semnatura confirmata (`oproceduri_comune.prg:169`):
|
||||
`oExecute(tcSql, tcCursor, tlProgress, tcTitluProgress, tnHandle, tlShowError, tlQuitOnError, tlReconnect)`.
|
||||
`tlReconnect` e al **8-lea** parametru si are **implicit `.T.`** (comentariul din cod, `:175`),
|
||||
deci trebuie pasat `.F.` EXPLICIT — altfel se obtine exact dialogul cu `QUIT`.
|
||||
Atentie la parametrii 3-7 care trebuie completati ca sa se ajunga la al 8-lea: pentru fiecare, ia
|
||||
din cod valoarea pe care codul o considera implicita cand parametrul lipseste, ca sa nu schimbi
|
||||
din greseala alt comportament (in special `tnHandle` si `tlQuitOnError`).
|
||||
- Se foloseste `oExecute`, NU `oExecuta` (aceasta din urma afiseaza mesaj propriu, neconditionat, pe
|
||||
orice esec). Nu se adauga niciun `amessagebox` propriu.
|
||||
- Nu exista niciun timeout Oracle configurat (`SQLSETPROP QueryTimeout`/`ConnectTimeout`) nicaieri:
|
||||
un query agatat blocheaza la nesfarsit, nu doar da eroare. De avut in vedere la testare.
|
||||
|
||||
**Pasul 4 — dialogul.**
|
||||
|
||||
Trei butoane:
|
||||
|
||||
```
|
||||
Exista <N> plati/incasari pe facturi cu TVA la incasare pentru care nu s-a adaugat
|
||||
nota de TVA exigibilizat.
|
||||
|
||||
[Adauga acum] [Continua] [Anuleaza]
|
||||
```
|
||||
|
||||
- **Adauga acum** — ruleaza `do_adauga_tva_exigibil` pe liniile deja identificate de interogare,
|
||||
apoi continua salvarea.
|
||||
- **Continua** — salveaza fara exigibilizare.
|
||||
- **Anuleaza** — `Return .F.`, ramane in formular fara sa salveze.
|
||||
|
||||
De ce buton si nu instructiune: sistemul stie deja care plati au nevoie de exigibilizare — asta e
|
||||
chiar interogarea de la pasul 3. O modala care spune "du-te si apasa un buton" ar fi fost
|
||||
inexecutabila in doua feluri: captionul difera intre cele doua clase (`:2643` vs `:6923`), iar
|
||||
`Command5.Enabled` se calculeaza dupa **randul curent** (`:5661-5667`, `:13850`) si `cmdSelect.Click`
|
||||
nu il recalculeaza — deci butonul poate fi gri exact dupa "Selecteaza tot".
|
||||
|
||||
`<N>` — **FIXAT 28.07.2026, marius.mutu: facturi DISTINCTE**, nu linii din `tact`. Actiunea pe care o
|
||||
propune butonul e per factura, nu per linie: trei plati partiale pe aceeasi factura sunt o singura
|
||||
factura de exigibilizat, si asa trebuie numarate. Textul dialogului se ajusteaza corespunzator
|
||||
("Exista <N> facturi cu TVA la incasare pentru care nu s-a adaugat nota de TVA exigibilizat").
|
||||
|
||||
**Pasul 5 — flag anti-bucla.**
|
||||
|
||||
Proprietate de formular `lAvertizatExigibilizare`, setata dupa prima avertizare; a doua oara in
|
||||
aceeasi sesiune de formular nu se mai avertizeaza.
|
||||
|
||||
Motiv: cand `chkTVAEX` e bifat si linia e plata/incasare, `do_adauga_tva_exigibil` cheama
|
||||
`creeaza_note_tva_incasare` (`:12598-12600`), unde `id_fact` vine din cursorul intors de
|
||||
`pack_contab.defalca_tva_incasare` (`:12412`, `a.id_fact As id_fact`). Daca procedura nu intoarce
|
||||
randuri, nu se insereaza nimic potrivit -> suprimarea nu prinde niciodata -> avertizare -> buton ->
|
||||
avertizare -> buton (**dubland notele generate**) -> avertizare, fara iesire in afara de "Continua".
|
||||
Ca "zero randuri" e un caz real: `oproceduri_inchidere.prg:843-848` il trateaza explicit.
|
||||
|
||||
### Acoperire — drumuri de instantiere
|
||||
|
||||
`frm_modific2007` / `frm_modific2024` sunt instantiate din: `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`.
|
||||
|
||||
Premisa "prinde si casa, si banca, si notele manuale" TINE.
|
||||
|
||||
> Nota de metoda: `COMUN/` e in `.gitignore`, deci Grep/ripgrep il sare implicit. Cautarile de tip
|
||||
> "cine apeleaza" se fac cu `rg --no-ignore` sau cu cale explicita, altfel intorc zero fals.
|
||||
|
||||
---
|
||||
|
||||
# NU intra in scop (amanat, cu motiv)
|
||||
|
||||
**Defectele din drumul de exigibilizare din meniu** (`inchidere_tva_sold`). De adaugat in TODOS.md
|
||||
cu descrierea de mai jos, care **inlocuieste** formularea anterioara — aceea descria un defect
|
||||
inexistent si ar fi trimis pe cine preia lucrarea catre o harta gresita.
|
||||
|
||||
Ce este de fapt:
|
||||
|
||||
1. `oproceduri_inchidere.prg:833` testeaza `Iif(m.lnCota = 21, m.lnSuma21, m.lnSuma11)` intr-o bucla
|
||||
`For lnCota = 1 To 7` (`:829`). `lnCota` nu ajunge niciodata 21, deci `lnSuma21` e cod mort, iar
|
||||
la `lnCota = 6` se ia soldul de 11% cu cota 1.21 (`:834`). Linia vecina `:837` o face corect
|
||||
(`Iif(m.lnCota = 6, m.lnSuma21T, ...)`). Este o greseala de tipar `6` -> `21`.
|
||||
2. `:802-803` citesc `soldn21` / `soldn11` neconditionat din `crsTVAIncasareTemp`. Aliasurile sunt
|
||||
emise doar de formele 2025 (`ovanzcump.vc2:44220-44225`, `:55069-55073`). Pe formele 2010
|
||||
(`:39660`, `:51403`) nu exista -> eroare VFP 12, modala, la apasarea butonului. Exigibilizarea
|
||||
din registru e rupta pe perioadele anterioare lui 2025.
|
||||
3. `lnSuma21`, `lnSuma11`, `lnSuma20`, `lnSuma19` lipsesc din lista `Local` (`:770-773`) — devin
|
||||
PRIVATE si se scurg in stiva de apel.
|
||||
|
||||
Ce NU este: `ovanzcump.vc2:39660` nu "pierde 24/20"; e forma 2010, folosita pe perioade < 2025, al
|
||||
carei cursor sursa `vjc2010`/`vjc2013` nu are deloc coloanele `ro21*`/`ro11*` (`oproceduri_decont.prg:18795-18801`),
|
||||
deci acolo omisiunea e corecta.
|
||||
|
||||
Nu afecteaza L3: butonul catre care trimite avertizarea L3 este `do_adauga_tva_exigibil`, care nu
|
||||
foloseste nicio lista de cote. Sunt doua butoane diferite, pe doua drumuri diferite.
|
||||
|
||||
**De scris in nota de release:** pe o factura cu TVA la incasare 21%, L3 avertizeaza corect, dar
|
||||
utilizatorul care merge pe drumul din meniu (registru -> exigibilizare) gaseste lista goala. Butonul
|
||||
din formular functioneaza.
|
||||
|
||||
Alte lucruri amanate:
|
||||
- Istoricul complet al atributului de TVA (mai multe perioade). ANAF v9 intoarce o singura perioada.
|
||||
- Al doilea apel ANAF la data curenta ("era platitor la data documentului, dar nu mai este azi").
|
||||
- Persistarea totalului cu TVA de taxare inversa pe randul din `anaf_efactura` la import: nu ar
|
||||
acoperi facturile deja importate; view-ul repara si istoricul.
|
||||
- Derivarea listelor de cote din `jtva_coloane` in loc de enumerare in mai multe locuri. E cauza
|
||||
radacina a defectelor gasite la L3 si L4.
|
||||
|
||||
---
|
||||
|
||||
# Ce exista deja (si se reutilizeaza)
|
||||
|
||||
| Sub-problema | Cod existent | Se reutilizeaza? |
|
||||
|---|---|---|
|
||||
| Perioada TVA de la ANAF | `ParseJsonANAFv8`, `validare.prg:2001-2114` | Da, integral. Se propaga, nu se parseaza din nou |
|
||||
| Detectia discordantei ROA vs ANAF | `lDiscordanta`, `ocautare.prg:143` | Da. Nu se scrie detectie noua |
|
||||
| Cache de sesiune | `goCacheANAF_Sesiune`, `ocautare.prg:127`, `:130` | Da, nemodificat |
|
||||
| Validare CNP / CIF | `VALIDARE_CNP` / `VALIDARE_CIF`, apelate prin `ANAF_ValidareCod` la `:594` | Da, integral |
|
||||
| Generarea notelor de exigibilizare | `do_adauga_tva_exigibil`, `omodificari.vc2:12483+` | Da (rulat din butonul dialogului) |
|
||||
| Tiparul de avertizare in `inainte_de_do_termin` | `omodificari.vc2:13165-13176` | Da, se copiaza forma |
|
||||
| Lista canonica de coloane TVA taxare inversa | `oproceduri_decont.prg:8670` | Da, se preia ca atare |
|
||||
|
||||
---
|
||||
|
||||
# Reguli de livrare
|
||||
|
||||
- Fiecare transa livreaza `docs\diff_runda<N>_<subiect>.patch`; write-back in binar
|
||||
(`txt2vcx.ps1`) si commit DOAR dupa aprobare. Patch-urile nu se comit.
|
||||
- Comentarii: o singura intrare cumulativa in antetul fisierului, `*!* DD.MM.YYYY` /
|
||||
`*!* marius.mutu` / 1-2 fraze. Fara comentarii in corpul codului. La L2 (corectie de eroare) nu se
|
||||
adauga comentariu.
|
||||
- `ocautare.prg`, `validare.prg` si `omodificari.vc2` contin octeti cp1252 (0xBA). Orice scriere cu
|
||||
Edit/Write ii corupe in `EF BF BD`. Se editeaza TOT ce e de editat, si abia DUPA ultima scriere se
|
||||
verifica byte-level si se repara o singura data, luand octetul corect din `svn cat`.
|
||||
- Scripturile `.sql` din SCRIPTURI_CLAR se scriu cu **CRLF**.
|
||||
- `changelog_roacont.txt`: cate o intrare scurta per transa. L1/L3/L4 = `:nou:` sau `:modificare:`;
|
||||
L2 = `:eroare:` (mesajul fals a ajuns la utilizatori).
|
||||
|
||||
---
|
||||
|
||||
# Ce ramane neverificat
|
||||
|
||||
Stare la 28.07.2026, dupa verificarea pe date (schema dev `MARIUSM_AUTO`). Detalii in
|
||||
`docs\handoff_transa2_conditii.md`, `handoff_transa3_conditii.md`, `handoff_transa3_deschise.md`.
|
||||
|
||||
- ~~Comportamentul `goExecutor` la timeout / conexiune cazuta~~ — INCHIS, vezi "Robustete" mai sus.
|
||||
- ~~Daca `pack_contab.defalca_tva_incasare` poate intoarce `id_fact` null/0~~ — INCHIS. `id_fact` in
|
||||
cursor e mereu parametrul trimis, deci nu poate fi null. Zero randuri ESTE posibil (filtrul final
|
||||
poate exclude tot), si e chiar garantat pe drumul `omodificari.vc2:12547-12561`, unde santinela
|
||||
`-5` ajunge ca parametru la `defalca_tva_incasare(-5, ...)`. **Flagul anti-bucla de la Pasul 5 e
|
||||
confirmat necesar, nu preventiv.**
|
||||
- ~~Cotele 21/11 in `pack_contab`~~ — INCHIS. `defalca_tva_incasare` deleaga la
|
||||
`creeaza_note_tva_incasare`, care are `DECODE` explicit pe `id_jtva_coloana` 211/215 (JC) si 38/42
|
||||
(JV) pentru `RO21*`/`RO11*`; `cauta_facturaTVAEx` filtreaza si el pe `RO21NT`/`RO11NT`.
|
||||
**Conditia de intrare a transei 3 e indeplinita.**
|
||||
- Numarul real de linii pe un decont de curier/procesator — RAMANE DESCHIS pe cifra. Schema dev nu
|
||||
are date reprezentative (`DECONT`: 2 randuri in toata baza; `EXTRAS CON`: p95 ~10 linii/lot, cu un
|
||||
ordin de marime sub estimarea din plan, dar pe loturi de test, nu activitate reala). **Nu schimba
|
||||
decizia**: o interogare unica de lungime fixa elimina `ORA-01795` indiferent de volum, deci nu
|
||||
exista prag sub care lista `IN(...)` ar fi de preferat.
|
||||
- Trasarea cap-coada a unei facturi cu linie `AE` (transa 2) — RAMANE DESCHISA pe date reale.
|
||||
In schema dev NU exista nicio factura venita din import eFactura cu taxare inversa (`anaf_efactura`:
|
||||
487 randuri primite, 8 cu `id_fact`, zero suprapunere cu randuri `TI*` nenule). Mecanismul a fost
|
||||
demonstrat numeric doar pe un caz construit din `jc2007` (`id_fact=8007136`, `ti19bft=19`,
|
||||
`totctva=119`: diferenta falsa de -19 se anuleaza exact cu `jtva_ti`). **De consemnat in nota de
|
||||
release**: verificarea finala ramane de facut pe prima factura reala de taxare inversa importata
|
||||
dupa aplicarea scriptului.
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
# ANEXA — istoricul review-ului
|
||||
|
||||
Nimic de implementat aici. Se pastreaza pentru trasabilitate.
|
||||
|
||||
## Metoda
|
||||
|
||||
Doua runde: `/autoplan` (CEO -> Design -> Eng) pe 27.07, apoi runda 2 cu trei voci independente
|
||||
(subagenti fara context de review) confruntate cu verificare proprie pe cod. Codex indisponibil pe
|
||||
masina, deci consensul e "voce independenta + verificare proprie", nu Claude/Codex. Faza DX sarita:
|
||||
produsul nu e pentru dezvoltatori.
|
||||
|
||||
## Afirmatii verificate pe cod
|
||||
|
||||
CONFIRMATE: `ParseJsonANAFv8` pune datele in cursor (`validare.prg:2012`); `ANAF_VerdictDinCursor`
|
||||
expune doar 5 campuri (`:1670-1675`); cache-ul pastreaza obiectul intreg (`ocautare.prg:127`,
|
||||
`:130`); `tact` poarta campurile necesare (`omodificari.vc2:4496`, `:5661`, `:13166`); precedentul
|
||||
de avertizare (`:13165-13172`); un singur SELECT pentru ambele view-uri (`import_efactura.prg:40`);
|
||||
coloanele `TI21T`=217, `TI11T`=219, `XX19TIB`=192, `XX19TIT`=193; `lb_anaf` multi-rand
|
||||
(`ocautare.prg:472-476`); localizarea defectului L2 in `Detalii` (`:648-650`, `:803`);
|
||||
`Return .F.` opreste salvarea (`_frm_base.vc2`, `do_termin`).
|
||||
|
||||
INFIRMATE: tipul coloanelor de perioada era declarat incert — sunt deja `D`; `mesaj` NU e
|
||||
echivalent cu `mesaj_ScpTVA` (V(100) vs C(244)); santinela `-5` inseamna "de completat la scriere",
|
||||
nu "rezolvat"; capcana `inchidere_tva_sold` e evitata prin `id_factd`/`id_factc` necompletate, nu
|
||||
prin `tipnota`; defectul de cote amanat era descris gresit.
|
||||
|
||||
## Decizii
|
||||
|
||||
D1-D21 (runda 1, `/autoplan`): mod SELECTIVE EXPANSION; lista de coloane `TI*`+`XX*TI*`; coloana in
|
||||
ambele view-uri; conditie de intrare prin trasare cap-coada; lista de cote cu 21/11; defect
|
||||
preexistent semnalat nu reparat; texte distincte pentru sfarsit vs anulare; log pe parsare esuata;
|
||||
eliminarea ramurilor inaccesibile din L2; corectarea localizarii defectului L2; data lipita de
|
||||
stare; banda multi-rand; interval pentru perioada inchisa; `Pemstatus`; defectul L2 mai larg
|
||||
(`:600`); banda neutra pentru CNP; regula de suprimare pe `tipnota`; `jtva_ti` coloana vizibila;
|
||||
fara a treia culoare; ordinea DB-inainte-de-exe.
|
||||
|
||||
D22-D33 (runda 2): N1 `mesaj_ScpTVA` in loc de `mesaj` (rastoarna D7); N2/N3/N4/N5/N6/N7;
|
||||
`4+32+256`; conditie de intrare pe `pack_contab`; rescrierea textului amanarii.
|
||||
|
||||
D34-D37 (poarta, marius.mutu): trei livrari separate, fixurile N7 raman amanate cu text rescris;
|
||||
L3 cu buton de actiune in dialog; L4 fara coloana vizibila; L1 cu data si la `lDiscordanta`.
|
||||
|
||||
Contradictie rezolvata la consolidare: D23 (cheia de suprimare pe perechea de conturi) cade in
|
||||
favoarea E.2 (`tipnota = 1 AND id_fact`, fara `-5`) — motivul lui D23 a disparut odata cu E.3.
|
||||
|
||||
Deciziile D36 si D37 au dizolvat trei constatari: N5, K-1 si N6 nu mai au obiect fara coloana
|
||||
vizibila; N3 si N4 nu mai au obiect cu butonul in dialog.
|
||||
|
||||
## Teme transversale
|
||||
|
||||
**Tema 1 — "corect pe hartie, inexecutabil de utilizator".** Trei constatari independente (caption
|
||||
diferit, buton conditionat de randul curent, coloana invizibila din cauza preferintelor de grid) au
|
||||
avut aceeasi forma. Toate trei au fost eliminate prin deciziile de la poarta.
|
||||
|
||||
**Tema 2 — planul verifica listele de cote in VFP si nu deschide niciun pachet Oracle.** De aici
|
||||
conditia de intrare pe `pack_contab` pentru transa 3.
|
||||
Reference in New Issue
Block a user