Files
comun/utile/Teste/cache_anaf/test_de_ce_rand_nou.prg
Marius Mutu 5c8a201438 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
2026-08-02 07:27:42 +03:00

240 lines
9.4 KiB
Plaintext

* test_de_ce_rand_nou.prg - izoleaza conditia din pack_istoric_cf.SAVE_ISTORIC_COD_FISCAL care
* declanseaza INSERT-ul pentru codul 1000012, desi verificarea a fost servita din cache si
* valorile par identice cu ultimul rand din istoric.
*
* Verifica pe rand: (a) cum arata exact sirul trimis din VFP (TRANSFORM(cui)), (b) daca
* interogarea de cautare a ultimului rand (where cod_fiscal = <sir>) chiar gaseste ceva,
* (c) octetii reali ai lui COD_FISCAL in randurile existente.
*
* Rulare: vfp9.exe -A -T "...\test_de_ce_rand_nou.prg" [cod]
LPARAMETERS tcCod
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, gnErorriSQL, gcUltimaEroareSQL
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_de_ce_rand_nou_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcTestLog)
gnErorriSQL = 0
gcUltimaEroareSQL = ''
ON ERROR DO ErrDeCe 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 WrLog5 WITH 'EROARE: conectare Oracle esuata - GATA'
QUIT
ENDIF
LOCAL loExecNou
loExecNou = CREATEOBJECT('oexec_fara_dialog3')
loExecNou.nHandle = gnHandle
goExecutor = loExecNou
DO WrLog5 WITH 'mediu OK, schema=' + gcS
LOCAL lcCod, lcSql
lcCod = IIF(TYPE('tcCod') = 'C' AND !EMPTY(tcCod), ALLTRIM(tcCod), '1000012')
DO WrLog5 WITH 'cod analizat: ' + lcCod
* (a) sirul construit exact ca in SalveazaIstoricDinCursor: Transform(cui) pe un camp N(13)
IF USED('crsSim')
USE IN crsSim
ENDIF
CREATE CURSOR crsSim (cui N(13))
INSERT INTO crsSim (cui) VALUES (VAL(lcCod))
SELECT crsSim
GO TOP
LOCAL lcTrimis
lcTrimis = TRANSFORM(crsSim.cui)
DO WrLog5 WITH '(a) TRANSFORM(cui) = [' + lcTrimis + '] len=' + TRANSFORM(LEN(lcTrimis))
* (b) octetii lui COD_FISCAL in randurile existente
lcSql = 'SELECT ID, DUMP(COD_FISCAL) AS D, LENGTH(COD_FISCAL) AS L, PLATITORTVAMFIN AS PM,'
lcSql = lcSql + ' PLATITORTVAVIES AS PV, INACTIV AS IN_, TVAINCASARE AS TI, SPLITTVA AS SP'
lcSql = lcSql + ' FROM ISTORIC_CODURI_FISCALE WHERE COD_FISCAL_N = ' + lcCod + ' ORDER BY ID'
IF goExecutor.oExecuta(lcSql, 'crsD')
DO WrLog5 WITH '(b) randuri existente:'
SELECT crsD
SCAN
DO WrLog5 WITH ' id=' + TRANSFORM(crsD.ID) + ' len=' + TRANSFORM(crsD.L) + ;
' pm=' + TRANSFORM(NVL(crsD.PM, -1)) + ' pv=' + TRANSFORM(NVL(crsD.PV, -1)) + ;
' inactiv=' + TRANSFORM(NVL(crsD.IN_, -1)) + ' tvainc=' + TRANSFORM(NVL(crsD.TI, -1)) + ;
' split=' + TRANSFORM(NVL(crsD.SP, -1))
DO WrLog5 WITH ' ' + ALLTRIM(NVL(crsD.D, ''))
SELECT crsD
ENDSCAN
USE IN (SELECT('crsD'))
ENDIF
* (b2) au datele de interval componenta de ORA? (VFP trimite inapoi doar data, fara ora)
lcSql = 'SELECT ID, TO_CHAR(DATA_INCEPUT_TVAINC,' + CHR(39) + 'DD.MM.YYYY HH24:MI:SS' + CHR(39) + ') AS T1,'
lcSql = lcSql + ' TO_CHAR(DATA_INCEPUT_SCPTVA,' + CHR(39) + 'DD.MM.YYYY HH24:MI:SS' + CHR(39) + ') AS T2,'
lcSql = lcSql + ' TO_CHAR(DATA_INACTIVARE,' + CHR(39) + 'DD.MM.YYYY HH24:MI:SS' + CHR(39) + ') AS T3'
lcSql = lcSql + ' FROM ISTORIC_CODURI_FISCALE WHERE COD_FISCAL_N = ' + lcCod + ' ORDER BY ID'
IF goExecutor.oExecuta(lcSql, 'crsT')
DO WrLog5 WITH '(b2) ora din datele de interval:'
SELECT crsT
SCAN
DO WrLog5 WITH ' id=' + TRANSFORM(crsT.ID) + ' iInc=[' + ALLTRIM(NVL(crsT.T1, '')) + ']' + ;
' iScp=[' + ALLTRIM(NVL(crsT.T2, '')) + '] inact=[' + ALLTRIM(NVL(crsT.T3, '')) + ']'
SELECT crsT
ENDSCAN
USE IN (SELECT('crsT'))
ENDIF
* (c) exact interogarea de cautare din pachet, cu sirul trimis din VFP
PRIVATE pcCautat
pcCautat = lcTrimis
lcSql = 'SELECT ID FROM (SELECT ID FROM ISTORIC_CODURI_FISCALE WHERE COD_FISCAL = ?pcCautat'
lcSql = lcSql + ' ORDER BY DATAORAV DESC, ID DESC) WHERE ROWNUM = 1'
IF goExecutor.oExecuta(lcSql, 'crsL')
DO WrLog5 WITH '(c) cautarea din pachet (cod_fiscal = sirul trimis): ' + ;
IIF(RECCOUNT('crsL') > 0, 'GASIT id=' + TRANSFORM(crsL.ID), 'NU GASESTE NIMIC -> pachetul face INSERT')
USE IN (SELECT('crsL'))
ENDIF
* (d) acelasi lucru, dar cautand pe cod_fiscal_n
lcSql = 'SELECT ID FROM (SELECT ID FROM ISTORIC_CODURI_FISCALE WHERE COD_FISCAL_N = ' + lcCod
lcSql = lcSql + ' ORDER BY DATAORAV DESC, ID DESC) WHERE ROWNUM = 1'
IF goExecutor.oExecuta(lcSql, 'crsL2')
DO WrLog5 WITH '(d) aceeasi cautare pe COD_FISCAL_N: ' + ;
IIF(RECCOUNT('crsL2') > 0, 'GASIT id=' + TRANSFORM(crsL2.ID), 'nu gaseste')
USE IN (SELECT('crsL2'))
ENDIF
* (e) doua apeluri identice de salvare, la rand: al doilea NU ar trebui sa mai adauge rand
PUBLIC gnWm5
gnWm5 = 0
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsW5')
gnWm5 = crsW5.IDMAX
USE IN (SELECT('crsW5'))
ENDIF
DO WrLog5 WITH '(e) watermark inainte de cele doua salvari: ' + TRANSFORM(gnWm5)
DO SalveazaOData WITH lcCod, 1
DO SalveazaOData WITH lcCod, 2
lcSql = 'SELECT ID, COD_FISCAL_N FROM ISTORIC_CODURI_FISCALE WHERE ID > ' + TRANSFORM(gnWm5) + ' ORDER BY ID'
IF goExecutor.oExecuta(lcSql, 'crsN5')
DO WrLog5 WITH ' randuri adaugate de cele doua salvari: ' + TRANSFORM(RECCOUNT('crsN5'))
SELECT crsN5
SCAN
DO WrLog5 WITH ' id=' + TRANSFORM(crsN5.ID) + ' cod=' + TRANSFORM(crsN5.COD_FISCAL_N)
SELECT crsN5
ENDSCAN
USE IN (SELECT('crsN5'))
ENDIF
IF gnWm5 > 0
=goExecutor.oExecuta('DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ' + TRANSFORM(gnWm5))
=goExecutor.oExecuta('COMMIT')
DO WrLog5 WITH 'curatenie: sterse randurile cu ID > ' + TRANSFORM(gnWm5)
ENDIF
DO WrLog5 WITH 'GATA ' + TTOC(DATETIME())
QUIT
*** apeleaza pachetul cu EXACT parametrii pe care ii trimite SalveazaIstoricDinCursor
*** pentru un rand venit din cache (valorile citite din ultimul rand de istoric)
PROCEDURE SalveazaOData
LPARAMETERS tcCod, tnPas
LOCAL lcSql, lcSel
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
lcSel = SELECT()
lcSql = 'SELECT FIRMA, ADRESA, JUDET, REGCOM, INACTIV, TVAINCASARE, SPLITTVA,'
lcSql = lcSql + ' DATA_INCEPUT_SCPTVA, DATA_SFARSIT_SCPTVA, DATA_ANUL_IMP_SCPTVA,'
lcSql = lcSql + ' DATA_INCEPUT_TVAINC, DATA_SFARSIT_TVAINC, DATA_INACTIVARE, DATA_REACTIVARE,'
lcSql = lcSql + ' DATA_INCEPUT_SPLITTVA, DATA_ANULARE_SPLITTVA'
lcSql = lcSql + ' FROM (SELECT * FROM ISTORIC_CODURI_FISCALE WHERE COD_FISCAL_N = ' + tcCod
lcSql = lcSql + ' ORDER BY ID DESC) WHERE ROWNUM = 1'
IF !goExecutor.oExecuta(lcSql, 'crsSrc')
DO WrLog5 WITH ' pas ' + TRANSFORM(tnPas) + ': nu pot citi randul sursa'
RETURN
ENDIF
pcCodFiscal = ALLTRIM(tcCod)
pcFirma = ALLTRIM(NVL(crsSrc.FIRMA, ''))
pcAdresa = ALLTRIM(NVL(crsSrc.ADRESA, ''))
pcJudet = ALLTRIM(NVL(crsSrc.JUDET, ''))
pcRegCom = ALLTRIM(NVL(crsSrc.REGCOM, ''))
pcCodPostal = ''
pcTelefon = ''
pcFax = ''
pcDataTvamfin = ''
pnPlatitorTvaMfin = 0
pcStare = ''
pnPlatitorTvaVies = 0
pnInterogareVies = 0
pnIdUtil = gnIdUtil
pnInactiv = NVL(crsSrc.INACTIV, 0)
pnTvaIncasare = NVL(crsSrc.TVAINCASARE, 0)
pnSplitTva = NVL(crsSrc.SPLITTVA, 0)
pdInceputScpTva = NVL(crsSrc.DATA_INCEPUT_SCPTVA, {})
pdSfarsitScpTva = NVL(crsSrc.DATA_SFARSIT_SCPTVA, {})
pdAnulImpScpTva = NVL(crsSrc.DATA_ANUL_IMP_SCPTVA, {})
pdInceputTvaInc = NVL(crsSrc.DATA_INCEPUT_TVAINC, {})
pdSfarsitTvaInc = NVL(crsSrc.DATA_SFARSIT_TVAINC, {})
pdInactivare = NVL(crsSrc.DATA_INACTIVARE, {})
pdReactivare = NVL(crsSrc.DATA_REACTIVARE, {})
pdInceputSplitTva = NVL(crsSrc.DATA_INCEPUT_SPLITTVA, {})
pdAnulareSplitTva = NVL(crsSrc.DATA_ANULARE_SPLITTVA, {})
pnDinCache = 1
USE IN (SELECT('crsSrc'))
lcSql = "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(lcSql)
=goExecutor.oExecuta('COMMIT')
DO WrLog5 WITH ' pas ' + TRANSFORM(tnPas) + ': salvare OK (pnDinCache=1)'
ELSE
DO WrLog5 WITH ' pas ' + TRANSFORM(tnPas) + ': salvare ESUATA'
ENDIF
SELECT (lcSel)
ENDPROC
PROCEDURE WrLog5
LPARAMETERS tcText
STRTOFILE(TRANSFORM(tcText) + CHR(13) + CHR(10), gcTestLog, .T.)
ENDPROC
PROCEDURE ErrDeCe
LPARAMETERS tnError, tcMessage, tcProgram, tnLine
DO WrLog5 WITH 'EROARE ' + TRANSFORM(tnError) + ' [' + TRANSFORM(tcMessage) + '] in ' + ;
TRANSFORM(tcProgram) + ' linia ' + TRANSFORM(tnLine)
RETURN
ENDPROC
DEFINE CLASS oexec_fara_dialog3 AS oexecutor
FUNCTION oExecuta
LPARAMETERS tcSql, tcCursor, tlProgress, tcTitluProgress, tnHandle, tlShowError, tlQuitOnError, tlReconnect
LOCAL lcSql, lcCursor, lnHandle, lnRez
lcSql = IIF(EMPTY(tcSql), This.cSql, tcSql)
lcCursor = IIF(EMPTY(tcCursor), This.cCursor, tcCursor)
lnHandle = IIF(EMPTY(tnHandle), This.nHandle, tnHandle)
lnRez = This.oExecute(lcSql, lcCursor, tlProgress, tcTitluProgress, lnHandle)
IF lnRez < 1
gnErorriSQL = gnErorriSQL + 1
gcUltimaEroareSQL = TRANSFORM(This.cEroare)
DO WrLog5 WITH ' SQL ESUAT: ' + LEFT(TRANSFORM(This.cEroare), 120)
ENDIF
RETURN (lnRez >= 1)
ENDFUNC
ENDDEFINE