Cache ANAF pe ISTORIC_CODURI_FISCALE: verificare din memorie, plasa la tacere ANAF

Verificarile de partener nu mai depind exclusiv de raspunsul ANAF: se citeste
intai cache-ul din ISTORIC_CODURI_FISCALE (mutat in CONTAFIN_ORACLE), cu
provenienta afisata pe ecrane (sursa / data_sursa) si cu plasa de siguranta
cand ANAF tace. Ordinea cache/ANAF e configurabila; cache-ul expira.

- programe/validare.prg: verificare single si pe loturi peste cache, contract
  404 separat de caderea de serviciu, expirarea cache-ului, corectii la
  verdictul pe firma si la etichetarea CACHE_INDISP.
- programe/ocautare.prg: plasa de siguranta si banda de provenienta la cautarea
  de partener.
- programe/oproceduri_comune.prg: VERIFICA_RTVAI_DATA citeste si cache-ul.
- clase/overificari.vc2: propagarea provenientei in interfata.
- utile/Teste/: harness-uri de testare headless - echivalenta cache/ANAF pe 200
  de coduri reale, marginile pe inactiv si TVA la incasare, mock batch ANAF,
  baseline D394 si sondele de diagnostic ANAF.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JCzVWfqscv1xyo5uvJiWiW
This commit is contained in:
2026-08-02 01:31:30 +03:00
parent ebb20fab7e
commit 859e67e874
17 changed files with 3889 additions and 84 deletions

View File

@@ -1596,6 +1596,8 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
*< OBJECTDATA: ObjPath="_grdbase1.cInactiv.Check1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="_grdbase1.Column26.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="_grdbase1.Column26.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="_grdbase1.Column27.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="_grdbase1.Column27.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="But_verifica1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Gridextra1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="chkMFIN" UniqueID="" Timestamp="" />
@@ -1658,7 +1660,7 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
ADD OBJECT '_grdbase1' AS _grdbase WITH ;
Anchor = 15, ;
ColumnCount = 26, ;
ColumnCount = 27, ;
DeleteMark = .F., ;
HeaderHeight = 32, ;
Height = 283, ;
@@ -1835,7 +1837,13 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
Column26.DynamicBackColor = "RGB(255,202,228)", ;
Column26.Name = "Column26", ;
Column26.ReadOnly = .T., ;
Column26.Width = 150
Column26.Width = 150, ;
Column27.ColumnOrder = 27, ;
Column27.ControlSource = "IIF(EMPTY(NVL(sursa,'')),'',IIF(ALLTRIM(sursa)=='ANAF','ANAF','CACHE '+DTOC(NVL(data_sursa,DATE()))+IIF(ALLTRIM(sursa)=='CACHE_INDISP',' (ANAF indisponibil)','')))", ;
Column27.Name = "Column27", ;
Column27.ReadOnly = .T., ;
Column27.Visible = .T., ;
Column27.Width = 230
*< END OBJECT: ClassLib="_grd_base.vcx" BaseClass="grid" />
ADD OBJECT '_grdbase1.cInactiv.Check1' AS checkbox WITH ;
@@ -2170,6 +2178,22 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT '_grdbase1.Column27.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Provenienta", ;
Name = "Header1"
*< END OBJECT: BaseClass="header" />
ADD OBJECT '_grdbase1.Column27.Text1' AS textbox WITH ;
BackColor = 255,255,255, ;
BorderStyle = 0, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT '_grdbase1.Column3.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "CIF/CNP", ;
@@ -2695,7 +2719,6 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
lcConditieSuplimentara = Iif(m.llLiniaCurenta, "recno() >= " + Alltrim(Str(m.lnRecord)), ".T.")
If m.llServiciuWebANAF
SET STEP ON
&& verificare serviciu web ANAF
SELECT distinct cod_fiscal, IIF(!EMPTY(NVL(data, {})), data, DATE(m.gnAn, m.gnLuna, 1)) as data ;
FROM crsVerificareParteneri ;
@@ -2722,7 +2745,8 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
LOCATE FOR ALLTRIM(Strtran(cod_fiscal, loVerificare.GetCodTara(cod_fiscal),'')) = ALLTRIM(STR(.cui)) AND (EMPTY(NVL(data, {})) OR data = m.ldData)
IF FOUND()
Replace firma With .denumire, adresa With .adresa, datatvamfin With TRANSFORM(.data), platitortvamfin With .tva, stare With .mesaj, cod WITH ALLTRIM(STR(.cui)), ;
tvaincasare WITH .tvaincasare, splittva WITH .splittva, inactiv WITH .inactiv
tvaincasare WITH .tvaincasare, splittva WITH .splittva, inactiv WITH .inactiv, ;
sursa WITH NVL(.sursa, 'ANAF'), data_sursa WITH .data_sursa
ENDIF
ENDWITH
ENDSCAN && (m.lcCursorVerificareANAF)
@@ -2887,6 +2911,20 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
this._grDBASE1.HeaderHeight = 32
ENDPROC
PROCEDURE Load
*** campurile de provenienta (cache/ANAF) trebuie sa existe INAINTE ca grid-ul sa se construiasca (Load ruleaza inaintea obiectelor din forma);
*** ALTER TABLE nu functioneaza pe acest cursor (are campuri peste 10 caractere, ex. platitortvamfin) - se rematerializeaza cu SELECT
LOCAL lcAliasTmp
IF TYPE('crsVerificareParteneri.sursa') = 'U'
lcAliasTmp = 'crsVPTmp' + Sys(2015)
SELECT *, SPACE(20) AS sursa, {} AS data_sursa FROM crsVerificareParteneri INTO CURSOR (lcAliasTmp) READWRITE
USE IN (SELECT('crsVerificareParteneri'))
SELECT * FROM (lcAliasTmp) INTO CURSOR crsVerificareParteneri READWRITE
USE IN (SELECT(lcAliasTmp))
ENDIF
DODEFAULT()
ENDPROC
PROCEDURE meniu_dblclick
*** Verificare cod fiscal de pe inregistrarea curenta
Local loDate As "empty"

View File

@@ -39,7 +39,9 @@ $p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }
- `LINENO()` din handler e relativ la inceputul metodei: linia in `.vc2` = linia raportata +
linia `PROCEDURE`.
- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare); sterge `.fxp`-ul vechi
daca ai editat scriptul intre rulari.
daca ai editat scriptul intre rulari. Daca nu-l stergi, VFP ruleaza codul vechi din `.fxp`
fara niciun semn - testul poate trece si raportul poate parea valid, desi modificarea nu a
fost executata; se prinde doar dupa ce lipseste din log o linie pe care o scrie doar codul nou.
- Forme modale: `Show(1)` blocheaza. Replica in script doar liniile relevante din Show, sau
seteaza `WindowType = 0`.

View File

@@ -62,6 +62,13 @@
*!* programului si starea de pe calculator; utilizatorul isi poate sterge propria setare, ca sa revina
*!* la setarea firmei sau la implicitul programului
*!* 30.07.2026
*!* marius.mutu
*!* verificare ANAF: cand serviciul e cazut sau apelul esueaza, verdictul se citeste din istoricul de
*!* coduri fiscale (cache Oracle), daca istoricul are ceva proaspat; banda de stare si detaliile (F4)
*!* arata atunci data verificarii citite din istoric, cu mentiune explicita cand ANAF e indisponibil;
*!* ordinea de incercare ANAF/istoric e configurabila per firma
*!* #DEFINE CRLF CHR(13) + CHR(10)
#INCLUDE COMUN\ROA.H
@@ -69,6 +76,7 @@ Procedure ANAF_StarePartener
Lparameters tcCodFiscal, tdData, tlDoarCache, tlNecesitaApel, tlNegasit, tcClasaEsec, tnTipPersoana
Local lcCodFiscal, lcCui, loRezANAF, lcCheieCache, lnI, llValid, loOut, ldData, llNegasit, lcStareServiciu
Local lcOrdine, loVerificareANAF As "VerificareANAF", lcSelectOrig
tlNecesitaApel = .F.
tlNegasit = .F.
@@ -114,29 +122,54 @@ Procedure ANAF_StarePartener
Endif
lcCheieCache = 'C' + m.lcCui + '_' + Dtos(m.ldData)
If goCacheANAF_Sesiune.GetKey(m.lcCheieCache) = 0
lcStareServiciu = ANAF_StareServiciu()
Do Case
Case m.lcStareServiciu == 'CAZUT'
tlNecesitaApel = .F.
tcClasaEsec = 'FARA_RASPUNS'
Return .Null.
Case m.lcStareServiciu == 'SE_TESTEAZA'
tlNecesitaApel = .T.
tcClasaEsec = 'SE_TESTEAZA'
Return .Null.
Endcase
tlNecesitaApel = .T.
If m.tlDoarCache
Return .Null.
*** ordinea ANAF/istoric (OPTIUNI.ANAFCACHEORDINE_UNIC, VerificareANAF.OrdineCache din validare.prg);
*** implicit ANAF,CACHE - pe CACHE,ANAF se incearca intai istoricul, iar apelul ANAF se sare cand e proaspat
lcOrdine = 'ANAF,CACHE'
lcSelectOrig = Select()
Try
loVerificareANAF = Createobject("VerificareANAF")
lcOrdine = loVerificareANAF.OrdineCache('UNIC')
Catch
Endtry
If Select() <> m.lcSelectOrig And Used(m.lcSelectOrig)
Select (m.lcSelectOrig)
Endif
If m.lcOrdine == 'CACHE,ANAF'
loRezANAF = ANAF_CitesteDinIstoric(m.lcCui, m.ldData, 'CACHE')
Endif
If Vartype(m.loRezANAF) <> 'O'
lcStareServiciu = ANAF_StareServiciu()
Do Case
Case m.lcStareServiciu == 'CAZUT'
tlNecesitaApel = .F.
tcClasaEsec = 'FARA_RASPUNS'
*** plasa de siguranta: ANAF cazut - verdict din istoric, daca e proaspat, etichetat distinct
loRezANAF = ANAF_CitesteDinIstoric(m.lcCui, m.ldData, 'CACHE_INDISP')
If Vartype(m.loRezANAF) = 'O'
tcClasaEsec = ''
Endif
Case m.lcStareServiciu == 'SE_TESTEAZA'
tlNecesitaApel = .T.
tcClasaEsec = 'SE_TESTEAZA'
Otherwise
tlNecesitaApel = .T.
If !m.tlDoarCache
llNegasit = .F.
loRezANAF = ANAF_VerificaCuiSingle(m.lcCui, m.ldData, @llNegasit, @tcClasaEsec)
Do Case
Case m.tcClasaEsec == 'FARA_RASPUNS'
ANAF_SeteazaStareServiciu('CAZUT', 'CUI=' + m.lcCui)
*** plasa de siguranta: apelul a esuat - acelasi fallback pe istoric
loRezANAF = ANAF_CitesteDinIstoric(m.lcCui, m.ldData, 'CACHE_INDISP')
If Vartype(m.loRezANAF) = 'O'
tcClasaEsec = ''
Endif
Case m.tcClasaEsec == ''
ANAF_SeteazaStareServiciu('VIU', 'CUI=' + m.lcCui)
Endcase
Endif
Endcase
Endif
llNegasit = .F.
loRezANAF = ANAF_VerificaCuiSingle(m.lcCui, m.ldData, @llNegasit, @tcClasaEsec)
Do Case
Case m.tcClasaEsec == 'FARA_RASPUNS'
ANAF_SeteazaStareServiciu('CAZUT', 'CUI=' + m.lcCui)
Case m.tcClasaEsec == ''
ANAF_SeteazaStareServiciu('VIU', 'CUI=' + m.lcCui)
Endcase
If Vartype(m.loRezANAF) = 'O'
goCacheANAF_Sesiune.Add(m.loRezANAF, m.lcCheieCache)
Endif
@@ -160,9 +193,57 @@ Procedure ANAF_StarePartener
Addproperty(loOut, "dAnulareScpTVA", Iif(Pemstatus(loRezANAF, 'dAnulareScpTVA', 5), Nvl(loRezANAF.dAnulareScpTVA, {}), {}))
Addproperty(loOut, "cMesajScpTVA", Iif(Pemstatus(loRezANAF, 'cMesajScpTVA', 5), Alltrim(Nvl(loRezANAF.cMesajScpTVA, '')), ''))
Addproperty(loOut, "dData", m.ldData)
Addproperty(loOut, "cSursa", Iif(Pemstatus(loRezANAF, 'cSursa', 5), loRezANAF.cSursa, 'ANAF'))
Addproperty(loOut, "dDataSursa", Iif(Pemstatus(loRezANAF, 'dDataSursa', 5), Nvl(loRezANAF.dDataSursa, {}), {}))
Return loOut
Endproc && ANAF_StarePartener
*************************************
*** Citeste din ISTORIC_CODURI_FISCALE (VerificareANAF.CitesteIstoricPentruCoduri, validare.prg) verdictul
*** cache pentru un singur CUI normalizat, daca e proaspat; tcSursa eticheteaza rezultatul ('CACHE' sau
*** 'CACHE_INDISP'). Intoarce .NULL. cand istoricul nu are nimic proaspat pentru codul dat, fara eroare
*************************************
Procedure ANAF_CitesteDinIstoric
Lparameters tcCui, tdData, tcSursa
Local loVerificareANAF As "VerificareANAF", lcAliasCache, loRez, lcSelectOrig
loRez = .Null.
lcAliasCache = 'crsANAFIstoricOcautare'
lcSelectOrig = Select()
Try
Use In (Select(m.lcAliasCache))
loVerificareANAF = Createobject("VerificareANAF")
loVerificareANAF.CitesteIstoricPentruCoduri(m.tcCui, m.tdData, m.lcAliasCache)
If Used(m.lcAliasCache) And Reccount(m.lcAliasCache) > 0
Select (m.lcAliasCache)
Go Top
If !Empty(Nvl(denumire, ''))
loRez = Createobject("Empty")
Addproperty(loRez, "cui", cui)
Addproperty(loRez, "scpTVA", Nvl(scpTVA, .F.))
Addproperty(loRez, "statusInactivi", Nvl(statusInactivi, .F.))
Addproperty(loRez, "denumire", Nvl(denumire, ""))
Addproperty(loRez, "mesaj", Nvl(mesaj, ""))
Addproperty(loRez, "dInceputScpTVA", Nvl(data_inceput_ScpTVA, {}))
Addproperty(loRez, "dSfarsitScpTVA", Nvl(data_sfarsit_ScpTVA, {}))
Addproperty(loRez, "dAnulareScpTVA", Nvl(data_anul_imp_ScpTVA, {}))
Addproperty(loRez, "cMesajScpTVA", Nvl(mesaj_ScpTVA, ""))
Addproperty(loRez, "cSursa", m.tcSursa)
Addproperty(loRez, "dDataSursa", Nvl(data_sursa, {}))
Endif
Endif
Catch
loRez = .Null.
Endtry
If Used(m.lcAliasCache)
Use In (Select(m.lcAliasCache))
Endif
If Select() <> m.lcSelectOrig And Used(m.lcSelectOrig)
Select (m.lcSelectOrig)
Endif
Return m.loRez
Endproc && ANAF_CitesteDinIstoric
Procedure ANAF_StareServiciu
If Type('gcANAF_StareServiciu') = 'U'
Public gcANAF_StareServiciu, gtANAF_StareServiciuMoment, gnANAF_StareServiciuStamp
@@ -789,7 +870,26 @@ DEFINE CLASS anaf_verif_cautare AS Custom
lcPerioada = This.SufixPerioadaTVA(toStare)
Return 'ANAF: ' + This.TextStare(toStare, m.lcPerioada) + ' (' + ;
Iif(Empty(m.lcDenANAF), '', m.lcDenANAF + Iif(m.tlCuVirgula, ', ', ' ')) + m.lcCodOk + ')' + ;
Iif(Empty(m.lcPerioada), ' la ' + Dtoc(toStare.dData), '')
Iif(Empty(m.lcPerioada), ' la ' + Dtoc(toStare.dData), '') + ;
This.SufixSursa(toStare)
ENDPROC
PROCEDURE SufixSursa
Lparameters toStare
*** eticheteaza verdictele care nu vin dintr-un raspuns ANAF proaspat, ci din istoricul cache (contract 4.5)
If !Pemstatus(m.toStare, 'cSursa', 5)
Return ''
Endif
*!* 01.08.2026 marius.mutu: marcaj explicit al sursei, la fel ca in grid si in dialogul de verificare
Do Case
Case toStare.cSursa == 'ANAF'
Return ' (sursa: ANAF)'
Case toStare.cSursa == 'CACHE'
Return ' (sursa: CACHE ' + Dtoc(Nvl(toStare.dDataSursa, Date())) + ')'
Case toStare.cSursa == 'CACHE_INDISP'
Return ' (sursa: CACHE ' + Dtoc(Nvl(toStare.dDataSursa, Date())) + ', ANAF indisponibil)'
Endcase
Return ''
ENDPROC
PROCEDURE TextPerioadaTVA

View File

@@ -64,6 +64,10 @@
*!* 22.07.2025
*!* GetNamePermutations - limitare la 4 cuvinte si maxim 10 permutari
*!* 31.07.2026
*!* marius.mutu
*!* verifica_partener_show_info: marcaj de provenienta (cache ANAF) langa denumirea firmei, cand disponibil
#Include COMUN\ROA.H
Define Class oexecutor As Custom
@@ -4597,6 +4601,7 @@ Procedure verificare_parteneri
Endproc && verificare_parteneri
*!* 01.08.2026 marius.mutu istoricul e comun tuturor firmelor, nu se mai filtreaza pe schema_sursa
Procedure verificare_parteneri_istoric
Lparameters tcCodFiscal, tcNume
@@ -4613,7 +4618,7 @@ Procedure verificare_parteneri_istoric
Endif
Text To lcSql Noshow
select id, dataora, id_util, dataorav, id_utilv, cod_fiscal, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, stare, platitortvavies, util, utilv
select id, dataora, id_util, dataorav, id_utilv, cod_fiscal, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, stare, platitortvavies, util, utilv
from vistoric_coduri_fiscale
where cod_fiscal = ?pcCodFiscal
Endtext
@@ -4764,7 +4769,7 @@ Function verifica_partener_show_info
*** tcMesajIntrebare: IN, optional, daca se intreaba ceva la sfarsitul formularului (ex: Se completeaza datele in formularul partener nou?)
Local lcCodFiscal, lcDenumire, lcText, llCodRO, llPlatitorTVAMfin, llPlatitorTVAVIES, lnDialogType
Local lnRaspuns, loPartener
Local lnRaspuns, loPartener, lcProvenienta
lcCodFiscal = Transform(m.tcCodFiscal)
lcDenumire = Transform(m.tcDenumire)
@@ -4776,9 +4781,16 @@ Function verifica_partener_show_info
llTvaIncasare = loPartener.tvaincasare
llSplitTVA = loPartener.splittva
llInactiv = loPartener.inactiv
*!* 01.08.2026 marius.mutu: marcaj explicit al sursei (ANAF live / cache), nu doar pe randurile din cache
lcProvenienta = ''
If Pemstatus(m.loPartener, 'sursa', 5) And !Empty(Alltrim(Nvl(loPartener.sursa, '')))
lcProvenienta = Iif(Alltrim(Nvl(loPartener.sursa, '')) == 'ANAF', '(sursa: ANAF)', ;
'(sursa: CACHE ' + Dtoc(Nvl(loPartener.data_sursa, Date())) + Iif(Alltrim(Nvl(loPartener.sursa, '')) == 'CACHE_INDISP', ', ANAF indisponibil', '') + ')')
Endif
lcText = 'VERIFICARE CIF: ' + m.lcCodFiscal + ' ' + m.lcDenumire + crlf + crlf + ;
Alltrim(loPartener.firma) + crlf + ;
Iif(!Empty(m.lcProvenienta), m.lcProvenienta + crlf, '') + ;
Iif((m.llPlatitorTVAMfin And !m.llCodRO) Or (!m.llPlatitorTVAMfin And m.llCodRO), ' *** ATENTIE *** ', '') + ;
Iif(m.llPlatitorTVAMfin, "PLATITOR TVA (" + Alltrim(loPartener.datatvamfin) + ")", "NEPLATITOR TVA") + crlf + ;
'Stare: ' + Alltrim(loPartener.stare) + crlf + ;

View File

