* test_s3b_incasare_paritate_campuri.prg * Headless: pentru fiecare din cele patru tipuri de incasare (1=Fara incasare, 2=Chitanta, * 3=Bon fiscal, 4=POS Card), formularul nou (frm_facturare_articole2) aduce poDate in aceeasi * stare ca dialogul vechi (frm_alte_date) - fara sa treaca prin do_scrie_factura/Termina, deci * fara sa scrie nimic in Oracle si fara sa emita niciun document. * Specificatie: docs\nota_s3b_testare.md sectiunea 2b. Nu acopera lcListaIncasare/do_scrie_factura * insusi (ar cere emitere reala sau un mock detaliat pe goExecutor - vezi sectiunea 2a/2b, ultimul * paragraf) - asta ramane proba manuala a lui Marius, cerut si de raport_s3b_incasare.md sectiunea 10. * * ATENTIE la citirea rezultatelor: din cele cinci campuri cerute de specificatie (poDate.incasat, * incasatCARD, incasatTichete, id_casa, ntip_incasare), doar poDate.incasat si poDate.id_casa sunt * scrise efectiv de actualizeaza_tipincasare()/Init - verificat pe cod (ofacturare.vc2, ferestre_ * cere_date.vc2). incasatCARD, incasatTichete si ntip_incasare sunt scrise abia in Termina / * inainte_de_do_termin (calea care emite, exclusa explicit din acest test - sectiunea 2a). Pentru * aceste trei campuri parizatea verificata aici e reala, dar putin adanca: confirma doar ca NICIUNA * din cele doua cai nu le atinge la simplul toggle al opt_incasat (raman la valoarea implicita 0 pe * ambele cai), nu ca Termina le populeaza identic pe ambele cai. * * SECVENTIAL, nu simultan: frm_alte_date e creata, testata pe toate cele patru tipuri si eliberata * COMPLET inainte sa existe frm_facturare_articole2 - niciodata doua forme vii in acelasi timp. * Motiv: ambele forme au propriul cboTipFactura cu RowSource IDENTIC ("...into cursor cTipFacturaX", * ofacturare.vc2:16157 si ferestre_cere_date.vc2:2388), reevaluat la fiecare apel al lui * actualizeaza_tipincasare() (Thisform.cboTipFactura.Refresh(), prima linie a metodei pe ambele * forme); cu ambele vii simultan in aceeasi sesiune de date (fara DataSession propriu), doua * comboboxuri concureaza pe acelasi nume de cursor - suspectat ca varianta paralela (rulata de patru * ori, toate agatate in acelasi punct) bloca aici, la nivel de tabel, fara sa arunce o exceptie * catchabila prin ON ERROR. Nota cerea "acelasi poDate", nu simultaneitate - pastrata aici prin * pastrarea aceluiasi obiect poDate intre cele doua faze, cu cele cinci campuri resetate explicit * la starea de start intre faze (ca a doua forma sa porneasca de la aceeasi stare ca prima). * * Rulare: vfp9.exe -A -T "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\test_s3b_incasare_paritate_campuri.prg" * Log: D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out\test_s3b_incasare_paritate_campuri.log SET SAFETY OFF SET TALK OFF SET NOTIFY OFF PUBLIC gcLog, gnFail, gnPass gcLog = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out\test_s3b_incasare_paritate_campuri.log" IF !DIRECTORY("D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out") MD "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out" ENDIF STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcLog) gnFail = 0 gnPass = 0 ON ERROR DO AfErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() DO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto_roafacturare.prg" WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT' IF TYPE('gnHandle') <> 'N' OR gnHandle <= 0 DO AfLog WITH "FAIL: conexiune Oracle esuata" DO Final ENDIF SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE PUBLIC gcMockUltimMesaj, gnMockUltimTip gcMockUltimMesaj = "" gnMockUltimTip = 0 DO AfLog WITH "ENV OK, gnAn=" + TRANSFORM(gnAn) + " gnLuna=" + TRANSFORM(gnLuna) IF !actualizeaza_optiuni_program() DO AfLog WITH "FAIL: actualizeaza_optiuni_program()" DO Final ENDIF gnScadereStoc = 0 gnIdUtil = 8 * aliniaza sucursala cu singura plaja POS/card existenta, evita blocajul Oracle pe cursor OUT gnIdSucursala = 167 goExecutor.oExecuta([begin pack_sesiune.set_Id_Util(?gnIdUtil); end;]) DO AfLog WITH "gnScadereStoc=" + TRANSFORM(gnScadereStoc) * gridextras.vcx e referit din ofacturare.vcx cu cale relativa, rezolvabila doar din exe/IDE - * necesar pentru frm_facturare_articole2 (frm_alte_date nu are grid, dar SET-urile sunt ADDITIVE) SET CLASSLIB TO "D:\ROA\ROAFACTURARE\COMUN\utile\gridextras\gridextras.vcx" ADDITIVE SET PATH TO "D:\ROA\ROAFACTURARE\COMUN\utile\gridextras" ADDITIVE SET CLASSLIB TO "D:\ROA\ROAFACTURARE\COMUN\clase\_cb_base.vcx" ADDITIVE IF USED('crscursuri') USE IN crscursuri ENDIF CREATE CURSOR crscursuri (curs N(12,4), nume_val C(10), multiplicator N(6)) DO creeaza_facturacrs WITH 'crsfactura' SELECT *, CAST(NULL AS C(100)) AS gestiune FROM crsfactura INTO CURSOR crsfact_tmp READWRITE USE IN crsfactura SELECT * FROM crsfact_tmp INTO CURSOR crsfactura READWRITE USE IN crsfact_tmp DO ProbaParitate DO Final PROCEDURE ProbaParitate * VARIANTA SECVENTIALA (23.08.2026): nota cerea "acelasi poDate", nu "ambele forme vii in * acelasi timp" - simultaneitatea era detaliu de implementare, nu cerinta (confirmat de * team-lead). Motivul schimbarii: frm_alte_date SI frm_facturare_articole2 au fiecare propriul * cboTipFactura, cu RowSource IDENTIC ("select tip_saftname, cod from saft_tip_facturi into * cursor cTipFacturaX" - ofacturare.vc2:16157, ferestre_cere_date.vc2:2388), refacut la fiecare * apel al lui actualizeaza_tipincasare() (Thisform.cboTipFactura.Refresh(), prima linie a * metodei pe ambele forme). Cu ambele forme vii simultan, in aceeasi sesiune de date (fara * DataSession propriu pe niciuna), doua comboboxuri concureaza pe acelasi nume de cursor tinta - * suspiciunea unei asteptari de lacat la nivel de tabel, care nu trece prin ON ERROR (nu e o * exceptie aruncata). Aici: loVechi e creata, testata COMPLET si eliberata inainte sa existe * loNou - niciodata doua forme vii simultan. * * poDate ramane ACELASI obiect intre cele doua faze (nu se recreeaza) - dar cele cinci campuri * se retin la start si se restaureaza explicit intre faze, ca a doua forma sa porneasca de la * aceeasi stare ca prima, nu de la ce a lasat prima in urma. PRIVATE poDate, poGeneratorNumere, loVechi, loNou, i LOCAL laTip[4], laNume[4], laRezVechi[4,5] laTip[1] = 1 laTip[2] = 2 laTip[3] = 3 laTip[4] = 4 laNume[1] = "Fara incasare" laNume[2] = "Chitanta" laNume[3] = "Bon fiscal" laNume[4] = "POS Card" poDate = CREATEOBJECT("oDateFactura", 25000, 1) poDate.nIdTipDoc = 5 poDate.totalctva = 1000 DO AfLog WITH "poDate.tip=" + TRANSFORM(poDate.tip) + " poDate.eProforma=" + TRANSFORM(poDate.eProforma) + " poDate.incasat=" + TRANSFORM(poDate.incasat) poGeneratorNumere = CREATEOBJECT("oGeneratorNumere") poGeneratorNumere.ResetNumere() DO ProbaSerii WITH poDate.nIdTipDoc poDate.rezultat_serii = poGeneratorNumere.creeaza_cursor_serii(poDate.nIdTipDoc) * starea de start a celor cinci campuri, INAINTE de orice forma - se restaureaza intre faze LOCAL lnStartIncasat, lnStartCard, lnStartTichete, lnStartCasa, lnStartTipInc lnStartIncasat = poDate.incasat lnStartCard = poDate.incasatCARD lnStartTichete = poDate.incasatTichete lnStartCasa = poDate.id_casa lnStartTipInc = poDate.ntip_incasare DO AfLog WITH "stare start poDate: incasat=" + TRANSFORM(lnStartIncasat) + " incasatCARD=" + TRANSFORM(lnStartCard) + ; " incasatTichete=" + TRANSFORM(lnStartTichete) + " id_casa=" + TRANSFORM(lnStartCasa) + " ntip_incasare=" + TRANSFORM(lnStartTipInc) LOCAL lnTip, lcNumeTip * ---------- FAZA 1: doar frm_alte_date (calea veche), complet, apoi Release() ---------- DO AsiguraSaftTipFacturi DO AfLog WITH "inainte de Createobject frm_alte_date: USED('saft_tip_facturi')=" + TRANSFORM(USED('saft_tip_facturi')) + ; " USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) loVechi = CREATEOBJECT('frm_alte_date') DO Assert WITH VARTYPE(loVechi) = 'O', "Createobject frm_alte_date (calea veche)" IF VARTYPE(loVechi) <> 'O' RETURN ENDIF loVechi.Visible = .F. DO AfLog WITH "dupa Createobject frm_alte_date: USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) FOR i = 1 TO 4 lnTip = laTip[i] lcNumeTip = laNume[i] DO AfLog WITH "vechi [" + lcNumeTip + "]: inainte de opt_incasat.Value=, USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) loVechi.opt_incasat.Value = lnTip DO AfLog WITH "vechi [" + lcNumeTip + "]: dupa opt_incasat.Value=, USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) laRezVechi[i,1] = poDate.incasat laRezVechi[i,2] = poDate.incasatCARD laRezVechi[i,3] = poDate.incasatTichete laRezVechi[i,4] = poDate.id_casa laRezVechi[i,5] = poDate.ntip_incasare DO AfLog WITH "vechi [" + lcNumeTip + "]: incasat=" + TRANSFORM(laRezVechi[i,1]) + " incasatCARD=" + TRANSFORM(laRezVechi[i,2]) + ; " incasatTichete=" + TRANSFORM(laRezVechi[i,3]) + " id_casa=" + TRANSFORM(laRezVechi[i,4]) + " ntip_incasare=" + TRANSFORM(laRezVechi[i,5]) DO AfLog WITH "vechi [" + lcNumeTip + "]: stare numere=" + StareToate() loVechi.opt_incasat.Value = 1 DO AfLog WITH "vechi [" + lcNumeTip + "]: dezalocat, stare numere=" + StareToate() ENDFOR loVechi.Release() RELEASE loVechi DO AfLog WITH "dupa Release loVechi: USED('saft_tip_facturi')=" + TRANSFORM(USED('saft_tip_facturi')) + ; " USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) * readuce poDate la starea de start, ca a doua forma sa porneasca identic cu prima poDate.incasat = lnStartIncasat poDate.incasatCARD = lnStartCard poDate.incasatTichete = lnStartTichete poDate.id_casa = lnStartCasa poDate.ntip_incasare = lnStartTipInc DO AfLog WITH "poDate resetat inainte de a doua forma: incasat=" + TRANSFORM(poDate.incasat) + " id_casa=" + TRANSFORM(poDate.id_casa) * ---------- FAZA 2: doar frm_facturare_articole2 (calea noua) ---------- DO AsiguraSaftTipFacturi DO AfLog WITH "inainte de Createobject frm_facturare_articole2: USED('saft_tip_facturi')=" + TRANSFORM(USED('saft_tip_facturi')) + ; " USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) loNou = CREATEOBJECT('frm_facturare_articole2') DO Assert WITH VARTYPE(loNou) = 'O', "Createobject frm_facturare_articole2 (calea noua)" IF VARTYPE(loNou) <> 'O' RETURN ENDIF loNou.Visible = .F. DO AfLog WITH "dupa Createobject frm_facturare_articole2: USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) FOR i = 1 TO 4 lnTip = laTip[i] lcNumeTip = laNume[i] DO AfLog WITH "nou [" + lcNumeTip + "]: inainte de opt_incasat.Value=, USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) loNou.seteaza_mod_incasare(lnTip) DO Assert WITH loNou.nmod_incasare() = lnTip, "[" + lcNumeTip + "] nmod_incasare() reflecta seteaza_mod_incasare(" + TRANSFORM(lnTip) + ")" DO AfLog WITH "nou [" + lcNumeTip + "]: dupa opt_incasat.Value=, USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) DO AfLog WITH "nou [" + lcNumeTip + "]: incasat=" + TRANSFORM(poDate.incasat) + " incasatCARD=" + TRANSFORM(poDate.incasatCARD) + ; " incasatTichete=" + TRANSFORM(poDate.incasatTichete) + " id_casa=" + TRANSFORM(poDate.id_casa) + " ntip_incasare=" + TRANSFORM(poDate.ntip_incasare) DO Assert WITH poDate.incasat = laRezVechi[i,1], "[" + lcNumeTip + "] poDate.incasat identic (vechi=" + TRANSFORM(laRezVechi[i,1]) + " nou=" + TRANSFORM(poDate.incasat) + ")" DO Assert WITH poDate.incasatCARD = laRezVechi[i,2], "[" + lcNumeTip + "] poDate.incasatCARD identic" DO Assert WITH poDate.incasatTichete = laRezVechi[i,3], "[" + lcNumeTip + "] poDate.incasatTichete identic" DO Assert WITH poDate.id_casa = laRezVechi[i,4], "[" + lcNumeTip + "] poDate.id_casa identic" DO Assert WITH poDate.ntip_incasare = laRezVechi[i,5], "[" + lcNumeTip + "] poDate.ntip_incasare identic" loNou.seteaza_mod_incasare(1) DO Assert WITH loNou.nmod_incasare() = 1, "[" + lcNumeTip + "] nmod_incasare() reflecta seteaza_mod_incasare(1) (dezalocare)" DO AfLog WITH "nou [" + lcNumeTip + "]: dezalocat, stare numere=" + StareToate() ENDFOR DO AfLog WITH "stare finala numere (asteptat nimic alocat): " + StareToate() DO Assert WITH !EsteAlocat(3) AND !EsteAlocat(16) AND !EsteAlocat(26), "nimic ramas alocat la finalul rularii" loNou.Release() RELEASE loNou DO AfLog WITH "dupa Release loNou: USED('saft_tip_facturi')=" + TRANSFORM(USED('saft_tip_facturi')) + ; " USED('cTipFacturaX')=" + TRANSFORM(USED('cTipFacturaX')) ENDPROC PROCEDURE AsiguraSaftTipFacturi * cboTipFactura (RowSourceType=3) citeste cursorul local saft_tip_facturi ca pe un tabel la * instantiere (ofacturare.vc2:16157 - frm_facturare_articole2, ferestre_cere_date.vc2:2388 - * frm_alte_date). Structura copiata din update_saft_tip_facturi (updateserver.prg:669-691), * fara apel la server - cursor local, dummy, cu randul gol si indexul pe cod ca in original. IF !USED('saft_tip_facturi') CREATE CURSOR saft_tip_facturi (cod N(3) NULL, tip_saftname C(200) NULL) INSERT INTO saft_tip_facturi (cod, tip_saftname) VALUES (NULL, '') INDEX ON cod TAG cod ENDIF ENDPROC FUNCTION EsteAlocat LPARAMETERS tnTip LOCAL lcCursor IF poGeneratorNumere.paPlaje(tnTip, 6) lcCursor = poGeneratorNumere.paPlaje(tnTip, 8) IF EMPTY(NVL(lcCursor, [])) OR !USED(lcCursor) RETURN .F. ENDIF RETURN RECCOUNT(lcCursor) > 0 ELSE RETURN poGeneratorNumere.paPlaje(tnTip, 1) <> 0 ENDIF ENDFUNC FUNCTION StareNumar LPARAMETERS tnTip LOCAL lcCursor, lnCount IF poGeneratorNumere.paPlaje(tnTip, 6) lcCursor = poGeneratorNumere.paPlaje(tnTip, 8) IF EMPTY(NVL(lcCursor, [])) OR !USED(lcCursor) lnCount = 0 ELSE lnCount = RECCOUNT(lcCursor) ENDIF RETURN "buffer:" + TRANSFORM(lnCount) ELSE RETURN "array:" + TRANSFORM(poGeneratorNumere.paPlaje(tnTip, 1)) ENDIF ENDFUNC FUNCTION StareToate RETURN "3=" + StareNumar(3) + "|16=" + StareNumar(16) + "|26=" + StareNumar(26) ENDFUNC PROCEDURE ProbaSerii LPARAMETERS tnIdTipDoc LOCAL lnOk, laErr[1], i, lcSql PRIVATE pnIdTipDoc, pnRezultat pnIdTipDoc = tnIdTipDoc pnRezultat = 0 lcSql = "{call " + gcS + ".pack_serii_numere.verifica_cursor_serii(?pnIdTipDoc,?gnIdUtil,?gnIdSucursala,?@pnRezultat)}" FOR i = 1 TO 3 lnOk = SQLEXEC(gnHandle, lcSql, "crsprobaserii") IF lnOk > 0 DO AfLog WITH "proba serii OK la incercarea " + TRANSFORM(i) + ", pnRezultat=" + TRANSFORM(pnRezultat) + " randuri=" + TRANSFORM(RECCOUNT("crsprobaserii")) USE IN (SELECT("crsprobaserii")) EXIT ELSE AERROR(laErr) DO AfLog WITH "proba serii ESEC la incercarea " + TRANSFORM(i) + ": " + TRANSFORM(laErr[1]) + " / " + TRANSFORM(laErr[2]) + " / " + TRANSFORM(laErr[5]) ENDIF ENDFOR ENDPROC PROCEDURE Assert LPARAMETERS tlCond, tcMsg IF tlCond gnPass = gnPass + 1 DO AfLog WITH "PASS: " + tcMsg ELSE gnFail = gnFail + 1 DO AfLog WITH "FAIL: " + tcMsg ENDIF ENDPROC PROCEDURE AfLog LPARAMETERS tcMsg STRTOFILE(tcMsg + CHR(13) + CHR(10), gcLog, 1) ENDPROC PROCEDURE AfErr LPARAMETERS tnErr, tcMsg, tcProg, tnLine gnFail = gnFail + 1 DO AfLog WITH "ERROR " + TRANSFORM(tnErr) + " [" + tcProg + ":" + TRANSFORM(tnLine) + "] " + tcMsg ENDPROC PROCEDURE Final DO AfLog WITH "TOTAL pass=" + TRANSFORM(gnPass) + " fail=" + TRANSFORM(gnFail) DO AfLog WITH "END " + TTOC(DATETIME()) QUIT ENDPROC