verificare partener: garda pe cont NULL, hook-uri de disciplina, docs compactate

- ooperatii_comune: verific_partener nu mai construieste SQL NULL cand contul
  primit e NULL (EMPTY(.NULL.) e .F. in VFP)
- utile\context_watch.ps1 si utile\docs_revizie_check.ps1: masurarea contextului
  sesiunii si cadenta reviziei de documentatie, prin hook-uri Claude Code
  (instalare in docs\monitorizare-context.md)
- reguli_lucru: delegare la subagenti, modificari minime si scoped, scrierea si
  revizuirea documentatiei, changelog strictul necesar (regulile 3, 6, 9, 11, 12)
- scripturi-migrare-db: continutul unui script (scoped, fara select, idempotent)
- teste noi pentru cele doua erori din achizitia de import
- restul documentatiei compactata, fara pierdere de reguli

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYbiinqXxdEqXi53x4Ro7K
This commit is contained in:
2026-08-02 22:30:44 +03:00
parent 20323d22b3
commit c4d869921d
28 changed files with 1788 additions and 867 deletions

View File

@@ -0,0 +1,543 @@
* test_repro_partener_scc_null.prg
* REPRODUCERE: "achizitie din import > interna", dublu click pe coloana "Partener credit"
* (Grid1.cPartC.Text1.DblClick -> LostFocus(.T.) -> verific_partener in ooperatii_comune.prg).
* Cand contul creditor al randului (introdc.scc) vine NULL din nota contabila configurata,
* SQL-ul construit prin concatenare in verific_partener devine .NULL., iar garda din
* oExecutor.oExecute (If Empty(tcSql)) NU il prinde - EMPTY(.NULL.) e .F. in VFP - deci
* SQLEXEC primeste un statement NULL si da eroarea
* "SQL statement parameter is required for non-prepared SQLEXEC() calls." (OEXECUTOR.OEXECUTE)
*
* Ramura cu valuta merge pentru ca acolo nota contabila are contul creditor completat (401).
*
* Scenarii, pe formularul real import_nota(.T.) + dialogul real import_adauga_factura:
* A. rand cu scc NULL -> dublu click pe Partener credit: SQL-ul ajuns la executor e NULL (BUG)
* B. acelasi rand cu scc = '401' -> dublu click: SQL valid (comportamentul ramurii cu valuta)
*
* Rulare: powershell -ExecutionPolicy Bypass -File test_repro_partener_scc_null.ps1
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET DECIMALS TO 4
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcUILog
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_repro_partener_scc_null_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
PUBLIC gnAsserts, gnPass, gcSqlPrimit, glSqlNull, gnApeluri
STORE 0 TO gnAsserts, gnPass, gnApeluri
gcSqlPrimit = ''
glSqlNull = .F.
ON ERROR DO PnErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
TRY
LOCAL gcAppPath, lcPath
gcAppPath = "D:\ROA\ROAGEST\"
SET DEFAULT TO (gcAppPath)
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
SET PATH TO &lcPath ADDITIVE
DO PnLog WITH 'SET PATH OK'
*----- CLASE -----
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
SET CLASSLIB TO GESTIUNI ADDITIVE
SET CLASSLIB TO CAUT ADDITIVE
SET CLASSLIB TO BAZA ADDITIVE
SET CLASSLIB TO comun ADDITIVE
SET CLASSLIB TO accessibility.vcx ADDITIVE
SET CLASSLIB TO messagebox ADDITIVE
SET CLASSLIB TO registry ADDITIVE
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
SET CLASSLIB TO DECABAZA ADDITIVE
SET CLASSLIB TO onomenclatoare ADDITIVE
SET CLASSLIB TO stocuri.vcx ADDITIVE
SET CLASSLIB TO rulaje.vcx ADDITIVE
SET CLASSLIB TO ointroduceri ADDITIVE
SET CLASSLIB TO ointroduceri_web ADDITIVE
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
SET CLASSLIB TO overificari ADDITIVE
SET CLASSLIB TO ferestre_oracle ADDITIVE
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
SET CLASSLIB TO configurare.vcx ADDITIVE
SET CLASSLIB TO serii_numere.vcx ADDITIVE
SET CLASSLIB TO omodificari.vcx ADDITIVE
SET CLASSLIB TO ocompensari.vcx ADDITIVE
SET CLASSLIB TO caut_ora ADDITIVE
SET CLASSLIB TO onote_contabile ADDITIVE
SET CLASSLIB TO otoolbar ADDITIVE
SET CLASSLIB TO bon_fisc ADDITIVE
SET CLASSLIB TO onom_articole ADDITIVE
SET CLASSLIB TO onom_retete ADDITIVE
SET CLASSLIB TO orapoarte ADDITIVE
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
SET CLASSLIB TO orapoarte_parametri ADDITIVE
SET CLASSLIB TO ONOM_CURS ADDITIVE
SET CLASSLIB TO ctl32_statusbar_fals.vcx ADDITIVE
SET CLASSLIB TO ctl32_common.vcx ADDITIVE
SET CLASSLIB TO ctl32_structs.vcx ADDITIVE
SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE
SET CLASSLIB TO ctl32_balloontip.vcx ADDITIVE
SET CLASSLIB TO ocriterii.vcx ADDITIVE
SET CLASSLIB TO oavize.vcx ADDITIVE
SET CLASSLIB TO onomenclatoare2 ADDITIVE
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
SET CLASSLIB TO oimportxml.vcx ADDITIVE
SET CLASSLIB TO excelxml.vcx ADDITIVE
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
DO PnLog WITH 'SET CLASSLIB OK'
*----- PROCEDURI (mock-urile PRIMELE) -----
SET PROCEDURE TO PROCEDURI
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
SET PROCEDURE TO acces_meniu ADDITIVE
SET PROCEDURE TO cauta_alfa ADDITIVE
SET PROCEDURE TO pmenu ADDITIVE
SET PROCEDURE TO proceduri_comune ADDITIVE
SET PROCEDURE TO quitapp ADDITIVE
SET PROCEDURE TO init_program ADDITIVE
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
SET PROCEDURE TO orapoarte.prg ADDITIVE
SET PROCEDURE TO mesaje ADDITIVE
SET PROCEDURE TO oserii_numere.prg ADDITIVE
SET PROCEDURE TO oexport.prg ADDITIVE
SET PROCEDURE TO wwConfig.prg ADDITIVE
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
SET PROCEDURE TO validare.prg ADDITIVE
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
SET PROCEDURE TO updateserver.prg ADDITIVE
SET PROCEDURE TO oinainte_de.prg ADDITIVE
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
SET PROCEDURE TO OINTRODUCERI ADDITIVE
SET PROCEDURE TO oHeader.prg ADDITIVE
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
SET PROCEDURE TO osecurity ADDITIVE
SET PROCEDURE TO ocautare ADDITIVE
SET PROCEDURE TO orefaceri ADDITIVE
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
SET PROCEDURE TO ini.prg ADDITIVE
SET PROCEDURE TO odocumente.prg ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
SET PROCEDURE TO wwutils.prg ADDITIVE
SET PROCEDURE TO iniacces.prg ADDITIVE
SET PROCEDURE TO version.prg ADDITIVE
SET PROCEDURE TO xdate.prg ADDITIVE
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
DO PnLog WITH 'SET PROCEDURE OK'
*----- Globale -----
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPPretV, gnPPretVal
STORE 2 TO gnPc, gnPval
gnPcant = 3
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
gl406 = .T.
gcS = 'CONTAFIN'
gnAn = YEAR(DATE())
gnLuna = MONTH(DATE())
gnIdFirma = 110
gnIdSucursala = 110
gcAcces = "1;2;3;4;5;6;7;8;"
gcFirma = gcS
PUBLIC nror(65000)
PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip
gnMockRaspuns = 6
gcMockUltimMesaj = ''
gnMockUltimTip = 0
PUBLIC gnButon, gcTempPath, gnHandle, gnTipGest, gcCondSucursala
gnButon = 1
gcTempPath = ADDBS(SYS(2023))
gnHandle = -1
gnTipGest = 0
gcCondSucursala = ''
PUBLIC goExecutor, goApp
goExecutor = CREATEOBJECT('spionexecutor')
goApp = CREATEOBJECT('dummyapp')
*----- poAct: antetul notei interne (lei) -----
PUBLIC poAct
poAct = CREATEOBJECT('Custom')
poAct.AddProperty('nume_val', '')
poAct.AddProperty('curs', 1)
poAct.AddProperty('proc_tva', 1.21)
poAct.AddProperty('nnir', 0)
poAct.AddProperty('id_valuta', 0)
poAct.AddProperty('id_fdoc', 1)
poAct.AddProperty('fdoc', 'FACTURA')
poAct.AddProperty('id_partc', 463)
poAct.AddProperty('partc', 'R.A.J.A. C-TA')
poAct.AddProperty('serie_act', '')
poAct.AddProperty('dataact', DATE())
poAct.AddProperty('tva_incasare', 1)
poAct.AddProperty('id_set', 1)
poAct.AddProperty('id_gestin', 1)
IF USED('jtva_coloane2')
USE IN ('jtva_coloane2')
ENDIF
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. NEEX. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. NEEX. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
IF USED('saft_taxtable')
USE IN ('saft_taxtable')
ENDIF
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
INDEX ON taxcode TAG taxcode
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
VALUES ('', 0, '', 0, 1, 1, 1, 1)
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
VALUES ('301104-Achizitii interne cota 21%', 301104, '', 21, 1, 0, 1, 0)
*----- introdc gol + sablonul notei interne: contul creditor (scc) vine NULL din nomenclator -----
DO CreeazaIntrodcNull WITH 'introdc'
DO CreeazaIntrodcNull WITH 'introdc_sablon'
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
id_jtva_coloana, ptva, explicatie_tva) ;
VALUES ('371', .NULL., 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. NEEX. 21%')
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
id_jtva_coloana, ptva, explicatie_tva) ;
VALUES ('4428', .NULL., 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. NEEX. 21%')
GO TOP IN introdc_sablon
IF USED('rul_temp')
USE IN ('rul_temp')
ENDIF
CREATE CURSOR rul_temp (denumire C(100), codmat C(30), cant N(14,3), pret_val N(18,4), ;
pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), acont C(20), serie C(30), ;
lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
SELECT introdc
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
SET ORDER TO ord_doc
PRIVATE tlIntern
tlIntern = .T.
DO PnLog WITH 'CREATEOBJECT(import_nota, .T. - achizitie interna)'
SELECT introdc
PUBLIC goObj
goObj = CREATEOBJECT('IMPORT_nota', .T.)
IF VARTYPE(goObj) <> 'O'
DO PnLog WITH 'FAIL: instantiere import_nota'
QUIT
ENDIF
goObj.lDialogAratat = .T.
goObj.oact = poAct
goObj.WindowType = 0
goObj.Visible = .T.
goObj.Show()
goObj.WindowState = 2
DOEVENTS FORCE
SELECT rul_temp
ZAP
goObj.gridart.Refresh()
DOEVENTS FORCE
*========================= factura interna, prin dialogul real =========================
PUBLIC goDlg
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
goDlg.cFelDoc = 'FACTURA'
goDlg.nIdFdoc = 1
goDlg.nNract = 15000
goDlg.dDataAct = DATE()
goDlg.nIdPartener = 463
goDlg.cPartener = 'R.A.J.A. C-TA'
goDlg.cExplicatia = 'Achizitie interna'
goDlg.nSuma = 1000
goDlg.nSumaLei = 0
goDlg.nCurs = 0
goDlg.nIdValuta = 0
goDlg.cValuta = ''
goDlg.chkInValutaCont.Value = 0
goDlg.chkParticipaValuta.Value = 1
goDlg.nIdExplicatieTva = 208
goDlg.cExplicatieTva = 'ACH. INT. NEEX. 21%'
goDlg.nProcentTva = 21
goDlg.optTipTva.Value = 1
goDlg.optTipTva.InteractiveChange()
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
DO PnLog WITH 'dialog completat, valideaza() = ' + TRANSFORM(goDlg.valideaza())
PUBLIC goT
goT = CREATEOBJECT('Empty')
=ADDPROPERTY(goT,'serie_act',ALLTRIM(NVL(goDlg.cSerieAct,'')))
=ADDPROPERTY(goT,'nract',goDlg.nNract)
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
=ADDPROPERTY(goT,'suma',goDlg.nSuma)
=ADDPROPERTY(goT,'suma_val',0)
=ADDPROPERTY(goT,'in_valuta',0)
=ADDPROPERTY(goT,'participa_valuta',.T.)
=ADDPROPERTY(goT,'id_valuta',0)
=ADDPROPERTY(goT,'curs',0)
=ADDPROPERTY(goT,'nume_val','')
=ADDPROPERTY(goT,'cTipTva','F')
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
=ADDPROPERTY(goT,'disc_baza_lei',0)
=ADDPROPERTY(goT,'disc_baza_val',0)
DO PnLog WITH 'do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
goDlg.Hide()
DOEVENTS FORCE
DO DumpIntrodc
*========================= SCENARIU A: scc NULL (asa vine din nota interna) =========================
SELECT introdc
LOCATE FOR tip_rand == 'B'
DO Assert WITH 'A0-randul B al facturii exista', IIF(FOUND(),1,0), 1
DO Assert WITH 'A1-introdc.scc este NULL pe randul B (ca in nota interna)', IIF(ISNULL(introdc.scc),1,0), 1
gcSqlPrimit = ''
glSqlNull = .F.
gnApeluri = 0
DO PnLog WITH 'SCENARIU A: dublu click pe Partener credit, cu scc NULL'
TRY
goObj.Grid1.cPartC.Text1.DblClick()
CATCH TO loExcA
DO PnLog WITH ' EXCEPTIE ' + TRANSFORM(loExcA.ErrorNo) + ' [' + loExcA.Message + '] in ' + loExcA.Procedure + ':' + TRANSFORM(loExcA.LineNo)
ENDTRY
DOEVENTS FORCE
DO PnLog WITH ' apeluri executor = ' + TRANSFORM(gnApeluri) + ' SQL NULL/gol = ' + TRANSFORM(glSqlNull)
DO Assert WITH 'A2-executorul NU primeste SQL NULL/gol la dublu click (scc NULL)', IIF(glSqlNull,1,0), 0
SELECT introdc
LOCATE FOR tip_rand == 'B'
DO Assert WITH 'A3-partenerul randului ramane neschimbat dupa dublu click (scc NULL)', NVL(introdc.id_partc,0), 463
*========================= SCENARIU B: scc = 401 (ca pe ramura cu valuta) =========================
SELECT introdc
LOCATE FOR tip_rand == 'B'
REPLACE scc WITH '401'
gcSqlPrimit = ''
glSqlNull = .F.
gnApeluri = 0
DO PnLog WITH 'SCENARIU B: dublu click pe Partener credit, cu scc = 401'
TRY
goObj.Grid1.cPartC.Text1.DblClick()
CATCH TO loExcB
DO PnLog WITH ' EXCEPTIE ' + TRANSFORM(loExcB.ErrorNo) + ' [' + loExcB.Message + '] in ' + loExcB.Procedure + ':' + TRANSFORM(loExcB.LineNo)
ENDTRY
DOEVENTS FORCE
DO PnLog WITH ' apeluri executor = ' + TRANSFORM(gnApeluri) + ' SQL NULL/gol = ' + TRANSFORM(glSqlNull)
DO PnLog WITH ' ultimul SQL = [' + LEFT(NVL(gcSqlPrimit,'<NULL>'), 200) + ']'
DO Assert WITH 'B1-executorul NU primeste SQL NULL/gol la dublu click (scc = 401)', IIF(glSqlNull,1,0), 0
DO PnLog WITH '========================================================='
DO PnLog WITH 'REZULTAT: ' + TRANSFORM(gnPass) + '/' + TRANSFORM(gnAsserts) + ' assert-uri PASS'
IF gnPass = gnAsserts
DO PnLog WITH 'REZULTAT: PASS'
ELSE
DO PnLog WITH 'REZULTAT: FAIL'
ENDIF
CATCH TO loExc
DO PnLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
ENDTRY
QUIT
*==================================================================================
PROCEDURE PnLog
LPARAMETERS tcMsg
SET SAFETY OFF
LOCAL lcL
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
ENDPROC
PROCEDURE PnErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO PnLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE Assert
LPARAMETERS tcNume, tnActual, tnAsteptat
gnAsserts = gnAsserts + 1
IF tnActual = tnAsteptat
gnPass = gnPass + 1
DO PnLog WITH ' PASS ' + tcNume
ELSE
DO PnLog WITH ' FAIL ' + tcNume + ' (actual=' + TRANSFORM(tnActual) + ', asteptat=' + TRANSFORM(tnAsteptat) + ')'
ENDIF
ENDPROC
PROCEDURE DumpIntrodc
LOCAL lnSel
lnSel = SELECT()
DO PnLog WITH 'DUMP introdc:'
SELECT introdc
SCAN
DO PnLog WITH ' recno=' + TRANSFORM(RECNO()) + ' tip_rand=' + tip_rand + ' nract=' + TRANSFORM(nract) + ;
' scd=[' + NVL(ALLTRIM(scd),'<NULL>') + '] scc=' + IIF(ISNULL(scc),'<NULL>','[' + ALLTRIM(NVL(scc,'')) + ']') + ;
' id_partc=' + TRANSFORM(NVL(id_partc,0)) + ' partc=[' + ALLTRIM(NVL(partc,'')) + '] suma=' + TRANSFORM(suma)
ENDSCAN
SELECT (lnSel)
ENDPROC
*-- introdc ca in productie: coloanele de conturi vin NULLABLE din Oracle (vnote_contabile)
PROCEDURE CreeazaIntrodcNull
LPARAMETERS tcAlias
IF USED(tcAlias)
USE IN (tcAlias)
ENDIF
CREATE CURSOR (tcAlias) ( ;
id_note N(14), explicatia C(100), scd C(10) NULL, ascd C(20) NULL, scc C(10) NULL, ascc C(20) NULL, ;
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
ENDPROC
PROCEDURE CreeazaJtvaColoaneView
LPARAMETERS tcCursor
IF USED(m.tcCursor)
USE IN (m.tcCursor)
ENDIF
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
VALUES (208, 'ACH. INT. NEEX. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
VALUES (209, 'TVA ACH. INT. NEEX. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
ENDPROC
DEFINE CLASS dummyapp AS Custom
PROCEDURE ReadIni
LPARAMETERS tcSection, tcKey
RETURN ''
ENDPROC
PROCEDURE WriteIni
LPARAMETERS tcSection, tcKey, tcValue
RETURN .T.
ENDPROC
ENDDEFINE
*-- Acelasi contract ca oExecutor.oExecute pe parametrul SQL: in productie, un statement
*-- NULL/gol ajunge la SQLEXEC si da eroarea 1466. Aici doar il inregistram.
DEFINE CLASS spionexecutor AS Custom
cEroare = ''
PROCEDURE oExecute
LPARAMETERS tcSql, tcCursor
gnApeluri = gnApeluri + 1
gcSqlPrimit = tcSql
IF ISNULL(m.tcSql) OR EMPTY(NVL(m.tcSql,''))
glSqlNull = .T.
DO PnLog WITH ' >>> executor: SQL ' + IIF(ISNULL(m.tcSql),'NULL','GOL') + ;
' (EMPTY(tcSql)=' + TRANSFORM(EMPTY(m.tcSql)) + ' - garda din oExecute nu il prinde)'
RETURN -1
ENDIF
IF !EMPTY(m.tcCursor) AND USED(m.tcCursor)
USE IN (m.tcCursor)
ENDIF
IF 'VCONFIG_CONT_IREG' $ UPPER(m.tcSql)
CREATE CURSOR (m.tcCursor) (valoare N(10))
INSERT INTO (m.tcCursor) VALUES (0)
RETURN 1
ENDIF
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
DO CreeazaJtvaColoaneView WITH m.tcCursor
RETURN 1
ENDIF
IF UPPER(ALLTRIM(NVL(m.tcCursor,''))) == 'RUL_TEMP'
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
RETURN 1
ENDIF
IF !EMPTY(m.tcCursor)
CREATE CURSOR (m.tcCursor) (id_temp N(1))
ENDIF
RETURN 1
ENDPROC
PROCEDURE oExecuta
LPARAMETERS tcSql, tcCursor
gnApeluri = gnApeluri + 1
gcSqlPrimit = tcSql
IF ISNULL(m.tcSql) OR EMPTY(NVL(m.tcSql,''))
glSqlNull = .T.
DO PnLog WITH ' >>> executor(oExecuta): SQL ' + IIF(ISNULL(m.tcSql),'NULL','GOL')
RETURN .F.
ENDIF
IF !EMPTY(m.tcCursor)
IF USED(m.tcCursor)
USE IN (m.tcCursor)
ENDIF
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
ELSE
CREATE CURSOR (m.tcCursor) (id_temp N(1))
ENDIF
ENDIF
RETURN .T.
ENDPROC
PROCEDURE oSelect2Value
LPARAMETERS tcSql, toValue
gnApeluri = gnApeluri + 1
gcSqlPrimit = tcSql
IF ISNULL(m.tcSql) OR EMPTY(NVL(m.tcSql,''))
glSqlNull = .T.
DO PnLog WITH ' >>> executor(oSelect2Value): SQL ' + IIF(ISNULL(m.tcSql),'NULL','GOL')
RETURN -1
ENDIF
toValue = ''
RETURN 1
ENDPROC
PROCEDURE oReset
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,18 @@
# test_repro_partener_scc_null.ps1 - rulare headless (fara harness/screenshots) a testului de
# reproducere pentru dublu click pe "Partener credit" cu contul creditor NULL.
# Rulare: powershell -ExecutionPolicy Bypass -File test_repro_partener_scc_null.ps1
$ErrorActionPreference = 'Stop'
$Teste = $PSScriptRoot
$Prg = Join-Path $Teste 'test_repro_partener_scc_null.prg'
$Fxp = [IO.Path]::ChangeExtension($Prg, '.fxp')
$Log = Join-Path $Teste 'test_repro_partener_scc_null_log.txt'
$Vfp = 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe'
Remove-Item $Fxp, $Log -ErrorAction SilentlyContinue
$p = Start-Process -FilePath $Vfp -ArgumentList '-A', '-T', "`"$Prg`"" -PassThru
if (-not $p.WaitForExit(240000)) {
$p.Kill()
throw 'TIMEOUT: testul nu s-a terminat in 240s'
}
if (-not (Test-Path $Log)) { throw "Lipseste logul $Log" }
Get-Content $Log

View File

@@ -0,0 +1,223 @@
* test_repro_anaf_path_nfjson.prg
* REPRODUCERE: in ROAGEST, la alegerea partenerului, banda arata mereu
* "ANAF nu a raspuns - verificare sarita", desi ANAF raspunde 200 pe aceeasi masina.
* Ipoteza testata: SET PATH din Programe\roagest.prg NU contine COMUN\UTILE\NFJSON,
* deci VerificareANAF.Init (validare.prg:1877, "Set Procedure To nfjsonread.prg Additive")
* arunca, CREATEOBJECT('VerificareANAF') esueaza in ANAF_VerificaCuiSingle si clasa de
* esec devine FARA_RASPUNS -> banda gri + serviciul ANAF marcat CAZUT pentru 10 minute.
*
* Scenarii:
* A. path ca in roagest.prg (fara NFJSON) -> CREATEOBJECT esueaza, clasa esec = FARA_RASPUNS
* B. acelasi path + COMUN\UTILE\NFJSON -> verdict ANAF real pentru CUI 13791411 (ARAFURA)
*
* Rulare: powershell -ExecutionPolicy Bypass -File test_repro_anaf_path_nfjson.ps1
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET DECIMALS TO 4
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcUILog, gnAsserts, gnPass
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\partener_anaf\test_repro_anaf_path_nfjson_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
STORE 0 TO gnAsserts, gnPass
ON ERROR DO PnErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
LOCAL lcCui, llNegasit, lcClasa, loRez, loEx, lcPath, gcAppPath
lcCui = '13791411'
TRY
*----- SET PATH exact ca in Programe\roagest.prg (fara COMUN\UTILE\NFJSON) -----
gcAppPath = "D:\ROA\ROAGEST\"
SET DEFAULT TO (gcAppPath)
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
SET PATH TO &lcPath
DO PnLog WITH 'SET PATH (ca in roagest.prg) OK'
SET PROCEDURE TO validare.prg
SET PROCEDURE TO ocautare.prg ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
DO PnLog WITH 'SET PROCEDURE OK: ' + SET('Procedure')
PUBLIC gnIdUtil, goExecutor, goLog, poLog
gnIdUtil = -3
goExecutor = CREATEOBJECT('executor_spion')
LOCAL lcLogApp
lcLogApp = "D:\ROA\ROAGEST\COMUN\utile\Teste\partener_anaf\test_repro_anaf_path_nfjson_applog.txt"
STRTOFILE('', lcLogApp)
poLog = NEWOBJECT("Log_Mesaje", "Log_Mesaje.prg", "", lcLogApp)
goLog = poLog
*===== A1: CREATEOBJECT('VerificareANAF') pe path-ul din roagest.prg =====
loEx = .NULL.
TRY
LOCAL loVerif
loVerif = CREATEOBJECT('VerificareANAF')
DO PnLog WITH 'A1 CREATEOBJECT(VerificareANAF): OK (nu reproduce)'
CATCH TO loEx
DO PnLog WITH 'A1 CREATEOBJECT(VerificareANAF): EXCEPTIE ' + loEx.Message + ;
' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
DO PnAssert WITH 'A1 VerificareANAF nu se poate instantia fara NFJSON pe path', !ISNULL(loEx)
*===== A2: fluxul real ANAF_VerificaCuiSingle -> clasa de esec =====
llNegasit = .F.
lcClasa = ''
loRez = ANAF_VerificaCuiSingle(m.lcCui, DATE(), @llNegasit, @lcClasa)
DO PnLog WITH 'A2 ANAF_VerificaCuiSingle: VARTYPE=' + VARTYPE(loRez) + ;
' negasit=' + TRANSFORM(llNegasit) + ' clasa_esec=[' + lcClasa + ']'
DO PnAssert WITH 'A2 clasa esec = FARA_RASPUNS (banda "ANAF nu a raspuns")', lcClasa == 'FARA_RASPUNS'
*===== A3: banda din ocautare - ANAF_StarePartener pe acelasi cod =====
LOCAL llNecesita, lcClasa3, loStare3
llNecesita = .F.
llNegasit = .F.
lcClasa3 = ''
loStare3 = ANAF_StarePartener(m.lcCui, DATE(), .F., @llNecesita, @llNegasit, @lcClasa3, 0)
DO PnLog WITH 'A3 ANAF_StarePartener: VARTYPE=' + VARTYPE(loStare3) + ' clasa_esec=[' + lcClasa3 + ']' + ;
' stare_serviciu=' + ANAF_StareServiciu()
DO PnAssert WITH 'A3 stare serviciu ANAF = CAZUT dupa primul cod', ANAF_StareServiciu() == 'CAZUT'
*===== B: acelasi mediu + COMUN\UTILE\NFJSON pe path =====
SET PATH TO (gcAppPath + 'COMUN\UTILE\NFJSON') ADDITIVE
DO PnLog WITH 'B SET PATH ... COMUN\UTILE\NFJSON ADDITIVE'
RELEASE goCacheANAF_Sesiune
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reluare scenariu B')
loEx = .NULL.
TRY
LOCAL loVerifB
loVerifB = CREATEOBJECT('VerificareANAF')
DO PnLog WITH 'B1 CREATEOBJECT(VerificareANAF): OK'
CATCH TO loEx
DO PnLog WITH 'B1 CREATEOBJECT(VerificareANAF): EXCEPTIE ' + loEx.Message
ENDTRY
DO PnAssert WITH 'B1 VerificareANAF se instantiaza cu NFJSON pe path', ISNULL(loEx)
llNegasit = .F.
lcClasa = ''
loRez = ANAF_VerificaCuiSingle(m.lcCui, DATE(), @llNegasit, @lcClasa)
IF VARTYPE(loRez) = 'O'
DO PnLog WITH 'B2 ANAF_VerificaCuiSingle: denumire=[' + ALLTRIM(NVL(loRez.denumire, '')) + ;
'] scpTVA=' + TRANSFORM(loRez.scpTVA) + ' clasa_esec=[' + lcClasa + ']'
ELSE
DO PnLog WITH 'B2 ANAF_VerificaCuiSingle: VARTYPE=' + VARTYPE(loRez) + ' clasa_esec=[' + lcClasa + ']'
ENDIF
DO PnAssert WITH 'B2 verdict ANAF primit pentru ' + m.lcCui, VARTYPE(loRez) = 'O'
DO PnAssert WITH 'B3 denumire ANAF = ARAFURA', VARTYPE(loRez) = 'O' AND 'ARAFURA' $ UPPER(ALLTRIM(NVL(loRez.denumire, '')))
*===== C: corpul lui ANAF_VerificaCuiSingle replicat inline, pas cu pas =====
LOCAL loVerifC, loHttpC, lcJson, loParsed, lnSalvate, llNegC, lcClasaC, loRezC
loVerifC = CREATEOBJECT('VerificareANAF')
TRY
loHttpC = ANAF_CreeazaCerereANAF(INT(VAL(m.lcCui)), DATE(), .F.)
lcJson = ALLTRIM(loHttpC.responseText)
DO PnLog WITH 'C1 ANAF_CreeazaCerereANAF: Status=' + TRANSFORM(loHttpC.Status) + ' raspuns(120)=' + LEFT(lcJson, 120)
CATCH TO loEx
lcJson = ''
DO PnLog WITH 'C1 ANAF_CreeazaCerereANAF: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
TRY
loParsed = nfjsonread(m.lcJson)
DO PnLog WITH 'C2 nfjsonread: OK, TYPE=' + VARTYPE(loParsed)
CATCH TO loEx
DO PnLog WITH 'C2 nfjsonread: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
TRY
USE IN (SELECT('crsANAFDiag'))
loVerifC.ParseJsonANAFv8(loParsed, 'crsANAFDiag')
DO PnLog WITH 'C3 ParseJsonANAFv8: OK, RECCOUNT=' + IIF(USED('crsANAFDiag'), TRANSFORM(RECCOUNT('crsANAFDiag')), '-')
CATCH TO loEx
DO PnLog WITH 'C3 ParseJsonANAFv8: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
TRY
lnSalvate = loVerifC.SalveazaIstoricDinCursor('crsANAFDiag', gnIdUtil)
DO PnLog WITH 'C4 SalveazaIstoricDinCursor: OK, salvate=' + TRANSFORM(lnSalvate)
CATCH TO loEx
DO PnLog WITH 'C4 SalveazaIstoricDinCursor: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
TRY
llNegC = .F.
lcClasaC = ''
loRezC = ANAF_VerdictDinCursor('crsANAFDiag', INT(VAL(m.lcCui)), @llNegC, @lcClasaC)
DO PnLog WITH 'C5 ANAF_VerdictDinCursor: VARTYPE=' + VARTYPE(loRezC) + ' negasit=' + TRANSFORM(llNegC) + ;
' clasa=[' + lcClasaC + ']' + IIF(VARTYPE(loRezC) = 'O', ' denumire=[' + ALLTRIM(NVL(loRezC.denumire, '')) + ']', '')
CATCH TO loEx
DO PnLog WITH 'C5 ANAF_VerdictDinCursor: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
*===== D: path-ul REAL, construit din blocul lcPath din Programe\roagest.prg =====
LOCAL lcSursa, lnStart, lnStop, lcBloc, lcScript, lcPathReal, loVerifD, loRezD, lcClasaD, llNegD
lcSursa = FILETOSTR("D:\ROA\ROAGEST\Programe\roagest.prg")
lnStart = ATC("lcPath = gcAppPath + 'Date;'", lcSursa)
lnStop = ATC("COMUNROA\]", SUBSTR(lcSursa, lnStart)) + lnStart - 1
lcBloc = SUBSTR(lcSursa, lnStart, lnStop - lnStart + LEN("COMUNROA\]"))
lcScript = "LPARAMETERS gcAppPath" + CHR(13)+CHR(10) + "LOCAL lcPath" + CHR(13)+CHR(10) + ;
lcBloc + CHR(13)+CHR(10) + "RETURN lcPath"
lcPathReal = EXECSCRIPT(lcScript, gcAppPath)
DO PnLog WITH 'D path din roagest.prg: ' + lcPathReal
RELEASE PROCEDURE nfjsonread.prg, nfjsoncreate.prg
RELEASE goCacheANAF_Sesiune
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reluare scenariu D')
SET PATH TO &lcPathReal
DO PnAssert WITH 'D1 nfjsonread descarcat inainte de test', !('NFJSONREAD' $ UPPER(SET('Procedure')))
llNegD = .F.
lcClasaD = ''
loRezD = ANAF_VerificaCuiSingle(m.lcCui, DATE(), @llNegD, @lcClasaD)
IF VARTYPE(loRezD) = 'O'
DO PnLog WITH 'D2 ANAF_VerificaCuiSingle pe path-ul real: denumire=[' + ALLTRIM(NVL(loRezD.denumire, '')) + '] clasa_esec=[' + lcClasaD + ']'
ELSE
DO PnLog WITH 'D2 ANAF_VerificaCuiSingle pe path-ul real: VARTYPE=' + VARTYPE(loRezD) + ' clasa_esec=[' + lcClasaD + ']'
ENDIF
DO PnAssert WITH 'D2 verdict ANAF pe path-ul din roagest.prg', VARTYPE(loRezD) = 'O'
DO PnAssert WITH 'D3 fara clasa de esec (banda arata verdictul, nu "ANAF nu a raspuns")', lcClasaD == ''
CATCH TO loEx
DO PnLog WITH 'EXCEPTIE NEPRINSA: ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
ENDTRY
DO PnLog WITH 'REZULTAT: ' + TRANSFORM(gnPass) + '/' + TRANSFORM(gnAsserts) + ' PASS'
QUIT
PROCEDURE PnAssert
LPARAMETERS tcNume, tlOk
gnAsserts = gnAsserts + 1
IF tlOk
gnPass = gnPass + 1
ENDIF
DO PnLog WITH IIF(tlOk, 'PASS ', 'FAIL ') + tcNume
ENDPROC
PROCEDURE PnErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO PnLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE PnLog
LPARAMETERS tcMsg
STRTOFILE(TRANSFORM(tcMsg) + CHR(13)+CHR(10), gcUILog, .T.)
ENDPROC
DEFINE CLASS executor_spion AS Custom
*-- tine locul lui goExecutor: salvarea in ISTORIC_CODURI_FISCALE nu face obiectul testului
PROCEDURE oExecuta
LPARAMETERS tcSql, tcAlias
RETURN .T.
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,18 @@
# test_repro_anaf_path_nfjson.ps1 - rulare headless a testului de reproducere pentru
# "ANAF nu a raspuns - verificare sarita" in ROAGEST (COMUN\UTILE\NFJSON lipsa din SET PATH).
# Rulare: powershell -ExecutionPolicy Bypass -File test_repro_anaf_path_nfjson.ps1
$ErrorActionPreference = 'Stop'
$Teste = $PSScriptRoot
$Prg = Join-Path $Teste 'test_repro_anaf_path_nfjson.prg'
$Fxp = [IO.Path]::ChangeExtension($Prg, '.fxp')
$Log = Join-Path $Teste 'test_repro_anaf_path_nfjson_log.txt'
$Vfp = 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe'
Remove-Item $Fxp, $Log -ErrorAction SilentlyContinue
$p = Start-Process -FilePath $Vfp -ArgumentList '-A', '-T', "`"$Prg`"" -PassThru
if (-not $p.WaitForExit(240000)) {
$p.Kill()
throw 'TIMEOUT: testul nu s-a terminat in 240s'
}
if (-not (Test-Path $Log)) { throw "Lipseste logul $Log" }
Get-Content $Log

62
utile/context_watch.ps1 Normal file
View File

@@ -0,0 +1,62 @@
# context_watch.ps1 - cat context ocupa sesiunea curenta Claude Code.
# Citeste ultimul "usage" din transcriptul JSONL al sesiunii (input + cache_read + cache_creation).
# Utilizare:
# - ca hook (PostToolUse): primeste pe stdin JSON-ul hook-ului, cu transcript_path;
# - manual: powershell -File context_watch.ps1 [-TranscriptPath <cale.jsonl>] [-Prag 250000]
# Iese cu 2 si scrie pe stderr cand contextul depaseste pragul (asa ajunge mesajul la agent).
[CmdletBinding()]
param(
[string]$TranscriptPath,
[int]$Prag = 250000,
[int]$PragMax = 275000,
[switch]$Intotdeauna,
[switch]$Stdout # UserPromptSubmit: mesajul se scrie pe stdout si se iese cu 0
)
if (-not $TranscriptPath) {
$stdin = [Console]::In.ReadToEnd()
if ($stdin) {
try { $TranscriptPath = (ConvertFrom-Json $stdin).transcript_path } catch { }
}
}
if (-not $TranscriptPath -or -not (Test-Path $TranscriptPath)) {
$dir = Join-Path $env:USERPROFILE ".claude\projects\$((Get-Location).Path -replace '[:\\/]','-')"
if (Test-Path $dir) {
$f = Get-ChildItem "$dir\*.jsonl" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if ($f) { $TranscriptPath = $f.FullName }
}
}
if (-not $TranscriptPath -or -not (Test-Path $TranscriptPath)) { exit 0 }
# doar coada fisierului - transcriptul poate avea zeci de MB
$fs = [IO.File]::Open($TranscriptPath, 'Open', 'Read', 'ReadWrite')
try {
$len = [Math]::Min(400KB, $fs.Length)
$fs.Seek(-$len, 'End') | Out-Null
$buf = New-Object byte[] $len
$fs.Read($buf, 0, $len) | Out-Null
} finally { $fs.Close() }
$coada = [Text.Encoding]::UTF8.GetString($buf)
$m = [regex]::Matches($coada, '"usage":\{.*?"output_tokens":\d+')
if ($m.Count -eq 0) { exit 0 }
$ultim = $m[$m.Count - 1].Value
$total = 0
foreach ($camp in @('input_tokens', 'cache_creation_input_tokens', 'cache_read_input_tokens')) {
if ($ultim -match ('"' + $camp + '":(\d+)')) { $total += [int]$Matches[1] }
}
$k = [Math]::Round($total / 1000)
$mesaj = ''
if ($total -ge $PragMax) {
$mesaj = "CONTEXT ${k}k - peste limita de $([Math]::Round($PragMax/1000))k (regula 9): scrie handoff-ul in docs\progres.md si preda sesiunea acum."
} elseif ($total -ge $Prag) {
$mesaj = "CONTEXT ${k}k - peste $([Math]::Round($Prag/1000))k (regula 9): actualizeaza docs\progres.md si pregateste predarea; deleaga la subagenti ce mai ai de citit/testat."
}
if ($mesaj) {
if ($Stdout) { Write-Output $mesaj; exit 0 }
[Console]::Error.WriteLine($mesaj)
exit 2
}
if ($Intotdeauna) { Write-Output "CONTEXT ${k}k" }
exit 0

View File

@@ -0,0 +1,27 @@
# docs_revizie_check.ps1 - reaminteste revizuirea periodica de compactare a documentatiei (regula 12).
# Marker: COMUN\docs\.ultima_revizie (data ultimei revizii, YYYY-MM-DD).
# Utilizare:
# ca hook (SessionStart): powershell -File docs_revizie_check.ps1 -Stdout
# dupa o revizie: powershell -File docs_revizie_check.ps1 -Marcheaza
param(
[int]$Zile = 30,
[switch]$Stdout,
[switch]$Marcheaza
)
$marker = Join-Path (Split-Path $PSScriptRoot -Parent) 'docs\.ultima_revizie'
if ($Marcheaza) {
Set-Content $marker (Get-Date -Format 'yyyy-MM-dd') -Encoding ascii
Write-Output "marcat: $(Get-Content $marker)"
exit 0
}
$ultima = if (Test-Path $marker) { [datetime]::ParseExact((Get-Content $marker -Raw).Trim(), 'yyyy-MM-dd', $null) } else { [datetime]'2000-01-01' }
$vechime = [int]((Get-Date) - $ultima).TotalDays
if ($vechime -lt $Zile) { exit 0 }
$mesaj = "DOCS: ultima revizuire de compactare acum $vechime zile (regula 12). Propune-i utilizatorului o runda pe COMUN\docs si docs\ ale proiectului; dupa aplicare ruleaza docs_revizie_check.ps1 -Marcheaza."
if ($Stdout) { Write-Output $mesaj; exit 0 }
[Console]::Error.WriteLine($mesaj)
exit 2