@@ -73,6 +73,33 @@
*!* anulare din oficiu) si mesajul ANAF integral (mesaj_ScpTVA), citite din cursorul deja parsat de
*!* ParseJsonANAFv8; parsarea esuata a datelor de perioada se logheaza
*!* 31.07.2026
*!* marius.mutu
*!* VerificareANAF: cache ANAF pe ISTORIC_CODURI_FISCALE (SalveazaIstoricDinCursor/CitesteIstoricPentruCoduri/
*!* OrdineCache/ZileCache/NormalizeazaCoduriCursor); VerificaListaCIF si ANAF_VerificaCuiSingle salveaza
*!* rezultatele ANAF in istoric; VerificaListaCIF primeste al patrulea parametru optional tcTraseu
*!* ('UNIC'/'MASA', implicit MASA) si citeste ordinea cu OrdineCache(tcTraseu), cu plasa de siguranta la
*!* tacere din istoric si provenienta (sursa/data_sursa) marcata in crsANAF si logata; VERIFICARE_CIF
*!* trimite si tvaincasare/splittva/inactiv la salvare; sursa/data_sursa ajung si pana la obiectul
*!* intors de VERIFICARE_CIF (GetEmptyMfinObj, Procedure ANAF, cursorul cVerificareCod)
*!* 01.08.2026
*!* marius.mutu
*!* VerificaListaCIF, ramura CACHE,ANAF: apelul ramas catre ANAF_SincronWebService_PlatitorTva foloseste
*!* acum un alias temporar (mergeuit apoi in crsANAF), ca randurile deja citite din cache sa nu mai fie
*!* sterse si reetichetate gresit CACHE_INDISP; plus golire explicita a aliasului la intrarea in
*!* VerificaListaCIF, ca sa nu mai acumuleze intre apeluri succesive cu alias implicit (Procedure ANAF) -
*!* defecte gasite la revizia de ansamblu dupa transa cache ANAF
*!* 01.08.2026
*!* marius.mutu
*!* SalveazaIstoricDinCursor trimite acum provenienta randului (sursa) la save_istoric_cod_fiscal, al
*!* 27-lea parametru pnDinCache; pachetul Oracle nu mai improspateaza DATAORAV_ANAF cand randul vine
*!* din cache (CACHE/CACHE_INDISP) - doar cand vin efectiv date noi de la ANAF - dar DATAORAV/ID_UTILV
*!* (urma de audit "cine si cand a verificat partenerul") se actualizeaza in continuare, indiferent de
*!* provenienta; altfel cache-ul isi reseta singur ceasul de prospetime la fiecare citire si nu mai
*!* expira niciodata
*!* http://ec.europa.eu/taxation_customs/vies/viesquer.do
*!* http://localhost/contafinupdate/verificarecod.aspx/verificarecod/verificare/CIF/1879855/MFIN
*!* http://localhost/contafinupdate/verificarecod.aspx/verificarecod/verificare/CNP/1810228134187
@@ -598,7 +625,7 @@ Define Class VerificareCod As Custom
Local loEx As Exception
Local lcMfinanteURL, lcMfinanteParams, lcRomfastURL, llMFINURL, loMFIN, loVIES, lcProcedura, llInterogareAnaf
Local lStare, lcApart, lcBloc, lcDataTVAMFIN, lcEtaj, lcLocalitate, lcNr, lcScara, lcStrada
Local llPlatitorTVAMFIN, lnSucces, llTVAIncasare, llSplitTVA, llInactiv, ldData
Local llPlatitorTVAMFIN, lnSucces, llTVAIncasare, llSplitTVA, llInactiv, ldData, lcSqlIstoric, lcSursa, ldDataSursa
Local lcTipInterogare, llInterogareVies, llInterogareMfin
If Empty(tcTipInterogare) Or Type('tcTipInterogare') <> 'C'
@@ -653,11 +680,13 @@ Define Class VerificareCod As Custom
llTVAIncasare = .F.
llSplitTVA = .F.
llInactiv = .F.
lcSursa = ''
ldDataSursa = {}
Create Cursor cVerificareCod (Valid L, eroare c(250), cod V(100) Null, firma V(100), adresa V(250), judet V(100), ;
regcom V(30), codpostal V(20), telefon V(30), fax V(30), datatvamfin V(30), platitortvamfin L, VIES L, PlatitorTVA L, ;
stare V(100), strada V(100), nr V(25), localitate V(100), Bloc V(30), Scara V(10), Etaj V(10), Apart V(20), ;
tvaincasare L, splittva L, inactiv L)
tvaincasare L, splittva L, inactiv L, sursa C(20), data_sursa D)
Cursortoxml("cVerificareCod", "lcXML", 1, 0, 0, "1")
Select cVerificareCod
@@ -698,6 +727,8 @@ Define Class VerificareCod As Custom
llTvaIncasare = loMFIN.tvaIncasare
llSplitTVA = loMFIN.SplitTVA
llInactiv = loMFIN.Inactiv
lcSursa = Nvl(loMFIN.sursa, 'ANAF')
ldDataSursa = Nvl(loMFIN.data_sursa, {})
Endif && llValid AND llInterogareMfin
If m.llValid And m.llRO And m.llInterogareMfin
@@ -723,7 +754,9 @@ Define Class VerificareCod As Custom
lcApart = loMFIN.apart
llTvaIncasare = loMFIN.tvaIncasare
llSplitTVA = loMFIN.SplitTVA
llInactiv = loMFIN.Inactiv
llInactiv = loMFIN.Inactiv
lcSursa = Nvl(loMFIN.sursa, 'ANAF')
ldDataSursa = Nvl(loMFIN.data_sursa, {})
Endif && llValid AND llInterogareMfin
*!* VERIFICARE VIES pentru platitori TVA
@@ -747,8 +780,8 @@ Define Class VerificareCod As Custom
lcStrada = This.RemoveCharacters(m.lcStrada)
TRY
Insert Into cVerificareCod(Valid, eroare, cod, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, VIES, PlatitorTVA, stare, strada, nr, localitate, bloc, scara, etaj, apart, tvaincasare, splittva, inactiv) ;
Values (m.llValid, Left(m.lcEroare, 250), m.lcVerificareCod, m.lcFirma, m.lcAdresa, m.lcJudet, m.lcRegCom, m.lcCodpostal, m.lcTelefon, m.lcFax, m.lcDataTVAMFIN, m.llPlatitorTVAMFIN, m.llVies, m.llPlatitorTVA, m.lcStare, m.lcStrada, m.lcNr, m.lcLocalitate, m.lcBloc, m.lcscara, m.lcetaj, m.lcapart, m.llTVAIncasare, m.llSplitTVA, m.llInactiv)
Insert Into cVerificareCod(Valid, eroare, cod, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, VIES, PlatitorTVA, stare, strada, nr, localitate, bloc, scara, etaj, apart, tvaincasare, splittva, inactiv, sursa, data_sursa) ;
Values (m.llValid, Left(m.lcEroare, 250), m.lcVerificareCod, m.lcFirma, m.lcAdresa, m.lcJudet, m.lcRegCom, m.lcCodpostal, m.lcTelefon, m.lcFax, m.lcDataTVAMFIN, m.llPlatitorTVAMFIN, m.llVies, m.llPlatitorTVA, m.lcStare, m.lcStrada, m.lcNr, m.lcLocalitate, m.lcBloc, m.lcscara, m.lcetaj, m.lcapart, m.llTVAIncasare, m.llSplitTVA, m.llInactiv, m.lcSursa, m.ldDataSursa)
Select cVerificareCod
Go Top
@@ -757,7 +790,8 @@ Define Class VerificareCod As Custom
*** ROA salvez datele in istoric_coduri_fiscale
If Type('goExecutor') = 'O'
Private pcCodFiscal, pcFirma, pcAdresa, pcJudet, pcRegCom, pcCodPostal, pcTelefon, pcFax, pcDataTvamfin, pnPlatitorTvaMfin, pcStare, pnPlatitorTvaVies, pnInterogareVies
Private pcCodFiscal, pcFirma, pcAdresa, pcJudet, pcRegCom, pcCodPostal, pcTelefon, pcFax, pcDataTvamfin, pnPlatitorTvaMfin, pcStare, pnPlatitorTvaVies, pnInterogareVies, ;
pnInactiv, pnTvaIncasare, pnSplitTva
pcCodFiscal = m.lcVerificareCod
pcFirma = m.lcFirma && Strtran(Strtran(Upper(Alltrim(Nvl(m.lcFirma, ''))), Chr(170), 'S'), Chr(222), 'T')
pcAdresa = m.lcAdresa && Strtran(Strtran(Upper(Alltrim(Nvl(m.lcAdresa, ''))), Chr(170), 'S'), Chr(222), 'T')
@@ -771,8 +805,14 @@ Define Class VerificareCod As Custom
pcStare = Upper(Alltrim(Nvl(m.lcStare, '')))
pnPlatitorTvaVies = Iif(m.llPlatitorTVA, 1, 0)
pnInterogareVies = Iif(m.llVies, 1, 0)
pnInactiv = Iif(m.llInactiv, 1, 0)
pnTvaIncasare = Iif(m.llTVAIncasare, 1, 0)
pnSplitTva = Iif(m.llSplitTVA, 1, 0)
If !Empty(m.pcFirma)
lnSucces = goExecutor.oExecuta("begin pack_parteneri.save_istoric_cod_fiscal(?pcCodFiscal,?pcFirma,?pcAdresa,?pcJudet,?pcRegCom,?pcCodPostal,?pcTelefon,?pcFax,?pcDataTvamfin,?pnPlatitorTvaMfin,?pcStare,?pnPlatitorTvaVies,?pnInterogareVies,?gnIdUtil); end;")
*!* 02.08.2026 marius.mutu: tnDinCache = 2 - salvare fara date de interval, nu marcheaza prospetime de cache
lcSqlIstoric = "begin pack_parteneri.save_istoric_cod_fiscal(?pcCodFiscal,?pcFirma,?pcAdresa,?pcJudet,?pcRegCom,?pcCodPostal,?pcTelefon,?pcFax,?pcDataTvamfin,?pnPlatitorTvaMfin,?pcStare," + ;
"?pnPlatitorTvaVies,?pnInterogareVies,?gnIdUtil,?pnInactiv,?pnTvaIncasare,?pnSplitTva,tnDinCache=>2); end;"
lnSucces = goExecutor.oExecuta(m.lcSqlIstoric)
Endif
Endif
*** CONTAFIN salvez datele in istoric_coduri_fiscale
@@ -810,7 +850,8 @@ Define Class VerificareCod As Custom
&& verificare serviciu web ANAF
loVerificareANAF = Createobject("VerificareANAF") && validare.prg
lcCursorVerificareANAF = loVerificareANAF.VerificaListaCIF(m.lcCodFiscal, m.ldData)
*!* 01.08.2026 marius.mutu: verificare unui singur CIF cerut manual - traseu UNIC (ANAF intai), nu implicitul MASA
lcCursorVerificareANAF = loVerificareANAF.VerificaListaCIF(m.lcCodFiscal, m.ldData, , 'UNIC')
If Used(m.lcCursorVerificareANAF)
If Reccount(m.lcCursorVerificareANAF) >= 1
Select (m.lcCursorVerificareANAF)
@@ -836,6 +877,8 @@ Define Class VerificareCod As Custom
loMFIN.TVAIncasare = tvaincasare
loMFIN.SplitTVA = splittva
loMFIN.Inactiv = inactiv
loMFIN.sursa = Nvl(sursa, 'ANAF')
loMFIN.data_sursa = Nvl(data_sursa, {})
Endif
Endif
@@ -1559,7 +1602,9 @@ Define Class VerificareCod As Custom
AddProperty(loMFIN, "Apart", "")
AddProperty(loMFIN, "TvaIncasare", .F.)
AddProperty(loMFIN, "SplitTVA", .F.)
AddProperty(loMFIN, "Inactiv", .F.)
AddProperty(loMFIN, "Inactiv", .F.)
AddProperty(loMFIN, "sursa", '')
AddProperty(loMFIN, "data_sursa", {})
Return loMFIN
Endfunc && GetEmptyMfinObj
Enddefine
@@ -1637,6 +1682,7 @@ Function ANAF_VerificaCuiSingle
If !Empty(m.lcJsonString) And Left(m.lcJsonString, 1) = '{'
Use In (Select(m.lcAliasTemp))
loVerificareANAF.ParseJsonANAFv8(nfjsonread(m.lcJsonString), m.lcAliasTemp)
loVerificareANAF.SalveazaIstoricDinCursor(m.lcAliasTemp, gnIdUtil)
loResult = ANAF_VerdictDinCursor(m.lcAliasTemp, m.lnCuiCautat, @tlNegasit, @tcClasaEsec)
Else
tcClasaEsec = 'RASPUNS_NEINTELES'
@@ -1671,6 +1717,8 @@ Function ANAF_VerdictDinCursor
If Used(m.tcAlias)
Select (m.tcAlias)
*!* 01.08.2026 marius.mutu: pozitionare explicita - apelantul poate lasa cursorul pe EOF
Go Top
lnReccountTemp = Reccount()
If m.lnReccountTemp = 1 And !Empty(denumire)
loResult = Createobject("empty")
@@ -1813,6 +1861,9 @@ Endfunc && ANAF_SondaOpreste
*********************************************
Define Class VerificareANAF As Custom
*!* 01.08.2026 marius.mutu: ultimul esec ANAF de pe traseul batch - se arata o singura data, la final, doar daca raman coduri neacoperite
cMesajANAF = ''
Procedure Init
If !'nfjsonread' $ Lower(Set("Procedure"))
Set Procedure To nfjsonread.prg Additive
@@ -1826,16 +1877,27 @@ Define Class VerificareANAF As Custom
*** VerificaListaCIF("31103995,1879855", Date(), "crsANAF")
*** Verifica codurile fiscale din lista, la data
*** Intoarce un cursor crsANAF (cui N(13), Data d, denumire c(60), adresa c(244), tva L, data_sfarsit d, data_anul_imp d, mesaj c(100))
*** Ordinea ANAF/cache vine din OrdineCache(tcTraseu) - tcTraseu optional ('UNIC'/'MASA'), implicit 'MASA'
*** cand lipseste sau e gol; pe CACHE,ANAF codurile cu rand proaspat in istoric nu se mai trimit la ANAF;
*** indiferent de ordine, codurile ramase fara raspuns (tacere) se completeaza din istoric drept plasa de
*** siguranta - codul gasit explicit "notFound" de ANAF nu atinge cache-ul, pentru ca primeste deja un
*** rand in crsANAF (denumire goala) si nu mai e considerat "tacere"
*************************************
Function VerificaListaCIF
Lparameters tcListaCIF, tdData, tcAlias
Lparameters tcListaCIF, tdData, tcAlias, tcTraseu
* tcListaCIF: lista coduri fiscale sau numele unui cursor cu coduri fiscale
* tcTraseu: optional, 'UNIC' sau 'MASA' (vezi OrdineCache); implicit 'MASA' cand lipseste - apelantii
* existenti (fara al patrulea parametru) raman pe comportamentul de azi
Local llUsed, lcCursorListaCIF, lnRec, lnRecs, lcAlias
*!* 31.07.2026 marius.mutu: al patrulea parametru tcTraseu forteaza OrdineCache(tcTraseu) in loc de 'MASA' fix
Local lcOrdine, ldData, lcAliasNorm, lcListaCoduriN, lcCursorRamas, lnCuiCurent, lcCodFiscalCurent, ldDataCurenta, llGasitCache, lcCursorAnafTemp, loRandAnaf, lnFaraRaspuns
lcCursorListaCIF = ""
llUsed = .F.
lcAlias = ""
lnFaraRaspuns = 0
This.cMesajANAF = ''
goLog.Log('tcListaCIF: ' + tcListaCIF, 'VerificaListaCIF')
If Used(tcListaCIF)
@@ -1844,7 +1906,8 @@ Define Class VerificareANAF As Custom
llUsed = .T.
Else
* lista
lcCursorListaCIF = "cListaCIFTemp"
*!* 01.08.2026 marius.mutu: nume unic - "cListaCIFTemp" colida cu variabila locala din overificari.vc2:2734
lcCursorListaCIF = "crsListaCIFIntern"
lnRecs = Getwordcount(m.tcListaCIF, ',')
Create Cursor (lcCursorListaCIF) (cod_fiscal c(30) Null, data D null)
For lnRec = 1 To m.lnRecs
@@ -1853,14 +1916,150 @@ Define Class VerificareANAF As Custom
Endfor
Endif
lcAlias = This.ANAF_SincronWebService_PlatitorTva(m.lcCursorListaCIF, m.tdData, m.tcAlias)
ldData = Iif(!Empty(m.tdData) And Type('tdData') = "D", m.tdData, Date())
lcAlias = Iif(!Empty(m.tcAlias) And Type('tcAlias') = "C", m.tcAlias, "crsANAF")
*!* 01.08.2026 marius.mutu: golire explicita la intrare - dupa fixul de mai jos, nimic altceva nu mai garanteaza un alias curat pe niciun traseu
Use In (Select(m.lcAlias))
lcOrdine = This.OrdineCache(Iif(Empty(m.tcTraseu), 'MASA', Upper(Alltrim(m.tcTraseu))))
lcAliasNorm = This.NormalizeazaCoduriCursor(m.lcCursorListaCIF, m.ldData)
If Left(m.lcOrdine, 5) == 'CACHE'
* CACHE,ANAF: codurile cu rand proaspat in istoric nu se mai trimit la ANAF
lcListaCoduriN = ''
Select (m.lcAliasNorm)
Scan For cui_n <> 0
lcListaCoduriN = m.lcListaCoduriN + Iif(Empty(m.lcListaCoduriN), '', ',') + Alltrim(Str(cui_n))
Select (m.lcAliasNorm)
Endscan
This.CitesteIstoricPentruCoduri(m.lcListaCoduriN, m.ldData, m.lcAlias, 'CACHE')
lcCursorRamas = 'crsListaRamasANAF'
Use In (Select(m.lcCursorRamas))
Create Cursor (m.lcCursorRamas) (cod_fiscal c(30) Null, data D null)
Select (m.lcAliasNorm)
Scan
lnCuiCurent = cui_n
lcCodFiscalCurent = cod_fiscal
ldDataCurenta = data
llGasitCache = .F.
If m.lnCuiCurent <> 0 And Used(m.lcAlias) And Reccount(m.lcAlias) > 0
Select (m.lcAlias)
Locate For cui = m.lnCuiCurent
llGasitCache = Found()
Endif
If !m.llGasitCache
Insert Into (m.lcCursorRamas) (cod_fiscal, data) Values (m.lcCodFiscalCurent, m.ldDataCurenta)
Endif
Select (m.lcAliasNorm)
Endscan
If Reccount(m.lcCursorRamas) > 0
*!* 01.08.2026 marius.mutu: alias temporar - ANAF_SincronWebService_PlatitorTva goleste neconditionat aliasul primit (:2025), iar aici e deja populat din cache
lcCursorAnafTemp = 'crsAnafBatchTemp'
Use In (Select(m.lcCursorAnafTemp))
lcCursorAnafTemp = This.ANAF_SincronWebService_PlatitorTva(m.lcCursorRamas, m.tdData, m.lcCursorAnafTemp)
If Used(m.lcCursorAnafTemp) And Reccount(m.lcCursorAnafTemp) > 0
Select (m.lcCursorAnafTemp)
Scan
Scatter Name loRandAnaf Memo
Insert Into (m.lcAlias) FROM NAME loRandAnaf
Select (m.lcCursorAnafTemp)
Endscan
Endif
Use In (Select(m.lcCursorAnafTemp))
Endif
Use In (Select(m.lcCursorRamas))
Else
* ANAF,CACHE: comportamentul de azi, ANAF intai pentru toate codurile
lcAlias = This.ANAF_SincronWebService_PlatitorTva(m.lcCursorListaCIF, m.tdData, m.lcAlias)
Endif
If !m.llUsed
Use In (Select(lcCursorListaCIF))
Endif
* plasa de siguranta la tacere, indiferent de ordine: codurile fara rand in crsANAF (nici din ANAF,
* nici din cache) se completeaza acum din istoric, marcate CACHE_INDISP; un rand deja prezent
* (raspuns ANAF gasit sau notFound, sau deja servit din cache mai sus) nu e atins
Select (m.lcAliasNorm)
Scan For cui_n <> 0
lnCuiCurent = cui_n
llGasitCache = .F.
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
Select (m.lcAlias)
Locate For cui = m.lnCuiCurent
llGasitCache = Found()
Endif
If !m.llGasitCache
This.CitesteIstoricPentruCoduri(Transform(m.lnCuiCurent), m.ldData, m.lcAlias, 'CACHE_INDISP')
If Used(m.lcAlias)
Select (m.lcAlias)
Locate For cui = m.lnCuiCurent
Endif
lnFaraRaspuns = m.lnFaraRaspuns + Iif(Used(m.lcAlias) And Found(), 0, 1)
Endif
Select (m.lcAliasNorm)
Endscan
Use In (Select(m.lcAliasNorm))
*!* 01.08.2026 marius.mutu: un singur mesaj la final, doar cand au ramas coduri fara verdict (nici de la ANAF, nici din cache)
If m.lnFaraRaspuns > 0 And !Empty(This.cMesajANAF)
AMESSAGEBOX(This.cMesajANAF + Chr(13) + Chr(10) + Alltrim(Str(m.lnFaraRaspuns)) + ' coduri fiscale nu au putut fi verificate.', 0 + 48, _Screen.Caption)
Endif
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
This.SalveazaIstoricDinCursor(m.lcAlias, gnIdUtil)
Endif
* criteriul 9: fiecare rand completat din cache (CACHE sau CACHE_INDISP) se lasa si in goLog, cu codul si data_sursa
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
Select (m.lcAlias)
Scan For Left(Nvl(sursa, ''), 5) == 'CACHE'
goLog.Log('cache cui=' + Transform(cui) + ' sursa=' + Alltrim(sursa) + ' data_sursa=' + Dtoc(Nvl(data_sursa, {})), 'VerificaListaCIF')
Select (m.lcAlias)
Endscan
Endif
Return m.lcAlias
Endfunc && AnafPlatitorTVA
*************************************
*** Normalizeaza codurile fiscale dintr-un cursor in forma tcCursorListaCIF (cod_fiscal C(30)[, data D]),
*** dupa acelasi tipar ca ANAF_SincronWebService_PlatitorTva (cod tara RO, doar cifre, <=10 caractere).
*** Cand sursa nu are coloana data (ex. orapoarte.prg:1994/2311, cursor doar cu cod_fiscal), se
*** foloseste tdData pentru toate randurile - acelasi fallback ca llDataCursor din functia de mai sus
*** Intoarce un cursor nou (cod_fiscal, data, cui_n N(13)) - cui_n = 0 cand codul nu e un CUI RO valid
*************************************
Function NormalizeazaCoduriCursor
Lparameters tcCursorListaCIF, tdData
Local loVerificareCod As "VerificareCod", lcCodFiscal, lcCodTara, lcCodFiscalFRO, lcAliasNorm, lcSelect, llDataCursor, ldDataRand, ldDataImplicit
lcSelect = Select()
lcAliasNorm = 'crsCoduriNormalizate'
Use In (Select(m.lcAliasNorm))
Create Cursor (m.lcAliasNorm) (cod_fiscal C(30), data D, cui_n N(13))
ldDataImplicit = Iif(Type('tdData') = 'D' And !Empty(m.tdData), m.tdData, Date())
llDataCursor = (Type(m.tcCursorListaCIF + '.data') = 'D')
loVerificareCod = Createobject("VerificareCod")
Select (m.tcCursorListaCIF)
Scan
*!* 01.08.2026 marius.mutu: cursoarele sursa au cod_fiscal/data nullable - fara Nvl, insertul de mai jos pica pe coloanele not null
lcCodFiscal = Alltrim(Nvl(cod_fiscal, ''))
lcCodTara = loVerificareCod.GetCodTara(m.lcCodFiscal)
lcCodFiscalFRO = Strtran(m.lcCodFiscal, m.lcCodTara, '')
lcCodFiscalFRO = Strtran(Strtran(Strtran(m.lcCodFiscalFRO, ' ', ''), 'RO', ''), 'R', '')
ldDataRand = Iif(m.llDataCursor And !Empty(Nvl(data, {})), Nvl(data, {}), m.ldDataImplicit)
Insert Into (m.lcAliasNorm) (cod_fiscal, data, cui_n) Values ;
(m.lcCodFiscal, m.ldDataRand, Iif(m.lcCodTara = 'RO' And Isdigit(m.lcCodFiscalFRO) And Len(m.lcCodFiscalFRO) <= 10, Int(Val(m.lcCodFiscalFRO)), 0))
Select (m.tcCursorListaCIF)
Endscan
Select (m.lcSelect)
Return m.lcAliasNorm
Endfunc && NormalizeazaCoduriCursor
*
Function ANAF_SincronWebService_PlatitorTva
Lparameters tcCursorListaCIF, tdData, tcAlias
@@ -1903,7 +2102,7 @@ Define Class VerificareANAF As Custom
Try
loHTTP = Createobject('Microsoft.XMLHTTP') && 04.07.2016
Catch To loEx
AMESSAGEBOX(loEx.Message, 0 + 16, _Screen.Caption)
This.cMesajANAF = loEx.Message
Endtry
Endif
If Type('loHTTP') <> 'O'
@@ -1960,46 +2159,16 @@ Define Class VerificareANAF As Custom
lcSend = nfjsoncreate(@laCoduri)
goLog.Log('lcSend: ' + m.lcSend, 'ANAF_SincronWebService_PlatitorTva')
lcJsonString = ''
*!* 31.07.2026 marius.mutu: procesarea raspunsului (status+corp) mutata in ProceseazaRaspunsHTTP, mai jos
Try
loHTTP.Open('POST', lcServer, .F.) && !!! POST e blocat de furnizor
loHTTP.setRequestHeader("Content-Type", "application/json;")
loHTTP.Send(lcSend)
If loHTTP.Status = 200
lcJsonString = ALLTRIM(loHTTP.responseText)
IF LEFT(m.lcJsonString,1) <> '{'
IF 'mentenanta'$LOWER(m.lcJsonString)
AMESSAGEBOX('Serviciul web ANAF este in mentenanta!',0+48,_screen.Caption)
ELSE
AMESSAGEBOX('Serviciul web ANAF nu a intors un raspuns corespunzator.!' + CHR(13) + CHR(10) + m.lcJsonString,0+48,_screen.Caption)
ENDIF
lcJsonString = ''
ENDIF
ENDIF
lcAlias = This.ProceseazaRaspunsHTTP(loHTTP.Status, loHTTP.responseText, m.tcAlias)
Catch To loEx
AMESSAGEBOX(loEx.Message, 0 + 16, _Screen.Caption)
Endtry
This.cMesajANAF = loEx.Message
Endtry
*
goLog.Log('lcJsonString: ' + m.lcJsonString, 'ANAF_SincronWebService_PlatitorTva')
*
If Not Empty(m.lcJsonString)
TRY
loJsonObject = nfjsonread(m.lcJsonString) && nfJson from http://vfpx.codeplex.com/
lcCodJudet = ""
IF TYPE('loJsonObject.found_vfpsafe_[1].adresa_domiciliu_fiscal.dcod_judet') <> 'U'
lcCodJudet = loJsonObject.found_vfpsafe_[1].adresa_domiciliu_fiscal.dcod_judet
ENDIF
IF !EMPTY(m.lcCodJudet)
lcAlias = This.ParseJsonANAFv8(loJsonObject, m.tcAlias)
ELSE
lcMesaj = 'Serviciul web ANAF intors mesaj de eroare: ' + IIF(TYPE('loJsonObject.message') = 'C', loJsonObject.message, '')
AMESSAGEBOX(m.lcMesaj, 0+48, _screen.Caption)
ENDIF
CATCH TO loEx
AMESSAGEBOX(loEx.Message, 0 + 16, _Screen.Caption)
ENDTRY
Endif
If m.lnGrup < m.lnGrupuri
INKEY(m.lnWaitSeconds)&& astept o secunda intre interogari
ENDIF
@@ -2008,6 +2177,51 @@ Define Class VerificareANAF As Custom
Return m.lcAlias
Endfunc && ANAF_SincronWebService_PlatitorTva
*************************************
*** Proceseaza UN raspuns HTTP deja primit pe calea batch (status + corp), separat de trimiterea
*** cererii ca sa poata fi testat direct, cu status+corp fabricate, fara transport HTTP real.
*** Corpul se citeste indiferent de status (nu doar pe 200) - ANAF poate intoarce si 404 cu corp
*** JSON complet cand toate codurile din grup sunt inexistente (masurat 27.07.2026), la fel ca pe
*** calea single-CUI (ANAF_VerificaCuiSingle). Un raspuns e considerat inteles cand are structura
*** found/notFound, chiar daca found e gol (lot integral notFound); altfel ramane tacere - cursorul
*** nu se modifica, deci codurile din grup raman fara rand in crsANAF, ca la o cadere reala de serviciu
*************************************
Function ProceseazaRaspunsHTTP
Lparameters tnStatus, tcResponseText, tcAlias
Local lcAlias, lcJsonString, loJsonObject, loEx As Exception, lcMesaj, llRaspunsInteles
lcAlias = Iif(!Empty(m.tcAlias) And Type('tcAlias') = "C", m.tcAlias, "crsANAF")
lcJsonString = Alltrim(Nvl(m.tcResponseText, ''))
goLog.Log('tnStatus: ' + Transform(m.tnStatus) + ' lcJsonString: ' + m.lcJsonString, 'ANAF_SincronWebService_PlatitorTva')
If Empty(m.lcJsonString) Or Left(m.lcJsonString, 1) <> '{'
If !Empty(m.lcJsonString)
IF 'mentenanta'$LOWER(m.lcJsonString)
This.cMesajANAF = 'Serviciul web ANAF este in mentenanta!'
ELSE
This.cMesajANAF = 'Serviciul web ANAF nu a intors un raspuns corespunzator.'
ENDIF
Endif
Return m.lcAlias && tacere: fara corp folosibil, cursorul ramane neschimbat
Endif
Try
loJsonObject = nfjsonread(m.lcJsonString) && nfJson from http://vfpx.codeplex.com/
llRaspunsInteles = (Type('loJsonObject') = 'O' And Pemstatus(m.loJsonObject, 'found_vfpsafe_', 5))
If m.llRaspunsInteles
lcAlias = This.ParseJsonANAFv8(m.loJsonObject, m.tcAlias)
Else
lcMesaj = 'Serviciul web ANAF a intors mesaj de eroare: ' + IIF(TYPE('loJsonObject.message') = 'C', loJsonObject.message, '')
This.cMesajANAF = m.lcMesaj
Endif
Catch To loEx
This.cMesajANAF = loEx.Message
Endtry
Return m.lcAlias
Endfunc && ProceseazaRaspunsHTTP
*************************************
*** Parseaza obiectul cu raspunsul de la ANAF si creeaza cursorul crsANAF
*** intoarce numele cursorului creat
@@ -2027,7 +2241,8 @@ Define Class VerificareANAF As Custom
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
dataInceputSplitTVA D, dataAnulareSplitTVA D, statusSplitTVA L, ;
tva L, tvaincasare L, splittva L, inactiv L, ;
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20))
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
sursa C(20), data_sursa D)
Endif
If !Isnull(loJsonObject)
@@ -2130,7 +2345,8 @@ Define Class VerificareANAF As Custom
loDate.splittva = loDate.statusSplitTVA
loDate.inactiv = loDate.statusInactivi
loDate.mesaj = loDate.mesaj_ScpTVA
loDate.sursa = 'ANAF'
IF !EMPTY(NVL(loDate.cui, 0))
Insert Into (m.lcAlias) FROM NAME loDate
ENDIF
@@ -2143,7 +2359,8 @@ Define Class VerificareANAF As Custom
SCATTER NAME loDate MEMO BLANK
loDate.cui = m.lnCUI
loDate.sursa = 'ANAF'
IF !EMPTY(NVL(loDate.cui, 0))
Insert Into (m.lcAlias) FROM NAME loDate
ENDIF
@@ -2385,6 +2602,232 @@ Define Class VerificareANAF As Custom
Return loAdresa
Endproc
*************************************
*** Parcurge un cursor in forma crsANAF si salveaza fiecare rand in ISTORIC_CODURI_FISCALE
*** prin pack_parteneri.save_istoric_cod_fiscal (26 parametri); commit din 100 in 100 si la final
*** Intoarce numarul de randuri salvate cu succes
*************************************
Function SalveazaIstoricDinCursor
Lparameters tcAlias, tnIdUtil
Local lnSalvate, lcSelect, lcSqlIstoric, lnRecnoInit
Private pcCodFiscal, pcFirma, pcAdresa, pcJudet, pcRegCom, pcCodPostal, pcTelefon, pcFax, pcDataTvamfin, ;
pnPlatitorTvaMfin, pcStare, pnPlatitorTvaVies, pnInterogareVies, pnIdUtil, ;
pnInactiv, pnTvaIncasare, pnSplitTva, ;
pdInceputScpTva, pdSfarsitScpTva, pdAnulImpScpTva, pdInceputTvaInc, pdSfarsitTvaInc, ;
pdInactivare, pdReactivare, pdInceputSplitTva, pdAnulareSplitTva, pnDinCache
lnSalvate = 0
If Empty(m.tcAlias) Or !Used(m.tcAlias)
Return m.lnSalvate
Endif
lcSelect = Select()
pnIdUtil = m.tnIdUtil
Select (m.tcAlias)
lnRecnoInit = Recno()
Scan For cui <> 0
pcCodFiscal = Transform(cui)
pcFirma = Nvl(firma, '')
pcAdresa = Nvl(adresa, '')
pcJudet = Nvl(judet, '')
pcRegCom = Nvl(nrRegCom, '')
pcCodPostal = ''
pcTelefon = ''
pcFax = ''
pcDataTvamfin = ''
pnPlatitorTvaMfin = 0
pcStare = ''
pnPlatitorTvaVies = 0
pnInterogareVies = 0
pnInactiv = Iif(Nvl(inactiv, .F.), 1, 0)
pnTvaIncasare = Iif(Nvl(tvaincasare, .F.), 1, 0)
pnSplitTva = Iif(Nvl(splittva, .F.), 1, 0)
pdInceputScpTva = data_inceput_ScpTVA
pdSfarsitScpTva = data_sfarsit_ScpTVA
pdAnulImpScpTva = data_anul_imp_ScpTVA
pdInceputTvaInc = dataInceputTvaInc
pdSfarsitTvaInc = dataSfarsitTvaInc
pdInactivare = dataInactivare
pdReactivare = dataReactivare
pdInceputSplitTva = dataInceputSplitTVA
pdAnulareSplitTva = dataAnulareSplitTVA
*!* 01.08.2026 marius.mutu: pnDinCache=1 cand randul vine din cache - opreste improspatarea DATAORAV_ANAF pe ecoul din cache, jos in pachet
pnDinCache = Iif(Left(Nvl(sursa, ''), 5) == 'CACHE', 1, 0)
lcSqlIstoric = "begin pack_parteneri.save_istoric_cod_fiscal(?pcCodFiscal,?pcFirma,?pcAdresa,?pcJudet,?pcRegCom,?pcCodPostal,?pcTelefon,?pcFax,?pcDataTvamfin,?pnPlatitorTvaMfin,?pcStare," + ;
"?pnPlatitorTvaVies,?pnInterogareVies,?pnIdUtil,?pnInactiv,?pnTvaIncasare,?pnSplitTva,?pdInceputScpTva,?pdSfarsitScpTva," + ;
"?pdAnulImpScpTva,?pdInceputTvaInc,?pdSfarsitTvaInc,?pdInactivare,?pdReactivare,?pdInceputSplitTva,?pdAnulareSplitTva,?pnDinCache); end;"
If goExecutor.oExecuta(m.lcSqlIstoric)
lnSalvate = m.lnSalvate + 1
If Mod(m.lnSalvate, 100) = 0
goExecutor.oExecuta('COMMIT')
Endif
Endif
Select (m.tcAlias)
Endscan
If m.lnSalvate > 0
goExecutor.oExecuta('COMMIT')
Endif
*!* 01.08.2026 marius.mutu: Scan lasa pointerul pe EOF - il pun la loc, ca sa nu afectez apelantul
Select (m.tcAlias)
Try
Go m.lnRecnoInit
Catch
Go Top
Endtry
Select (m.lcSelect)
Return m.lnSalvate
Endfunc && SalveazaIstoricDinCursor
*************************************
*** Citeste din ISTORIC_CODURI_FISCALE ultima verificare proaspata (pe DATAORAV_ANAF) pentru
*** codurile din tcListaCoduriN (normalizate, numerice, separate prin virgula) si calculeaza
*** in SQL, la tdData, verdictele din intervale (platitor TVA, TVA la incasare, split TVA, inactiv)
*** Adauga randurile in tcAlias (cursor in forma crsANAF + sursa/data_sursa), creandu-l daca lipseste
*** tcSursa (optional, implicit 'CACHE') eticheteaza randurile inserate - 'CACHE' sau 'CACHE_INDISP'
*** Un rand NU se intoarce cand tdData e inainte de inceputul unui interval cunoscut (scpTVA/TVAINC/
*** inactivare) - ANAF intoarce o singura perioada, nu istoricul complet, deci pentru o data anterioara
*** primei perioade memorate cache-ul nu poate afirma "nu era" - codul ramane netratat, merge la ANAF
*** Intoarce numele cursorului; ramane gol, fara eroare, cand nu gaseste nimic
*************************************
Function CitesteIstoricPentruCoduri
Lparameters tcListaCoduriN, tdData, tcAlias, tcSursa
Local lcAlias, lcCursorIstoric, lcSql, ldData, lnZileCache, lcSelect, lcSursa
*!* 30.07.2026 marius.mutu: pdDataCache/pnZileCache Private, nu Local, ca sa fie vizibile in goExecutor.oExecuta la bind
Private pdDataCache, pnZileCache
lcAlias = Iif(!Empty(m.tcAlias) And Type('tcAlias') = "C", m.tcAlias, "crsANAF")
ldData = Iif(Type('tdData') = 'D' And !Empty(m.tdData), m.tdData, Date())
lcSursa = Iif(!Empty(m.tcSursa) And Type('tcSursa') = 'C', Upper(Alltrim(m.tcSursa)), 'CACHE')
pdDataCache = m.ldData
lcSelect = Select()
If !Used(m.lcAlias)
*!* 31.07.2026 marius.mutu: aceeasi forma ca crsANAF din ParseJsonANAFv8 - Null pe cele 9 campuri de data muta problema in ParseJsonANAFv8 (SCATTER/aritmetica pe date); NULL-ul din Oracle e tratat cu Nvl la Insert Into, mai jos
Create Cursor (m.lcAlias) (cui N(13), data D, denumire V(100), firma V(100), adresa C(244), nrRegCom C(30), scpTVA L, data_inceput_ScpTVA D, data_sfarsit_ScpTVA D, data_anul_imp_ScpTVA D, mesaj_ScpTVA C(244), ;
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
dataInceputSplitTVA D, dataAnulareSplitTVA D, statusSplitTVA L, ;
tva L, tvaincasare L, splittva L, inactiv L, ;
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
sursa C(20), data_sursa D)
Endif
If Empty(m.tcListaCoduriN)
Select (m.lcSelect)
Return m.lcAlias
Endif
lnZileCache = This.ZileCache()
pnZileCache = m.lnZileCache
lcCursorIstoric = 'crsIstoricCacheTemp'
Use In (Select(m.lcCursorIstoric))
*!* 01.08.2026 marius.mutu: v_tvainc - margine exclusiva (data_sfarsit_tvainc - 1), aliniata cu pack_roartvai; ground truth rtvai_istoric confirma [inceput,sfarsit)
TEXT To lcSql TEXTMERGE Noshow
select cod_fiscal_n, firma, adresa, judet, regcom, dataorav_anaf,
data_inceput_scptva, data_sfarsit_scptva, data_anul_imp_scptva,
data_inceput_tvainc, data_sfarsit_tvainc, data_inactivare, data_reactivare,
data_inceput_splittva, data_anulare_splittva,
case when ?pdDataCache between data_inceput_scptva and nvl(data_sfarsit_scptva, to_date('29991231','yyyymmdd')) then 1 else 0 end as v_scptva,
case when ?pdDataCache between data_inceput_tvainc and nvl(data_sfarsit_tvainc - 1, to_date('29991231','yyyymmdd')) then 1 else 0 end as v_tvainc,
case when ?pdDataCache between data_inceput_splittva and nvl(data_anulare_splittva, to_date('29991231','yyyymmdd')) then 1 else 0 end as v_splittva,
case when data_inactivare is not null and ?pdDataCache >= data_inactivare and (data_reactivare is null or ?pdDataCache < data_reactivare) then 1 else 0 end as v_inactiv
from (select i.*, row_number() over (partition by cod_fiscal_n order by id desc) as rn
from istoric_coduri_fiscale i
where cod_fiscal_n in (<<m.tcListaCoduriN>>)
and dataorav_anaf is not null
and sysdate - dataorav_anaf <= ?pnZileCache)
where rn = 1
and (data_inceput_scptva is null or ?pdDataCache >= data_inceput_scptva)
and (data_inceput_tvainc is null or ?pdDataCache >= data_inceput_tvainc)
and (data_inactivare is null or ?pdDataCache >= data_inactivare)
ENDTEXT
If goExecutor.oExecuta(m.lcSql, m.lcCursorIstoric) And Used(m.lcCursorIstoric)
Select (m.lcCursorIstoric)
Scan
*!* 31.07.2026 marius.mutu: campurile din VALUES calificate cu alias literal crsIstoricCacheTemp - necalificat da eroare 12 (inghitita de ON ERROR), Insert Into ramanea mereu gol
Insert Into (m.lcAlias) (cui, data, denumire, firma, adresa, judet, nrRegCom, ;
data_inceput_ScpTVA, data_sfarsit_ScpTVA, data_anul_imp_ScpTVA, ;
dataInceputTvaInc, dataSfarsitTvaInc, dataInactivare, dataReactivare, ;
dataInceputSplitTVA, dataAnulareSplitTVA, ;
scpTVA, statusTvaIncasare, statusSplitTVA, statusInactivi, ;
tva, tvaincasare, splittva, inactiv, sursa, data_sursa) Values ;
(crsIstoricCacheTemp.cod_fiscal_n, m.ldData, Nvl(crsIstoricCacheTemp.firma, ''), Nvl(crsIstoricCacheTemp.firma, ''), Nvl(crsIstoricCacheTemp.adresa, ''), Nvl(crsIstoricCacheTemp.judet, ''), Nvl(crsIstoricCacheTemp.regcom, ''), ;
Nvl(crsIstoricCacheTemp.data_inceput_scptva, {}), Nvl(crsIstoricCacheTemp.data_sfarsit_scptva, {}), Nvl(crsIstoricCacheTemp.data_anul_imp_scptva, {}), ;
Nvl(crsIstoricCacheTemp.data_inceput_tvainc, {}), Nvl(crsIstoricCacheTemp.data_sfarsit_tvainc, {}), Nvl(crsIstoricCacheTemp.data_inactivare, {}), Nvl(crsIstoricCacheTemp.data_reactivare, {}), ;
Nvl(crsIstoricCacheTemp.data_inceput_splittva, {}), Nvl(crsIstoricCacheTemp.data_anulare_splittva, {}), ;
(crsIstoricCacheTemp.v_scptva = 1), (crsIstoricCacheTemp.v_tvainc = 1), (crsIstoricCacheTemp.v_splittva = 1), (crsIstoricCacheTemp.v_inactiv = 1), ;
(crsIstoricCacheTemp.v_scptva = 1), (crsIstoricCacheTemp.v_tvainc = 1), (crsIstoricCacheTemp.v_splittva = 1), (crsIstoricCacheTemp.v_inactiv = 1), m.lcSursa, crsIstoricCacheTemp.dataorav_anaf)
Endscan
Use In (Select(m.lcCursorIstoric))
Endif
Select (m.lcSelect)
Return m.lcAlias
Endfunc && CitesteIstoricPentruCoduri
*************************************
*** Citeste din OPTIUNI (per schema) ordinea traseelor de verificare ANAF/cache
*** tcTraseu: 'UNIC' (un singur cod) sau 'MASA' (lot); implicit cand randul lipseste din OPTIUNI:
*** 'ANAF,CACHE' pe UNIC, 'CACHE,ANAF' pe MASA
*************************************
Function OrdineCache
Lparameters tcTraseu
Local lcTraseu, lcVarName, lcImplicit, lcSql, lcCursor, lcOrdine, lcSelect
*!* 31.07.2026 marius.mutu: lcSelect salvat/restaurat - fara asta apelantul ramanea cu work area-ul schimbat
lcSelect = Select()
lcTraseu = Upper(Alltrim(Nvl(m.tcTraseu, '')))
lcImplicit = Iif(m.lcTraseu == 'MASA', 'CACHE,ANAF', 'ANAF,CACHE')
lcVarName = 'ANAFCACHEORDINE_' + Iif(m.lcTraseu == 'MASA', 'MASA', 'UNIC')
lcCursor = 'crsOptiuneOrdineCache'
lcOrdine = ''
lcSql = "select varvalue from optiuni where varname = '" + m.lcVarName + "'"
If goExecutor.oExecuta(m.lcSql, m.lcCursor) And Used(m.lcCursor)
If Reccount(m.lcCursor) > 0
lcOrdine = Upper(Strtran(Alltrim(Nvl(&lcCursor..varvalue, '')), ' ', ''))
Endif
Use In (Select(m.lcCursor))
Endif
Select (m.lcSelect)
Return Iif(Empty(m.lcOrdine), m.lcImplicit, m.lcOrdine)
Endfunc && OrdineCache
*************************************
*** Citeste din OPTIUNI (per schema) vechimea maxima a cache-ului, in zile, masurata pe DATAORAV_ANAF
*** Implicit cand randul lipseste din OPTIUNI: 30
*************************************
Function ZileCache
Local lcCursor, lcSql, lnZile, lcSelect
*!* 31.07.2026 marius.mutu: lcSelect salvat/restaurat - acelasi defect ca la OrdineCache
lcSelect = Select()
lcCursor = 'crsOptiuneZileCache'
lnZile = 30
lcSql = "select varvalue from optiuni where varname = 'ANAFCACHEZILE'"
If goExecutor.oExecuta(m.lcSql, m.lcCursor) And Used(m.lcCursor)
If Reccount(m.lcCursor) > 0 And !Empty(Alltrim(Nvl(&lcCursor..varvalue, '')))
lnZile = Val(Alltrim(&lcCursor..varvalue))
Endif
Use In (Select(m.lcCursor))
Endif
If m.lnZile <= 0
lnZile = 30
Endif
Select (m.lcSelect)
Return m.lnZile
Endfunc && ZileCache
Enddefine && VerificareANAF

