#13: formular de facturare unificat - etapa curenta
Squash al branch-ului de lucru plan13-s2. Clase: ofacturare (nucleul formularului unificat), ofacturare_comun, ferestre_cere_date, ocomenzi, caut_ora (lista de preturi in combo-urile de cautare), omodificari. Programe: ofacturare impartit - ofacturare_antet, ofacturare_rutare_scriere si ogrid_latimi sunt fisiere noi; oproceduri_facturare primeste discountul pe linie si cota standard de TVA cand articolul nu are cota pe politica. Documentatie: capcana SQLExec no_data_found, conventia de encoding, depanarea testelor VFP si regulile de lucru - conflictele cu modificarile venite din alte proiecte sunt rezolvate pastrand ambele parti. Loguri de rulare a testelor scoase din versionare; testele raman. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PkyjGyrV2S7932om4kfSiK
This commit is contained in:
323
utile/Teste/facturare_unificat/test_s3b_incasare_nealocare.prg
Normal file
323
utile/Teste/facturare_unificat/test_s3b_incasare_nealocare.prg
Normal file
@@ -0,0 +1,323 @@
|
||||
* 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
|
||||
Reference in New Issue
Block a user