Cache ANAF: verificarea in masa a codurilor fiscale, pe transe (SVN r17935)

Verificarea "in masa" (VerificaListaCIF ... 'MASA') pica pe ORA-01795 peste 1000
de coduri, iar esecul trimitea tot lotul la ANAF, cu pauze de o secunda la fiecare
100 de coduri. Pe langa asta, fiecare rand servit din cache era salvat inapoi in
istoric si logat separat.

- programe/validare.prg: CitesteIstoricPentruCoduri citeste pe transe de maxim
  1000 de coduri legate cu OR in aceeasi interogare (fara obiecte noi in baza,
  compatibil cu Oracle 10g); plasa de siguranta cere codurile neacoperite o
  singura data, nu cod cu cod; SalveazaIstoricDinCursor sare peste randurile cu
  sursa CACHE*; bucla de log per rand devine o singura linie cu totalul.
- clase/overificari.vc2: completarea tabelului de parteneri foloseste index pe
  codul normalizat si SEEK in loc de LOCATE cu UDF (era patratic).
- utile/Teste/cache_anaf/: harness-uri de masurare si non-regresie pentru
  timpii de mai jos.

Masurat pe MARIUSM_AUTO, cu ANAF blocat: 1000 de coduri 5,1 s -> 0,318 s;
1001 coduri 16,6 s cu ORA-01795 -> 0,553 s fara eroare; 3000 de coduri 1,565 s;
200 de coduri din cache 3,93 s -> 0,05 s, cu 0 randuri noi in istoric;
completarea tabelului pentru 2000 de parteneri 11,97 s -> 0,028 s.
Randurile intoarse si verdictele raman identice.

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 07:27:42 +03:00
parent 4342aae78c
commit 5c8a201438
8 changed files with 2043 additions and 15 deletions

View File