View File

@@ -0,0 +1,200 @@
10117033
10181036
10190190
10294736
10298355
10302235
10488023
10716130
10801421
10856656
10959066
1098943
1099507
11087755
1109546
11201891
11242034
11267330
11285736
11447722
11468008
11557148
11570015
11578825
11588780
11628184
11758273
11874227
11906760
11952970
11966827
11980333
11993007
12025653
12037739
12079629
12085370
122112121
12242741
123456789
12456257
12530043
12751583
12803623
12875883
13155970
13196856
13205563
13256834
13293530
13312578
13345702
13397167
13420154
13450597
1347483
1351530
1356341
1357649
13604025
13653389
13665367
13683142
13712450
13819121
13838336
1387925
13894522
14010993
14157693
14208851
14232426
14325363
14368127
14395920
14399840
14506076
14637721
14738700
14772507
14780607
14830713
14832110
14852126
14871357
14899110
14916459
14996555
15011806
15027136
15029846
15032728
15033936
15048864
15068357
15080814
15105587
15124740
15134434
15145832
15194916
15224006
15274691
15371066
15450895
15475660
15502862
15528854
15565496
15575236
15601491
15601874
15606146
15618914
15637258
1566173
15666083
15697055
157049
1581009
1582276
15905547
15927162
15989068
16000996
16020713
16026414
16069946
16132636
16196435
16310504
16328048
16371013
16385035
16412130
16417277
16426909
1643195
16517934
16531742
16627333
16677560
16753323
16798228
16864100
16890282
16900629
16915220
16935031
16945230
16978679
17009454
17032996
17093594
17116493
17217943
17267739
17412120
1741282
17454036
174540361
17457202
17511069
17521968
17567221
17610992
17646279
1775137
17832263
17920187
17922480
18020949
18024037
18110090
18113940
18167215
18250522
18268236
18290799
18320040
18344503
18359407
18390330
18412764
18477500
1857130
1860712
18630505
1863689
18637228
18696941
18716402
18721751
1872733
18749388
18760300
18761640
1877986
1879596
18796568

View File

@@ -0,0 +1,267 @@
* mock_batch_anaf.prg - mock pentru calea BATCH de verificare ANAF (VerificareANAF.ANAF_SincronWebService_PlatitorTva,
* COMUN\programe\validare.prg:1865-2009), fara niciun apel HTTP real. Poveste S11 (docs\stories-cache-anaf.md).
*
* ALEGERE (functie vs strat HTTP): mock la nivel de METODA, prin subclasare - NU la nivelul stratului HTTP
* de dedesubt. Metoda originala foloseste Createobject('winHTTP.winHTTPrequest.5.1') / Createobject('Microsoft.XMLHTTP')
* cu ProgID literal, direct in validare.prg - nu exista nicio proprietate/metoda suprascriabila prin care sa
* injectez un obiect fals fara sa editez validare.prg, iar inlocuirea globala a inregistrarii COM (regsvr32/
* registry) ar afecta toata masina, nu doar acest test - inacceptabil ca efect secundar, deci exclusa. In schimb,
* VerificareANAF e o clasa VFP obisnuita (Define Class VerificareANAF As Custom, validare.prg:1814), deci o
* subclasa AICI (VerificareANAFMockBatch) suprascrie DOAR ANAF_SincronWebService_PlatitorTva si MOSTENESTE
* neschimbata ParseJsonANAFv8 (validare.prg:2015) - logica REALA de parsare (toate campurile crsANAF, inclusiv
* sursa/data_sursa adaugate de S3 la Create Cursor) ramane exercitata real; doar transportul HTTP e simulat.
* Grupurile de maxim 100 coduri sunt reproduse identic cu originalul (lnReqNo=100), fara INKEY(1) intre grupuri
* (asteptarea de 1 secunda din original nu are rost intr-un test headless).
*
* GAP pentru S5 (contractul 404 pe calea batch): subclasa suprascrie INTREGUL ANAF_SincronWebService_PlatitorTva,
* deci NU exercita codul real pe care S5 il va adauga/modifica in validare.prg (gate-ul "If loHTTP.Status = 200",
* validare.prg:1968). Pentru ca S5 sa-si testeze headless codul real, are nevoie de un punct de injectie in
* validare.prg pe care NU l-am facut (nu e fisierul meu) - vezi docs\diff-S11-mock-batch.md, sectiunea "Pentru S5".
* Scenariul HTTP404_CORP_COMPLET de mai jos arata AMBELE comportamente (azi: corpul e ignorat; propus: cu
* glANAFBatchIgnoraGate404 = .T., corpul se parseaza chiar si la status<>200) - fixture de referinta pentru S5.
*
* CONFIGURARE (construita INLINE in programul principal apelant, NU intr-o PROCEDURA/FUNCTION separata - vezi
* capcana l, COMUN\docs\depanare_testare_vfp.md: CREATEOBJECT/ADDPROPERTY apelate dintr-o procedura se comporta
* gresit in acest runtime headless; obiectele de configurare trebuie construite direct in main):
* goANAFBatchMock - Collection, cheie 'C'+CUI normalizat (NormalizeazaCUI din validare.prg), valoare:
* - obiect Empty cu proprietati de raspuns (vezi lista mai jos) -> intra in "found"
* - sirul 'NOTFOUND' -> intra explicit in "notFound"
* - cheie lipsa din colectie -> tratat implicit tot ca 'NOTFOUND'
* (simuleaza raspunsul ANAF pentru un CUI pe care nu-l cunoaste)
* goANAFBatchScenariuPerGrup - Collection optionala, cheie TRANSFORM(nr. grup, 1-based), valoare = scenariu -
* suprascrie gcANAFBatchScenariu DOAR pentru acel grup (test cu >100 coduri,
* grupuri cu comportament diferit)
* gcANAFBatchScenariu - scenariul implicit pentru toate grupurile fara override in colectia de mai sus:
* 'NORMAL' (implicit daca lipseste) / 'TACERE' / 'RASPUNS_NEINTELES' /
* 'HTTP404_CORP_COMPLET'
* glANAFBatchIgnoraGate404 - .F. implicit (comportamentul de AZI) - cu .T., scenariul HTTP404_CORP_COMPLET
* parseaza corpul oricum (simuleaza fixul propus pentru S5)
*
* Proprietatile unui obiect de raspuns "gasit" (toate optionale, implicit gol/.F. cand lipsesc):
* denumire, adresa, nrRegCom, data (C, 'YYYY-MM-DD')
* scpTVA (L), dataInceputScpTVA, dataSfarsitScpTVA, dataAnulImpScpTVA (C 'YYYY-MM-DD'), mesajScpTVA (C)
* inactiv (L), dataInactivare, dataReactivare, dataPublicare, dataRadiere (C 'YYYY-MM-DD')
* tvaIncasare (L), dataInceputTvaInc, dataSfarsitTvaInc, dataActualizareTvaInc, dataPublicareTvaInc (C 'YYYY-MM-DD'), tipActTvaInc (C)
* splitTva (L), dataInceputSplitTVA, dataAnulareSplitTVA (C 'YYYY-MM-DD')
* Datele sunt STRING 'YYYY-MM-DD' (acelasi format trimis de ANAF), nu Date VFP - fara ambiguitate legata de SET DATE.
* SENSIBILITATE LA DATA (adaugat 31.07.2026): daca perechea tcPropStart/tcPropEnd e prezenta pe item,
* PropBool evalueaza boolean-ul FATA de data ceruta (tdData, parametrul catre ANAF_SincronWebService_PlatitorTva),
* nu mai intoarce un boolean fix - la fel ca API-ul ANAF real (cere "data" per CUI, validare.prg:2098).
* Fara acele proprietati de data pe item, cade pe boolean-ul static de dinainte (compatibilitate cu testele
* existente care nu seteaza date). Mock-ul ramane marginit la O SINGURA perioada per camp (nu omniscient).
* Toate 4 campuri (scpTVA/tvaIncasare/splitTva/inactiv) folosesc BETWEEN inclusiv la ambele capete (adaugat
* 01.08.2026) - doc_WS_V9.txt (documentatia oficiala ANAF) nu precizeaza daca ziua dataReactivare insasi mai
* conteaza inactiva, deci mock-ul NU copiaza aici sfarsitul exclusiv folosit de cache pentru inactiv
* (validare.prg:2675) - acea margine ramane neverificata, vezi test_margine_inactiv_frontiera.prg.
*
* CONTOR DE APELURI (esential pentru S6 - codurile din cache nu trebuie sa ajunga la ANAF):
* gnANAFBatchApeluri - numeric, o unitate per GRUP efectiv trimis (indiferent de rezultat) - echivalentul
* unui loHTTP.Send() real
* gcANAFBatchCuiuriTrimise - CSV, toate CUI-urile normalizate incluse efectiv intr-un grup trimis, in ordine -
* un CUI proaspat din cache NU trebuie sa apara niciodata aici
* Ambele se initializeaza (gnANAFBatchApeluri = 0, gcANAFBatchCuiuriTrimise = '') INLINE in programul principal,
* inainte de primul apel; mock-ul doar le incrementeaza/concateneaza (fara CREATEOBJECT, sigur din metoda de clasa).
Define Class VerificareANAFMockBatch As VerificareANAF
Procedure ANAF_SincronWebService_PlatitorTva
Lparameters tcCursorListaCIF, tdData, tcAlias
Local lcAlias, lnRecords, lnReqNo, lnGrupuri, lnGrup, lnRec1, lnRec2
Local lcCuiOriginal, lcCuiNorm, lcKey, loItem, lcScenariu, lcFound, lcNotFound, lcBody
Local loJsonObject, loEx As Exception, llNumeric, lnI
lcAlias = Iif(!Empty(m.tcAlias) And Type('tcAlias') = 'C', m.tcAlias, 'crsANAF')
Use In (Select(m.lcAlias))
lnRecords = Reccount(m.tcCursorListaCIF)
If m.lnRecords = 0
Return m.lcAlias
Endif
lnReqNo = 100
lnGrupuri = Max(Ceiling(m.lnRecords / m.lnReqNo), 1)
For lnGrup = 1 To m.lnGrupuri
lnRec1 = m.lnReqNo * (m.lnGrup - 1) + 1
lnRec2 = Min(m.lnReqNo * m.lnGrup, m.lnRecords)
lcScenariu = This.ScenariuPentruGrup(m.lnGrup)
lcFound = ''
lcNotFound = ''
Select (m.tcCursorListaCIF)
Scan For Between(Recno(), m.lnRec1, m.lnRec2)
lcCuiOriginal = Alltrim(cod_fiscal)
lcCuiNorm = NormalizeazaCUI(m.lcCuiOriginal)
llNumeric = !Empty(m.lcCuiNorm) And Len(m.lcCuiNorm) <= 10
If m.llNumeric
For lnI = 1 To Len(m.lcCuiNorm)
If !Isdigit(Substr(m.lcCuiNorm, lnI, 1))
llNumeric = .F.
Exit
Endif
Endfor
Endif
If !m.llNumeric
Loop
Endif
If Type('gnANAFBatchApeluri') = 'N'
gcANAFBatchCuiuriTrimise = gcANAFBatchCuiuriTrimise + Iif(Empty(gcANAFBatchCuiuriTrimise), '', ',') + m.lcCuiNorm
Endif
lcKey = 'C' + m.lcCuiNorm
If Type('goANAFBatchMock') = 'O' And goANAFBatchMock.GetKey(m.lcKey) > 0
loItem = goANAFBatchMock.Item(m.lcKey)
Else
loItem = 'NOTFOUND'
Endif
If Vartype(m.loItem) = 'C'
lcNotFound = lcNotFound + Iif(Empty(m.lcNotFound), '', ',') + m.lcCuiNorm
Else
lcFound = lcFound + Iif(Empty(m.lcFound), '', ',') + This.JsonRaspuns(m.loItem, m.lcCuiNorm, m.tdData)
Endif
Endscan
If Type('gnANAFBatchApeluri') = 'N'
gnANAFBatchApeluri = gnANAFBatchApeluri + 1
Endif
Do Case
Case m.lcScenariu == 'TACERE' Or m.lcScenariu == 'RASPUNS_NEINTELES'
* fara raspuns folosibil - grupul nu adauga niciun rand (ca la lcJsonString = '' in original)
Case m.lcScenariu == 'HTTP404_CORP_COMPLET' And !This.lIgnoraGate404()
* replica gate-ul de AZI (validare.prg:1968, "If loHTTP.Status = 200"): corpul exista dar e ignorat
Otherwise
* NORMAL, sau HTTP404_CORP_COMPLET cu glANAFBatchIgnoraGate404 = .T. (fixture pentru fixul propus S5)
lcBody = '{"found":[' + m.lcFound + '],"notFound":[' + m.lcNotFound + ']}'
Try
loJsonObject = nfjsonread(m.lcBody)
lcAlias = This.ParseJsonANAFv8(m.loJsonObject, m.tcAlias)
Catch To loEx
* pastreaza comportamentul original: o eroare de parsare nu opreste testul, doar grupul respectiv
Endtry
Endcase
Endfor
Return m.lcAlias
Endproc && ANAF_SincronWebService_PlatitorTva
*-- scenariul unui grup: intai override-ul per grup (goANAFBatchScenariuPerGrup), apoi implicitul global
Procedure ScenariuPentruGrup
Lparameters tnGrup
Local lcCheie
lcCheie = Transform(m.tnGrup)
If Type('goANAFBatchScenariuPerGrup') = 'O' And goANAFBatchScenariuPerGrup.GetKey(m.lcCheie) > 0
Return goANAFBatchScenariuPerGrup.Item(m.lcCheie)
Endif
If Type('gcANAFBatchScenariu') = 'C' And !Empty(gcANAFBatchScenariu)
Return gcANAFBatchScenariu
Endif
Return 'NORMAL'
Endproc
Procedure lIgnoraGate404
Return (Type('glANAFBatchIgnoraGate404') = 'L' And glANAFBatchIgnoraGate404)
Endproc
*-- serializeaza un raspuns "gasit" pentru un CUI, in forma JSON asteptata de ParseJsonANAFv8 (validare.prg:2015);
*-- campurile lipsa din obiectul de configurare primesc valori implicite neutre (siruri goale / false).
*!* 31.07.2026 marius.mutu: primeste tdData, il propaga la PropBool (booleanele devin sensibile la data ceruta)
Procedure JsonRaspuns
Lparameters toItem, tcCuiNorm, tdData
Local lcJ
lcJ = '{"date_generale":{'
lcJ = lcJ + '"cui":' + Transform(Val(m.tcCuiNorm)) + ','
lcJ = lcJ + '"data":"' + This.PropStr(m.toItem, 'data', '2024-01-01') + '",'
lcJ = lcJ + '"denumire":"' + This.PropStr(m.toItem, 'denumire', 'FIRMA TEST ' + m.tcCuiNorm) + '",'
lcJ = lcJ + '"adresa":"' + This.PropStr(m.toItem, 'adresa', 'ADRESA TEST') + '",'
lcJ = lcJ + '"nrRegCom":"' + This.PropStr(m.toItem, 'nrRegCom', '') + '"'
lcJ = lcJ + '},'
lcJ = lcJ + '"inregistrare_scop_tva":{'
lcJ = lcJ + '"scpTVA":' + This.PropBool(m.toItem, 'scpTVA', m.tdData, 'dataInceputScpTVA', 'dataSfarsitScpTVA') + ','
lcJ = lcJ + '"perioade_tva":[{'
lcJ = lcJ + '"data_inceput_ScpTVA":"' + This.PropStr(m.toItem, 'dataInceputScpTVA', '') + '",'
lcJ = lcJ + '"data_sfarsit_ScpTVA":"' + This.PropStr(m.toItem, 'dataSfarsitScpTVA', '') + '",'
lcJ = lcJ + '"data_anul_imp_ScpTVA":"' + This.PropStr(m.toItem, 'dataAnulImpScpTVA', '') + '",'
lcJ = lcJ + '"mesaj_ScpTVA":"' + This.PropStr(m.toItem, 'mesajScpTVA', '') + '"'
lcJ = lcJ + '}]'
lcJ = lcJ + '},'
lcJ = lcJ + '"inregistrare_RTVAI":{'
lcJ = lcJ + '"dataInceputTvaInc":"' + This.PropStr(m.toItem, 'dataInceputTvaInc', '') + '",'
lcJ = lcJ + '"dataSfarsitTvaInc":"' + This.PropStr(m.toItem, 'dataSfarsitTvaInc', '') + '",'
lcJ = lcJ + '"dataActualizareTvaInc":"' + This.PropStr(m.toItem, 'dataActualizareTvaInc', '') + '",'
lcJ = lcJ + '"dataPublicareTvaInc":"' + This.PropStr(m.toItem, 'dataPublicareTvaInc', '') + '",'
lcJ = lcJ + '"tipActTvaInc":"' + This.PropStr(m.toItem, 'tipActTvaInc', '') + '",'
lcJ = lcJ + '"statusTvaIncasare":' + This.PropBool(m.toItem, 'tvaIncasare', m.tdData, 'dataInceputTvaInc', 'dataSfarsitTvaInc')
lcJ = lcJ + '},'
lcJ = lcJ + '"stare_inactiv":{'
lcJ = lcJ + '"dataInactivare":"' + This.PropStr(m.toItem, 'dataInactivare', '') + '",'
lcJ = lcJ + '"dataReactivare":"' + This.PropStr(m.toItem, 'dataReactivare', '') + '",'
lcJ = lcJ + '"dataPublicare":"' + This.PropStr(m.toItem, 'dataPublicare', '') + '",'
lcJ = lcJ + '"dataRadiere":"' + This.PropStr(m.toItem, 'dataRadiere', '') + '",'
lcJ = lcJ + '"statusInactivi":' + This.PropBool(m.toItem, 'inactiv', m.tdData, 'dataInactivare', 'dataReactivare')
lcJ = lcJ + '},'
lcJ = lcJ + '"inregistrare_SplitTVA":{'
lcJ = lcJ + '"dataInceputSplitTVA":"' + This.PropStr(m.toItem, 'dataInceputSplitTVA', '') + '",'
lcJ = lcJ + '"dataAnulareSplitTVA":"' + This.PropStr(m.toItem, 'dataAnulareSplitTVA', '') + '",'
lcJ = lcJ + '"statusSplitTVA":' + This.PropBool(m.toItem, 'splitTva', m.tdData, 'dataInceputSplitTVA', 'dataAnulareSplitTVA')
lcJ = lcJ + '}'
lcJ = lcJ + '}'
Return m.lcJ
Endproc
Procedure PropStr
Lparameters toItem, tcProp, tcImplicit
If Type('toItem.' + m.tcProp) <> 'U'
Return Transform(Evaluate('toItem.' + m.tcProp))
Endif
Return m.tcImplicit
Endproc
*-- sensibil la data ceruta, ca serviciul real (ANAF trimite "data" per CUI, validare.prg:2098):
*-- daca item are perechea tcPropStart/tcPropEnd (siruri 'YYYY-MM-DD'), evalueaza tdData IN acea
*-- SINGURA perioada cunoscuta (mock-ul nu e omniscient, la fel ca ANAF v9 - o singura pereche
*-- data_inceput/data_sfarsit, nu o lista, vezi docs\handoff_cache_anaf.md); fara acele
*-- proprietati pe item, cade pe boolean-ul static dinainte (compatibil cu testele existente).
*-- BETWEEN inclusiv pe toate 4 campurile (tlSfarsitExclusiv nefolosit la niciun apel): documentatia
*-- oficiala ANAF (doc_WS_V9.txt) descrie fiecare boolean doar ca "true/false ... la data cautata",
*-- fara sa precizeze daca ziua dataReactivare insasi mai conteaza inactiva - nu e o regula
*-- documentata, deci nu se copiaza aici alegerea (exclusiva) facuta de cache in validare.prg:2675;
*-- vezi test_margine_inactiv_frontiera.prg pentru cazul care ar evidentia diferenta, daca exista.
*!* 01.08.2026 marius.mutu: PropBool nu mai copiaza sfarsitul exclusiv al cache-ului pentru inactiv (vezi docs\diff-S13-teste-echivalenta.md)
Procedure PropBool
Lparameters toItem, tcProp, tdData, tcPropStart, tcPropEnd, tlSfarsitExclusiv
Local llStatic, ldStart, ldEnd, llExclusiv
llStatic = (Vartype(m.tdData) <> 'D') Or Empty(m.tcPropStart) Or (Type('toItem.' + m.tcPropStart) = 'U')
If m.llStatic
If Type('toItem.' + m.tcProp) == 'L' And Evaluate('toItem.' + m.tcProp)
Return 'true'
Endif
Return 'false'
Endif
llExclusiv = (Vartype(m.tlSfarsitExclusiv) == 'L' And m.tlSfarsitExclusiv)
ldStart = This.ParseDataIso(Evaluate('toItem.' + m.tcPropStart))
ldEnd = Iif(Empty(m.tcPropEnd) Or Type('toItem.' + m.tcPropEnd) = 'U', {}, This.ParseDataIso(Evaluate('toItem.' + m.tcPropEnd)))
If Empty(m.ldStart)
Return 'false'
Endif
If m.tdData >= m.ldStart And (Empty(m.ldEnd) Or Iif(m.llExclusiv, m.tdData < m.ldEnd, m.tdData <= m.ldEnd))
Return 'true'
Endif
Return 'false'
Endproc
*-- 'YYYY-MM-DD' (formatul ANAF, vezi antet) -> Date VFP; sir gol/lipsa/invalid -> {} (data goala)
Procedure ParseDataIso
Lparameters tcIso
If Vartype(m.tcIso) <> 'C' Or Len(Alltrim(m.tcIso)) <> 10
Return {}
Endif
Return Date(Val(Substr(m.tcIso, 1, 4)), Val(Substr(m.tcIso, 6, 2)), Val(Substr(m.tcIso, 9, 2)))
Endproc
Enddefine && VerificareANAFMockBatch

View File

