* test_s3b_incasare_nealocare.prg * Headless: un ciclu complet de bifare/debifare a casetelor "Alte date" si "Incasare" nu lasa * alocat niciun numar de bon fiscal (3) / chitanta (16) / POS-Card (26), in ambele scenarii de * start. Sub comutarea pe casete, bifarea "Incasare" ALOCA o chitanta si debifarea o dezaloca * (ramura "fara incasare" din actualizeaza_tipincasare); invariantul e pe ciclul intreg, nu pe * apelul individual. Scenariile de start: * A - document nou (poDate.incasat = 0 la construire) * B - document copiat cu incasare presetata (poDate.incasat <> 0 la construire, * asta ALOCA deja chitanta la Init - comportament asteptat, nu un fail) * Specificatie: docs\nota_s3b_testare.md sectiunea 1. * * Rulare: vfp9.exe -A -T "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\test_s3b_incasare_nealocare.prg" * Log: D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out\test_s3b_incasare_nealocare.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_nealocare.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 * seriile de facturi (tipdoc 5) si de incasare (3/16/26) sunt pe utilizator in MARIUSM_AUTO gnIdUtil = 8 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 SET CLASSLIB TO "D:\ROA\ROAFACTURARE\COMUN\utile\gridextras\gridextras.vcx" ADDITIVE SET PATH TO "D:\ROA\ROAFACTURARE\COMUN\utile\gridextras" ADDITIVE * grd_factura.cCodMat.cboCodmat e declarat AS combosql OF cautare.vcx, dar clasa e in _cb_base.vcx 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 * cboTipFactura (RowSourceType=3) citeste cursorul local saft_tip_facturi ca pe un tabel - * fara el deschis explicit, Createobject('frm_facturare_articole2') da "File 'saft_tip_facturi.dbf' does not exist" IF !USED('saft_tip_facturi') update_saft_tip_facturi() ENDIF DO Scenariu_A DO Scenariu_B DO Final PROCEDURE Scenariu_A * Document nou: poDate.incasat ramane 0 la construire - grupul de incasare nu aloca nimic * la Init, iar togglingul repetat al celor doua acordeoane nu trebuie sa schimbe nimic. PRIVATE poDate, poGeneratorNumere, loForm, i, lcInitial, lcCurent DO AfLog WITH "=== Scenariul A: document nou (poDate.incasat = 0 la construire) ===" poDate = CREATEOBJECT("oDateFactura", 25000, 1) poDate.nIdTipDoc = 5 poDate.totalctva = 1000 DO AfLog WITH "A: 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) DO Assert WITH poDate.incasat = 0, "A: poDate.incasat ramane 0 inainte de instantiere" loForm = CREATEOBJECT('frm_facturare_articole2') DO Assert WITH VARTYPE(loForm) = 'O', "A: Createobject frm_facturare_articole2" IF VARTYPE(loForm) <> 'O' RETURN ENDIF DO Assert WITH ObjExists(loForm, 'opt_incasat'), "A: opt_incasat prezent (poDate.tip intre 1 si 4)" lcInitial = StareToate() DO AfLog WITH "A: stare initiala dupa Createobject: " + lcInitial DO Assert WITH !EsteAlocat(3) AND !EsteAlocat(16) AND !EsteAlocat(26), "A: nimic alocat la construire" FOR i = 1 TO 5 loForm.chk_incasare.Value = 1 loForm.do_comuta_incasare() loForm.chk_incasare.Value = 0 loForm.do_comuta_incasare() ENDFOR lcCurent = StareToate() DO AfLog WITH "A: stare dupa 5x ciclu incasare (bifat+debifat): " + lcCurent DO Assert WITH lcCurent == lcInitial, "A: neschimbat dupa 5x ciclu incasare (bifat+debifat)" FOR i = 1 TO 5 loForm.chk_alte_date.Value = 1 loForm.do_comuta_alte_date() loForm.chk_alte_date.Value = 0 loForm.do_comuta_alte_date() ENDFOR lcCurent = StareToate() DO AfLog WITH "A: stare dupa 5x ciclu alte date (bifat+debifat): " + lcCurent DO Assert WITH lcCurent == lcInitial, "A: neschimbat dupa 5x ciclu alte date (bifat+debifat)" FOR i = 1 TO 5 loForm.chk_incasare.Value = 1 loForm.do_comuta_incasare() loForm.chk_alte_date.Value = 1 loForm.do_comuta_alte_date() loForm.chk_incasare.Value = 0 loForm.do_comuta_incasare() loForm.chk_alte_date.Value = 0 loForm.do_comuta_alte_date() ENDFOR lcCurent = StareToate() DO AfLog WITH "A: stare dupa 5x ciclu pe ambele casete: " + lcCurent DO Assert WITH lcCurent == lcInitial, "A: neschimbat dupa 5x ciclu pe ambele casete" loForm.Release() RELEASE loForm ENDPROC PROCEDURE Scenariu_B * Document copiat: poDate.incasat <> 0 la construire - Init aloca deja chitanta (16), * asta e comportamentul ASTEPTAT (nu un fail). Assertul e ca togglingul repetat NU * mai schimba nimic fata de starea de dupa construire, si ca la final curatenia * (opt_incasat.Value = 1) dezaloca explicit tot ce a fost alocat. PRIVATE poDate, poGeneratorNumere, loForm, i, lcDupaConstruire, lcCurent DO AfLog WITH "=== Scenariul B: document copiat (poDate.incasat <> 0 la construire) ===" poDate = CREATEOBJECT("oDateFactura", 25000, 1) poDate.nIdTipDoc = 5 poDate.totalctva = 1000 poDate.incasat = 100 DO AfLog WITH "B: poDate.tip=" + TRANSFORM(poDate.tip) + " poDate.eProforma=" + TRANSFORM(poDate.eProforma) + " poDate.incasat inainte de Createobject=" + TRANSFORM(poDate.incasat) poGeneratorNumere = CREATEOBJECT("oGeneratorNumere") poGeneratorNumere.ResetNumere() DO ProbaSerii WITH poDate.nIdTipDoc poDate.rezultat_serii = poGeneratorNumere.creeaza_cursor_serii(poDate.nIdTipDoc) DO AfLog WITH "B: stare numere inainte de Createobject: " + StareToate() loForm = CREATEOBJECT('frm_facturare_articole2') DO Assert WITH VARTYPE(loForm) = 'O', "B: Createobject frm_facturare_articole2" IF VARTYPE(loForm) <> 'O' RETURN ENDIF DO AfLog WITH "B: poDate.incasat dupa Init=" + TRANSFORM(poDate.incasat) + " (asteptat = poDate.totalctva)" DO Assert WITH loForm.ct_incasare.opt_incasat.Value = 1, "B: opt_incasat.Value=1 (chitanta) la construire (poDate.incasat era <> 0)" DO Assert WITH loForm.chk_incasare.Value = 1, "B: caseta Incasare bifata de seteaza_mod_incasare(2) la construire" DO Assert WITH loForm.nmod_incasare() = 2, "B: nmod_incasare()=2 (chitanta) la construire" lcDupaConstruire = StareToate() DO AfLog WITH "B: stare numere dupa construire: " + lcDupaConstruire DO Assert WITH EsteAlocat(16) AND !EsteAlocat(3) AND !EsteAlocat(26), "B: doar chitanta (16) alocata la construire, nu si bonul/POS-ul" FOR i = 1 TO 5 loForm.chk_incasare.Value = 0 loForm.do_comuta_incasare() loForm.chk_incasare.Value = 1 loForm.do_comuta_incasare() ENDFOR lcCurent = StareToate() DO AfLog WITH "B: stare dupa 5x ciclu incasare (debifat+bifat): " + lcCurent DO Assert WITH lcCurent == lcDupaConstruire, "B: neschimbat dupa 5x ciclu incasare (debifat+bifat)" FOR i = 1 TO 5 loForm.chk_alte_date.Value = 1 loForm.do_comuta_alte_date() loForm.chk_alte_date.Value = 0 loForm.do_comuta_alte_date() ENDFOR lcCurent = StareToate() DO AfLog WITH "B: stare dupa 5x ciclu alte date (bifat+debifat): " + lcCurent DO Assert WITH lcCurent == lcDupaConstruire, "B: neschimbat dupa 5x ciclu alte date (bifat+debifat)" FOR i = 1 TO 5 loForm.chk_incasare.Value = 0 loForm.do_comuta_incasare() loForm.chk_alte_date.Value = 1 loForm.do_comuta_alte_date() loForm.chk_incasare.Value = 1 loForm.do_comuta_incasare() loForm.chk_alte_date.Value = 0 loForm.do_comuta_alte_date() ENDFOR lcCurent = StareToate() DO AfLog WITH "B: stare dupa 5x ciclu pe ambele casete: " + lcCurent DO Assert WITH lcCurent == lcDupaConstruire, "B: neschimbat dupa 5x ciclu pe ambele casete" * Curatenie obligatorie inainte de Release - altfel ramane un numar real alocat in MARIUSM_AUTO. * "Fara incasare" e acum caseta debifata: opt_incasat.Value=1 inseamna chitanta, nu golire. loForm.chk_incasare.Value = 0 loForm.do_comuta_incasare() DO Assert WITH loForm.nmod_incasare() = 1, "B: nmod_incasare()=1 dupa debifarea casetei" lcCurent = StareToate() DO AfLog WITH "B: stare numere dupa curatenie (chk_incasare=0): " + lcCurent DO Assert WITH !EsteAlocat(3) AND !EsteAlocat(16) AND !EsteAlocat(26), "B: toate trei numerele dezalocate dupa curatenie" loForm.Release() RELEASE loForm ENDPROC FUNCTION EsteAlocat * .T. daca tipul tnTip are un numar alocat, in oricare din cele doua reprezentari * (array paPlaje(tip,1) fara buffer, sau cursorul paPlaje(tip,8) cu buffer) 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 * reprezentare textuala a starii unui tip, pentru comparatie exacta inainte/dupa 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 * apel direct al procedurii Oracle din creeaza_cursor_serii: logheaza eroarea reala (goExecutor * ar deschide amessagebox modal, care agata rularea headless) si incalzeste starea pachetului 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 FUNCTION ObjExists * prezenta reala in colectia Objects: dupa RemoveObject, PEMSTATUS(...,5) si TYPE() raman .T./'O' * Cautarea e RECURSIVA: dupa S7 controalele de sub grila stau in containerele ct_*, nu la * nivel de formular, iar o cautare plata ar raporta tacut "lipseste". LPARAMETERS toContainer, tcName LOCAL i, loO FOR i = 1 TO toContainer.Objects.Count loO = toContainer.Objects(i) IF UPPER(loO.Name) == UPPER(tcName) RETURN .T. ENDIF IF TYPE('loO.Objects.Count') = 'N' IF ObjExists(loO, tcName) RETURN .T. ENDIF ENDIF ENDFOR RETURN .F. ENDFUNC 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