@@ -100,6 +100,15 @@
*!* provenienta; altfel cache-ul isi reseta singur ceasul de prospetime la fiecare citire si nu mai
*!* expira niciodata
*!* 02.08.2026
*!* marius.mutu
*!* SalveazaIstoricDinCursor sare peste randurile provenite din cache - au fost deja salvate cand au
*!* ajuns prima data din ANAF; VerificaListaCIF lasa o singura linie in goLog cu totalul randurilor
*!* completate din cache (CACHE si CACHE_INDISP), in loc de o linie per rand; CitesteIstoricPentruCoduri
*!* interogheaza codurile pe transe de maxim 1000, legate cu OR in aceeasi interogare (peste 1000
*!* elemente "in (...)" da ORA-01795); plasa de siguranta din VerificaListaCIF aduna codurile ramase
*!* fara raspuns si cere istoricul intr-un singur apel, in loc de un apel Oracle per cod
*!* 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
@@ -1891,7 +1900,7 @@ Define Class VerificareANAF As Custom
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
Local lcOrdine, ldData, lcAliasNorm, lcListaCoduriN, lcCursorRamas, lnCuiCurent, lcCodFiscalCurent, ldDataCurenta, llGasitCache, lcCursorAnafTemp, loRandAnaf, lnFaraRaspuns, lnCache, lnCacheIndisp, lcListaCoduriRamase
lcCursorListaCIF = ""
llUsed = .F.
@@ -1981,6 +1990,7 @@ Define Class VerificareANAF As Custom
* 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
lcListaCoduriRamase = ''
Select (m.lcAliasNorm)
Scan For cui_n <> 0
lnCuiCurent = cui_n
@@ -1991,17 +2001,27 @@ Define Class VerificareANAF As Custom
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)
lcListaCoduriRamase = m.lcListaCoduriRamase + Iif(Empty(m.lcListaCoduriRamase), '', ',') + Transform(m.lnCuiCurent)
Endif
Select (m.lcAliasNorm)
Endscan
Use In (Select(m.lcAliasNorm))
If !Empty(m.lcListaCoduriRamase)
This.CitesteIstoricPentruCoduri(m.lcListaCoduriRamase, m.ldData, m.lcAlias, 'CACHE_INDISP')
lnRecs = Getwordcount(m.lcListaCoduriRamase, ',')
For lnRec = 1 To m.lnRecs
lnCuiCurent = Val(Getwordnum(m.lcListaCoduriRamase, m.lnRec, ','))
llGasitCache = .F.
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
Select (m.lcAlias)
Locate For cui = m.lnCuiCurent
llGasitCache = Found()
Endif
lnFaraRaspuns = m.lnFaraRaspuns + Iif(m.llGasitCache, 0, 1)
Endfor
Endif
*!* 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)
@@ -2011,13 +2031,22 @@ Define Class VerificareANAF As Custom
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
* criteriul 9: totalul randurilor completate din cache (CACHE si CACHE_INDISP), o singura linie in goLog
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
Select (m.lcAlias)
lnCache = 0
lnCacheIndisp = 0
Scan For Left(Nvl(sursa, ''), 5) == 'CACHE'
goLog.Log('cache cui=' + Transform(cui) + ' sursa=' + Alltrim(sursa) + ' data_sursa=' + Dtoc(Nvl(data_sursa, {})), 'VerificaListaCIF')
If Upper(Alltrim(sursa)) == 'CACHE_INDISP'
lnCacheIndisp = m.lnCacheIndisp + 1
Else
lnCache = m.lnCache + 1
Endif
Select (m.lcAlias)
Endscan
If m.lnCache + m.lnCacheIndisp > 0
goLog.Log('cache total=' + Transform(m.lnCache + m.lnCacheIndisp) + ' cache=' + Transform(m.lnCache) + ' cache_indisp=' + Transform(m.lnCacheIndisp), 'VerificaListaCIF')
Endif
Endif
Return m.lcAlias
@@ -2605,6 +2634,7 @@ Define Class VerificareANAF As Custom
*************************************
*** 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
*** Sare peste randurile provenite din cache (sursa incepe cu 'CACHE') - au fost deja salvate
*** Intoarce numarul de randuri salvate cu succes
*************************************
Function SalveazaIstoricDinCursor
@@ -2627,7 +2657,7 @@ Define Class VerificareANAF As Custom
Select (m.tcAlias)
lnRecnoInit = Recno()
Scan For cui <> 0
Scan For cui <> 0 And Left(Nvl(sursa, ''), 5) <> 'CACHE'
pcCodFiscal = Transform(cui)
pcFirma = Nvl(firma, '')
pcAdresa = Nvl(adresa, '')
@@ -2698,7 +2728,7 @@ Define Class VerificareANAF As Custom
Function CitesteIstoricPentruCoduri
Lparameters tcListaCoduriN, tdData, tcAlias, tcSursa
Local lcAlias, lcCursorIstoric, lcSql, ldData, lnZileCache, lcSelect, lcSursa
Local lcAlias, lcCursorIstoric, lcSql, ldData, lnZileCache, lcSelect, lcSursa, lcCondCod, lnTotalCod, lnTranse, lnTransa, lnI, lcTransa
*!* 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")
@@ -2727,6 +2757,21 @@ Define Class VerificareANAF As Custom
lcCursorIstoric = 'crsIstoricCacheTemp'
Use In (Select(m.lcCursorIstoric))
*!* 02.08.2026 marius.mutu: transe de maxim 1000 coduri legate cu OR - peste 1000 elemente "in (...)" da ORA-01795
lnTotalCod = Getwordcount(m.tcListaCoduriN, ',')
lnTranse = Ceiling(m.lnTotalCod / 1000)
lcCondCod = ''
For lnTransa = 1 To m.lnTranse
lcTransa = ''
For lnI = (m.lnTransa - 1) * 1000 + 1 To Min(m.lnTransa * 1000, m.lnTotalCod)
lcTransa = m.lcTransa + Iif(Empty(m.lcTransa), '', ',') + Getwordnum(m.tcListaCoduriN, m.lnI, ',')
Endfor
lcCondCod = m.lcCondCod + Iif(Empty(m.lcCondCod), '', ' or ') + 'cod_fiscal_n in (' + m.lcTransa + ')'
Endfor
If m.lnTranse > 1
lcCondCod = '(' + m.lcCondCod + ')'
Endif
*!* 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,
@@ -2739,7 +2784,7 @@ select cod_fiscal_n, firma, adresa, judet, regcom, dataorav_anaf,
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>>)
where <<m.lcCondCod>>
and dataorav_anaf is not null
and sysdate - dataorav_anaf <= ?pnZileCache)
where rn = 1