@@ -0,0 +1,437 @@
* test_echivalenta_cache_anaf_200.prg - S13, Testul 1, criteriul de acceptare LITERAL din
* stories-cache-anaf.md ("~200 de coduri... cel putin 3 date de referinta, inclusiv una in
* trecut"): o rulare cu OrdineCache('MASA')='CACHE,ANAF' si una cu 'ANAF,CACHE', pe acelasi lot
* de 200 CUI REALE (din NOM_PARTENERI, MARIUSM_AUTO) si aceleasi 3 date de referinta, trebuie sa
* dea verdicte identice (platitor TVA/scpTVA, TVA la incasare, inactiv).
*
* Diferit de test_echivalenta_cache_rtvai.prg (Testul de ADANCIME, 8 CUI cu istoric RTVAI real,
* deja facut) - acesta e testul de LARGIME/scara cerut explicit ca poarta de productie pentru
* 'CACHE,ANAF'. Foloseste acelasi mock S11 (mock_batch_anaf.prg), dar il forteaza pe o ordine
* aleasa (fara sa scrie in OPTIUNI, tabela partajata cu alte benzi) printr-o subclasa care
* suprascrie OrdineCache - vezi DEFINE CLASS de la finalul fisierului.
*
* PROIECTAREA FIXTURE-ULUI (200 coduri REALE, citite din codes_200_reale.txt, extrase din
* NOM_PARTENERI - vezi diff pentru interogare): fiecare cod primeste, deterministic dupa
* MOD(index,10), unul din 4 tipare de interval. Majoritatea (140/200) sunt "vanilla" - inregistrate
* de mult (acum 3 ani) si inca active pe toate 3 campurile - genereaza IDENTIC pe toate 3 date,
* FARA nicio abtinere (simuleaza firme stabile, cazul obisnuit).
*
* MOCK-UL ANAF ESTE SENSIBIL LA DATA CERUTA (corectie 31.07.2026, a doua trecere: reparat DIRECT in
* mock_batch_anaf.prg::PropBool, nu mai recalculat local in acest test): fiecare item ANAF primeste,
* O SINGURA DATA la construirea fixture-ului, perechea de date (dataInceputScpTVA/dataSfarsitScpTVA
* etc., STRING 'YYYY-MM-DD'); PropBool evalueaza boolean-ul FATA DE tdData la fiecare apel - exact ca
* API-ul ANAF real, care primeste "data" per CUI in cerere (validare.prg:2098). Mock-ul NU e omniscient:
* cunoaste O SINGURA perioada per camp (aceeasi limitare structurala reala a ANAF - o pereche
* data_inceput/data_sfarsit, nu o lista). Varianta anterioara (boolean fix, "stare curenta" indiferent
* de data) era artefact de fixture, nu simulare fidela - vezi docs\diff-S13-teste-echivalenta.md,
* sectiunea "Ancheta ceruta de team-lead", pentru mecanismul exact si dovada pe cod.
*
* Restul (60/200, cate 20 pe grup) exercita marginea cunoscuta, la a treia data de referinta (2 ani
* in urma):
* MOD(i,10)=1: scpTVA inchis acum 1 an (deschis 3 ani, inchis 1 an) -> la 2 ani in urma cade IN
* interiorul perioadei -> acum ca mock-ul e sensibil la data, ambele trasee
* calculeaza "era activ atunci" -> IDENTIC (nu mai e divergenta)
* MOD(i,10)=2: TVA la incasare pornita acum 1 an (deschisa) -> la 2 ani in urma cade INAINTE de
* inceputul singurei perioade cunoscute -> garda S6 se declanseaza -> cache-ul se
* ABTINE (randul intreg nu se mai intoarce) -> codul e trimis la ANAF (mock), care
* (marginit la propria perioada, neomniscient) raspunde tot "nu" pentru acea data ->
* verdict final IDENTIC, dar prin ABTINERE, nu prin cache - se vede in contorul de
* apeluri ANAF, nu in verdictul final. Asta ramane singura limitare REALA testabila
* cu acest fixture (ANAF nu are nicio informatie dinainte de perioada pe care o
* urmareste) - vezi si test_echivalenta_cache_rtvai.prg pentru dovada pe date reale.
* MOD(i,10)=3: inactiv intre acum 3 ani si acum 1 an (reactivat) -> la 2 ani in urma cade IN
* fereastra de inactivitate -> ambele trasee calculeaza "era inactiv atunci" ->
* IDENTIC (nu mai e divergenta)
* altfel (MOD(i,10) in 0,4,5,6,7,8,9 - 140 coduri): vanilla, IDENTIC pe toate 3 date
*
* ASTEPTAT la toate 3 date: 200/200 IDENTICE; la D3, 20 din ele (grupul 2) prin ABTINERE (nu prin
* cache), 0 DIVERGENTE. O divergenta ramasa dupa aceasta corectie ar fi categoria (c) - bug real -
* si se raporteaza ca atare, fara sa fie "reparata" sau ascunsa.
*
* Capcane (vezi COMUN\docs\depanare_testare_vfp.md si diff-S11-mock-batch.md): SET SAFETY OFF,
* obiecte de configurare (Collection/Empty) construite INLINE in main (nu in PROCEDURE), mock
* incarcat DUPA test_init_env_auto, ON ERROR + WriteTestLog, curatenie la inceput si FINALLY.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcTestLog
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_echivalenta_cache_anaf_200_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcTestLog)
ON ERROR DO VpaErr200 WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO WriteTestLog200 WITH 'EROARE: conectare Oracle esuata - GATA'
QUIT
ENDIF
DO WriteTestLog200 WITH 'mediu OK, schema=' + gcS
*!* 01.08.2026 marius.mutu: watermark pe ID, inainte de orice scriere - garda pt DELETE-urile din CurataIstoric200
PUBLIC gnIdMaxIstoric200
gnIdMaxIstoric200 = 0
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsWmIstoric200')
SELECT crsWmIstoric200
GO TOP
gnIdMaxIstoric200 = IDMAX
USE IN (SELECT('crsWmIstoric200'))
ENDIF
DO WriteTestLog200 WITH 'watermark ISTORIC_CODURI_FISCALE id_max=' + TRANSFORM(gnIdMaxIstoric200)
*!* 01.08.2026 marius.mutu: watermark invalid = SELECT esuat - avertisment explicit, stergerile se vor sari
IF gnIdMaxIstoric200 <= 0
DO WriteTestLog200 WITH 'ATENTIE: watermark invalid (0) - stergerile din ISTORIC_CODURI_FISCALE vor fi SARITE'
ENDIF
* mock-ul e o SUBCLASA a VerificareANAF - se incarca DUPA test_init_env_auto (vezi mock_batch_anaf.prg)
SET PROCEDURE TO "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\mock_batch_anaf.prg" ADDITIVE
PUBLIC goANAFBatchMock, goANAFBatchScenariuPerGrup, gcANAFBatchScenariu, glANAFBatchIgnoraGate404
PUBLIC gnANAFBatchApeluri, gcANAFBatchCuiuriTrimise, gcForceOrdine200
goANAFBatchMock = CREATEOBJECT('Collection')
goANAFBatchScenariuPerGrup = CREATEOBJECT('Collection')
gcANAFBatchScenariu = 'NORMAL'
glANAFBatchIgnoraGate404 = .F.
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
gcForceOrdine200 = 'CACHE,ANAF'
PUBLIC goMock200
goMock200 = CREATEOBJECT('VerificareANAFMockBatchOrdine200')
DO CurataIstoric200
* --- citeste cele 200 de coduri REALE dintr-un fisier text (un CUI pe linie, CRLF) ---
LOCAL lcCodesFile, lcCodesText
LOCAL ARRAY laCodes200[1]
lcCodesFile = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\codes_200_reale.txt"
lcCodesText = FILETOSTR(lcCodesFile)
LOCAL lnCodes200
lnCodes200 = ALINES(laCodes200, lcCodesText)
DO WriteTestLog200 WITH 'coduri citite din fisier: ' + TRANSFORM(lnCodes200)
* --- date de referinta ---
LOCAL ldY3, ldY1, ldD1, ldD2, ldD3
ldD1 = DATE()
ldY3 = ldD1 - 1095
ldY1 = ldD1 - 365
ldD2 = ldD1 - 90
ldD3 = ldD1 - 730
DO WriteTestLog200 WITH 'date referinta: D1(azi)=' + DTOC(ldD1) + ' D2(3 luni)=' + DTOC(ldD2) + ' D3(2 ani)=' + DTOC(ldD3)
* --- construieste seed-ul de cache (crsANAF-shape) si mock-ul ANAF, per cod, dupa MOD(index,10) ---
IF USED('crsSeedANAF200')
USE IN crsSeedANAF200
ENDIF
CREATE CURSOR crsSeedANAF200 (cui N(13), data D, denumire V(100), firma V(100), adresa C(244), nrRegCom C(30), ;
scpTVA L, data_inceput_ScpTVA D, data_sfarsit_ScpTVA D, data_anul_imp_ScpTVA D, mesaj_ScpTVA C(244), ;
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, ;
dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
dataInceputSplitTVA D, dataAnulareSplitTVA D, tva L, tvaincasare L, splittva L, inactiv L, ;
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
sursa C(20), data_sursa D)
IF USED('crsCoduri200Input')
USE IN crsCoduri200Input
ENDIF
CREATE CURSOR crsCoduri200Input (cod_fiscal C(30) Null, data D Null)
IF USED('crsGrupuri200')
USE IN crsGrupuri200
ENDIF
* pastreaza si intervalul seedat per cod - refolosit ca sa recalculez mock-ul la fiecare data,
* fara sa duplic logica de grup (vezi bucla de mai jos)
CREATE CURSOR crsGrupuri200 (cui N(13), grup N(2), ;
dScptvaStart D, dScptvaEnd D, dTvaincStart D, dTvaincEnd D, dInactivareD D, dReactivareD D)
LOCAL lnI, lcCuiTxt, lnCuiN, lnGrup
LOCAL ldScptvaStart, ldScptvaEnd, ldTvaincStart, ldTvaincEnd, ldInactivareD, ldReactivareD
LOCAL llScpTvaMock, llTvaIncMock, llInactivMock
FOR lnI = 1 TO lnCodes200
lcCuiTxt = ALLTRIM(laCodes200[lnI])
IF EMPTY(lcCuiTxt)
LOOP
ENDIF
lnCuiN = INT(VAL(lcCuiTxt))
lnGrup = MOD(lnI, 10)
DO CASE
CASE lnGrup = 1
* scpTVA inchis acum 1 an - divergenta asteptata la D3
ldScptvaStart = ldY3
ldScptvaEnd = ldY1
llScpTvaMock = .F.
ldTvaincStart = ldY3
ldTvaincEnd = {}
llTvaIncMock = .T.
ldInactivareD = {}
ldReactivareD = {}
llInactivMock = .F.
CASE lnGrup = 2
* TVA la incasare pornita acum 1 an - abtinere asteptata la D3
ldScptvaStart = ldY3
ldScptvaEnd = {}
llScpTvaMock = .T.
ldTvaincStart = ldY1
ldTvaincEnd = {}
llTvaIncMock = .T.
ldInactivareD = {}
ldReactivareD = {}
llInactivMock = .F.
CASE lnGrup = 3
* inactiv acum 3 ani, reactivat acum 1 an - divergenta asteptata la D3
ldScptvaStart = ldY3
ldScptvaEnd = {}
llScpTvaMock = .T.
ldTvaincStart = ldY3
ldTvaincEnd = {}
llTvaIncMock = .T.
ldInactivareD = ldY3
ldReactivareD = ldY1
llInactivMock = .F.
OTHERWISE
* vanilla - identic pe toate 3 date, fara abtinere
ldScptvaStart = ldY3
ldScptvaEnd = {}
llScpTvaMock = .T.
ldTvaincStart = ldY3
ldTvaincEnd = {}
llTvaIncMock = .T.
ldInactivareD = {}
ldReactivareD = {}
llInactivMock = .F.
ENDCASE
INSERT INTO crsSeedANAF200 (cui, data, data_inceput_ScpTVA, data_sfarsit_ScpTVA, ;
dataInceputTvaInc, dataSfarsitTvaInc, dataInactivare, dataReactivare, ;
scpTVA, tvaincasare, inactiv) VALUES ;
(lnCuiN, ldD1, ldScptvaStart, ldScptvaEnd, ldTvaincStart, ldTvaincEnd, ldInactivareD, ldReactivareD, ;
llScpTvaMock, llTvaIncMock, llInactivMock)
INSERT INTO crsCoduri200Input (cod_fiscal) VALUES (lcCuiTxt)
INSERT INTO crsGrupuri200 (cui, grup, dScptvaStart, dScptvaEnd, dTvaincStart, dTvaincEnd, dInactivareD, dReactivareD) ;
VALUES (lnCuiN, lnGrup, ldScptvaStart, ldScptvaEnd, ldTvaincStart, ldTvaincEnd, ldInactivareD, ldReactivareD)
* -- item mock ANAF, construit O SINGURA DATA (nu per data de referinta) - PropBool
* (mock_batch_anaf.prg, reparat 31.07.2026) recalculeaza sensibil la tdData la fiecare apel,
* din exact acest interval unic (STRING 'YYYY-MM-DD', formatul documentat al mock-ului) --
LOCAL loMockItem200
loMockItem200 = CREATEOBJECT('Empty')
ADDPROPERTY(loMockItem200, 'dataInceputScpTVA', Dtoiso200(ldScptvaStart))
ADDPROPERTY(loMockItem200, 'dataSfarsitScpTVA', Dtoiso200(ldScptvaEnd))
ADDPROPERTY(loMockItem200, 'dataInceputTvaInc', Dtoiso200(ldTvaincStart))
ADDPROPERTY(loMockItem200, 'dataSfarsitTvaInc', Dtoiso200(ldTvaincEnd))
ADDPROPERTY(loMockItem200, 'dataInactivare', Dtoiso200(ldInactivareD))
ADDPROPERTY(loMockItem200, 'dataReactivare', Dtoiso200(ldReactivareD))
goANAFBatchMock.Add(loMockItem200, 'C' + NormalizeazaCUI(lcCuiTxt))
ENDFOR
DO WriteTestLog200 WITH 'fixture construit: ' + TRANSFORM(RECCOUNT('crsSeedANAF200')) + ' coduri (grup1=20 scpTVA-inchis, grup2=20 tvainc-recent, grup3=20 inactiv-trecut, restul vanilla)'
goMock200.SalveazaIstoricDinCursor('crsSeedANAF200', gnIdUtil)
DO WriteTestLog200 WITH 'seed salvat in ISTORIC_CODURI_FISCALE'
* --- ruleaza ambele ordini, pe toate 3 datele, si compara ---
TRY
LOCAL lnDateIdx, ldDataCurenta, lcNumeData
LOCAL lnIdentice, lnDivergente, lnAbtinute, lnAsteptateDivergente, lnAsteptateAbtinute
LOCAL lcAliasA, lcAliasB, lcCuiuriCache, lcCuiuriAnaf
FOR lnDateIdx = 1 TO 3
DO CASE
CASE lnDateIdx = 1
ldDataCurenta = ldD1
lcNumeData = 'D1-azi'
CASE lnDateIdx = 2
ldDataCurenta = ldD2
lcNumeData = 'D2-3luni'
OTHERWISE
ldDataCurenta = ldD3
lcNumeData = 'D3-2ani'
ENDCASE
* -- mock-ul ANAF (goANAFBatchMock) NU se mai reconstruieste aici: e populat O SINGURA DATA,
* mai sus, la construirea fixture-ului - PropBool (mock_batch_anaf.prg) recalculeaza singur,
* la fiecare apel, boolean-ul sensibil la ldDataCurenta din intervalul unic memorat pe item --
* -- rulare CACHE,ANAF --
gcForceOrdine200 = 'CACHE,ANAF'
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
lcAliasA = 'crsRezCacheAnaf'
IF USED(lcAliasA)
USE IN (lcAliasA)
ENDIF
goMock200.VerificaListaCIF('crsCoduri200Input', ldDataCurenta, lcAliasA)
lcCuiuriCache = gcANAFBatchCuiuriTrimise
* -- rulare ANAF,CACHE --
gcForceOrdine200 = 'ANAF,CACHE'
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
lcAliasB = 'crsRezAnafCache'
IF USED(lcAliasB)
USE IN (lcAliasB)
ENDIF
goMock200.VerificaListaCIF('crsCoduri200Input', ldDataCurenta, lcAliasB)
lcCuiuriAnaf = gcANAFBatchCuiuriTrimise
DO WriteTestLog200 WITH lcNumeData + ' (' + DTOC(ldDataCurenta) + '): randuri CACHE,ANAF=' + TRANSFORM(IIF(USED(lcAliasA),RECCOUNT(lcAliasA),-1)) + ;
' randuri ANAF,CACHE=' + TRANSFORM(IIF(USED(lcAliasB),RECCOUNT(lcAliasB),-1)) + ' abtineri(cuiuri trimise sub CACHE,ANAF)=' + TRANSFORM(GETWORDCOUNT(lcCuiuriCache,','))
lnIdentice = 0
lnDivergente = 0
lnAbtinute = 0
lnAsteptateDivergente = 0
lnAsteptateAbtinute = 0
SELECT crsGrupuri200
SCAN
LOCAL lnCuiCurent2, lnGrupCurent, llGasitA, llGasitB, lnTvaA, lnTvaIA, lnInactA, lnTvaB, lnTvaIB, lnInactB, llAbtinut, llDivergent
lnCuiCurent2 = cui
lnGrupCurent = grup
llGasitA = .F.
IF USED(lcAliasA)
SELECT (lcAliasA)
LOCATE FOR cui = lnCuiCurent2
llGasitA = FOUND()
IF llGasitA
lnTvaA = IIF(tva,1,0)
lnTvaIA = IIF(tvaincasare,1,0)
lnInactA = IIF(inactiv,1,0)
ENDIF
ENDIF
llGasitB = .F.
IF USED(lcAliasB)
SELECT (lcAliasB)
LOCATE FOR cui = lnCuiCurent2
llGasitB = FOUND()
IF llGasitB
lnTvaB = IIF(tva,1,0)
lnTvaIB = IIF(tvaincasare,1,0)
lnInactB = IIF(inactiv,1,0)
ENDIF
ENDIF
llAbtinut = (',' + TRANSFORM(lnCuiCurent2) + ',') $ (',' + lcCuiuriCache + ',')
llDivergent = .F.
IF llGasitA AND llGasitB
llDivergent = (lnTvaA <> lnTvaB) OR (lnTvaIA <> lnTvaIB) OR (lnInactA <> lnInactB)
ELSE
llDivergent = .T. && lipsa unui rand e ea insasi o divergenta de raportat
ENDIF
IF llDivergent
lnDivergente = lnDivergente + 1
* dupa corectia mock-ului (sensibil la data), NU mai e asteptata nicio divergenta,
* in niciun grup, la nicio data - orice divergenta ramasa e categoria (c), bug real
DO WriteTestLog200 WITH ' DIVERGENT (NEASTEPTAT - posibil bug) ' + lcNumeData + ' cui=' + TRANSFORM(lnCuiCurent2) + ' grup=' + TRANSFORM(lnGrupCurent) + ;
' CACHE,ANAF(tva=' + TRANSFORM(lnTvaA) + ' tvainc=' + TRANSFORM(lnTvaIA) + ' inactiv=' + TRANSFORM(lnInactA) + ')' + ;
' ANAF,CACHE(tva=' + TRANSFORM(lnTvaB) + ' tvainc=' + TRANSFORM(lnTvaIB) + ' inactiv=' + TRANSFORM(lnInactB) + ')'
ELSE
lnIdentice = lnIdentice + 1
ENDIF
IF llAbtinut
lnAbtinute = lnAbtinute + 1
IF lnGrupCurent = 2 AND lnDateIdx = 3
lnAsteptateAbtinute = lnAsteptateAbtinute + 1
ENDIF
ENDIF
SELECT crsGrupuri200
ENDSCAN
DO WriteTestLog200 WITH lcNumeData + ' REZULTAT: identice=' + TRANSFORM(lnIdentice) + ;
' divergente=' + TRANSFORM(lnDivergente) + ' (asteptat: 0, in orice grup, la orice data)' + ;
' abtinute=' + TRANSFORM(lnAbtinute) + ' (asteptate=' + TRANSFORM(lnAsteptateAbtinute) + ')'
IF USED(lcAliasA)
USE IN (lcAliasA)
ENDIF
IF USED(lcAliasB)
USE IN (lcAliasB)
ENDIF
ENDFOR
CATCH TO loExc200
DO WriteTestLog200 WITH 'CATCH ErrorNo=' + TRANSFORM(loExc200.ErrorNo) + ' Message=' + loExc200.Message + ' Proc=' + loExc200.Procedure + ' Line=' + TRANSFORM(loExc200.LineNo)
FINALLY
DO CurataIstoric200
ENDTRY
DO WriteTestLog200 WITH 'GATA'
QUIT
PROCEDURE WriteTestLog200
LPARAMETERS tcMesaj
STRTOFILE(TTOC(DATETIME()) + ' ' + tcMesaj + CHR(13)+CHR(10), gcTestLog, 1)
ENDPROC
PROCEDURE VpaErr200
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO WriteTestLog200 WITH 'ON ERROR nEroare=' + TRANSFORM(tnErr) + ' mesaj=' + tcMsg + ' program=' + tcProg + ' linia=' + TRANSFORM(tnLine)
ENDPROC
*-- sterge cele 200 CUI reale ale acestui test din ISTORIC_CODURI_FISCALE (citite din fisierul
*-- codes_200_reale.txt) - nu atinge alte coduri din alte suite/benzi
PROCEDURE CurataIstoric200
LOCAL lcCodesFileC, lcCodesTextC, lcListaC, lnIC, lnCountC
LOCAL ARRAY laCodesC[1]
LOCAL lnSterse
lcCodesFileC = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\codes_200_reale.txt"
IF !FILE(lcCodesFileC)
DO WriteTestLog200 WITH 'CurataIstoric200: fisier de coduri lipsa, nimic de sters'
RETURN
ENDIF
lcCodesTextC = FILETOSTR(lcCodesFileC)
lnCountC = ALINES(laCodesC, lcCodesTextC)
lcListaC = ''
FOR lnIC = 1 TO lnCountC
IF !EMPTY(ALLTRIM(laCodesC[lnIC]))
lcListaC = lcListaC + IIF(EMPTY(lcListaC),'',',') + ALLTRIM(laCodesC[lnIC])
ENDIF
ENDFOR
IF EMPTY(lcListaC)
RETURN
ENDIF
*!* 01.08.2026 marius.mutu: watermark invalid - nu sterg nimic (fara el, DELETE ar lovi tot istoricul comun)
IF TYPE('gnIdMaxIstoric200') <> 'N' OR gnIdMaxIstoric200 <= 0
DO WriteTestLog200 WITH 'CurataIstoric200: SARIT - watermark invalid, nu sterg nimic'
RETURN
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
lnSterse = goExecutor.oExecuta([DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ] + TRANSFORM(gnIdMaxIstoric200) + [ AND COD_FISCAL_N IN (] + lcListaC + [)])
=goExecutor.oExecuta('COMMIT')
DO WriteTestLog200 WITH 'CurataIstoric200: sters=' + TRANSFORM(lnSterse)
ENDPROC
*-- 'YYYY-MM-DD' (formatul mock-ului ANAF, mock_batch_anaf.prg) dintr-o Date VFP; data goala -> '' --
PROCEDURE Dtoiso200
LPARAMETERS tdVal
IF EMPTY(tdVal)
RETURN ''
ENDIF
RETURN LEFT(DTOS(tdVal),4) + '-' + SUBSTR(DTOS(tdVal),5,2) + '-' + SUBSTR(DTOS(tdVal),7,2)
ENDPROC
*-- subclasa care forteaza ordinea printr-o variabila publica (gcForceOrdine200), ca sa nu scriu
*-- in OPTIUNI (tabela partajata cu alte benzi care ruleaza in paralel pe aceeasi schema) - acelasi
*-- tipar folosit de S6 in testul lui propriu (docs\diff-S6-citire-cache.md)
DEFINE CLASS VerificareANAFMockBatchOrdine200 AS VerificareANAFMockBatch
PROCEDURE OrdineCache
LPARAMETERS tcTraseu
RETURN gcForceOrdine200
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,232 @@
* test_echivalenta_cache_rtvai.prg - S13, Testul 1 EXTINS: echivalenta cache vs ANAF cu RTVAI
* ca al treilea termen de comparatie (docs\stories-cache-anaf.md sectiunea S13, extindere ceruta
* in handoff_cache_anaf.md - "ANAF nu da istoricul complet").
*
* PROBLEMA cu testul simplu cache-vs-ANAF (deja facut de S6, 200 coduri sintetice, 0 diferente):
* daca ANAF si cache-ul stiu AMANDOI o singura perioada (ANAF nu intoarce istoricul complet -
* verificat direct pe serviciu: CUI 16548698 da 2015-05-27->2024-11-01, rtvai_istoric are 9
* perioade din 2013), cei doi termeni sunt de acord CHIAR SI CAND raspunsul e gresit pentru o
* data din trecut. Testul simplu nu ar prinde asta niciodata.
*
* SOLUTIE: pe 8 CUI REALE (companii reale, alese din rtvai_istoric pe MARIUSM_AUTO/CONTAFIN_ORACLE,
* 7-9 perioade fiecare - interogare si tabel complet in docs\diff-S13-teste-echivalenta.md), pentru
* fiecare cod:
* - seed ISTORIC_CODURI_FISCALE cu O SINGURA perioada (cea mai recenta din rtvai_istoric - proxy
* pentru "ce ar spune ANAF azi", documentat/asumat explicit, vezi diff) - asta e SIMULTAN
* termenul (a) cache SI baza termenului (b) ANAF (vezi mai jos)
* - termen (a) CACHE: CitesteIstoricPentruCoduri REALA (validare.prg, cu garda S6) la o data
* VECHE, dinaintea perioadei seedate
* - termen (b) ANAF: simplul test de interval [pLatStart,pLatEnd] - ACELASI interval cu care a
* fost seedat cache-ul (nu exista alt canal ANAF disponibil headless) - reprezinta explicit
* ce ar raspunde cache-ul DACA garda S6 nu ar exista (formula v_tvainc e identica)
* - termen (c) RTVAI: pack_roartvai.PartenerInRTVAI, PROCEDURA REALA neschimbata (S2 nu a
* atins-o inca), citeste rtvai_istoric COMPLET (toate perioadele)
* Plus control: aceeasi comparatie la o data DIN INTERIORUL perioadei seedate - toti 3 termenii
* trebuie sa fie de acord (garda nu trebuie sa strice calea normala).
*
* PASS per cod: la data veche, (a) abtine (nu returneaza rand - garda S6 functioneaza), (b) = 0
* (ANAF/cache-fara-garda ar fi spus gresit "nu"), (c) = 1 (RTVAI, ground truth, spune "da") -
* garda impiedica exact propagarea verdictului gresit pe care (b) l-ar fi dat. La data control,
* (a)=(b)=(c)=1.
*
* Fara CREATEOBJECT/ADDPROPERTY in interiorul unei PROCEDURE (capcana l, depanare_testare_vfp.md) -
* obiectele se construiesc INLINE in programul principal.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcTestLog, gnTestOk, gnTestTotal
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_echivalenta_cache_rtvai_log.txt"
gnTestOk = 0
gnTestTotal = 0
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcTestLog)
ON ERROR DO VpaErrRTVAI WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO WriteTestLogRTVAI WITH 'EROARE: conectare Oracle esuata - GATA'
QUIT
ENDIF
DO WriteTestLogRTVAI WITH 'mediu OK, schema=' + gcS
*!* 01.08.2026 marius.mutu: watermark pe ID, inainte de orice scriere - garda pt DELETE-ul din CurataIstoricRTVAITest
PUBLIC gnIdMaxIstoricRTVAI
gnIdMaxIstoricRTVAI = 0
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsWmIstoricRTVAI')
SELECT crsWmIstoricRTVAI
GO TOP
gnIdMaxIstoricRTVAI = IDMAX
USE IN (SELECT('crsWmIstoricRTVAI'))
ENDIF
*!* 01.08.2026 marius.mutu: watermark invalid = SELECT esuat - avertisment explicit, stergerile se vor sari
IF gnIdMaxIstoricRTVAI <= 0
DO WriteTestLogRTVAI WITH 'ATENTIE: watermark invalid (0) - stergerile din ISTORIC_CODURI_FISCALE vor fi SARITE'
ENDIF
DO WriteTestLogRTVAI WITH 'watermark ISTORIC_CODURI_FISCALE id_max=' + TRANSFORM(gnIdMaxIstoricRTVAI)
DO CurataIstoricRTVAITest
PUBLIC goVerifRTVAI
goVerifRTVAI = CREATEOBJECT('VerificareANAF')
* -- 8 CUI REALE, alese din rtvai_istoric (interogare + tabel complet de perioade in diff) --
* cui, pLatStart/pLatEnd = perioada cea mai recenta cunoscuta (proxy ANAF), dOld = in perioada
* VECHE (inainte de pLatStart), dCtrl = in interiorul perioadei recente (control)
IF USED('crsCoduriTest')
USE IN crsCoduriTest
ENDIF
CREATE CURSOR crsCoduriTest (cui N(10), pLatStart D, pLatEnd D, dOld D, dCtrl D)
INSERT INTO crsCoduriTest VALUES (8060237, {^2018-06-14}, {^2020-04-30}, {^2013-03-01}, {^2019-01-01})
INSERT INTO crsCoduriTest VALUES (16548698, {^2015-05-27}, {^2024-11-01}, {^2013-06-01}, {^2016-01-01})
INSERT INTO crsCoduriTest VALUES (17254755, {^2013-12-12}, {^2019-07-07}, {^2013-04-01}, {^2015-01-01})
INSERT INTO crsCoduriTest VALUES (18010589, {^2018-10-31}, {^2019-07-31}, {^2013-04-01}, {^2019-02-01})
INSERT INTO crsCoduriTest VALUES (21438829, {^2019-04-01}, {^2020-01-31}, {^2013-06-01}, {^2019-08-01})
INSERT INTO crsCoduriTest VALUES (28333609, {^2020-04-01}, {^2020-07-31}, {^2013-04-01}, {^2020-06-01})
INSERT INTO crsCoduriTest VALUES (28493170, {^2019-06-19}, {^2019-12-31}, {^2013-04-01}, {^2019-09-01})
INSERT INTO crsCoduriTest VALUES (30719386, {^2016-05-25}, {^2018-02-28}, {^2014-01-01}, {^2017-01-01})
LOCAL lnCui, ldLatStart, ldLatEnd, ldOld, ldCtrl
LOCAL llAAbstineOld, lnAOld, lnBOld, lnCOld, lnACtrl, lnBCtrl, lnCCtrl, llOk
LOCAL lnAllOk, lnTotal
lnAllOk = 0
lnTotal = 0
SELECT crsCoduriTest
SCAN
lnCui = cui
ldLatStart = pLatStart
ldLatEnd = pLatEnd
ldOld = dOld
ldCtrl = dCtrl
* -- seed cache cu perioada "cunoscuta de ANAF" (aceeasi forma ca crsANAF din ParseJsonANAFv8) --
IF USED('crsSeedANAF')
USE IN crsSeedANAF
ENDIF
CREATE CURSOR crsSeedANAF (cui N(13), data D, denumire V(100), firma V(100), adresa C(244), nrRegCom C(30), ;
scpTVA L, data_inceput_ScpTVA D, data_sfarsit_ScpTVA D, data_anul_imp_ScpTVA D, mesaj_ScpTVA C(244), ;
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, ;
dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
dataInceputSplitTVA D, dataAnulareSplitTVA D, tva L, tvaincasare L, splittva L, inactiv L, ;
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
sursa C(20), data_sursa D)
INSERT INTO crsSeedANAF (cui, data, dataInceputTvaInc, dataSfarsitTvaInc, tvaincasare) ;
VALUES (lnCui, DATE(), ldLatStart, ldLatEnd, .T.)
goVerifRTVAI.SalveazaIstoricDinCursor('crsSeedANAF', gnIdUtil)
USE IN crsSeedANAF
* -- termen (a): cache REAL (cu garda S6), la data VECHE - asteptat: abtinere (niciun rand) --
IF USED('crsCacheOld')
USE IN crsCacheOld
ENDIF
goVerifRTVAI.CitesteIstoricPentruCoduri(TRANSFORM(lnCui), ldOld, 'crsCacheOld')
llAAbstineOld = .T.
lnAOld = -1
IF USED('crsCacheOld')
SELECT crsCacheOld
LOCATE FOR cui = lnCui
IF FOUND()
llAAbstineOld = .F.
lnAOld = IIF(tvaincasare, 1, 0)
ENDIF
ENDIF
* -- termen (b): ANAF - acelasi interval unic folosit la seed (nu exista alt canal ANAF headless) --
lnBOld = IIF(BETWEEN(ldOld, ldLatStart, ldLatEnd), 1, 0)
* -- termen (c): RTVAI - procedura REALA neschimbata, citeste rtvai_istoric complet --
lnCOld = ObtineVerdictRTVAI(lnCui, ldOld)
* -- control: data in interiorul perioadei cunoscute - toti 3 termenii trebuie sa fie de acord --
IF USED('crsCacheCtrl')
USE IN crsCacheCtrl
ENDIF
goVerifRTVAI.CitesteIstoricPentruCoduri(TRANSFORM(lnCui), ldCtrl, 'crsCacheCtrl')
lnACtrl = -1
IF USED('crsCacheCtrl')
SELECT crsCacheCtrl
LOCATE FOR cui = lnCui
IF FOUND()
lnACtrl = IIF(tvaincasare, 1, 0)
ENDIF
ENDIF
lnBCtrl = IIF(BETWEEN(ldCtrl, ldLatStart, ldLatEnd), 1, 0)
lnCCtrl = ObtineVerdictRTVAI(lnCui, ldCtrl)
lnTotal = lnTotal + 1
llOk = (lnCOld = 1) AND llAAbstineOld AND (lnBOld = 0) AND ;
(lnCCtrl = 1) AND (lnACtrl = 1) AND (lnBCtrl = 1)
IF llOk
lnAllOk = lnAllOk + 1
ENDIF
DO WriteTestLogRTVAI WITH 'cui=' + TRANSFORM(lnCui) + ;
' | dOld=' + DTOC(ldOld) + ' a(abstine)=' + TRANSFORM(llAAbstineOld) + ' a(val)=' + TRANSFORM(lnAOld) + ' b=' + TRANSFORM(lnBOld) + ' c=' + TRANSFORM(lnCOld) + ;
' | dCtrl=' + DTOC(ldCtrl) + ' a=' + TRANSFORM(lnACtrl) + ' b=' + TRANSFORM(lnBCtrl) + ' c=' + TRANSFORM(lnCCtrl) + ;
' -> ' + IIF(llOk, 'PASS', 'FAIL')
IF USED('crsCacheOld')
USE IN crsCacheOld
ENDIF
IF USED('crsCacheCtrl')
USE IN crsCacheCtrl
ENDIF
SELECT crsCoduriTest
ENDSCAN
DO WriteTestLogRTVAI WITH 'REZULTAT criteriul-8-extins-RTVAI: ' + TRANSFORM(lnAllOk) + '/' + TRANSFORM(lnTotal) + ' coduri PASS'
DO CurataIstoricRTVAITest
QUIT
*-- verdict "TVA la incasare la data D" din rtvai_istoric COMPLET (istoricul importat, nu ANAF),
*-- prin procedura Oracle REALA pack_roartvai.PartenerInRTVAI (neschimbata de S2 inca) --
PROCEDURE ObtineVerdictRTVAI
LPARAMETERS tnCui, tdData
PRIVATE pnCodFiscal, pdData, pcDenumire, pnRTVAI
pnCodFiscal = tnCui
pdData = tdData
pcDenumire = ''
pnRTVAI = 0
LOCAL lcSql
lcSql = [begin pack_roartvai.PartenerInRTVAI(?pnCodFiscal, ?pdData, ?@pcDenumire, ?@pnRTVAI); end;]
IF !goExecutor.oExecuta(lcSql)
RETURN -1
ENDIF
RETURN pnRTVAI
ENDPROC
PROCEDURE WriteTestLogRTVAI
LPARAMETERS tcMesaj
STRTOFILE(TTOC(DATETIME()) + ' ' + tcMesaj + CHR(13)+CHR(10), gcTestLog, 1)
ENDPROC
PROCEDURE VpaErrRTVAI
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO WriteTestLogRTVAI WITH 'ON ERROR nEroare=' + TRANSFORM(tnErr) + ' mesaj=' + tcMsg + ' program=' + tcProg + ' linia=' + TRANSFORM(tnLine)
ENDPROC
*-- sterge DOAR cele 8 CUI reale folosite de acest test din ISTORIC_CODURI_FISCALE --
PROCEDURE CurataIstoricRTVAITest
LOCAL lnSterse
*!* 01.08.2026 marius.mutu: watermark invalid - nu sterg nimic (fara el, DELETE ar lovi tot istoricul comun)
IF TYPE('gnIdMaxIstoricRTVAI') <> 'N' OR gnIdMaxIstoricRTVAI <= 0
DO WriteTestLogRTVAI WITH 'CurataIstoricRTVAITest: SARIT - watermark invalid, nu sterg nimic'
RETURN
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
lnSterse = goExecutor.oExecuta([DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ] + TRANSFORM(gnIdMaxIstoricRTVAI) + [ AND COD_FISCAL_N IN ] + ;
[(8060237,16548698,17254755,18010589,21438829,28333609,28493170,30719386)])
=goExecutor.oExecuta('COMMIT')
DO WriteTestLogRTVAI WITH 'CurataIstoricRTVAITest: sters=' + TRANSFORM(lnSterse)
ENDPROC

View File

