Files
comun/utile/Teste/cache_anaf/test_mock_batch_anaf_demo.prg
Marius Mutu 859e67e874 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
2026-08-02 01:33:18 +03:00

495 lines
23 KiB
Plaintext

* 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