@@ -0,0 +1,238 @@
* test_margine_inactiv_frontiera.prg - S13, marginea NEVERIFICATA semnalata in
* docs\diff-S13-teste-echivalenta.md ("REPARATIA FINALA"): CitesteIstoricPentruCoduri (cache REAL,
* validare.prg:2697, formula "?pdDataCache < data_reactivare") trateaza ziua dataReactivare insasi
* ca NEinactiva (sfarsit exclusiv). Documentatia oficiala ANAF (doc_WS_V9.txt, verificata separat -
* citeaza fiecare boolean doar ca "true/false ... la data cautata", fara sa precizeze granita) NU
* confirma si NU infirma aceasta alegere - deci mock-ul (mock_batch_anaf.prg::PropBool, dupa
* reparatia din 01.08.2026) NU mai copiaza sfarsitul exclusiv al cache-ului, foloseste acelasi
* BETWEEN inclusiv ca la scpTVA/tvaIncasare/splitTva.
*
* SCOP: nu decide care variant e "corecta" (nu exista sursa externa care sa spuna) - doar
* demonstreaza, cu rulare reala, exact ZIUA in care cache-ul REAL si mock-ul REPARAT ar da verdicte
* diferite daca cineva ar interoga exact la data reactivarii. O divergenta aici e rezultatul
* ASTEPTAT si CORECT al reparatiei (nu mai e ascunsa de o formula copiata) - se raporteaza ca atare,
* nu ca "FAIL". Cele 3 date de control (inainte de sfarsit, exact la inceput, dupa sfarsit) trebuie
* sa fie de acord pe ambele cai - daca nu sunt, ATUNCI e semnal de bug real.
*
* Fara CREATEOBJECT/ADDPROPERTY in interiorul unei PROCEDURE (capcana l, depanare_testare_vfp.md) -
* obiectele se construiesc INLINE in programul principal.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcTestLog
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_margine_inactiv_frontiera_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcTestLog)
ON ERROR DO VpaErrMargine WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO WriteTestLogMargine WITH 'EROARE: conectare Oracle esuata - GATA'
QUIT
ENDIF
DO WriteTestLogMargine WITH 'mediu OK, schema=' + gcS
*!* 01.08.2026 marius.mutu: watermark pe ID, inainte de orice scriere - garda pt DELETE-ul din CurataIstoricMargine
PUBLIC gnIdMaxIstoricMargine
gnIdMaxIstoricMargine = 0
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsWmIstoricMargine')
SELECT crsWmIstoricMargine
GO TOP
gnIdMaxIstoricMargine = IDMAX
USE IN (SELECT('crsWmIstoricMargine'))
ENDIF
*!* 01.08.2026 marius.mutu: watermark invalid = SELECT esuat - avertisment explicit, stergerile se vor sari
IF gnIdMaxIstoricMargine <= 0
DO WriteTestLogMargine WITH 'ATENTIE: watermark invalid (0) - stergerile din ISTORIC_CODURI_FISCALE vor fi SARITE'
ENDIF
DO WriteTestLogMargine WITH 'watermark ISTORIC_CODURI_FISCALE id_max=' + TRANSFORM(gnIdMaxIstoricMargine)
* mock-ul e o SUBCLASA a VerificareANAF - se incarca DUPA test_init_env_auto (vezi mock_batch_anaf.prg)
SET PROCEDURE TO "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\mock_batch_anaf.prg" ADDITIVE
PUBLIC goANAFBatchMock, gnANAFBatchApeluri, gcANAFBatchCuiuriTrimise
goANAFBatchMock = CREATEOBJECT('Collection')
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
PUBLIC goVerifMargine
goVerifMargine = CREATEOBJECT('VerificareANAFMockBatch')
DO CurataIstoricMargine
* -- 1 CUI de test, cifra de control valida (VALIDARE_CIF), nefolosit de alta suita din transa --
LOCAL lnCui, lcCui, ldInactivare, ldReactivare
lnCui = 80100377
lcCui = TRANSFORM(lnCui)
ldInactivare = {^2023-01-15}
ldReactivare = {^2024-06-01}
* -- seed cache (aceeasi forma ca crsANAF din ParseJsonANAFv8) --
IF USED('crsSeedMargine')
USE IN crsSeedMargine
ENDIF
CREATE CURSOR crsSeedMargine (cui N(13), data D, denumire V(100), firma V(100), adresa C(244), nrRegCom C(30), ;
scpTVA L, data_inceput_ScpTVA D, data_sfarsit_ScpTVA D, data_anul_imp_ScpTVA D, mesaj_ScpTVA C(244), ;
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, ;
dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
dataInceputSplitTVA D, dataAnulareSplitTVA D, tva L, tvaincasare L, splittva L, inactiv L, ;
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
sursa C(20), data_sursa D)
INSERT INTO crsSeedMargine (cui, data, dataInactivare, dataReactivare, inactiv) ;
VALUES (lnCui, DATE(), ldInactivare, ldReactivare, .T.)
goVerifMargine.SalveazaIstoricDinCursor('crsSeedMargine', gnIdUtil)
USE IN crsSeedMargine
DO WriteTestLogMargine WITH 'seed cache: cui=' + lcCui + ' dataInactivare=' + DTOC(ldInactivare) + ' dataReactivare=' + DTOC(ldReactivare)
* -- item mock ANAF (aceeasi perioada, ca si cum ANAF ar fi raspuns cu ea) --
LOCAL loMockItem
loMockItem = CREATEOBJECT('Empty')
ADDPROPERTY(loMockItem, 'dataInactivare', DtoisoMargine(ldInactivare))
ADDPROPERTY(loMockItem, 'dataReactivare', DtoisoMargine(ldReactivare))
goANAFBatchMock.Add(loMockItem, 'C' + lcCui)
* -- cursor cu 1 CUI, forma ceruta de ANAF_SincronWebService_PlatitorTva (scan pe cod_fiscal) --
IF USED('crsCuiMargine')
USE IN crsCuiMargine
ENDIF
CREATE CURSOR crsCuiMargine (cod_fiscal C(30))
INSERT INTO crsCuiMargine VALUES (lcCui)
* -- 5 date de proba: inceput (ambele inclusiv, trebuie sa fie de acord), o zi inainte de sfarsit
* (interior, trebuie sa fie de acord), EXACT sfarsitul (marginea disputata - divergenta ASTEPTATA),
* o zi dupa sfarsit (trebuie sa fie de acord) --
IF USED('crsProbeMargine')
USE IN crsProbeMargine
ENDIF
CREATE CURSOR crsProbeMargine (eticheta C(30), proba D, asteptare C(20))
INSERT INTO crsProbeMargine VALUES ('inceput (inclusiv)', ldInactivare, 'ACORD')
INSERT INTO crsProbeMargine VALUES ('o zi inainte de sfarsit', ldReactivare - 1, 'ACORD')
INSERT INTO crsProbeMargine VALUES ('EXACT sfarsitul (frontiera)', ldReactivare, 'DIVERGENTA')
INSERT INTO crsProbeMargine VALUES ('o zi dupa sfarsit', ldReactivare + 1, 'ACORD')
LOCAL lnTotalProbe, lnAcordCorect, lnFrontieraCorecta, lnNeasteptat
lnTotalProbe = 0
lnAcordCorect = 0
lnFrontieraCorecta = 0
lnNeasteptat = 0
SELECT crsProbeMargine
SCAN
LOCAL lcEticheta, ldProba, lcAsteptare, llCacheInactiv, llCacheAbtine, llMockInactiv
lcEticheta = eticheta
ldProba = proba
lcAsteptare = asteptare
* -- termen (a): CACHE REAL, formula exclusiva la sfarsit (validare.prg:2697, neschimbata) --
IF USED('crsCacheMargine')
USE IN crsCacheMargine
ENDIF
goVerifMargine.CitesteIstoricPentruCoduri(lcCui, ldProba, 'crsCacheMargine')
llCacheAbtine = .T.
llCacheInactiv = .F.
IF USED('crsCacheMargine')
SELECT crsCacheMargine
LOCATE FOR cui = lnCui
IF FOUND()
llCacheAbtine = .F.
llCacheInactiv = inactiv
ENDIF
ENDIF
* -- termen (b): MOCK/"ANAF", PropBool reparat (BETWEEN inclusiv, fara sa copieze cache-ul) --
IF USED('crsMockRezMargine')
USE IN crsMockRezMargine
ENDIF
goVerifMargine.ANAF_SincronWebService_PlatitorTva('crsCuiMargine', ldProba, 'crsMockRezMargine')
llMockInactiv = .F.
IF USED('crsMockRezMargine')
SELECT crsMockRezMargine
LOCATE FOR cui = lnCui
IF FOUND()
llMockInactiv = inactiv
ENDIF
ENDIF
lnTotalProbe = lnTotalProbe + 1
*!* 01.08.2026 marius.mutu: ALLTRIM inainte de == - campul asteptare e C(20), padding-ul stricase comparatia (toate randurile cadeau pe ramura ACORD)
IF ALLTRIM(lcAsteptare) == 'DIVERGENTA'
DO CASE
CASE llCacheAbtine
lnNeasteptat = lnNeasteptat + 1
DO WriteTestLogMargine WITH ' ' + lcEticheta + ' (' + DTOC(ldProba) + '): NEASTEPTAT - cache s-a abtinut, nu mai poate fi comparat'
CASE !llCacheInactiv AND llMockInactiv
* exact divergenta prezisa: cache (sfarsit exclusiv) = NU mai e inactiv; mock (inclusiv) = INCA inactiv
lnFrontieraCorecta = lnFrontieraCorecta + 1
DO WriteTestLogMargine WITH ' ' + lcEticheta + ' (' + DTOC(ldProba) + '): DIVERGENTA CONFIRMATA (asteptata) - cache(inactiv=' + TRANSFORM(llCacheInactiv) + ', sfarsit exclusiv) mock(inactiv=' + TRANSFORM(llMockInactiv) + ', sfarsit inclusiv) - marginea ramane neverificata fata de ANAF real, vezi antetul fisierului'
OTHERWISE
lnNeasteptat = lnNeasteptat + 1
DO WriteTestLogMargine WITH ' ' + lcEticheta + ' (' + DTOC(ldProba) + '): NEASTEPTAT - cache(inactiv=' + TRANSFORM(llCacheInactiv) + ') mock(inactiv=' + TRANSFORM(llMockInactiv) + ') nu (mai) corespunde formulelor cunoscute'
ENDCASE
ELSE
IF !llCacheAbtine AND (llCacheInactiv == llMockInactiv)
lnAcordCorect = lnAcordCorect + 1
DO WriteTestLogMargine WITH ' ' + lcEticheta + ' (' + DTOC(ldProba) + '): ACORD (asteptat) - cache(inactiv=' + TRANSFORM(llCacheInactiv) + ') mock(inactiv=' + TRANSFORM(llMockInactiv) + ')'
ELSE
lnNeasteptat = lnNeasteptat + 1
DO WriteTestLogMargine WITH ' ' + lcEticheta + ' (' + DTOC(ldProba) + '): NEASTEPTAT - cache abtine=' + TRANSFORM(llCacheAbtine) + ' cache(inactiv=' + TRANSFORM(llCacheInactiv) + ') mock(inactiv=' + TRANSFORM(llMockInactiv) + ')'
ENDIF
ENDIF
IF USED('crsCacheMargine')
USE IN crsCacheMargine
ENDIF
IF USED('crsMockRezMargine')
USE IN crsMockRezMargine
ENDIF
SELECT crsProbeMargine
ENDSCAN
DO WriteTestLogMargine WITH 'REZULTAT: total=' + TRANSFORM(lnTotalProbe) + ' acord-in-interior=' + TRANSFORM(lnAcordCorect) + '/3 (asteptat 3)' + ;
' divergenta-la-frontiera=' + TRANSFORM(lnFrontieraCorecta) + '/1 (asteptat 1 - marginea ramane neverificata fata de ANAF real)' + ;
' neasteptat=' + TRANSFORM(lnNeasteptat) + ' (asteptat 0)'
DO CurataIstoricMargine
DO WriteTestLogMargine WITH 'GATA'
QUIT
PROCEDURE WriteTestLogMargine
LPARAMETERS tcMesaj
STRTOFILE(TTOC(DATETIME()) + ' ' + tcMesaj + CHR(13)+CHR(10), gcTestLog, 1)
ENDPROC
PROCEDURE VpaErrMargine
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO WriteTestLogMargine WITH 'ON ERROR nEroare=' + TRANSFORM(tnErr) + ' mesaj=' + tcMsg + ' program=' + tcProg + ' linia=' + TRANSFORM(tnLine)
ENDPROC
*-- 'YYYY-MM-DD' (formatul mock-ului ANAF, mock_batch_anaf.prg) dintr-o Date VFP; data goala -> '' --
PROCEDURE DtoisoMargine
LPARAMETERS tdVal
IF EMPTY(tdVal)
RETURN ''
ENDIF
RETURN LEFT(DTOS(tdVal),4) + '-' + SUBSTR(DTOS(tdVal),5,2) + '-' + SUBSTR(DTOS(tdVal),7,2)
ENDPROC
*-- sterge DOAR CUI-ul de test al acestui fisier din ISTORIC_CODURI_FISCALE --
PROCEDURE CurataIstoricMargine
LOCAL lnSterse
*!* 01.08.2026 marius.mutu: watermark invalid - nu sterg nimic (fara el, DELETE ar lovi tot istoricul comun)
IF TYPE('gnIdMaxIstoricMargine') <> 'N' OR gnIdMaxIstoricMargine <= 0
DO WriteTestLogMargine WITH 'CurataIstoricMargine: SARIT - watermark invalid, nu sterg nimic'
RETURN
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
lnSterse = goExecutor.oExecuta([DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ] + TRANSFORM(gnIdMaxIstoricMargine) + [ AND COD_FISCAL_N IN (80100377)])
=goExecutor.oExecuta('COMMIT')
DO WriteTestLogMargine WITH 'CurataIstoricMargine: sters=' + TRANSFORM(lnSterse)
ENDPROC

View File

@@ -0,0 +1,185 @@
* test_margine_tvaincasare_frontiera.prg - S13, test de REGRESIE pentru fixul de 01.08.2026 la
* marginea tvaincasare (validare.prg:2708, "nvl(data_sfarsit_tvainc - 1, ...)" - acum EXCLUSIV).
* Scris initial (versiune veche, pastrata in istoricul git) ca sa EXPUNA divergenta cache/RTVAI la
* frontiera - a reusit, si a produs sectiunea A-ter din handoff (decizie Marius: cache aliniat la
* conventia -1 folosita deja de pack_roartvai.PartenerInRTVAI). Dupa fix, testul verifica ACORDUL.
*
* CAZUL: CUI real 1768121, o singura perioada RTVAI continua 01.01.2013 -> 01.01.2021, FARA nicio
* reintrare ulterioara in rtvai_istoric (un singur rand I si un singur rand D, nimic dupa). Data
* 01.01.2021 e eveniment real (publicat 15.10.2020, inainte ca importul RTVAI sa moara pe
* 23.10.2020) - nu artefact de import oprit.
*
* Fara CREATEOBJECT/ADDPROPERTY in interiorul unei PROCEDURE (capcana l, depanare_testare_vfp.md) -
* obiectele se construiesc INLINE in programul principal.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcTestLog
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_margine_tvaincasare_frontiera_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcTestLog)
ON ERROR DO VpaErrTvainc WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO WriteTestLogTvainc WITH 'EROARE: conectare Oracle esuata - GATA'
QUIT
ENDIF
DO WriteTestLogTvainc WITH 'mediu OK, schema=' + gcS
*!* 01.08.2026 marius.mutu: watermark pe ID, inainte de orice scriere - garda pt DELETE-ul din CurataIstoricTvaincTest
PUBLIC gnIdMaxIstoricTvainc
gnIdMaxIstoricTvainc = 0
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsWmIstoricTvainc')
SELECT crsWmIstoricTvainc
GO TOP
gnIdMaxIstoricTvainc = IDMAX
USE IN (SELECT('crsWmIstoricTvainc'))
ENDIF
*!* 01.08.2026 marius.mutu: watermark invalid = SELECT esuat - avertisment explicit, stergerile se vor sari
IF gnIdMaxIstoricTvainc <= 0
DO WriteTestLogTvainc WITH 'ATENTIE: watermark invalid (0) - stergerile din ISTORIC_CODURI_FISCALE vor fi SARITE'
ENDIF
DO WriteTestLogTvainc WITH 'watermark ISTORIC_CODURI_FISCALE id_max=' + TRANSFORM(gnIdMaxIstoricTvainc)
PUBLIC goVerifTvainc
goVerifTvainc = CREATEOBJECT('VerificareANAF')
DO CurataIstoricTvaincTest
LOCAL lnCui, ldInceput, ldSfarsit
lnCui = 1768121
ldInceput = {^2013-01-01}
ldSfarsit = {^2021-01-01}
* -- seed cache cu EXACT aceeasi perioada ca in rtvai_istoric (aceeasi forma ca crsANAF) --
IF USED('crsSeedTvainc')
USE IN crsSeedTvainc
ENDIF
CREATE CURSOR crsSeedTvainc (cui N(13), data D, denumire V(100), firma V(100), adresa C(244), nrRegCom C(30), ;
scpTVA L, data_inceput_ScpTVA D, data_sfarsit_ScpTVA D, data_anul_imp_ScpTVA D, mesaj_ScpTVA C(244), ;
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, ;
dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
dataInceputSplitTVA D, dataAnulareSplitTVA D, tva L, tvaincasare L, splittva L, inactiv L, ;
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
sursa C(20), data_sursa D)
INSERT INTO crsSeedTvainc (cui, data, dataInceputTvaInc, dataSfarsitTvaInc, tvaincasare) ;
VALUES (lnCui, DATE(), ldInceput, ldSfarsit, .T.)
goVerifTvainc.SalveazaIstoricDinCursor('crsSeedTvainc', gnIdUtil)
USE IN crsSeedTvainc
DO WriteTestLogTvainc WITH 'seed cache: cui=' + TRANSFORM(lnCui) + ' dataInceputTvaInc=' + DTOC(ldInceput) + ' dataSfarsitTvaInc=' + DTOC(ldSfarsit)
* -- 4 date de proba: interior, o zi inainte de sfarsit, EXACT sfarsitul (marginea care era
* divergenta inainte de fix), o zi dupa sfarsit - toate patru trebuie ACORD dupa fix --
IF USED('crsProbeTvainc')
USE IN crsProbeTvainc
ENDIF
CREATE CURSOR crsProbeTvainc (eticheta C(40), proba D, asteptare C(20))
INSERT INTO crsProbeTvainc VALUES ('interior (8 ani in perioada)', {^2020-01-01}, 'ACORD')
INSERT INTO crsProbeTvainc VALUES ('o zi inainte de sfarsit', ldSfarsit - 1, 'ACORD')
INSERT INTO crsProbeTvainc VALUES ('EXACT sfarsitul (frontiera)', ldSfarsit, 'ACORD')
INSERT INTO crsProbeTvainc VALUES ('o zi dupa sfarsit', ldSfarsit + 1, 'ACORD')
LOCAL lnTotalProbe, lnAcordCorect, lnNeasteptat
lnTotalProbe = 0
lnAcordCorect = 0
lnNeasteptat = 0
SELECT crsProbeTvainc
SCAN
LOCAL lcEticheta, ldProba, lcAsteptare, llCacheTvainc, llCacheAbtine, lnRtvaiVal
lcEticheta = eticheta
ldProba = proba
lcAsteptare = asteptare
* -- termen (a): CACHE REAL, formula acum exclusiva (validare.prg:2708, "- 1", fixul de 01.08.2026) --
IF USED('crsCacheTvainc')
USE IN crsCacheTvainc
ENDIF
goVerifTvainc.CitesteIstoricPentruCoduri(TRANSFORM(lnCui), ldProba, 'crsCacheTvainc')
llCacheAbtine = .T.
llCacheTvainc = .F.
IF USED('crsCacheTvainc')
SELECT crsCacheTvainc
LOCATE FOR cui = lnCui
IF FOUND()
llCacheAbtine = .F.
llCacheTvainc = tvaincasare
ENDIF
ENDIF
* -- termen (c): RTVAI REAL, pack_roartvai.PartenerInRTVAI (neschimbata, foloseste -1 la sfarsit) --
lnRtvaiVal = ObtineVerdictRTVAITvainc(lnCui, ldProba)
lnTotalProbe = lnTotalProbe + 1
IF !llCacheAbtine AND (IIF(llCacheTvainc,1,0) = lnRtvaiVal)
lnAcordCorect = lnAcordCorect + 1
DO WriteTestLogTvainc WITH ' ' + lcEticheta + ' (' + DTOC(ldProba) + '): ACORD (asteptat) - cache(tvaincasare=' + TRANSFORM(llCacheTvainc) + ') rtvai=' + TRANSFORM(lnRtvaiVal)
ELSE
lnNeasteptat = lnNeasteptat + 1
DO WriteTestLogTvainc WITH ' ' + lcEticheta + ' (' + DTOC(ldProba) + '): NEASTEPTAT - cache abtine=' + TRANSFORM(llCacheAbtine) + ' cache(tvaincasare=' + TRANSFORM(llCacheTvainc) + ') rtvai=' + TRANSFORM(lnRtvaiVal)
ENDIF
IF USED('crsCacheTvainc')
USE IN crsCacheTvainc
ENDIF
SELECT crsProbeTvainc
ENDSCAN
DO WriteTestLogTvainc WITH 'REZULTAT: total=' + TRANSFORM(lnTotalProbe) + ' acord=' + TRANSFORM(lnAcordCorect) + '/4 (asteptat 4 - regresie fix, inclusiv EXACT sfarsitul)' + ;
' neasteptat=' + TRANSFORM(lnNeasteptat) + ' (asteptat 0)'
DO CurataIstoricTvaincTest
DO WriteTestLogTvainc WITH 'GATA'
QUIT
*-- verdict "TVA la incasare la data D" din rtvai_istoric COMPLET (istoricul importat, nu ANAF),
*-- prin procedura Oracle REALA pack_roartvai.PartenerInRTVAI (neschimbata) - aceeasi ca in
*-- test_echivalenta_cache_rtvai.prg::ObtineVerdictRTVAI --
PROCEDURE ObtineVerdictRTVAITvainc
LPARAMETERS tnCui, tdData
PRIVATE pnCodFiscal, pdData, pcDenumire, pnRTVAI
pnCodFiscal = tnCui
pdData = tdData
pcDenumire = ''
pnRTVAI = 0
LOCAL lcSql
lcSql = [begin pack_roartvai.PartenerInRTVAI(?pnCodFiscal, ?pdData, ?@pcDenumire, ?@pnRTVAI); end;]
IF !goExecutor.oExecuta(lcSql)
RETURN -1
ENDIF
RETURN pnRTVAI
ENDPROC
PROCEDURE WriteTestLogTvainc
LPARAMETERS tcMesaj
STRTOFILE(TTOC(DATETIME()) + ' ' + tcMesaj + CHR(13)+CHR(10), gcTestLog, 1)
ENDPROC
PROCEDURE VpaErrTvainc
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO WriteTestLogTvainc WITH 'ON ERROR nEroare=' + TRANSFORM(tnErr) + ' mesaj=' + tcMsg + ' program=' + tcProg + ' linia=' + TRANSFORM(tnLine)
ENDPROC
*-- sterge DOAR CUI-ul de test al acestui fisier din ISTORIC_CODURI_FISCALE --
PROCEDURE CurataIstoricTvaincTest
LOCAL lnSterse
*!* 01.08.2026 marius.mutu: watermark invalid - nu sterg nimic (fara el, DELETE ar lovi tot istoricul comun)
IF TYPE('gnIdMaxIstoricTvainc') <> 'N' OR gnIdMaxIstoricTvainc <= 0
DO WriteTestLogTvainc WITH 'CurataIstoricTvaincTest: SARIT - watermark invalid, nu sterg nimic'
RETURN
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
lnSterse = goExecutor.oExecuta([DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ] + TRANSFORM(gnIdMaxIstoricTvainc) + [ AND COD_FISCAL_N IN (1768121)])
=goExecutor.oExecuta('COMMIT')
DO WriteTestLogTvainc WITH 'CurataIstoricTvaincTest: sters=' + TRANSFORM(lnSterse)
ENDPROC

View File

@@ -0,0 +1,494 @@
* test_mock_batch_anaf_demo.prg - test demonstrativ headless pentru mock_batch_anaf.prg (poveste S11).
* Verifica cele 6 scenarii cerute (lot complet, lot partial, lot integral notFound, tacere, raspuns
* neinteles, HTTP 404 cu corp complet) plus acumularea pe mai multe grupuri (>100 coduri) si contorul
* de apeluri/CUI-uri trimise (esential pentru S6). Fara retea, fara UI - doar clasa VerificareANAFMockBatch
* si cursorul crsANAF rezultat.
*
* CONTRACT ACTUALIZAT 31.07.2026 (dupa S6): la tacere/raspuns neinteles/gate 404, cursorul de iesire
* se creeaza INTOTDEAUNA (plasa de siguranta din VerificaListaCIF cheama necondiionat
* CitesteIstoricPentruCoduri) - absenta datelor se exprima prin RECCOUNT=0, nu prin !USED(). Scenariile
* 4/5/6 si noul 4b verifica asta explicit; niciun apelant real nu distingea intre cursor-lipsa si
* cursor-gol (toti fac USED()+SCAN sau USED()+RECCOUNT), deci schimbarea de contract e sigura -
* decizie orchestrator, vezi docs\diff-S14b-validare-traseu.md si docs\diff-S14c-teste-s11.md.
* IMPORTANT (capcana l, COMUN\docs\depanare_testare_vfp.md): CREATEOBJECT/ADDPROPERTY apelate dintr-o
* PROCEDURE/FUNCTION se comporta gresit in acest runtime headless. Tot ce construieste obiecte de
* configurare (Empty+AddProperty, Collection) sta in programul PRINCIPAL, fara nicio DO catre un helper -
* de aceea scriptul e "plat" (fara PROCEDURE-uri de scenariu), doar cu bannere de comentarii intre
* scenarii; singurele PROCEDURE-uri sunt WriteTestLog si VpaErr (fara CREATEOBJECT in interior).
*
* Ordinea SET PROCEDURE e INVERSA fata de mock_anaf_verificare.prg (partener_anaf): acolo mock-ul
* trebuia incarcat PRIMUL, ca sa castige coliziunea de nume de FUNCTION. Aici nu exista coliziune de
* nume (VerificareANAFMockBatch != VerificareANAF) - clasa mea e o SUBCLASA si are nevoie ca parintele
* VerificareANAF sa fie deja definit (validare.prg, incarcat de test_init_env_auto), deci mock_batch_anaf.prg
* se incarca DUPA test_init_env_auto.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcTestLog, gnTestOk, gnTestTotal
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_mock_batch_anaf_demo_log.txt"
gnTestOk = 0
gnTestTotal = 0
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcTestLog)
ON ERROR DO VpaErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO WriteTestLog WITH 'EROARE: conectare Oracle esuata - GATA'
QUIT
ENDIF
DO WriteTestLog WITH 'mediu OK, schema=' + gcS
*!* 01.08.2026 marius.mutu: watermark pe ID, inainte de orice scriere - garda pt DELETE-ul din CurataIstoricTest
PUBLIC gnIdMaxIstoricTest
gnIdMaxIstoricTest = 0
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsWmIstoricTest')
SELECT crsWmIstoricTest
GO TOP
gnIdMaxIstoricTest = IDMAX
USE IN (SELECT('crsWmIstoricTest'))
ENDIF
*!* 01.08.2026 marius.mutu: watermark invalid = SELECT esuat - avertisment explicit, stergerile se vor sari
IF gnIdMaxIstoricTest <= 0
DO WriteTestLog WITH 'ATENTIE: watermark invalid (0) - stergerile din ISTORIC_CODURI_FISCALE vor fi SARITE'
ENDIF
DO WriteTestLog WITH 'watermark ISTORIC_CODURI_FISCALE id_max=' + TRANSFORM(gnIdMaxIstoricTest)
*-- S4 a adaugat, la finalul VerificaListaCIF, scrierea in ISTORIC_CODURI_FISCALE
*-- (SalveazaIstoricDinCursor) - curatenie ACUM, ca sa nu depindem de o rulare anterioara
*-- intrerupta (nu exista cand a fost scris testul initial, S4 a venit dupa).
DO CurataIstoricTest
*-- mock-ul e o SUBCLASA a VerificareANAF (validare.prg) - se incarca DUPA test_init_env_auto (vezi antet)
SET PROCEDURE TO "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\mock_batch_anaf.prg" ADDITIVE
DO WriteTestLog WITH 'mock_batch_anaf.prg incarcat'
PUBLIC goANAFBatchMock, goANAFBatchScenariuPerGrup, gcANAFBatchScenariu, glANAFBatchIgnoraGate404
PUBLIC gnANAFBatchApeluri, gcANAFBatchCuiuriTrimise
goANAFBatchMock = CREATEOBJECT('Collection')
goANAFBatchScenariuPerGrup = CREATEOBJECT('Collection')
gcANAFBatchScenariu = 'NORMAL'
glANAFBatchIgnoraGate404 = .F.
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
PUBLIC goMockANAF
goMockANAF = CREATEOBJECT('VerificareANAFMockBatch')
TRY
*=========================================================================
* Scenariul 1: lot COMPLET - toate cele 3 CUI-uri configurate, gasite la ANAF
*=========================================================================
goANAFBatchMock = CREATEOBJECT('Collection')
LOCAL loR1, loR2, loR3
loR1 = CREATEOBJECT('Empty')
ADDPROPERTY(loR1, 'denumire', 'ALFA PLATITOR SRL')
ADDPROPERTY(loR1, 'scpTVA', .T.)
ADDPROPERTY(loR1, 'dataInceputScpTVA', '2020-01-01')
goANAFBatchMock.Add(loR1, 'C1000001')
loR2 = CREATEOBJECT('Empty')
ADDPROPERTY(loR2, 'denumire', 'BETA INACTIV SRL')
ADDPROPERTY(loR2, 'inactiv', .T.)
ADDPROPERTY(loR2, 'dataInactivare', '2021-06-15')
goANAFBatchMock.Add(loR2, 'C1000002')
loR3 = CREATEOBJECT('Empty')
ADDPROPERTY(loR3, 'denumire', 'GAMA SPLITTVA SRL')
ADDPROPERTY(loR3, 'splitTva', .T.)
ADDPROPERTY(loR3, 'dataInceputSplitTVA', '2022-03-01')
ADDPROPERTY(loR3, 'tvaIncasare', .T.)
ADDPROPERTY(loR3, 'dataInceputTvaInc', '2022-03-01')
goANAFBatchMock.Add(loR3, 'C1000003')
IF USED('cLotComplet')
USE IN cLotComplet
ENDIF
CREATE CURSOR cLotComplet (cod_fiscal C(30))
INSERT INTO cLotComplet (cod_fiscal) VALUES ('1000001')
INSERT INTO cLotComplet (cod_fiscal) VALUES ('1000002')
INSERT INTO cLotComplet (cod_fiscal) VALUES ('1000003')
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
IF USED('crsLotComplet')
USE IN crsLotComplet
ENDIF
LOCAL lcRezAlias
lcRezAlias = goMockANAF.VerificaListaCIF('cLotComplet', DATE(), 'crsLotComplet')
IF USED('crsLotComplet') AND RECCOUNT('crsLotComplet') = 3
SELECT crsLotComplet
LOCATE FOR cui = 1000001
LOCAL llOk1
llOk1 = FOUND() AND ALLTRIM(denumire) == 'ALFA PLATITOR SRL' AND tva AND !inactiv
LOCATE FOR cui = 1000002
llOk1 = llOk1 AND FOUND() AND inactiv AND !tva
LOCATE FOR cui = 1000003
llOk1 = llOk1 AND FOUND() AND splittva AND tvaincasare
IF llOk1 AND gnANAFBatchApeluri = 1 AND gcANAFBatchCuiuriTrimise == '1000001,1000002,1000003'
DO VerificaTrece WITH 'lot-complet', '3 randuri corecte (tva/inactiv/splittva), 1 apel, cuiuri=' + gcANAFBatchCuiuriTrimise
ELSE
DO VerificaCade WITH 'lot-complet', 'campuri gresite sau contor apeluri=' + TRANSFORM(gnANAFBatchApeluri) + ' cuiuri=[' + gcANAFBatchCuiuriTrimise + ']'
ENDIF
ELSE
DO VerificaCade WITH 'lot-complet', 'cursor lipsa sau numar randuri gresit (asteptat 3)'
ENDIF
*=========================================================================
* Scenariul 2: lot PARTIAL - 2 gasite, 1 explicit NOTFOUND
*=========================================================================
goANAFBatchMock = CREATEOBJECT('Collection')
LOCAL loR4, loR5
loR4 = CREATEOBJECT('Empty')
ADDPROPERTY(loR4, 'denumire', 'DELTA GASIT SRL')
ADDPROPERTY(loR4, 'scpTVA', .T.)
goANAFBatchMock.Add(loR4, 'C1000004')
loR5 = CREATEOBJECT('Empty')
ADDPROPERTY(loR5, 'denumire', 'EPSILON GASIT SRL')
goANAFBatchMock.Add(loR5, 'C1000005')
goANAFBatchMock.Add('NOTFOUND', 'C1000006')
IF USED('cLotPartial')
USE IN cLotPartial
ENDIF
CREATE CURSOR cLotPartial (cod_fiscal C(30))
INSERT INTO cLotPartial (cod_fiscal) VALUES ('1000004')
INSERT INTO cLotPartial (cod_fiscal) VALUES ('1000005')
INSERT INTO cLotPartial (cod_fiscal) VALUES ('1000006')
IF USED('crsLotPartial')
USE IN crsLotPartial
ENDIF
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
lcRezAlias = goMockANAF.VerificaListaCIF('cLotPartial', DATE(), 'crsLotPartial')
IF USED('crsLotPartial') AND RECCOUNT('crsLotPartial') = 3
SELECT crsLotPartial
LOCATE FOR cui = 1000004
LOCAL llOk2
llOk2 = FOUND() AND ALLTRIM(denumire) == 'DELTA GASIT SRL'
LOCATE FOR cui = 1000006
llOk2 = llOk2 AND FOUND() AND EMPTY(denumire)
IF llOk2
DO VerificaTrece WITH 'lot-partial', '3 randuri (2 cu date, 1 doar cu cui negasit)'
ELSE
DO VerificaCade WITH 'lot-partial', 'randuri lipsa sau campuri gresite'
ENDIF
ELSE
DO VerificaCade WITH 'lot-partial', 'cursor lipsa sau numar randuri gresit (asteptat 3)'
ENDIF
*=========================================================================
* Scenariul 3: lot INTEGRAL notFound - niciun CUI configurat (cazul care azi
* deschide fereastra de eroare la validare.prg:1986-1994, pe traseul real)
*=========================================================================
goANAFBatchMock = CREATEOBJECT('Collection')
IF USED('cLotNotfound')
USE IN cLotNotfound
ENDIF
CREATE CURSOR cLotNotfound (cod_fiscal C(30))
INSERT INTO cLotNotfound (cod_fiscal) VALUES ('1000007')
INSERT INTO cLotNotfound (cod_fiscal) VALUES ('1000008')
IF USED('crsLotNotfound')
USE IN crsLotNotfound
ENDIF
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
lcRezAlias = goMockANAF.VerificaListaCIF('cLotNotfound', DATE(), 'crsLotNotfound')
IF USED('crsLotNotfound') AND RECCOUNT('crsLotNotfound') = 2
SELECT crsLotNotfound
LOCATE FOR cui = 1000007
LOCAL llOk3
llOk3 = FOUND() AND EMPTY(denumire) AND ALLTRIM(sursa) == 'ANAF'
LOCATE FOR cui = 1000008
llOk3 = llOk3 AND FOUND() AND EMPTY(denumire) AND ALLTRIM(sursa) == 'ANAF'
IF llOk3 AND gnANAFBatchApeluri = 1
DO VerificaTrece WITH 'lot-integral-notfound', '2 randuri, doar cui completat, sursa=ANAF (notFound explicit, distinct de tacere - vezi scenariile 4/4b), 1 apel'
ELSE
DO VerificaCade WITH 'lot-integral-notfound', 'randuri gresite'
ENDIF
ELSE
DO VerificaCade WITH 'lot-integral-notfound', 'cursor lipsa sau numar randuri gresit (asteptat 2)'
ENDIF
*=========================================================================
* Scenariul 4: TACERE - fara raspuns folosibil (echivalent unui timeout/exceptie
* la trimitere). CONTRACT NOU (dupa S6): cursorul de iesire se creeaza INTOTDEAUNA
* (plasa de siguranta din VerificaListaCIF cheama necondiionat CitesteIstoricPentruCoduri,
* care face Create Cursor daca alias-ul nu exista deja) - absenta datelor se exprima
* prin RECCOUNT=0 (CUI 1000009 nu are niciodata istoric in acest test), nu prin !USED().
* Toti cei 4 apelanti reali (orapoarte.prg, overificari.vc2, validare.prg:830-831) testeaza
* USED()+SCAN sau USED()+RECCOUNT>=1 - un cursor gol produce acelasi efect practic ca lipsa
* lui, deci schimbarea de contract nu rupe pe nimeni (decizie orchestrator 31.07.2026).
*=========================================================================
goANAFBatchMock = CREATEOBJECT('Collection')
gcANAFBatchScenariu = 'TACERE'
IF USED('cLotTacere')
USE IN cLotTacere
ENDIF
CREATE CURSOR cLotTacere (cod_fiscal C(30))
INSERT INTO cLotTacere (cod_fiscal) VALUES ('1000009')
IF USED('crsLotTacere')
USE IN crsLotTacere
ENDIF
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
lcRezAlias = goMockANAF.VerificaListaCIF('cLotTacere', DATE(), 'crsLotTacere')
IF USED('crsLotTacere') AND RECCOUNT('crsLotTacere') = 0 AND gnANAFBatchApeluri = 1 AND gcANAFBatchCuiuriTrimise == '1000009'
DO VerificaTrece WITH 'tacere', 'cursor creat dar gol (Reccount=0, 1000009 fara istoric) - contract nou S6; apelul (grupul) tot s-a incercat (apeluri=1, cui trimis)'
ELSE
DO VerificaCade WITH 'tacere', 'cursor/randuri neasteptate (used=' + TRANSFORM(USED('crsLotTacere')) + ' reccount=' + TRANSFORM(IIF(USED('crsLotTacere'), RECCOUNT('crsLotTacere'), -1)) + ') sau contor gresit (apeluri=' + TRANSFORM(gnANAFBatchApeluri) + ')'
ENDIF
gcANAFBatchScenariu = 'NORMAL'
*=========================================================================
* Scenariul 4b: TACERE + ISTORIC EXISTENT - demonstreaza ca distinctia tacere vs.
* cod inexistent confirmat de ANAF (notFound, scenariul 3) tot se poate observa dupa
* schimbarea de contract de mai sus, desi ambele produc acum un cursor: prin campul
* `sursa`. CUI 1000012 seedat manual in ISTORIC_CODURI_FISCALE (istoric real, nu prin
* ANAF) - la tacere, plasa de siguranta il gaseste si completeaza randul cu
* sursa='CACHE_INDISP' si denumirea din istoric; scenariul 3 (notFound explicit)
* produce sursa='ANAF' cu denumire goala. Fara istoric (scenariul 4, CUI 1000009):
* niciun rand deloc pentru acel cui - a treia stare, tot distincta.
*=========================================================================
LOCAL lcSqlSeed4b
lcSqlSeed4b = [insert into istoric_coduri_fiscale (dataora, id_util, dataorav, id_utilv, ] + ;
[cod_fiscal, firma, cod_fiscal_n, dataorav_anaf, inactiv, tvaincasare, splittva, ] + ;
[data_inceput_tvainc, data_sfarsit_tvainc) values (sysdate, ] + TRANSFORM(gnIdUtil) + ;
[, sysdate, ] + TRANSFORM(gnIdUtil) + [, '1000012', 'ETA TACERE CACHE SRL', 1000012, ] + ;
[sysdate, 0, 1, 0, to_date('2015-01-01','yyyy-mm-dd'), null)]
=goExecutor.oExecuta(m.lcSqlSeed4b)
=goExecutor.oExecuta('COMMIT')
goANAFBatchMock = CREATEOBJECT('Collection')
gcANAFBatchScenariu = 'TACERE'
IF USED('cLotTacere4b')
USE IN cLotTacere4b
ENDIF
CREATE CURSOR cLotTacere4b (cod_fiscal C(30))
INSERT INTO cLotTacere4b (cod_fiscal) VALUES ('1000012')
IF USED('crsLotTacere4b')
USE IN crsLotTacere4b
ENDIF
gnANAFBatchApeluri = 0
*-- 'UNIC' forteaza ANAF,CACHE (S14b) - altfel ordinea implicita MASA=CACHE,ANAF ar servi
*-- 1000012 direct din cache INAINTE de ANAF (sursa=CACHE, nu CACHE_INDISP) si TACERE nu s-ar exercita
lcRezAlias = goMockANAF.VerificaListaCIF('cLotTacere4b', DATE(), 'crsLotTacere4b', 'UNIC')
LOCAL llOk4b
llOk4b = .F.
IF USED('crsLotTacere4b') AND RECCOUNT('crsLotTacere4b') = 1
SELECT crsLotTacere4b
LOCATE FOR cui = 1000012
llOk4b = FOUND() AND ALLTRIM(sursa) == 'CACHE_INDISP' AND ALLTRIM(denumire) == 'ETA TACERE CACHE SRL' AND !EMPTY(data_sursa)
ENDIF
IF llOk4b
DO VerificaTrece WITH 'tacere-cu-istoric-distinct-de-notfound', 'CUI cu istoric la tacere -> 1 rand, sursa=CACHE_INDISP, denumire din istoric - distinct de notFound (sursa=ANAF, scenariul 3) si de tacere fara istoric (0 randuri, scenariul 4)'
ELSE
DO VerificaCade WITH 'tacere-cu-istoric-distinct-de-notfound', 'randul CACHE_INDISP asteptat nu a aparut corect (used=' + TRANSFORM(USED('crsLotTacere4b')) + ')'
ENDIF
gcANAFBatchScenariu = 'NORMAL'
*=========================================================================
* Scenariul 5: RASPUNS NEINTELES - raspuns primit dar nu porneste cu '{' (corp
* nevalid); acelasi efect ca tacerea (cursor gol via RECCOUNT=0), dar cod de
* scenariu distinct. CONTRACT NOU (dupa S6): vezi Scenariul 4.
*=========================================================================
gcANAFBatchScenariu = 'RASPUNS_NEINTELES'
IF USED('crsLotTacere')
USE IN crsLotTacere
ENDIF
gnANAFBatchApeluri = 0
lcRezAlias = goMockANAF.VerificaListaCIF('cLotTacere', DATE(), 'crsLotTacere')
IF USED('crsLotTacere') AND RECCOUNT('crsLotTacere') = 0 AND gnANAFBatchApeluri = 1
DO VerificaTrece WITH 'raspuns-neinteles', 'cursor creat dar gol (Reccount=0, scenariu distinct de tacere, acelasi efect) - contract nou S6'
ELSE
DO VerificaCade WITH 'raspuns-neinteles', 'cursor/randuri neasteptate (used=' + TRANSFORM(USED('crsLotTacere')) + ' reccount=' + TRANSFORM(IIF(USED('crsLotTacere'), RECCOUNT('crsLotTacere'), -1)) + ')'
ENDIF
gcANAFBatchScenariu = 'NORMAL'
*=========================================================================
* Scenariul 6: HTTP 404 cu corp COMPLET {"found":[],"notFound":[<cui>]} -
* AZI corpul e ignorat (gate "Status = 200", validare.prg:1968); cu
* glANAFBatchIgnoraGate404 = .T. se simuleaza fixul propus pentru S5
*=========================================================================
goANAFBatchMock = CREATEOBJECT('Collection')
LOCAL loR404
loR404 = CREATEOBJECT('Empty')
ADDPROPERTY(loR404, 'denumire', 'ZETA 404 SRL')
goANAFBatchMock.Add(loR404, 'C1000010')
goANAFBatchMock.Add('NOTFOUND', 'C1000011')
IF USED('cLot404')
USE IN cLot404
ENDIF
CREATE CURSOR cLot404 (cod_fiscal C(30))
INSERT INTO cLot404 (cod_fiscal) VALUES ('1000010')
INSERT INTO cLot404 (cod_fiscal) VALUES ('1000011')
gcANAFBatchScenariu = 'HTTP404_CORP_COMPLET'
glANAFBatchIgnoraGate404 = .F.
IF USED('crsLot404')
USE IN crsLot404
ENDIF
lcRezAlias = goMockANAF.VerificaListaCIF('cLot404', DATE(), 'crsLot404')
LOCAL llOk6a
*-- contract nou S6: cursor creat dar gol (0 randuri, 1000010/1000011 fara istoric), nu absent
llOk6a = USED('crsLot404') AND RECCOUNT('crsLot404') = 0
glANAFBatchIgnoraGate404 = .T.
IF USED('crsLot404')
USE IN crsLot404
ENDIF
lcRezAlias = goMockANAF.VerificaListaCIF('cLot404', DATE(), 'crsLot404')
LOCAL llOk6b
llOk6b = USED('crsLot404') AND RECCOUNT('crsLot404') = 2
IF m.llOk6a AND m.llOk6b
DO VerificaTrece WITH 'http-404-corp-complet', 'gate AZI ignora corpul (0 randuri); cu glANAFBatchIgnoraGate404=.T. (fixture S5) parseaza 2 randuri'
ELSE
DO VerificaCade WITH 'http-404-corp-complet', 'gate-azi=' + TRANSFORM(m.llOk6a) + ' fixture-viitor=' + TRANSFORM(m.llOk6b)
ENDIF
gcANAFBatchScenariu = 'NORMAL'
glANAFBatchIgnoraGate404 = .F.
*=========================================================================
* Scenariul 7: GRUPURI MULTIPLE (>100 coduri) - 101 CUI-uri intr-un singur apel
* -> 2 grupuri (100 + 1); primul override 'TACERE' pe grupul 2 (S4: acumulare in
* cursor pe mai multe grupuri, dar contorul de apeluri/cuiuri numara AMBELE grupuri
* chiar daca al doilea nu produce randuri)
*=========================================================================
goANAFBatchMock = CREATEOBJECT('Collection')
LOCAL lnG, lcCuiG, loRG
FOR lnG = 1 TO 101
lcCuiG = TRANSFORM(2000000 + lnG)
loRG = CREATEOBJECT('Empty')
ADDPROPERTY(loRG, 'denumire', 'GRUP TEST ' + lcCuiG)
goANAFBatchMock.Add(loRG, 'C' + lcCuiG)
ENDFOR
IF USED('cLotGrupuri')
USE IN cLotGrupuri
ENDIF
CREATE CURSOR cLotGrupuri (cod_fiscal C(30))
FOR lnG = 1 TO 101
INSERT INTO cLotGrupuri (cod_fiscal) VALUES (TRANSFORM(2000000 + lnG))
ENDFOR
goANAFBatchScenariuPerGrup = CREATEOBJECT('Collection')
goANAFBatchScenariuPerGrup.Add('TACERE', '2')
IF USED('crsLotGrupuri')
USE IN crsLotGrupuri
ENDIF
gnANAFBatchApeluri = 0
gcANAFBatchCuiuriTrimise = ''
lcRezAlias = goMockANAF.VerificaListaCIF('cLotGrupuri', DATE(), 'crsLotGrupuri')
LOCAL lnCuiuriTrimise
lnCuiuriTrimise = GETWORDCOUNT(gcANAFBatchCuiuriTrimise, ',')
IF USED('crsLotGrupuri') AND RECCOUNT('crsLotGrupuri') = 100 AND gnANAFBatchApeluri = 2 AND lnCuiuriTrimise = 101
DO VerificaTrece WITH 'grupuri-multiple', '2 grupuri trimise (apeluri=2, cuiuri=101), doar grupul 1 (100) a produs randuri - grupul 2 (TACERE) nu'
ELSE
DO VerificaCade WITH 'grupuri-multiple', 'randuri=' + TRANSFORM(IIF(USED('crsLotGrupuri'), RECCOUNT('crsLotGrupuri'), -1)) + ' apeluri=' + TRANSFORM(gnANAFBatchApeluri) + ' cuiuri=' + TRANSFORM(lnCuiuriTrimise)
ENDIF
goANAFBatchScenariuPerGrup = CREATEOBJECT('Collection')
*=========================================================================
* Scenariul 8: E4 chiar a scris in ISTORIC_CODURI_FISCALE - foloseste randurile
* lasate de Scenariul 1 (lot-complet, CUI 1000001/1000002/1000003), scrise de
* VerificaListaCIF -> SalveazaIstoricDinCursor (validare.prg:1875-1877). Verifica
* atat numarul de randuri cat si ca DATAORAV_ANAF (nu DATAORAV) s-a pus pe azi -
* semnul ca apelul a adus efectiv date de interval (contract-cache-anaf.md 2.3). ATENTIE:
* DATAORAV_ANAF se pune DOAR cand cel putin una din cele 9 date de interval e trimisa, NU
* la simplele flag-uri booleene inactiv/tvaincasare/splittva (decizie S1, motivata in
* docs\diff-S1-oracle-istoric.md ~93-102) - de-asta CUI 1000003 (splitTva/tvaIncasare) are
* si cate o data de inceput in fixture-ul Scenariului 1, nu doar flag-urile goale.
*=========================================================================
LOCAL lnIstoricOk
lnIstoricOk = 0
=goExecutor.oSelect2Value([SELECT COUNT(*) AS NR FROM ISTORIC_CODURI_FISCALE ] + ;
[WHERE DATAORAV_ANAF IS NOT NULL AND TRUNC(DATAORAV_ANAF) = TRUNC(SYSDATE) AND ( ] + ;
[ (COD_FISCAL_N = 1000001 AND NVL(INACTIV,0) = 0) ] + ;
[ OR (COD_FISCAL_N = 1000002 AND NVL(INACTIV,0) = 1) ] + ;
[ OR (COD_FISCAL_N = 1000003 AND NVL(SPLITTVA,0) = 1 AND NVL(TVAINCASARE,0) = 1) )], @lnIstoricOk)
IF m.lnIstoricOk = 3
DO VerificaTrece WITH 'e4-scriere-istoric', '3 randuri in ISTORIC_CODURI_FISCALE cu DATAORAV_ANAF=azi si flag-urile corecte (inactiv/splittva/tvaincasare)'
ELSE
DO VerificaCade WITH 'e4-scriere-istoric', 'randuri gasite=' + TRANSFORM(m.lnIstoricOk) + ' (asteptat 3)'
ENDIF
DO WriteTestLog WITH 'GATA - ' + TRANSFORM(gnTestOk) + '/' + TRANSFORM(gnTestTotal) + ' scenarii PASS'
CATCH TO loExc
DO WriteTestLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
FINALLY
*-- curatenie si la FINAL (inclusiv dupa o eventuala eroare) - fara ea, fiecare
*-- rulare acumuleaza randuri noi in ISTORIC_CODURI_FISCALE (raportat de team-lead,
*-- 110 randuri ramase dupa o singura rulare de regresie S5).
DO CurataIstoricTest
ENDTRY
QUIT
*==================================================================================
PROCEDURE VerificaTrece
LPARAMETERS tcScenariu, tcDetaliu
gnTestTotal = gnTestTotal + 1
gnTestOk = gnTestOk + 1
DO WriteTestLog WITH 'PASS ' + tcScenariu + ': ' + tcDetaliu
ENDPROC
PROCEDURE VerificaCade
LPARAMETERS tcScenariu, tcDetaliu
gnTestTotal = gnTestTotal + 1
DO WriteTestLog WITH 'FAIL ' + tcScenariu + ': ' + tcDetaliu
ENDPROC
PROCEDURE WriteTestLog
LPARAMETERS tcMesaj
STRTOFILE(TTOC(DATETIME()) + ' ' + tcMesaj + CHR(13)+CHR(10), gcTestLog, 1)
ENDPROC
*-- sterge DOAR codurile de test proprii acestui fisier (1000001-1000099, 2000001-2000199) din
*-- ISTORIC_CODURI_FISCALE, scrise de SalveazaIstoricDinCursor (S4) la fiecare VerificaListaCIF.
*-- Fara CREATEOBJECT/ADDPROPERTY in interior - sigur ca PROCEDURE apelata prin DO (capcana l).
*-- Nu atinge 8000xxx/9000xxx (partener_anaf) sau alte coduri din alte suite.
PROCEDURE CurataIstoricTest
LOCAL lnSterse
*!* 01.08.2026 marius.mutu: watermark invalid - nu sterg nimic (fara el, DELETE ar lovi tot istoricul comun)
IF TYPE('gnIdMaxIstoricTest') <> 'N' OR gnIdMaxIstoricTest <= 0
DO WriteTestLog WITH 'CurataIstoricTest: SARIT - watermark invalid, nu sterg nimic'
RETURN
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
lnSterse = goExecutor.oExecuta([DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ] + TRANSFORM(gnIdMaxIstoricTest) + [ AND ] + ;
[((COD_FISCAL_N BETWEEN 1000000 AND 1000099) OR (COD_FISCAL_N BETWEEN 2000000 AND 2000199))])
=goExecutor.oExecuta('COMMIT')
DO WriteTestLog WITH 'CurataIstoricTest: sters=' + TRANSFORM(lnSterse)
ENDPROC
PROCEDURE VpaErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO WriteTestLog WITH 'ON ERROR nEroare=' + TRANSFORM(tnErr) + ' mesaj=' + tcMsg + ' program=' + tcProg + ' linia=' + TRANSFORM(tnLine)
ENDPROC

View File

@@ -0,0 +1,270 @@
* test_regresie_d394_baseline.prg - S13, Testul 2: captureaza baseline-ul D394 (randuri crsJTVA +
* timp) INAINTE de S2, pe o luna REALA deja depusa (MARIUSM_AUTO are un istoric real de facturi,
* 2006-2026 - nu e o schema goala). Luna aleasa: 03/2026 (30 facturi JC, 25 cu cod_fiscal RO, din
* care 2 CUI apar si in rtvai_istoric - vezi docs\diff-S13-teste-echivalenta.md pentru interogarile
* care au ales luna).
*
* S2 (pack_roartvai.PartenerInRTVAI cu precedenta pe istoric) NU e inca aplicata (handoff_cache_anaf.md:
* "MUTARE" in lucru, S2 asteapta rescrierea dupa mutarea tabelei) - nu exista "dupa" de comparat acum.
* Acest script CAPTUREAZA baseline-ul "inainte" si lasa harness-ul gata de rulat identic dupa S2.
*
* Ce face:
* 1. Reconstruieste manual setup-ul clasei D394_2025 (oUnitate + cursoarele create in ::List(),
* Programe\oproceduri_decont.prg:8366-8517), FARA formularul modal (frm_decl394_2025.Show(1)
* ar bloca headless) si FARA scrie_optiune (evita scrieri in OPTIUNI, tabela partajata cu alte
* povesti care ruleaza in paralel pe aceeasi schema).
* 2. Cheama This.citeste_date_jtva() si This.configureaza_date_jtva() - PIPELINE REAL, neschimbat -
* configureaza_date_jtva contine Update-ul per-rand cu VERIFICA_RTVAI_DATA (oproceduri_decont.prg:8929),
* exact linia pe care S2 o afecteaza indirect (schimba raspunsul lui pack_roartvai.PartenerInRTVAI,
* apelat de VERIFICA_RTVAI_DATA din oproceduri_comune.prg:5126).
* 3. Continua cu sectiunile 1_2/4_5/6/7/amef - pipeline-ul complet, ca sa poata compara si acolo.
* 4. Masoara timpul separat per etapa (citeste/configureaza/sectiuni), nu doar total.
* 5. Exporta CRSJTVA complet (COPY TO .dbf) - fisier baseline langa acest script, comparabil rand
* cu rand (dupa SEQ) cu o rulare identica de dupa S2.
*
* NU modifica oproceduri_decont.prg (nu e fisierul meu - D394_2025 nu apare in nicio banda din
* stories-cache-anaf.md). Foloseste doar metode publice existente, neschimbate.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcTestLog
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_regresie_d394_baseline_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcTestLog)
ON ERROR DO VpaErrD394 WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT', 2026, 3
IF gnHandle <= 0
DO WriteTestLogD394 WITH 'EROARE: conectare Oracle esuata - GATA'
QUIT
ENDIF
DO WriteTestLogD394 WITH 'mediu OK, schema=' + gcS + ' gnAn=' + TRANSFORM(gnAn) + ' gnLuna=' + TRANSFORM(gnLuna)
LOCAL loD394
loD394 = CREATEOBJECT('D394_2025')
* --- reconstructie manuala a setup-ului din D394_2025::List() (oproceduri_decont.prg:8366-8517),
* FARA formular si FARA scrie_optiune ---
* pounitate trebuie PRIVATE (nu Local) - pregateste_sectiunea_amef (:9395) o refera direct intr-un
* SELECT nativ VFP ca 'pounitate.nramef'; VFP rezolva asta doar daca variabila e vizibila in josul
* stivei de apeluri (Private), exact ca la capcana 2 din handoff_cache_anaf.md (SQL Oracle cu ?)
PRIVATE pounitate
pounitate = CREATEOBJECT("empty")
ADDPROPERTY(pounitate, "tva_incasare", goCalendar.tva_incasare)
ADDPROPERTY(pounitate, "an", gnAn)
ADDPROPERTY(pounitate, "luna1", gnLuna)
ADDPROPERTY(pounitate, "luna2", gnLuna)
ADDPROPERTY(pounitate, "tip", 'LUNAR')
ADDPROPERTY(pounitate, "luniextra", 0)
ADDPROPERTY(pounitate, "tvanedeductibil", 0)
ADDPROPERTY(pounitate, "codi", STRTRAN(STRTRAN(ALLTRIM(UPPER(NVL(goFirma.cod_fiscal, ''))), 'RO', ''), 'R', ''))
ADDPROPERTY(pounitate, "deni", NVL(ALLTRIM(goFirma.firma), ''))
ADDPROPERTY(pounitate, "adr", NVL(ALLTRIM(goFirma.adresa), ''))
pounitate.adr = PADR(pounitate.adr, 150, ' ')
ADDPROPERTY(pounitate, "tel", '')
ADDPROPERTY(pounitate, "fax", '')
ADDPROPERTY(pounitate, "email", '')
ADDPROPERTY(pounitate, "taraR", "")
ADDPROPERTY(pounitate, "codiR", "")
ADDPROPERTY(pounitate, "deniR", "")
ADDPROPERTY(pounitate, "adrR", "")
ADDPROPERTY(pounitate, "telR", "")
ADDPROPERTY(pounitate, "faxR", "")
ADDPROPERTY(pounitate, "emailR", "")
ADDPROPERTY(pounitate, "numeD", "")
ADDPROPERTY(pounitate, "functieD", "")
ADDPROPERTY(pounitate, "operatiuni", 1)
ADDPROPERTY(pounitate, "tvaincasare", goCalendar.tva_incasare)
ADDPROPERTY(pounitate, "nr_facturi_emise", 0)
ADDPROPERTY(pounitate, "nr_facturi_beneficiari", 0)
ADDPROPERTY(pounitate, "nr_facturi_terti", 0)
ADDPROPERTY(pounitate, "lPerioadaDoarRO", .F.)
ADDPROPERTY(pounitate, "ExportSectiuneaI", 1)
ADDPROPERTY(pounitate, "PersoaneAfiliate", 0)
ADDPROPERTY(pounitate, "DenRepr", '')
ADDPROPERTY(pounitate, "AdrRepr", '')
pounitate.AdrRepr = PADR(pounitate.AdrRepr, 150, ' ')
ADDPROPERTY(pounitate, "CuiRepr", '')
ADDPROPERTY(pounitate, "TipRepr", '')
ADDPROPERTY(pounitate, "TelRepr", '')
ADDPROPERTY(pounitate, "FaxRepr", '')
ADDPROPERTY(pounitate, "EmailRepr", '')
ADDPROPERTY(pounitate, "DenIntocmit", '')
ADDPROPERTY(pounitate, "CuiIntocmit", '')
ADDPROPERTY(pounitate, "PJIntocmit", 1)
ADDPROPERTY(pounitate, "CalitateIntocmit", PADR('', 100, ' '))
ADDPROPERTY(pounitate, "Calitate2Intocmit", PADR('', 100, ' '))
ADDPROPERTY(pounitate, "FunctieIntocmit", PADR('', 100, ' '))
ADDPROPERTY(pounitate, "NrAMEF", 1)
ADDPROPERTY(pounitate, "OptiuneANAF", 0)
ADDPROPERTY(pounitate, "cTextFacturiEmiseAlocate", "")
loD394.oUnitate = pounitate
IF USED('crsFdocTip')
USE IN crsFdocTip
ENDIF
CREATE CURSOR crsFdocTip (id_fdoc N(10) null, fel_document c(100) null, tip_doc c(10) Null, bifa N(1))
LOCAL llSucces
llSucces = update_serii(.F., [isautofactura = 1 or isbeneficiari = 1 or isterti = 1 or isfurnizori = 1])
IF !llSucces
IF USED('crsSerii')
USE IN crsSerii
ENDIF
CREATE CURSOR crsSerii (seria c(20), isautofactura N(1), isbeneficiari N(1), isterti N(1), isfurnizori N(1))
ENDIF
IF USED('crsSectiuneaI')
USE IN crsSectiuneaI
ENDIF
CREATE CURSOR crsSectiuneaI (punct c(4) Null, baza N(20) Null, TVA N(20) Null, proctva N(2) Null)
IF USED('crsSectiuneaI4')
USE IN crsSectiuneaI4
ENDIF
CREATE CURSOR crsSectiuneaI4 (punct c(4) Null, TVA21 N(20) Null, TVA11 N(20) Null, TVA19 N(20) Null, TVA09 N(20) Null, TVA05 N(20) Null, TVA24 N(20) Null, TVA20 N(20) Null)
IF USED('crsSectiuneaI6')
USE IN crsSectiuneaI6
ENDIF
CREATE CURSOR crsSectiuneaI6 (punct c(4) Null, incasari N(20) Null, costuri N(20) Null, marja N(20) Null, TVA N(20) Null)
IF USED('crsSectiuneaI7')
USE IN crsSectiuneaI7
ENDIF
CREATE CURSOR crsSectiuneaI7 (caen c(4) Null, TIP c(10), baza N(20), TVA21 N(20) Null, TVA11 N(20) Null, TVA19 N(20) Null, TVA09 N(20) Null, TVA05 N(20) Null, TVA24 N(20) Null, TVA20 N(20) Null)
IF USED('crsFacturiAlocate')
USE IN crsFacturiAlocate
ENDIF
CREATE CURSOR crsFacturiAlocate (seria c(20) Null, nr1 N(20), nr2 N(20))
IF USED('crsFacturiEmise')
USE IN crsFacturiEmise
ENDIF
CREATE CURSOR crsFacturiEmise (seria c(20) Null, nr1 N(20), nr2 N(20))
IF USED('crsFacturiEmiseTip')
USE IN crsFacturiEmiseTip
ENDIF
CREATE CURSOR crsFacturiEmiseTip (TIP c(20), ntip N(1), seria c(20) Null, nr N(20))
IF USED('crsAutoFacturi')
USE IN crsAutoFacturi
ENDIF
CREATE CURSOR crsAutoFacturi (seria c(20) Null, nr N(20), baza21 N(16,4) Null, baza11 N(16,4) Null, baza19 N(16,4) Null, baza09 N(16,4) Null, baza05 N(16,4) Null, baza24 N(16,4) Null, baza20 N(16,4) Null, ;
TVA21 N(16,4) Null, TVA11 N(16,4) Null, TVA19 N(16,4) Null, TVA09 N(16,4) Null, TVA05 N(16,4) Null, TVA24 N(16,4) Null, TVA20 N(16,4) Null)
IF USED('crsFacturiTerti')
USE IN crsFacturiTerti
ENDIF
CREATE CURSOR crsFacturiTerti (punct c(4) Null, seria c(20) Null, nr1 N(20), nr2 N(20), denumire c(100) Null, cod_fiscal c(20) Null)
IF USED('crsSeriiFacturi')
USE IN crsSeriiFacturi
ENDIF
CREATE CURSOR crsSeriiFacturi (TIP c(20), seria c(20), descriere c(100))
INSERT INTO crsSeriiFacturi (TIP, seria, descriere) ;
SELECT 'AUTOFACTURA' As TIP, serie As seria, 'x' As descriere FROM crsSerii WHERE isautofactura = 1 ;
UNION SELECT 'BENEFICIARI', serie, 'x' FROM crsSerii WHERE isbeneficiari = 1 ;
UNION SELECT 'TERTI', serie, 'x' FROM crsSerii WHERE isterti = 1 ;
UNION SELECT 'FURNIZORI', serie, 'x' FROM crsSerii WHERE isfurnizori = 1
ADDPROPERTY(pounitate, "serie_autofacturare", cursor2lista("crsSerii", "serie", ",", [isautofactura=1]))
ADDPROPERTY(pounitate, "serie_facturi_beneficiari", cursor2lista("crsSerii", "serie", ",", [isbeneficiari=1]))
ADDPROPERTY(pounitate, "serie_facturi_terti", cursor2lista("crsSerii", "serie", ",", [isterti=1]))
ADDPROPERTY(pounitate, "serie_facturi_furnizori", cursor2lista("crsSerii", "serie", ",", [isfurnizori=1]))
close_serii()
IF USED('crsAMEF')
USE IN crsAMEF
ENDIF
CREATE CURSOR crsAMEF (TIP N(1), luna N(2), nramef N(10), nrbonuri N(10), incasari N(16,4), ;
baza21 N(16,4) Null, baza11 N(16,4) Null, baza19 N(16,4) Null, baza09 N(16,4) Null, baza05 N(16,4) Null, baza20 N(16,4) Null, ;
TVA21 N(16,4) Null, TVA11 N(16,4) Null, TVA19 N(16,4) Null, TVA09 N(16,4) Null, TVA05 N(16,4) Null, TVA20 N(16,4) Null)
IF USED('crsJTVA')
USE IN crsJTVA
ENDIF
CREATE CURSOR crsJTVA(seq N(20), tipj c(2), tippart N(1), tipdoc c(2) Null, TIP c(2), dataact D Null, dataireg D Null, serie_act c(10) Null, nract N(20) Null, id_fdoc N(12) Null, fel_document c(30) Null, id_sucursala N(7) Null, sucursala c(100) Null, ;
iscif N(1) Null, cifvalid N(1) Null, id_part N(20) Null, cod_fiscal c(30) Null, cod_fiscalfro c(30) Null, atribut_fiscal c(2) Null, denumire c(100) Null, TIP_PERSOANA N(1) Null, AFILIAT N(5) Null, CODTARA V(5) NULL, ;
TARA c(100) Null, COD_TARA c(10) Null, JUDET c(100) Null, COD_JUDET c(10) Null, LOCALITATE c(100) Null, STRADA c(100) Null, NUMAR c(20) Null, Bloc c(20) Null, SCARA c(50) Null, APART c(100) Null, ;
baza N(16,4) Null, TVA N(16,4) Null, tibaza N(16,4) Null, titva N(16,4) Null, ;
baza21 N(16,4) Null, baza11 N(16,4) Null, baza19 N(16,4) Null, baza09 N(16,4) Null, baza05 N(16,4) Null, baza24 N(16,4) Null, baza20 N(16,4) Null, baza00 N(16,4) Null, ;
TVA21 N(16,4) Null, TVA11 N(16,4) Null, TVA19 N(16,4) Null, TVA09 N(16,4) Null, TVA05 N(16,4) Null, TVA24 N(16,4) Null, TVA20 N(16,4) Null, ;
tibaza21 N(16,4) Null, tibaza11 N(16,4) Null, tibaza19 N(16,4) Null, tibaza09 N(16,4) Null, tibaza05 N(16,4) Null, tibaza24 N(16,4) Null, tibaza20 N(16,4) Null, ;
titva21 N(16,4) Null, titva11 N(16,4) Null, titva19 N(16,4) Null, titva09 N(16,4) Null, titva05 N(16,4) Null, titva24 N(16,4) Null, titva20 N(16,4) Null, ;
tva_incasare N(1), FACT_TVA_INCASARE N(1), NRFACT N(1), EMISA_PERIOADA N(1), ;
ro21t N(16,4) Null, ro11t N(16,4) Null, ro19t N(16,4) Null, RO09T N(16,4) Null, ro05t N(16,4) Null, ro24t N(16,4) Null, ro20t N(16,4) Null)
* --- rulare pipeline REAL, neschimbat, cu masurare de timp per etapa ---
TRY
LOCAL lnT0, lnT1, lnT2, lnT3, loExcD394
lnT0 = SECONDS()
llSucces = loD394.citeste_date_jtva()
lnT1 = SECONDS()
DO WriteTestLogD394 WITH 'citeste_date_jtva: succes=' + TRANSFORM(llSucces) + ' timp=' + TRANSFORM(lnT1-lnT0) + 's randuri crsJTVA=' + TRANSFORM(IIF(USED('crsJTVA'),RECCOUNT('crsJTVA'),-1))
IF llSucces AND USED('crsJTVA')
llSucces = loD394.configureaza_date_jtva()
ENDIF
lnT2 = SECONDS()
DO WriteTestLogD394 WITH 'configureaza_date_jtva (contine Update...VERIFICA_RTVAI_DATA per rand, oproceduri_decont.prg:8929): succes=' + TRANSFORM(llSucces) + ' timp=' + TRANSFORM(lnT2-lnT1) + 's'
IF llSucces
llSucces = loD394.pregateste_sectiunea_1_2()
ENDIF
IF llSucces
llSucces = loD394.pregateste_sectiunea_4_5()
ENDIF
IF llSucces
llSucces = loD394.pregateste_sectiunea_6()
ENDIF
IF llSucces
llSucces = loD394.pregateste_sectiunea_7()
ENDIF
IF llSucces
llSucces = loD394.pregateste_sectiunea_amef()
ENDIF
lnT3 = SECONDS()
DO WriteTestLogD394 WITH 'sectiuni 1_2/4_5/6/7/amef: succes=' + TRANSFORM(llSucces) + ' timp=' + TRANSFORM(lnT3-lnT2) + 's'
DO WriteTestLogD394 WITH 'TOTAL echivalent do_citeste_date: ' + TRANSFORM(lnT3-lnT0) + 's'
IF USED('crsJTVA')
LOCAL lnRandCrsJTVA, lnAI, lcBaseline
lnRandCrsJTVA = RECCOUNT('crsJTVA')
SELECT COUNT(*) AS nr FROM crsJTVA WHERE TIP = 'AI' INTO CURSOR crsNrAI
lnAI = crsNrAI.nr
USE IN crsNrAI
DO WriteTestLogD394 WITH 'crsJTVA: randuri=' + TRANSFORM(lnRandCrsJTVA) + ' randuri TIP=AI (achizitii TVA la incasare, afectate de VERIFICA_RTVAI_DATA)=' + TRANSFORM(lnAI)
lcBaseline = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\baseline_d394_2026_03_crsjtva_inainte_s2.dbf"
IF FILE(lcBaseline)
DELETE FILE (lcBaseline)
ENDIF
SELECT crsJTVA
GO TOP
COPY TO (lcBaseline)
DO WriteTestLogD394 WITH 'baseline salvat: ' + lcBaseline
ELSE
DO WriteTestLogD394 WITH 'EROARE: crsJTVA nu exista dupa pipeline'
ENDIF
CATCH TO loExcD394
DO WriteTestLogD394 WITH 'CATCH ErrorNo=' + TRANSFORM(loExcD394.ErrorNo) + ' Message=' + loExcD394.Message + ' Proc=' + loExcD394.Procedure + ' Line=' + TRANSFORM(loExcD394.LineNo)
ENDTRY
DO WriteTestLogD394 WITH 'GATA'
QUIT
PROCEDURE WriteTestLogD394
LPARAMETERS tcMesaj
STRTOFILE(TTOC(DATETIME()) + ' ' + tcMesaj + CHR(13)+CHR(10), gcTestLog, 1)
ENDPROC
PROCEDURE VpaErrD394
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO WriteTestLogD394 WITH 'ON ERROR nEroare=' + TRANSFORM(tnErr) + ' mesaj=' + tcMsg + ' program=' + tcProg + ' linia=' + TRANSFORM(tnLine)
ENDPROC

View File

@@ -0,0 +1,103 @@
* sonda_anaf_inline.prg
* Diagnostic (NU repara nimic): PACK_PARTENERI e VALID pe MARIUSM_AUTO, cu semnatura
* SAVE_ISTORIC_COD_FISCAL identica (27 parametri, aceeasi ordine/tip) cu apelul din
* SalveazaIstoricDinCursor (validare.prg:2639-2642) - vezi sonda_pack_parteneri.txt.
* Ipoteza PACK_PARTENERI INVALID e infirmata. Acest script REPLICA inline corpul lui
* ANAF_VerificaCuiSingle (validare.prg:1640), FARA sa modifice validare.prg, cu
* Try/Catch separat pe fiecare din cele trei sub-apeluri (ParseJsonANAFv8,
* SalveazaIstoricDinCursor, ANAF_VerdictDinCursor), ca sa vedem exact care arunca.
*
* Rulare headless:
* & "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -A -T ;
* "D:\ROA\ROACONT\COMUN\utile\Teste\partener_anaf\sonda_anaf_inline.prg"
* Rezultatul se scrie in %TEMP%\sonda_anaf_inline.txt
PUBLIC gcLogFile
gcLogFile = ADDBS(SYS(2023)) + 'sonda_anaf_inline.txt'
SET SAFETY OFF
SET TALK OFF
STRTOFILE('START ' + TTOC(DATETIME()) + CHR(13)+CHR(10), gcLogFile)
ON ERROR DO SondaErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO SondaLog WITH 'EROARE: conectare Oracle esuata, gnHandle=' + TRANSFORM(gnHandle)
QUIT
ENDIF
DO SondaLog WITH 'mediu OK, gcS=' + gcS
DO SondaLog WITH 'TYPE(gnIdUtil)=' + TYPE('gnIdUtil') + ' gnIdUtil=' + TRANSFORM(gnIdUtil)
LOCAL loVerifANAF, loHttpG, loEx As Exception
LOCAL lcJsonStringG, lcAliasG, lnCuiCautatG, ldDataG
LOCAL llNegasitG, lcClasaEsecG, loResultG
lcAliasG = 'crsANAFSingleTemp'
lnCuiCautatG = 1879855
ldDataG = DATE()
llNegasitG = .F.
lcClasaEsecG = ''
loResultG = .NULL.
lcJsonStringG = ''
loVerifANAF = CREATEOBJECT('VerificareANAF')
DO SondaLog WITH 'PAS G Createobject(VerificareANAF): OK'
TRY
loHttpG = ANAF_CreeazaCerereANAF(m.lnCuiCautatG, m.ldDataG, .F.)
lcJsonStringG = ALLTRIM(loHttpG.responseText)
DO SondaLog WITH 'PAS G ANAF_CreeazaCerereANAF: OK, Status=' + TRANSFORM(loHttpG.Status) + ' len(json)=' + TRANSFORM(LEN(m.lcJsonStringG))
CATCH TO loEx
DO SondaLog WITH 'PAS G ANAF_CreeazaCerereANAF: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
IF !EMPTY(m.lcJsonStringG) AND LEFT(m.lcJsonStringG, 1) = '{'
USE IN (SELECT(m.lcAliasG))
TRY
loVerifANAF.ParseJsonANAFv8(nfjsonread(m.lcJsonStringG), m.lcAliasG)
DO SondaLog WITH 'PAS G ParseJsonANAFv8: OK, alias deschis=' + TRANSFORM(USED(m.lcAliasG)) + ' RECCOUNT=' + IIF(USED(m.lcAliasG), TRANSFORM(RECCOUNT(m.lcAliasG)), '-')
CATCH TO loEx
DO SondaLog WITH 'PAS G ParseJsonANAFv8: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
TRY
loVerifANAF.SalveazaIstoricDinCursor(m.lcAliasG, gnIdUtil)
DO SondaLog WITH 'PAS G SalveazaIstoricDinCursor: OK, alias deschis=' + TRANSFORM(USED(m.lcAliasG)) + ' RECCOUNT=' + IIF(USED(m.lcAliasG), TRANSFORM(RECCOUNT(m.lcAliasG)), '-')
IF USED(m.lcAliasG)
LOCAL lnSelSaveG
lnSelSaveG = SELECT()
SELECT (m.lcAliasG)
DO SondaLog WITH 'PAS G dupa Salveaza - pozitie cursor: RECNO=' + TRANSFORM(RECNO()) + ' EOF=' + TRANSFORM(EOF()) + ' denumire=[' + NVL(denumire, '<NULL>') + '] cui=' + TRANSFORM(NVL(cui, -1))
SELECT (m.lnSelSaveG)
ENDIF
CATCH TO loEx
DO SondaLog WITH 'PAS G SalveazaIstoricDinCursor: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
TRY
loResultG = ANAF_VerdictDinCursor(m.lcAliasG, m.lnCuiCautatG, @llNegasitG, @lcClasaEsecG)
DO SondaLog WITH 'PAS G ANAF_VerdictDinCursor: OK, VARTYPE(loResultG)=' + VARTYPE(loResultG) + ' tlNegasit=' + TRANSFORM(llNegasitG) + ' tcClasaEsec=' + m.lcClasaEsecG
CATCH TO loEx
DO SondaLog WITH 'PAS G ANAF_VerdictDinCursor: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
ELSE
DO SondaLog WITH 'PAS G: raspuns gol sau nu incepe cu {, sarim parsarea'
ENDIF
DO SondaLog WITH 'REZULTAT: TERMINAT ' + TTOC(DATETIME())
QUIT
PROCEDURE SondaErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO SondaLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE SondaLog
LPARAMETERS tcMsg
LOCAL lcL
lcL = FILETOSTR(gcLogFile)
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcLogFile)
ENDPROC

View File

@@ -0,0 +1,149 @@
* sonda_anaf_single.prg
* Diagnostic (NU repara nimic): pe schema MARIUSM_AUTO, ecranul de cautare partener arata
* pentru toate codurile fiscale banda "ANAF nu a raspuns - verificare sarita"
* (COMUN\programe\ocautare.prg:801), desi ANAF raspunde OK 200 la curl direct pe aceeasi masina.
* Scopul scriptului: izoleaza pasul care arunca exceptie in ANAF_VerificaCuiSingle /
* ANAF_CreeazaCerereANAF (validare.prg), pas cu pas, cu Try/Catch separat pe fiecare bucata.
*
* Rulare headless (nu tine VFP IDE sau roacont.exe deschis):
* & "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -A -T ;
* "D:\ROA\ROACONT\COMUN\utile\Teste\partener_anaf\sonda_anaf_single.prg"
* Rezultatul se scrie in %TEMP%\sonda_anaf_single.txt
PUBLIC gcLogFile
gcLogFile = ADDBS(SYS(2023)) + 'sonda_anaf_single.txt'
SET SAFETY OFF
SET TALK OFF
STRTOFILE('START ' + TTOC(DATETIME()) + CHR(13)+CHR(10), gcLogFile)
DO SondaLog WITH 'SET(SAFETY)=' + SET('SAFETY') + ' SET(RESOURCE)=' + SET('RESOURCE')
ON ERROR DO SondaErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO SondaLog WITH 'EROARE: conectare Oracle esuata, gnHandle=' + TRANSFORM(gnHandle)
DO SondaLog WITH 'REZULTAT: NEDETERMINAT'
QUIT
ENDIF
DO SondaLog WITH 'mediu OK, gnAn=' + TRANSFORM(gnAn) + ' luna=' + TRANSFORM(gnLuna) + ' gcS=' + gcS
* ===== pas 0: instantiere VerificareANAF, ca in ANAF_VerificaCuiSingle - incarca =====
* ===== nfjsonread.prg / nfjsoncreate.prg ca proceduri (VerificareANAF.Init) =====
LOCAL loVerifANAF, loEx1 As Exception
TRY
loVerifANAF = CREATEOBJECT('VerificareANAF')
DO SondaLog WITH 'PAS0 CREATEOBJECT(VerificareANAF): OK, nfjsonread/nfjsoncreate incarcate'
CATCH TO loEx1
DO SondaLog WITH 'PAS0 CREATEOBJECT(VerificareANAF): EXCEPTIE ' + loEx1.Message + ' [' + loEx1.Procedure + ':' + TRANSFORM(loEx1.LineNo) + ']'
ENDTRY
* ===== pas A: doar Createobject('winHTTP.winHTTPrequest.5.1') =====
LOCAL loHttpA, loEx2 As Exception
TRY
loHttpA = CREATEOBJECT('winHTTP.winHTTPrequest.5.1')
DO SondaLog WITH 'PAS A winHTTP.winHTTPrequest.5.1: OK, VARTYPE=' + VARTYPE(loHttpA)
CATCH TO loEx2
DO SondaLog WITH 'PAS A winHTTP.winHTTPrequest.5.1: EXCEPTIE ' + loEx2.Message + ' [' + loEx2.Procedure + ':' + TRANSFORM(loEx2.LineNo) + ']'
ENDTRY
* ===== pas B: nfjsoncreate pe un array cu un obiect (cui + data), ca in ANAF_CreeazaCerereANAF =====
LOCAL loColB As "empty", laCoduriB[1], lcSendB, loEx3 As Exception
TRY
loColB = CREATEOBJECT('empty')
ADDPROPERTY(loColB, 'cui', 1879855)
ADDPROPERTY(loColB, 'data', '2026-08-01')
laCoduriB[1] = loColB
lcSendB = nfjsoncreate(@laCoduriB)
DO SondaLog WITH 'PAS B nfjsoncreate: OK, rezultat=' + TRANSFORM(lcSendB)
CATCH TO loEx3
DO SondaLog WITH 'PAS B nfjsoncreate: EXCEPTIE ' + loEx3.Message + ' [' + loEx3.Procedure + ':' + TRANSFORM(loEx3.LineNo) + ']'
ENDTRY
* ===== pas C: ANAF_CreeazaCerereANAF(1879855, Date(), .F.) direct, sincron =====
LOCAL loHttpC, loEx4 As Exception
TRY
loHttpC = ANAF_CreeazaCerereANAF(1879855, DATE(), .F.)
IF VARTYPE(loHttpC) = 'O'
DO SondaLog WITH 'PAS C ANAF_CreeazaCerereANAF: OK, Status=' + TRANSFORM(loHttpC.Status) + ' responseText(200)=' + LEFT(ALLTRIM(loHttpC.responseText), 200)
ELSE
DO SondaLog WITH 'PAS C ANAF_CreeazaCerereANAF: OK dar VARTYPE=' + VARTYPE(loHttpC) + ' (nu e obiect)'
ENDIF
CATCH TO loEx4
DO SondaLog WITH 'PAS C ANAF_CreeazaCerereANAF: EXCEPTIE ' + loEx4.Message + ' [' + loEx4.Procedure + ':' + TRANSFORM(loEx4.LineNo) + ']'
ENDTRY
* ===== pas E: nfjsonread + ParseJsonANAFv8 direct pe raspunsul de la pasul C, izolat =====
LOCAL loParsedE, loEx5 As Exception
IF VARTYPE(loHttpC) = 'O'
TRY
loParsedE = nfjsonread(ALLTRIM(loHttpC.responseText))
DO SondaLog WITH 'PAS E nfjsonread: OK, TYPE=' + TYPE('loParsedE') + ' PEMSTATUS(found_vfpsafe_)=' + TRANSFORM(PEMSTATUS(loParsedE, 'found_vfpsafe_', 5))
loVerifANAF.ParseJsonANAFv8(loParsedE, 'crsDiagE')
DO SondaLog WITH 'PAS E ParseJsonANAFv8: OK, RECCOUNT(crsDiagE)=' + TRANSFORM(RECCOUNT('crsDiagE'))
IF USED('crsDiagE') AND RECCOUNT('crsDiagE') > 0
SELECT crsDiagE
GO TOP
DO SondaLog WITH 'PAS E primul rand: cui=' + TRANSFORM(NVL(cui, 0)) + ' denumire=' + NVL(denumire, '')
ENDIF
CATCH TO loEx5
DO SondaLog WITH 'PAS E nfjsonread/ParseJsonANAFv8: EXCEPTIE ' + loEx5.Message + ' [' + loEx5.Procedure + ':' + TRANSFORM(loEx5.LineNo) + ']'
ENDTRY
ELSE
DO SondaLog WITH 'PAS E: sarit, loHttpC nu e obiect (PAS C a esuat)'
ENDIF
* ===== pas F: exact linia "Use In (Select(alias))" din ANAF_VerificaCuiSingle, pe un alias =====
* ===== care NU e deschis (ca la primul apel din sesiune) =====
LOCAL lcAliasF, lnSelF, loEx6 As Exception
lcAliasF = "crsANAFSingleTemp"
lnSelF = SELECT(m.lcAliasF)
DO SondaLog WITH 'PAS F SELECT(' + m.lcAliasF + ')=' + TRANSFORM(lnSelF) + ' inainte de orice Use'
TRY
Use In (SELECT(m.lcAliasF))
DO SondaLog WITH 'PAS F Use In (Select(alias)) pe alias neschis: OK'
CATCH TO loEx6
DO SondaLog WITH 'PAS F Use In (Select(alias)) pe alias neschis: EXCEPTIE ' + loEx6.Message + ' [' + loEx6.Procedure + ':' + TRANSFORM(loEx6.LineNo) + ']'
ENDTRY
* ===== pas D: fluxul real, ANAF_VerificaCuiSingle, pentru cele 3 coduri fiscale =====
LOCAL lcCui, loResult, llNegasit, lcClasaEsec, lnI
LOCAL ARRAY laCui[3]
laCui[1] = '1879855'
laCui[2] = '12751583'
laCui[3] = '11980333'
FOR lnI = 1 TO 3
lcCui = laCui[lnI]
llNegasit = .F.
lcClasaEsec = ''
loResult = ANAF_VerificaCuiSingle(m.lcCui, DATE(), @llNegasit, @lcClasaEsec)
IF VARTYPE(loResult) = 'O'
DO SondaLog WITH 'PAS D CUI=' + m.lcCui + ' -> OBIECT, denumire=' + NVL(loResult.denumire, '') + ' tlNegasit=' + TRANSFORM(llNegasit) + ' tcClasaEsec=' + m.lcClasaEsec
ELSE
DO SondaLog WITH 'PAS D CUI=' + m.lcCui + ' -> VARTYPE=' + VARTYPE(loResult) + ' tlNegasit=' + TRANSFORM(llNegasit) + ' tcClasaEsec=' + m.lcClasaEsec
ENDIF
IF USED('crsANAFSingleTemp')
LOCAL lnSelSaveD
lnSelSaveD = SELECT()
SELECT crsANAFSingleTemp
DO SondaLog WITH 'PAS D dupa CUI=' + m.lcCui + ': crsANAFSingleTemp deschis, RECCOUNT=' + TRANSFORM(RECCOUNT()) + ' RECNO=' + TRANSFORM(RECNO()) + ' EOF=' + TRANSFORM(EOF()) + ' denumire=[' + NVL(denumire, '<NULL>') + ']'
SELECT (m.lnSelSaveD)
ELSE
DO SondaLog WITH 'PAS D dupa CUI=' + m.lcCui + ': crsANAFSingleTemp NU e deschis'
ENDIF
ENDFOR
DO SondaLog WITH 'REZULTAT: TERMINAT ' + TTOC(DATETIME())
QUIT
PROCEDURE SondaErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO SondaLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE SondaLog
LPARAMETERS tcMsg
LOCAL lcL
lcL = FILETOSTR(gcLogFile)
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcLogFile)
ENDPROC

View File

@@ -0,0 +1,103 @@
* sonda_pack_parteneri.prg
* Diagnostic (NU repara nimic, doar SELECT-uri): verifica pe schema MARIUSM_AUTO daca
* PACK_PARTENERI e INVALID sau are alta semnatura pentru SAVE_ISTORIC_COD_FISCAL, in
* contextul mutarii ISTORIC_CODURI_FISCALE si recompilarii pachetului din 31.07/01.08.2026
* (vezi D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_01_02_COMUN_PACK_PARTENERI.sql).
* Foloseste goExecutor (aceeasi conexiune Oracle ca restul harnessului), doar SELECT-uri
* pe dictionarul de date (all_objects/all_arguments/all_errors/all_tables) - nimic scris.
*
* Rulare headless:
* & "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -A -T ;
* "D:\ROA\ROACONT\COMUN\utile\Teste\partener_anaf\sonda_pack_parteneri.prg"
* Rezultatul se scrie in %TEMP%\sonda_pack_parteneri.txt
PUBLIC gcLogFile
gcLogFile = ADDBS(SYS(2023)) + 'sonda_pack_parteneri.txt'
SET SAFETY OFF
SET TALK OFF
STRTOFILE('START ' + TTOC(DATETIME()) + CHR(13)+CHR(10), gcLogFile)
ON ERROR DO SondaErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
DO SondaLog WITH 'EROARE: conectare Oracle esuata, gnHandle=' + TRANSFORM(gnHandle)
QUIT
ENDIF
DO SondaLog WITH 'mediu OK, gcS=' + gcS
* ===== a) obiecte INVALID pe MARIUSM_AUTO =====
LOCAL llSucces
llSucces = goExecutor.oExecuta("SELECT object_name, object_type, status, last_ddl_time FROM all_objects WHERE owner = 'MARIUSM_AUTO' AND status <> 'VALID' ORDER BY object_type, object_name", "crsInvalid")
IF m.llSucces
SELECT crsInvalid
DO SondaLog WITH 'a) obiecte INVALID pe MARIUSM_AUTO: RECCOUNT=' + TRANSFORM(RECCOUNT())
SCAN
DO SondaLog WITH ' ' + ALLTRIM(object_type) + ' ' + ALLTRIM(object_name) + ' status=' + ALLTRIM(status) + ' last_ddl=' + TTOC(last_ddl_time)
ENDSCAN
ELSE
DO SondaLog WITH 'a) EROARE la interogarea all_objects (INVALID)'
ENDIF
* ===== b) starea PACK_PARTENERI + semnatura SAVE_ISTORIC_COD_FISCAL =====
llSucces = goExecutor.oExecuta("SELECT object_type, status, last_ddl_time FROM all_objects WHERE owner='MARIUSM_AUTO' AND object_name='PACK_PARTENERI'", "crsStare")
IF m.llSucces
SELECT crsStare
DO SondaLog WITH 'b) PACK_PARTENERI RECCOUNT=' + TRANSFORM(RECCOUNT())
SCAN
DO SondaLog WITH ' ' + ALLTRIM(object_type) + ' status=' + ALLTRIM(status) + ' last_ddl=' + TTOC(last_ddl_time)
ENDSCAN
ELSE
DO SondaLog WITH 'b) EROARE la interogarea all_objects (PACK_PARTENERI)'
ENDIF
llSucces = goExecutor.oExecuta("SELECT argument_name, position, data_type FROM all_arguments WHERE owner='MARIUSM_AUTO' AND package_name='PACK_PARTENERI' AND object_name='SAVE_ISTORIC_COD_FISCAL' ORDER BY position", "crsArg")
IF m.llSucces
SELECT crsArg
DO SondaLog WITH 'b) SAVE_ISTORIC_COD_FISCAL argumente: RECCOUNT=' + TRANSFORM(RECCOUNT())
SCAN
DO SondaLog WITH ' pos=' + TRANSFORM(position) + ' ' + NVL(argument_name, '<return>') + ' ' + ALLTRIM(data_type)
ENDSCAN
ELSE
DO SondaLog WITH 'b) EROARE la interogarea all_arguments'
ENDIF
* ===== c) erori de compilare, daca PACK_PARTENERI e INVALID =====
llSucces = goExecutor.oExecuta("SELECT line, position, text FROM all_errors WHERE owner='MARIUSM_AUTO' AND name='PACK_PARTENERI' ORDER BY sequence", "crsErr")
IF m.llSucces
SELECT crsErr
DO SondaLog WITH 'c) all_errors PACK_PARTENERI: RECCOUNT=' + TRANSFORM(RECCOUNT())
SCAN
DO SondaLog WITH ' linia ' + TRANSFORM(line) + ':' + TRANSFORM(position) + ' ' + ALLTRIM(text)
ENDSCAN
ELSE
DO SondaLog WITH 'c) EROARE la interogarea all_errors'
ENDIF
* ===== d) a ramas tabela locala ISTORIC_CODURI_FISCALE pe schema? =====
llSucces = goExecutor.oExecuta("SELECT table_name FROM all_tables WHERE owner='MARIUSM_AUTO' AND table_name LIKE 'ISTORIC_CODURI_FISCALE%'", "crsTab")
IF m.llSucces
SELECT crsTab
DO SondaLog WITH 'd) tabele ISTORIC_CODURI_FISCALE% pe MARIUSM_AUTO: RECCOUNT=' + TRANSFORM(RECCOUNT())
SCAN
DO SondaLog WITH ' ' + ALLTRIM(table_name)
ENDSCAN
ELSE
DO SondaLog WITH 'd) EROARE la interogarea all_tables'
ENDIF
DO SondaLog WITH 'REZULTAT: TERMINAT ' + TTOC(DATETIME())
QUIT
PROCEDURE SondaErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO SondaLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE SondaLog
LPARAMETERS tcMsg
LOCAL lcL
lcL = FILETOSTR(gcLogFile)
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcLogFile)
ENDPROC

View File

@@ -52,6 +52,13 @@
* ANAF plus data verificarii. Scenariile 11-13 (VerificaDataDocument/VerificaCacheData/
* VerificaDataFallback) acopera data documentului; mock_anaf_verificare.prg retine data primita
* in gdANAFUltimaData (PUBLIC, declarata mai jos).
*
* S12 (contract-cache-anaf.md, 31.07.2026): scenariile cache-ului ANAF pe ISTORIC_CODURI_FISCALE
* (plasa S9/ocautare.prg + helper-ele S3/validare.prg) - CUI-uri dedicate cu cifra de control CIF
* valida (8000090/8000197/8000294/8000391/8000499, gnIdCacheA/B/C/D/F)
* (gnIdCacheA/B/C/D/F), randuri de istoric inserate prin pack_parteneri.save_istoric_cod_fiscal
* (InsereazaIstoricTest); interogarile pe ISTORIC_CODURI_FISCALE se numara cu dummyexecutoristorictest
* (acelasi tipar ca dummyexecutorH2test), ca sa dovedeasca cand cache-ul e sarit sau folosit o singura data.
SET SAFETY OFF
SET TALK OFF
@@ -85,6 +92,21 @@ IF gnHandle <= 0
ENDIF
DO VpaLog WITH 'mediu OK, schema=' + gcS
*!* 01.08.2026 marius.mutu: watermark pe ID, o singura data la inceput - garda pt toate DELETE-urile din ISTORIC_CODURI_FISCALE de mai jos
PUBLIC gnIdMaxIstoricV2UI
gnIdMaxIstoricV2UI = 0
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsWmIstoricV2UI')
SELECT crsWmIstoricV2UI
GO TOP
gnIdMaxIstoricV2UI = IDMAX
USE IN (SELECT('crsWmIstoricV2UI'))
ENDIF
*!* 01.08.2026 marius.mutu: watermark invalid = SELECT esuat - avertisment explicit, stergerile se vor sari
IF gnIdMaxIstoricV2UI <= 0
DO VpaLog WITH 'ATENTIE: watermark invalid (0) - stergerile din ISTORIC_CODURI_FISCALE vor fi SARITE'
ENDIF
DO VpaLog WITH 'watermark ISTORIC_CODURI_FISCALE id_max=' + TRANSFORM(gnIdMaxIstoricV2UI)
*-- RE-TEST RUNDA 10: fix aplicat in ocautare.prg (guard '_BAZA' eliminat, NewObject pe _label
*-- din _baza.vcx rezolvat pe SET PATH, cu fallback anaf_label) - FARA workaround de test, cale
*-- reala (Activeaza se apeleaza natural, fara SET CLASSLIB manual).
@@ -148,6 +170,7 @@ glMockSondaReusitaManual = .T.
PUBLIC gnIdConcord, gnIdDiscord, gnIdPereche, gnIdNopereche, gnIdPersfiz, gnIdSpatiu, gnIdInactiv, gnIdInexistent
PUBLIC gnIdCnpInv, gnIdCifInv, gnMockInputBox, gnMockInputCount, gcMockUltimPrompt, gcMockInputSecventa
PUBLIC gnIdCadere, gnIdNenumeric
PUBLIC gnIdCacheA, gnIdCacheB, gnIdCacheC, gnIdCacheD, gnIdCacheF
gnMockInputBox = 1
gnMockInputCount = 0
gcMockUltimPrompt = ''
@@ -308,6 +331,17 @@ TRY
DO RuleazaIzolat WITH 'VerificaSondaReuseste'
DO RuleazaIzolat WITH 'VerificaSondaExpira'
*=========================================================================
* Scenariile S12 (contract-cache-anaf.md): cache-ul ANAF pe ISTORIC_CODURI_FISCALE, prin
* plasa de siguranta din ocautare.prg (S9) si helper-ele din validare.prg (S3)
*=========================================================================
DO RuleazaIzolat WITH 'VerificaCacheIndispIstoricPopulat'
DO RuleazaIzolat WITH 'VerificaCacheIndispIstoricGol'
DO RuleazaIzolat WITH 'VerificaCacheIndispIstoricVechi'
DO RuleazaIzolat WITH 'VerificaCodInexistentNuAtingeCache'
DO RuleazaIzolat WITH 'VerificaSeTesteazaNuAtingeCache'
DO RuleazaIzolat WITH 'VerificaOrdineCacheAnafSarit'
DO VpaLog WITH 'GATA - toate scenariile executate'
DO HarnessStep WITH 4, 'toate scenariile executate'
DO HarnessDone WITH 'done'
@@ -325,12 +359,29 @@ QUIT
PROCEDURE CurataDateTest
*-- CORESP_TIP_PART are FK_CORESP_TIP_PART_001 catre NOM_PARTENERI - copilul se sterge inaintea
*-- parintelui (ORA-02292), aceeasi lista de coduri in ambele instructiuni (lcCoduri).
LOCAL lnOk, lnOkCoresp, lcCoduri
lcCoduri = ['RO1112223','7654320','RO7654320','RO 7654320','9000004','9000012','9000039','1234567890128','1234567890123','1234567','RO9000055','TEST NENUMERIC OIL MARKET SRL']
LOCAL lnOk, lnOkCoresp, lcCoduri, lnOkIstoric
lcCoduri = ['RO1112223','7654320','RO7654320','RO 7654320','9000004','9000012','9000039','1234567890128','1234567890123','1234567','RO9000055','TEST NENUMERIC OIL MARKET SRL','8000090','8000197','8000294','8000391','8000499']
lnOkCoresp = goExecutor.oExecuta([DELETE FROM CORESP_TIP_PART WHERE ID_PART IN (SELECT ID_PART FROM NOM_PARTENERI WHERE COD_FISCAL IN (] + m.lcCoduri + [))])
lnOk = goExecutor.oExecuta([DELETE FROM NOM_PARTENERI WHERE COD_FISCAL IN (] + m.lcCoduri + [)])
*-- S12: randuri de istoric ale scenariilor de cache (9000039 e reutilizat de scenariul 4, testul lui isi
*-- insereaza propriul rand pt. CUI-ul existent gnIdInexistent) - plasa de siguranta, fiecare scenariu isi
*-- sterge deja randul propriu la final, dar CurataDateTest acopera si opririle premature (CATCH/FINALLY).
*!* 01.08.2026 marius.mutu: garda pe ID > watermark, prin StergeIstoricV2UI (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
lnOkIstoric = StergeIstoricV2UI("COD_FISCAL IN ('8000090','8000197','8000294','8000391','8000499','9000039')")
DO VpaLog WITH 'CurataDateTest: sters coresp_tip_part=' + TRANSFORM(m.lnOkCoresp) + ' nom_parteneri=' + TRANSFORM(m.lnOk) + ' istoric_coduri_fiscale=' + TRANSFORM(m.lnOkIstoric)
ENDPROC
*!* 01.08.2026 marius.mutu: helper unic pt DELETE-urile din ISTORIC_CODURI_FISCALE - garda watermark o singura data
PROCEDURE StergeIstoricV2UI
LPARAMETERS tcCondCod
LOCAL lnOkD
IF TYPE('gnIdMaxIstoricV2UI') <> 'N' OR gnIdMaxIstoricV2UI <= 0
DO VpaLog WITH 'StergeIstoricV2UI: SARIT - watermark invalid, nu sterg nimic (' + m.tcCondCod + ')'
RETURN 0
ENDIF
lnOkD = goExecutor.oExecuta("DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > " + TRANSFORM(gnIdMaxIstoricV2UI) + " AND " + m.tcCondCod)
=goExecutor.oExecuta('COMMIT')
DO VpaLog WITH 'CurataDateTest: sters coresp_tip_part=' + TRANSFORM(m.lnOkCoresp) + ' nom_parteneri=' + TRANSFORM(m.lnOk)
RETURN lnOkD
ENDPROC
PROCEDURE CreeazaDateTest
@@ -373,6 +424,22 @@ PROCEDURE CreeazaDateTest
lcIns = [INSERT INTO NOM_PARTENERI (NUME,DENUMIRE,COD_FISCAL,STERS,ID_MOD,INACTIV,TIP_PERSOANA,INSTITUTIE_PUBLICA,ENTITATE_AFILIATA) VALUES ] + ;
[('TEST ANAF NENUMERIC SRL','TEST ANAF NENUMERIC SRL','TEST NENUMERIC OIL MARKET SRL',0,0,0,1,0,0)]
=goExecutor.oExecuta(m.lcIns)
*-- S12: parteneri disposable pt. scenariile de cache (istoric ANAF pe ISTORIC_CODURI_FISCALE)
lcIns = [INSERT INTO NOM_PARTENERI (NUME,DENUMIRE,COD_FISCAL,STERS,ID_MOD,INACTIV,TIP_PERSOANA,INSTITUTIE_PUBLICA,ENTITATE_AFILIATA) VALUES ] + ;
[('TEST ANAF CACHE A SRL','TEST ANAF CACHE A SRL','8000090',0,0,0,1,0,0)]
=goExecutor.oExecuta(m.lcIns)
lcIns = [INSERT INTO NOM_PARTENERI (NUME,DENUMIRE,COD_FISCAL,STERS,ID_MOD,INACTIV,TIP_PERSOANA,INSTITUTIE_PUBLICA,ENTITATE_AFILIATA) VALUES ] + ;
[('TEST ANAF CACHE B SRL','TEST ANAF CACHE B SRL','8000197',0,0,0,1,0,0)]
=goExecutor.oExecuta(m.lcIns)
lcIns = [INSERT INTO NOM_PARTENERI (NUME,DENUMIRE,COD_FISCAL,STERS,ID_MOD,INACTIV,TIP_PERSOANA,INSTITUTIE_PUBLICA,ENTITATE_AFILIATA) VALUES ] + ;
[('TEST ANAF CACHE C SRL','TEST ANAF CACHE C SRL','8000294',0,0,0,1,0,0)]
=goExecutor.oExecuta(m.lcIns)
lcIns = [INSERT INTO NOM_PARTENERI (NUME,DENUMIRE,COD_FISCAL,STERS,ID_MOD,INACTIV,TIP_PERSOANA,INSTITUTIE_PUBLICA,ENTITATE_AFILIATA) VALUES ] + ;
[('TEST ANAF CACHE D SRL','TEST ANAF CACHE D SRL','8000391',0,0,0,1,0,0)]
=goExecutor.oExecuta(m.lcIns)
lcIns = [INSERT INTO NOM_PARTENERI (NUME,DENUMIRE,COD_FISCAL,STERS,ID_MOD,INACTIV,TIP_PERSOANA,INSTITUTIE_PUBLICA,ENTITATE_AFILIATA) VALUES ] + ;
[('TEST ANAF CACHE F SRL','TEST ANAF CACHE F SRL','8000499',0,0,0,1,0,0)]
=goExecutor.oExecuta(m.lcIns)
=goExecutor.oExecuta('COMMIT')
gnIdConcord = 0
@@ -387,6 +454,11 @@ PROCEDURE CreeazaDateTest
gnIdCifInv = 0
gnIdCadere = 0
gnIdNenumeric = 0
gnIdCacheA = 0
gnIdCacheB = 0
gnIdCacheC = 0
gnIdCacheD = 0
gnIdCacheF = 0
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = 'RO 7654320'], @gnIdSpatiu)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = 'RO1112223'], @gnIdConcord)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = '7654320'], @gnIdDiscord)
@@ -399,10 +471,17 @@ PROCEDURE CreeazaDateTest
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = '1234567'], @gnIdCifInv)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = 'RO9000055'], @gnIdCadere)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = 'TEST NENUMERIC OIL MARKET SRL'], @gnIdNenumeric)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = '8000090'], @gnIdCacheA)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = '8000197'], @gnIdCacheB)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = '8000294'], @gnIdCacheC)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = '8000391'], @gnIdCacheD)
=goExecutor.oSelect2Value([SELECT ID_PART AS NR FROM NOM_PARTENERI WHERE COD_FISCAL = '8000499'], @gnIdCacheF)
DO VpaLog WITH 'CreeazaDateTest: id-uri alocate concord=' + TRANSFORM(gnIdConcord) + ' discord=' + TRANSFORM(gnIdDiscord) + ;
' pereche=' + TRANSFORM(gnIdPereche) + ' spatiu=' + TRANSFORM(gnIdSpatiu) + ;
' nopereche=' + TRANSFORM(gnIdNopereche) + ' persfiz=' + TRANSFORM(gnIdPersfiz) + ;
' cadere=' + TRANSFORM(gnIdCadere) + ' nenumeric=' + TRANSFORM(gnIdNenumeric)
' cadere=' + TRANSFORM(gnIdCadere) + ' nenumeric=' + TRANSFORM(gnIdNenumeric) + ;
' cacheA=' + TRANSFORM(gnIdCacheA) + ' cacheB=' + TRANSFORM(gnIdCacheB) + ' cacheC=' + TRANSFORM(gnIdCacheC) + ;
' cacheD=' + TRANSFORM(gnIdCacheD) + ' cacheF=' + TRANSFORM(gnIdCacheF)
ENDPROC
PROCEDURE PornesteCautare
@@ -2217,6 +2296,428 @@ PROCEDURE VerificaComutareOptiune
RELEASE goCacheANAF_Nivel
ENDPROC
PROCEDURE InsereazaIstoricTest
*-- S12: insereaza un rand in ISTORIC_CODURI_FISCALE prin pack_parteneri.save_istoric_cod_fiscal
*-- (26 parametri, acelasi apel ca in validare.prg), cu scpTVA activ din tdInceput - cel putin o
*-- data de interval, altfel DATAORAV_ANAF ramane null si randul nu conteaza ca proaspat (contract
*-- -cache-anaf.md 2.3). Fara CREATEOBJECT/ADDPROPERTY (doar variabile Private + goExecutor.oExecuta),
*-- deci sigura de apelat dintr-o PROCEDURA (spre deosebire de capcana l). Intoarce .T./.F.
LPARAMETERS tcCui, tcFirma, tdInceput
PRIVATE pcCodFiscal, pcFirma, pcAdresa, pcJudet, pcRegCom, pcCodPostal, pcTelefon, pcFax, pcDataTvamfin, ;
pnPlatitorTvaMfin, pcStare, pnPlatitorTvaVies, pnInterogareVies, pnIdUtil, ;
pnInactiv, pnTvaIncasare, pnSplitTva, ;
pdInceputScpTva, pdSfarsitScpTva, pdAnulImpScpTva, pdInceputTvaInc, pdSfarsitTvaInc, ;
pdInactivare, pdReactivare, pdInceputSplitTva, pdAnulareSplitTva
LOCAL lcSqlIstoric, llOk
pcCodFiscal = m.tcCui
pcFirma = m.tcFirma
pcAdresa = ''
pcJudet = ''
pcRegCom = ''
pcCodPostal = ''
pcTelefon = ''
pcFax = ''
pcDataTvamfin = ''
pnPlatitorTvaMfin = 0
pcStare = ''
pnPlatitorTvaVies = 0
pnInterogareVies = 0
pnIdUtil = 0
pnInactiv = 0
pnTvaIncasare = 0
pnSplitTva = 0
pdInceputScpTva = m.tdInceput
pdSfarsitScpTva = {}
pdAnulImpScpTva = {}
pdInceputTvaInc = {}
pdSfarsitTvaInc = {}
pdInactivare = {}
pdReactivare = {}
pdInceputSplitTva = {}
pdAnulareSplitTva = {}
lcSqlIstoric = "begin pack_parteneri.save_istoric_cod_fiscal(?pcCodFiscal,?pcFirma,?pcAdresa,?pcJudet,?pcRegCom,?pcCodPostal,?pcTelefon,?pcFax,?pcDataTvamfin,?pnPlatitorTvaMfin,?pcStare," + ;
"?pnPlatitorTvaVies,?pnInterogareVies,?pnIdUtil,?pnInactiv,?pnTvaIncasare,?pnSplitTva,?pdInceputScpTva,?pdSfarsitScpTva," + ;
"?pdAnulImpScpTva,?pdInceputTvaInc,?pdSfarsitTvaInc,?pdInactivare,?pdReactivare,?pdInceputSplitTva,?pdAnulareSplitTva); end;"
llOk = goExecutor.oExecuta(m.lcSqlIstoric)
IF m.llOk
=goExecutor.oExecuta('COMMIT')
ENDIF
RETURN m.llOk
ENDPROC
PROCEDURE VerificaCacheIndispIstoricPopulat
*-- S12 scenariile 1+6 (contract-cache-anaf.md, plasa S9): ANAF cazut + istoric proaspat pt.
*-- acelasi CUI -> verdict citit din istoric, etichetat CACHE_INDISP, cu dDataSursa completat si
*-- sufixul "ANAF indisponibil" pe banda; AL DOILEA apel (formular nou, acelasi CUI) vine din
*-- goCacheANAF_Sesiune, FARA o a doua interogare pe ISTORIC_CODURI_FISCALE (contor prin dummy
*-- executor, acelasi tipar ca H2/discriminatorul de documente, mai sus in fisier).
LOCAL loFormP, loVerifP, lnOk, lcCapP, lnInainte, llInsP, loReal, loFormP2, loVerifP2, lnOk2, loDummy, loExcP2
IF TYPE('goCacheANAF_Sesiune') = 'O'
goCacheANAF_Sesiune = CREATEOBJECT('Collection')
ENDIF
llInsP = InsereazaIstoricTest('8000090', 'TEST S12 CACHE POPULAT SRL', {^2020-01-01})
IF !m.llInsP
DO VpaLog WITH 'FAIL cache-indisp-populat (S12/1): insert istoric esuat - ' + goExecutor.cEroare
RETURN
ENDIF
ANAF_SeteazaStareServiciu('CAZUT', 'test S12/1')
lnOk = goExecutor.oExecute([SELECT DISTINCT DENUMIRE, NUME, COD_FISCAL, ID_PART, INACTIV FROM NOM_PARTENERI ] + ;
[WHERE ID_PART = ] + TRANSFORM(gnIdCacheA), 'ctests12a')
loFormP = CREATEOBJECT('cauta_alfa_form', 'ctests12a', '', 'Denumire,Nume,Cod fiscal,Id,Inactiv', ;
'denumire,nume,cod_fiscal,id_part,inactiv', .F., '', 1, '', '', '', '')
loFormP.crs_cursor = 'ctests12a'
loFormP.lAles = .F.
loVerifP = CREATEOBJECT('anaf_verif_cautare')
ADDPROPERTY(loFormP, 'oVerifAlegere', loVerifP)
loVerifP.Activeaza(loFormP)
loFormP.WindowType = 0
loFormP.Show()
SELECT ctests12a
GO TOP
lnInainte = gnANAFCallCount
loFormP._GRID1.AfterRowColChange(1)
DO AsteaptaTimer WITH loVerifP
lcCapP = ALLTRIM(loFormP.lb_anaf.Caption)
IF gnANAFCallCount = lnInainte AND VARTYPE(loVerifP.oStare) = 'O' AND loVerifP.oStare.cSursa == 'CACHE_INDISP' ;
AND !EMPTY(loVerifP.oStare.dDataSursa) AND 'ANAF indisponibil' $ lcCapP AND 'date din' $ lcCapP
DO VpaLog WITH 'PASS cache-indisp-populat (S12/1): ANAF cazut + istoric proaspat -> cSursa=CACHE_INDISP, dDataSursa=' + ;
DTOC(loVerifP.oStare.dDataSursa) + ', banda=[' + lcCapP + '], 0 apeluri ANAF noi'
ELSE
DO VpaLog WITH 'FAIL cache-indisp-populat (S12/1): apeluri noi=' + TRANSFORM(gnANAFCallCount - lnInainte) + ;
' oStare=' + TRANSFORM(VARTYPE(loVerifP.oStare)) + ' banda=[' + lcCapP + ']'
ENDIF
*-- scenariul 6: al doilea apel, pe formular NOU, acelasi CUI - trebuie servit din goCacheANAF_Sesiune,
*-- FARA o a doua interogare pe ISTORIC_CODURI_FISCALE.
loReal = goExecutor
loDummy = CREATEOBJECT('dummyexecutoristorictest')
loDummy.oReal = loReal
goExecutor = loDummy
TRY
lnOk2 = goExecutor.oExecute([SELECT DISTINCT DENUMIRE, NUME, COD_FISCAL, ID_PART, INACTIV FROM NOM_PARTENERI ] + ;
[WHERE ID_PART = ] + TRANSFORM(gnIdCacheA), 'ctests12a2')
loFormP2 = CREATEOBJECT('cauta_alfa_form', 'ctests12a2', '', 'Denumire,Nume,Cod fiscal,Id,Inactiv', ;
'denumire,nume,cod_fiscal,id_part,inactiv', .F., '', 1, '', '', '', '')
loFormP2.crs_cursor = 'ctests12a2'
loFormP2.lAles = .F.
loVerifP2 = CREATEOBJECT('anaf_verif_cautare')
ADDPROPERTY(loFormP2, 'oVerifAlegere', loVerifP2)
loVerifP2.Activeaza(loFormP2)
loFormP2.WindowType = 0
loFormP2.Show()
SELECT ctests12a2
GO TOP
loFormP2._GRID1.AfterRowColChange(1)
DO AsteaptaTimer WITH loVerifP2
CATCH TO loExcP2
DO VpaLog WITH 'FAIL cache-sesiune-fara-oracle (S12/6, EXCEPTIE): ' + loExcP2.Message
FINALLY
goExecutor = loReal
ENDTRY
IF VARTYPE(loVerifP2.oStare) = 'O' AND loVerifP2.oStare.cSursa == 'CACHE_INDISP' AND loDummy.nIstoricQueryCount = 0
DO VpaLog WITH 'PASS cache-sesiune-fara-oracle (S12/6): al doilea apel (formular nou, acelasi CUI) servit din goCacheANAF_Sesiune, 0 interogari noi pe ISTORIC_CODURI_FISCALE'
ELSE
DO VpaLog WITH 'FAIL cache-sesiune-fara-oracle (S12/6): oStare=' + TRANSFORM(VARTYPE(loVerifP2.oStare)) + ;
' interogari-istoric=' + TRANSFORM(loDummy.nIstoricQueryCount)
ENDIF
TRY
loVerifP.Dezactiveaza()
loVerifP2.Dezactiveaza()
CATCH
ENDTRY
loFormP.Release()
loFormP2.Release()
IF USED('ctests12a')
USE IN ctests12a
ENDIF
IF USED('ctests12a2')
USE IN ctests12a2
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark, prin StergeIstoricV2UI (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
=StergeIstoricV2UI("COD_FISCAL = '8000090'")
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reset dupa S12/1')
ENDPROC
PROCEDURE VerificaCacheIndispIstoricGol
*-- S12 scenariul 2: ANAF cazut, istoric FARA niciun rand pt. CUI -> comportament identic cu azi
*-- (.NULL., banda "ANAF nu a raspuns - verificare sarita"), fara eticheta de cache.
LOCAL loFormG, loVerifG, lnOk, lcCapG, lnInainte
IF TYPE('goCacheANAF_Sesiune') = 'O'
goCacheANAF_Sesiune = CREATEOBJECT('Collection')
ENDIF
ANAF_SeteazaStareServiciu('CAZUT', 'test S12/2')
lnOk = goExecutor.oExecute([SELECT DISTINCT DENUMIRE, NUME, COD_FISCAL, ID_PART, INACTIV FROM NOM_PARTENERI ] + ;
[WHERE ID_PART = ] + TRANSFORM(gnIdCacheB), 'ctests12b')
loFormG = CREATEOBJECT('cauta_alfa_form', 'ctests12b', '', 'Denumire,Nume,Cod fiscal,Id,Inactiv', ;
'denumire,nume,cod_fiscal,id_part,inactiv', .F., '', 1, '', '', '', '')
loFormG.crs_cursor = 'ctests12b'
loFormG.lAles = .F.
loVerifG = CREATEOBJECT('anaf_verif_cautare')
ADDPROPERTY(loFormG, 'oVerifAlegere', loVerifG)
loVerifG.Activeaza(loFormG)
loFormG.WindowType = 0
loFormG.Show()
SELECT ctests12b
GO TOP
lnInainte = gnANAFCallCount
loFormG._GRID1.AfterRowColChange(1)
DO AsteaptaTimer WITH loVerifG
lcCapG = ALLTRIM(loFormG.lb_anaf.Caption)
IF gnANAFCallCount = lnInainte AND ISNULL(loVerifG.oStare) AND 'ANAF nu a raspuns - verificare sarita' $ lcCapG
DO VpaLog WITH 'PASS cache-indisp-istoric-gol (S12/2): ANAF cazut, istoric gol -> .NULL., banda identica cu azi [' + lcCapG + ']'
ELSE
DO VpaLog WITH 'FAIL cache-indisp-istoric-gol (S12/2): apeluri noi=' + TRANSFORM(gnANAFCallCount - lnInainte) + ;
' oStare=' + TRANSFORM(VARTYPE(loVerifG.oStare)) + ' banda=[' + lcCapG + ']'
ENDIF
loVerifG.Dezactiveaza()
loFormG.Release()
IF USED('ctests12b')
USE IN ctests12b
ENDIF
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reset dupa S12/2')
ENDPROC
PROCEDURE VerificaCacheIndispIstoricVechi
*-- S12 scenariul 3: ANAF cazut, istoric are un rand pt. CUI dar DATAORAV_ANAF mai vechi decat
*-- ANAFCACHEZILE (30 zile implicit) -> filtrul din CitesteIstoricPentruCoduri il exclude, deci
*-- comportamentul ramane identic cu istoricul gol (.NULL.).
LOCAL loFormV, loVerifV, lnOk, lcCapV, lnInainte, llInsV
IF TYPE('goCacheANAF_Sesiune') = 'O'
goCacheANAF_Sesiune = CREATEOBJECT('Collection')
ENDIF
llInsV = InsereazaIstoricTest('8000294', 'TEST S12 CACHE VECHI SRL', {^2020-01-01})
IF !m.llInsV
DO VpaLog WITH 'FAIL cache-indisp-istoric-vechi (S12/3): insert istoric esuat - ' + goExecutor.cEroare
RETURN
ENDIF
*-- imbatraneste DATAORAV_ANAF direct in Oracle - numai randul propriu de test (COD_FISCAL='8000294')
=goExecutor.oExecuta("UPDATE ISTORIC_CODURI_FISCALE SET DATAORAV_ANAF = SYSDATE - 40 WHERE COD_FISCAL = '8000294'")
=goExecutor.oExecuta('COMMIT')
ANAF_SeteazaStareServiciu('CAZUT', 'test S12/3')
lnOk = goExecutor.oExecute([SELECT DISTINCT DENUMIRE, NUME, COD_FISCAL, ID_PART, INACTIV FROM NOM_PARTENERI ] + ;
[WHERE ID_PART = ] + TRANSFORM(gnIdCacheC), 'ctests12c')
loFormV = CREATEOBJECT('cauta_alfa_form', 'ctests12c', '', 'Denumire,Nume,Cod fiscal,Id,Inactiv', ;
'denumire,nume,cod_fiscal,id_part,inactiv', .F., '', 1, '', '', '', '')
loFormV.crs_cursor = 'ctests12c'
loFormV.lAles = .F.
loVerifV = CREATEOBJECT('anaf_verif_cautare')
ADDPROPERTY(loFormV, 'oVerifAlegere', loVerifV)
loVerifV.Activeaza(loFormV)
loFormV.WindowType = 0
loFormV.Show()
SELECT ctests12c
GO TOP
lnInainte = gnANAFCallCount
loFormV._GRID1.AfterRowColChange(1)
DO AsteaptaTimer WITH loVerifV
lcCapV = ALLTRIM(loFormV.lb_anaf.Caption)
IF gnANAFCallCount = lnInainte AND ISNULL(loVerifV.oStare) AND 'ANAF nu a raspuns - verificare sarita' $ lcCapV
DO VpaLog WITH 'PASS cache-indisp-istoric-vechi (S12/3): istoric 40 zile (peste ANAFCACHEZILE=30) -> .NULL., nu se ofera nimic [' + lcCapV + ']'
ELSE
DO VpaLog WITH 'FAIL cache-indisp-istoric-vechi (S12/3): apeluri noi=' + TRANSFORM(gnANAFCallCount - lnInainte) + ;
' oStare=' + TRANSFORM(VARTYPE(loVerifV.oStare)) + ' banda=[' + lcCapV + ']'
ENDIF
loVerifV.Dezactiveaza()
loFormV.Release()
IF USED('ctests12c')
USE IN ctests12c
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark, prin StergeIstoricV2UI (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
=StergeIstoricV2UI("COD_FISCAL = '8000294'")
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reset dupa S12/3')
ENDPROC
PROCEDURE VerificaCodInexistentNuAtingeCache
*-- S12 scenariul 4: cod fiscal valid ca structura dar negasit la ANAF (tlNegasit) -> verdict
*-- "inexistent", istoricul NU e atins deloc (nici citit, nici folosit ca plasa) - chiar daca exista
*-- un rand proaspat pt. acelasi CUI. Contor de interogari pe ISTORIC_CODURI_FISCALE prin dummy
*-- executor (acelasi tipar ca H2/discriminatorul de documente, mai sus in fisier).
LOCAL loFormN, loVerifN, lnOk, lcCapN, llInsN, loReal, loDummy, loExcN4
IF TYPE('goCacheANAF_Sesiune') = 'O'
goCacheANAF_Sesiune = CREATEOBJECT('Collection')
ENDIF
llInsN = InsereazaIstoricTest('9000039', 'TEST S12 NU TREBUIE FOLOSIT SRL', {^2020-01-01})
IF !m.llInsN
DO VpaLog WITH 'FAIL cod-inexistent-nu-atinge-cache (S12/4): insert istoric esuat - ' + goExecutor.cEroare
RETURN
ENDIF
loReal = goExecutor
loDummy = CREATEOBJECT('dummyexecutoristorictest')
loDummy.oReal = loReal
goExecutor = loDummy
TRY
lnOk = goExecutor.oExecute([SELECT DISTINCT DENUMIRE, NUME, COD_FISCAL, ID_PART, INACTIV FROM NOM_PARTENERI ] + ;
[WHERE ID_PART = ] + TRANSFORM(gnIdInexistent), 'ctests12d')
loFormN = CREATEOBJECT('cauta_alfa_form', 'ctests12d', '', 'Denumire,Nume,Cod fiscal,Id,Inactiv', ;
'denumire,nume,cod_fiscal,id_part,inactiv', .F., '', 1, '', '', '', '')
loFormN.crs_cursor = 'ctests12d'
loFormN.lAles = .F.
loVerifN = CREATEOBJECT('anaf_verif_cautare')
ADDPROPERTY(loFormN, 'oVerifAlegere', loVerifN)
loVerifN.Activeaza(loFormN)
loFormN.WindowType = 0
loFormN.Show()
SELECT ctests12d
GO TOP
loFormN._GRID1.AfterRowColChange(1)
DO AsteaptaTimer WITH loVerifN
lcCapN = ALLTRIM(loFormN.lb_anaf.Caption)
CATCH TO loExcN4
lcCapN = 'EXCEPTIE: ' + loExcN4.Message
FINALLY
goExecutor = loReal
ENDTRY
IF 'Cod fiscal inexistent la ANAF (9000039)' $ lcCapN AND loDummy.nIstoricQueryCount = 0
DO VpaLog WITH 'PASS cod-inexistent-nu-atinge-cache (S12/4): verdict inexistent, 0 interogari pe ISTORIC_CODURI_FISCALE (istoric avea rand proaspat, neatins) - [' + lcCapN + ']'
ELSE
DO VpaLog WITH 'FAIL cod-inexistent-nu-atinge-cache (S12/4): banda=[' + lcCapN + '] interogari-istoric=' + TRANSFORM(loDummy.nIstoricQueryCount)
ENDIF
TRY
loVerifN.Dezactiveaza()
CATCH
ENDTRY
loFormN.Release()
IF USED('ctests12d')
USE IN ctests12d
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark, prin StergeIstoricV2UI (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
=StergeIstoricV2UI("COD_FISCAL = '9000039'")
ENDPROC
PROCEDURE VerificaSeTesteazaNuAtingeCache
*-- S12 scenariul 5: sonda in aer (stare SE_TESTEAZA) ramane neschimbata dupa S9 - randul NU face
*-- apel ANAF propriu si NU atinge istoricul (spre deosebire de CAZUT/FARA_RASPUNS, care citesc din
*-- cache); banda ramane "ANAF: se verifica ...", nu devine CACHE_INDISP.
LOCAL loFormT5, loVerifT5, lnOk, lcCapT5, lnInainte, llInsT5
IF TYPE('goCacheANAF_Sesiune') = 'O'
goCacheANAF_Sesiune = CREATEOBJECT('Collection')
ENDIF
llInsT5 = InsereazaIstoricTest('8000391', 'TEST S12 CACHE SONDA SRL', {^2020-01-01})
IF !m.llInsT5
DO VpaLog WITH 'FAIL se-testeaza-nu-atinge-cache (S12/5): insert istoric esuat - ' + goExecutor.cEroare
RETURN
ENDIF
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'pregatire S12/5')
gcMockSondaModo = 'MANUAL'
glMockSondaGataManual = .F.
lnOk = goExecutor.oExecute([SELECT DISTINCT DENUMIRE, NUME, COD_FISCAL, ID_PART, INACTIV FROM NOM_PARTENERI ] + ;
[WHERE ID_PART = ] + TRANSFORM(gnIdCacheD), 'ctests12e')
loFormT5 = CREATEOBJECT('cauta_alfa_form', 'ctests12e', '', 'Denumire,Nume,Cod fiscal,Id,Inactiv', ;
'denumire,nume,cod_fiscal,id_part,inactiv', .F., '', 1, '', '', '', '')
loFormT5.crs_cursor = 'ctests12e'
loFormT5.lAles = .F.
loVerifT5 = CREATEOBJECT('anaf_verif_cautare')
ADDPROPERTY(loFormT5, 'oVerifAlegere', loVerifT5)
loVerifT5.Activeaza(loFormT5) && NECUNOSCUT -> porneste sonda (mock) -> SE_TESTEAZA
loFormT5.WindowType = 0
loFormT5.Show()
SELECT ctests12e
GO TOP
lnInainte = gnANAFCallCount
loFormT5._GRID1.AfterRowColChange(1)
DOEVENTS FORCE
lcCapT5 = ALLTRIM(loFormT5.lb_anaf.Caption)
IF gnANAFCallCount = lnInainte AND ANAF_StareServiciu() == 'SE_TESTEAZA' AND 'ANAF: se verifica' $ lcCapT5 ;
AND (ISNULL(loVerifT5.oStare) OR loVerifT5.oStare.cSursa <> 'CACHE_INDISP')
DO VpaLog WITH 'PASS se-testeaza-nu-atinge-cache (S12/5): sonda in aer -> neschimbat, banda [' + lcCapT5 + '], nu trece prin cache desi istoricul are rand proaspat'
ELSE
DO VpaLog WITH 'FAIL se-testeaza-nu-atinge-cache (S12/5): apeluri noi=' + TRANSFORM(gnANAFCallCount - lnInainte) + ;
' stare=' + ANAF_StareServiciu() + ' banda=[' + lcCapT5 + ']'
ENDIF
loVerifT5.Dezactiveaza()
loFormT5.Release()
IF USED('ctests12e')
USE IN ctests12e
ENDIF
*!* 01.08.2026 marius.mutu: garda pe ID > watermark, prin StergeIstoricV2UI (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
=StergeIstoricV2UI("COD_FISCAL = '8000391'")
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reset dupa S12/5')
gcMockSondaModo = 'AUTO'
ENDPROC
PROCEDURE VerificaOrdineCacheAnafSarit
*-- S12 scenariul 7: OrdineCache('UNIC')=CACHE,ANAF + rand proaspat in istoric -> ANAF NU e apelat
*-- deloc (verificat prin gnANAFCallCount), verdictul vine direct din cache (cSursa=CACHE - pe acest
*-- traseu istoricul e incercat INAINTE de starea serviciului).
LOCAL loFormO, loVerifO, lnOk, lcCapO, lnInainte, llInsO, lcOrdineOrig, llAveaRand
IF TYPE('goCacheANAF_Sesiune') = 'O'
goCacheANAF_Sesiune = CREATEOBJECT('Collection')
ENDIF
llInsO = InsereazaIstoricTest('8000499', 'TEST S12 CACHE ORDINE SRL', {^2020-01-01})
IF !m.llInsO
DO VpaLog WITH 'FAIL ordine-cache-anaf-sarit (S12/7): insert istoric esuat - ' + goExecutor.cEroare
RETURN
ENDIF
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'pregatire S12/7')
lcOrdineOrig = ''
=goExecutor.oSelect2Value("SELECT VARVALUE AS NR FROM OPTIUNI WHERE VARNAME = 'ANAFCACHEORDINE_UNIC'", @lcOrdineOrig)
llAveaRand = !EMPTY(NVL(lcOrdineOrig, ''))
IF m.llAveaRand
=goExecutor.oExecuta("UPDATE OPTIUNI SET VARVALUE = 'CACHE,ANAF' WHERE VARNAME = 'ANAFCACHEORDINE_UNIC'")
ELSE
=goExecutor.oExecuta("INSERT INTO OPTIUNI (VARNAME, VARVALUE) VALUES ('ANAFCACHEORDINE_UNIC', 'CACHE,ANAF')")
ENDIF
=goExecutor.oExecuta('COMMIT')
lnOk = goExecutor.oExecute([SELECT DISTINCT DENUMIRE, NUME, COD_FISCAL, ID_PART, INACTIV FROM NOM_PARTENERI ] + ;
[WHERE ID_PART = ] + TRANSFORM(gnIdCacheF), 'ctests12f')
loFormO = CREATEOBJECT('cauta_alfa_form', 'ctests12f', '', 'Denumire,Nume,Cod fiscal,Id,Inactiv', ;
'denumire,nume,cod_fiscal,id_part,inactiv', .F., '', 1, '', '', '', '')
loFormO.crs_cursor = 'ctests12f'
loFormO.lAles = .F.
loVerifO = CREATEOBJECT('anaf_verif_cautare')
ADDPROPERTY(loFormO, 'oVerifAlegere', loVerifO)
loVerifO.Activeaza(loFormO)
loFormO.WindowType = 0
loFormO.Show()
SELECT ctests12f
GO TOP
lnInainte = gnANAFCallCount
loFormO._GRID1.AfterRowColChange(1)
DO AsteaptaTimer WITH loVerifO
lcCapO = ALLTRIM(loFormO.lb_anaf.Caption)
IF gnANAFCallCount = lnInainte AND VARTYPE(loVerifO.oStare) = 'O' AND loVerifO.oStare.cSursa == 'CACHE'
DO VpaLog WITH 'PASS ordine-cache-anaf-sarit (S12/7): OrdineCache=CACHE,ANAF + rand proaspat -> 0 apeluri ANAF, verdict din cache [' + lcCapO + ']'
ELSE
DO VpaLog WITH 'FAIL ordine-cache-anaf-sarit (S12/7): apeluri noi=' + TRANSFORM(gnANAFCallCount - lnInainte) + ;
' oStare=' + TRANSFORM(VARTYPE(loVerifO.oStare)) + ' banda=[' + lcCapO + ']'
ENDIF
loVerifO.Dezactiveaza()
loFormO.Release()
IF USED('ctests12f')
USE IN ctests12f
ENDIF
*-- restaureaza optiunea originala (per schema - alte teste/utilizatori depind de implicit)
IF m.llAveaRand
=goExecutor.oExecuta("UPDATE OPTIUNI SET VARVALUE = '" + STRTRAN(m.lcOrdineOrig, "'", "''") + "' WHERE VARNAME = 'ANAFCACHEORDINE_UNIC'")
ELSE
=goExecutor.oExecuta("DELETE FROM OPTIUNI WHERE VARNAME = 'ANAFCACHEORDINE_UNIC'")
ENDIF
=goExecutor.oExecuta('COMMIT')
*!* 01.08.2026 marius.mutu: garda pe ID > watermark, prin StergeIstoricV2UI (nu SCHEMA_SURSA - stergea randuri de referinta proprii)
=StergeIstoricV2UI("COD_FISCAL = '8000499'")
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reset dupa S12/7')
ENDPROC
PROCEDURE VpaErr
*-- OBLIGATORIU headless (depanare_testare_vfp.md): handlerul ON ERROR se termina cu QUIT.
*-- In fluxul normal, erorile din TRY-ul principal ajung la CATCH TO loExc (nu aici) - VpaErr
@@ -2303,3 +2804,34 @@ DEFINE CLASS dummyexecutordoctest AS Custom
RETURN This.oReal.oSelect2Value(m.tcSql, @tuValue)
ENDPROC
ENDDEFINE
*-- S12: dublura de goExecutor pentru scenariile de cache - numara interogarile care ating
*-- ISTORIC_CODURI_FISCALE (CitesteIstoricPentruCoduri trece prin oExecuta, validare.prg), ca sa
*-- dovedeasca cand cache-ul Oracle e sarit (cod negasit la ANAF) sau folosit o singura data (al
*-- doilea apel pe acelasi CUI vine din goCacheANAF_Sesiune).
DEFINE CLASS dummyexecutoristorictest AS Custom
oReal = .NULL.
cEroare = ''
nIstoricQueryCount = 0
PROCEDURE oExecuta
LPARAMETERS tcSql, tcCursor
LOCAL lnRez
IF 'ISTORIC_CODURI_FISCALE' $ UPPER(tcSql)
This.nIstoricQueryCount = This.nIstoricQueryCount + 1
ENDIF
lnRez = This.oReal.oExecuta(m.tcSql, m.tcCursor)
This.cEroare = This.oReal.cEroare
RETURN lnRez
ENDPROC
PROCEDURE oExecute
LPARAMETERS tcSql, tcCursor
LOCAL lnRez
lnRez = This.oReal.oExecute(m.tcSql, m.tcCursor)
This.cEroare = This.oReal.cEroare
RETURN lnRez
ENDPROC
PROCEDURE oSelect2Value
LPARAMETERS tcSql, tuValue
RETURN This.oReal.oSelect2Value(m.tcSql, @tuValue)
ENDPROC
ENDDEFINE