Files
comun/utile/Teste/editare_factura/test_s10_cablare_vfp.prg
Marius Mutu 8e022d332e #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
2026-09-09 21:38:25 +03:00

335 lines
15 KiB
Plaintext

* test_s10_cablare_vfp.prg
* Proba de cablare S10 (docs\raport_s10_cablare_vfp.md) - LIMITA semnalata explicit in
* docs\propunere_s10_proc_tvav.md §11.0: test_s10_proc_tvav.prg dovedeste ca pachetul Oracle
* (CASE-ul din PACK_FACTURARE.adauga_articol_factura) respecta flag-ul/parametrul nou, dar apeleaza
* pack_facturare DIRECT - nu dovedeste ca frm_facturare_articole2.do_scrie_articole (ofacturare.vc2,
* diff-ul din propunere §8) chiar APRINDE pack_facturare.nregenerare_editare si chiar TRIMITE al
* 28-lea argument. Aceasta proba umple exact acel gol.
*
* Metoda: mock pe goExecutor care CAPTUREAZA lcSql-ul trimis prin oExecute()/oExecuta(), FARA sa
* execute nimic in Oracle (tiparul S4e-5, verificare pe sirul SQL construit, nu pe rezultatul
* Oracle). Documentul se incarca REAL (IncarcaAntetFacturaEditare + IncarcaLiniiFacturaEditare,
* tiparul test_s9_8_flux.prg) - CITIRE, cu goExecutor REAL, inainte de orice mock; abia dupa
* incarcare se inlocuieste goExecutor cu mock-ul, inainte de a chema loForm.do_scrie_articole().
* Rezultat: ZERO scriere reala, nici in Oracle, nici in VANZARI_DETALII_TEMP - captura e strict pe
* text, nu pe efect.
*
* Parametru tnCaz:
* 1 = flag=0 (plRegenerareEditare NEDECLARAT - RELEASE explicit inainte, ca sa fie sigur Type()='U',
* exact starea unei prime emiteri, fara nicio regenerare in curs). Asterturi:
* - lcSql contine "pack_facturare.nregenerare_editare := 0"
* - fiecare apel adauga_articol_factura din text are 28 argumente (parametrul nou se trimite
* oricum, necondiționat - Oracle il ignora fara flag, cf. §11.0/§7.3 din propunere)
* 2 = flag=1 (plRegenerareEditare = .T., PRIVATE, cu poSnapshotEditare minimal construit ca sa
* treaca garda din StergeDocumentFacturare - an/luna = perioada activa, id_fact=0 ca sa sara
* peste ForteazaIdFactReemitere). Asterturi:
* - lcSql contine "pack_facturare.nregenerare_editare := 1"
* - fiecare apel adauga_articol_factura din text are 28 argumente
* - ORDINEA: "initializeaza_date_factura" apare INAINTEA lui "nregenerare_editare := 1" in
* acelasi sir - daca ordinea ar fi inversa, reset-ul din initializeaza_date_factura (aplicat
* pe Oracle, verificat la runtime in docs\raport_s10_aplicare_oracle.md §4.1) ar sterge
* flag-ul tacit, exact defectul pe care insertia din propunere §8.1 il evita prin ancorare
* DUPA capatul apelului la initializeaza_date_factura.
*
* Document folosit: 630 (CONTRACT-A din test_s9_8_flux.prg rularea 5 - driver deja validat pe el).
* Cursorul crsfactura e curatat local (explicatie/serie/lot golite, opt_facturare fortat la 0 pe
* toate randurile) DOAR in memorie, ca sa garanteze ca (a) textul capturat n-are ")" accidental
* intr-un camp text si (b) toate randurile cad pe branch-ul adauga_articol_factura, nu pe
* adauga_rata_factura (poArt.opt_facturare in (1,2)) - fara asta proba n-ar mai testa ce trebuie.
* Documentul real din baza NU e atins - toate modificarile sunt pe cursorul local incarcat in RAM.
*
* Tranzactia: do_scrie_articole() (ofacturare.vc2:19842) deschide Transactions=2 pe gnHandle
* (conexiunea REALA - SQLSetprop, nu goExecutor) si NU o inchide pe ramura de succes (o lasa
* deschisa pentru do_scrie_factura, care nu se apeleaza aici) - ROLLBACK explicit dupa fiecare caz,
* direct pe gnHandle, indiferent de rezultat.
LPARAMETERS tnCaz
SET SAFETY OFF
SET TALK OFF
PUBLIC gcErrLog, gnPass, gnFail
PUBLIC poDate
gcErrLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_s10_cablare_vfp_log_' + ;
STRTRAN(STRTRAN(STRTRAN(TTOC(DATETIME()), '/', ''), ':', ''), ' ', '_') + '.txt'
STRTOFILE('start ' + TRANSFORM(DATETIME()) + ' caz=' + TRANSFORM(tnCaz) + CHR(13) + CHR(10), gcErrLog)
ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto_roafacturare.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), gcErrLog, 1)
QUIT
ENDIF
gnIdUtil = 8
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_rutare_scriere.prg ADDITIVE
*!* la nume duplicat de procedura castiga PRIMUL fisier din lista SET PROCEDURE, nu ultimul
LOCAL lcProcExistent
lcProcExistent = SET("PROCEDURE")
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg", &lcProcExistent
LOCAL lcPathVechi, lcPathNou
lcPathVechi = SET("PATH")
lcPathNou = 'D:\ROA\ROAFACTURARE\COMUN\Utile\Teste\achizitie_import\stub_verificare;' + lcPathVechi
SET PATH TO &lcPathNou
PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip
gnMockRaspuns = 7
gcMockUltimMesaj = ''
gnMockUltimTip = 0
gnPass = 0
gnFail = 0
LOCAL lnCaz
lnCaz = VAL(TRANSFORM(tnCaz))
DO CASE
CASE lnCaz = 1
DO CazFlag WITH .F.
CASE lnCaz = 2
DO CazFlag WITH .T.
OTHERWISE
STRTOFILE('EROARE: tnCaz trebuie sa fie 1 (flag=0) / 2 (flag=1)' + CHR(13) + CHR(10), gcErrLog, 1)
ENDCASE
STRTOFILE('REZULTAT: ' + TRANSFORM(gnPass) + ' PASS / ' + TRANSFORM(gnFail) + ' FAIL' + CHR(13) + CHR(10), gcErrLog, 1)
STRTOFILE('end ' + TRANSFORM(DATETIME()) + CHR(13) + CHR(10), gcErrLog, 1)
QUIT
*==============================================================================================
* CazFlag: incarca REAL doc 630, curata local crsfactura, apeleaza loForm.do_scrie_articole() cu
* goExecutor MOCKAT (nicio scriere reala), verifica textul capturat.
*==============================================================================================
PROCEDURE CazFlag
LPARAMETERS tlFlagPornit
LOCAL loForm, loMock, loExecutorReal, lnIdV, lcPrefix
lnIdV = 630
lcPrefix = IIF(m.tlFlagPornit, 'FLAG1', 'FLAG0')
DO asserteaza WITH 'PRECONDITIE documentul ' + TRANSFORM(lnIdV) + ' e viu (STERS=0)', ;
Val1([select count(*) as v from vanzari where id_vanzare = ] + TRANSFORM(lnIdV) + [ and sters = 0]) = 1, ;
TRANSFORM(Val1([select count(*) as v from vanzari where id_vanzare = ] + TRANSFORM(lnIdV) + [ and sters = 0]))
LOCAL lnDiscRon, lnDiscVal
lnDiscRon = 0
lnDiscVal = 0
poDate = IncarcaAntetFacturaEditare(lnIdV, @lnDiscRon, @lnDiscVal)
DO asserteaza WITH lcPrefix + '-0a antetul documentului ' + TRANSFORM(lnIdV) + ' s-a incarcat', VARTYPE(poDate) = 'O', VARTYPE(poDate)
IF VARTYPE(poDate) <> 'O'
RETURN
ENDIF
IncarcaLiniiFacturaEditare(poDate, lnIdV)
DO asserteaza WITH lcPrefix + '-0b liniile documentului ' + TRANSFORM(lnIdV) + ' s-au incarcat', ;
USED('crsfactura') AND RECCOUNT('crsfactura') > 0, TRANSFORM(IIF(USED('crsfactura'), RECCOUNT('crsfactura'), -1))
IF !USED('crsfactura') OR RECCOUNT('crsfactura') = 0
RETURN
ENDIF
*!* curatare LOCALA (doar cursorul din RAM): (a) fara ")" accidental in text, (b) toate randurile
*!* pe branch-ul adauga_articol_factura, (c) fara NULL pe niciun camp NUMERIC folosit NEprotejat
*!* (fara Nvl()/Iif(Isnull())) in constructia lcSql din do_scrie_articole (ofacturare.vc2:19978-
*!* 20001) - un NULL real pe orice document istoric prabuseste tot sirul concatenat la NULL
*!* (VFP propaga NULL prin "+"), descoperit la runtime: PCOUNT()=1 dar VARTYPE(tcSql)='X' (NULL)
SELECT crsfactura
REPLACE ALL ;
id_temp WITH NVL(id_temp,0), id_articol WITH NVL(id_articol,0), ;
pret_achizitie WITH NVL(pret_achizitie,0), cu_tva WITH NVL(cu_tva,0), tip_valuta WITH NVL(tip_valuta,0), ;
pretftva WITH NVL(pretftva,0), vpretftva WITH NVL(vpretftva,0), ;
pretctva WITH NVL(pretctva,0), vpretctva WITH NVL(vpretctva,0), ;
id_valuta WITH NVL(id_valuta,0), gestionabil WITH NVL(gestionabil,0), cantitate WITH NVL(cantitate,0), ;
discountftva WITH NVL(discountftva,0), vdiscountftva WITH NVL(vdiscountftva,0), ;
discountctva WITH NVL(discountctva,0), vdiscountctva WITH NVL(vdiscountctva,0), ;
Curs WITH NVL(Curs,1), multiplicator WITH NVL(multiplicator,1), id_jtva_coloana WITH NVL(id_jtva_coloana,0), ;
pretv_orig WITH NVL(pretv_orig,0), ;
explicatie WITH 'test-s10-cablare', serie WITH '', lot WITH '', opt_facturare WITH 0 ;
IN crsfactura
*!* REPLACE ALL lasa pointerul pe EOF - Scan (folosit de do_scrie_articole) porneste de la
*!* POZITIA CURENTA, nu de la Top - fara acest GO TOP, bucla de articole rula 0 iteratii
GO TOP IN crsfactura
LOCAL lnRandurAsteptate
lnRandurAsteptate = RECCOUNT('crsfactura')
loForm = CREATEOBJECT('frm_facturare_articole2')
IF m.tlFlagPornit
PRIVATE plRegenerareEditare
PUBLIC poSnapshotEditare
plRegenerareEditare = .T.
poSnapshotEditare = CREATEOBJECT('Empty')
AddProperty(poSnapshotEditare, 'id_vanzare', m.lnIdV)
AddProperty(poSnapshotEditare, 'cod', 1)
AddProperty(poSnapshotEditare, 'an', gnAn)
AddProperty(poSnapshotEditare, 'luna', gnLuna)
AddProperty(poSnapshotEditare, 'id_fact', 0)
ELSE
IF TYPE('plRegenerareEditare') <> 'U'
RELEASE plRegenerareEditare
ENDIF
ENDIF
*!* dupa acest punct: NICIO citire/scriere reala in Oracle - totul trece prin mock
loExecutorReal = goExecutor
loMock = CREATEOBJECT('MockGoExecutorS10Cablare')
goExecutor = loMock
LOCAL llReturn
llReturn = loForm.do_scrie_articole()
*!* ROLLBACK explicit pe conexiunea REALA - do_scrie_articole nu inchide tranzactia pe succes
*!* (o lasa deschisa pentru do_scrie_factura, care nu se apeleaza aici)
goExecutor = loExecutorReal
SQLROLLBACK(gnHandle)
SQLSetProp(gnHandle, 'Transactions', 1)
DO asserteaza WITH lcPrefix + '-1 do_scrie_articole() a intors .T. (nicio eroare in constructia sirului)', llReturn, TRANSFORM(llReturn)
STRTOFILE(lcPrefix + ' apeluri capturate de mock: ' + TRANSFORM(loMock.nApeluri) + CHR(13) + CHR(10), gcErrLog, 1)
STRTOFILE(lcPrefix + ' --- lcSql capturat ---' + CHR(13) + CHR(10) + loMock.cSqlCapturat + CHR(13) + CHR(10), gcErrLog, 1)
LOCAL lcAsteptat
lcAsteptat = 'pack_facturare.nregenerare_editare := ' + IIF(m.tlFlagPornit, '1', '0') + ';'
DO asserteaza WITH lcPrefix + '-2 lcSql contine [' + lcAsteptat + ']', ;
lcAsteptat $ loMock.cSqlCapturat, IIF(lcAsteptat $ loMock.cSqlCapturat, 'gasit', 'LIPSA')
IF m.tlFlagPornit
LOCAL lnPozInit, lnPozFlag
lnPozInit = AT('initializeaza_date_factura', loMock.cSqlCapturat)
lnPozFlag = AT('nregenerare_editare := 1', loMock.cSqlCapturat)
DO asserteaza WITH lcPrefix + '-3 ORDINE: initializeaza_date_factura (pozitia ' + TRANSFORM(lnPozInit) + ;
') apare INAINTEA nregenerare_editare := 1 (pozitia ' + TRANSFORM(lnPozFlag) + ')', ;
lnPozInit > 0 AND lnPozFlag > 0 AND lnPozInit < lnPozFlag, ;
TRANSFORM(lnPozInit) + ' vs ' + TRANSFORM(lnPozFlag)
ENDIF
*!* AT() cu al treilea parametru (nr. de ordine al aparitiei) - gaseste direct a n-a aparitie,
*!* fara iterare manuala pe substring-uri
LOCAL lnNrApeluriAdauga, lnN, lnPozGasit, lnPozInceputArg, lnPozSfarsitRel, lcSegmentArg, lnVirgule
lnNrApeluriAdauga = 0
lnN = 0
DO WHILE .T.
lnN = lnN + 1
lnPozGasit = AT('adauga_articol_factura(', loMock.cSqlCapturat, lnN)
IF lnPozGasit = 0
EXIT
ENDIF
lnNrApeluriAdauga = lnNrApeluriAdauga + 1
lnPozInceputArg = lnPozGasit + LEN('adauga_articol_factura(')
lnPozSfarsitRel = AT(');', SUBSTR(loMock.cSqlCapturat, lnPozInceputArg))
lcSegmentArg = SUBSTR(loMock.cSqlCapturat, lnPozInceputArg, lnPozSfarsitRel - 1)
lnVirgule = OCCURS(',', lcSegmentArg)
DO asserteaza WITH lcPrefix + '-4.' + TRANSFORM(lnNrApeluriAdauga) + ' apelul #' + TRANSFORM(lnNrApeluriAdauga) + ;
' la adauga_articol_factura are 28 argumente (27 virgule)', lnVirgule = 27, TRANSFORM(lnVirgule) + ' virgule -> ' + TRANSFORM(lnVirgule + 1) + ' argumente'
ENDDO
DO asserteaza WITH lcPrefix + '-5 numarul de apeluri adauga_articol_factura = numarul de randuri din crsfactura (' + TRANSFORM(lnRandurAsteptate) + ')', ;
lnNrApeluriAdauga = lnRandurAsteptate, TRANSFORM(lnNrApeluriAdauga) + ' vs ' + TRANSFORM(lnRandurAsteptate)
IF m.tlFlagPornit
IF TYPE('poSnapshotEditare') <> 'U'
RELEASE poSnapshotEditare
ENDIF
ENDIF
IF TYPE('plRegenerareEditare') <> 'U'
RELEASE plRegenerareEditare
ENDIF
ENDPROC
*==============================================================================================
FUNCTION Val1
LPARAMETERS tcSql
LOCAL lnRet
lnRet = -1
IF USED('v_val10c')
USE IN v_val10c
ENDIF
IF goExecutor.oExecuta(tcSql, 'v_val10c')
SELECT v_val10c
IF RECCOUNT('v_val10c') > 0
GO TOP
lnRet = NVL(v_val10c.v, -1)
ENDIF
USE IN v_val10c
ELSE
STRTOFILE('EROARE Val1: ' + goExecutor.cEroare + CHR(13) + CHR(10), gcErrLog, 1)
ENDIF
RETURN lnRet
ENDFUNC
PROCEDURE asserteaza
LPARAMETERS tcNume, tlConditie, tcValoare
IF m.tlConditie
gnPass = gnPass + 1
STRTOFILE('PASS ' + m.tcNume + CHR(13) + CHR(10), gcErrLog, 1)
ELSE
gnFail = gnFail + 1
STRTOFILE('FAIL ' + m.tcNume + ' (valoare: ' + TRANSFORM(m.tcValoare) + ')' + CHR(13) + CHR(10), gcErrLog, 1)
ENDIF
ENDPROC
PROCEDURE test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
*!* daca a ramas o tranzactie manuala deschisa dupa o eroare in mijlocul CazFlag, o inchidem
*!* aici - nu lasam conexiunea agatata pe Transactions=2
IF TYPE('gnHandle') = 'N' AND gnHandle > 0
SQLROLLBACK(gnHandle)
SQLSetProp(gnHandle, 'Transactions', 1)
ENDIF
gnFail = gnFail + 1
STRTOFILE('REZULTAT: ' + TRANSFORM(gnPass) + ' PASS / ' + TRANSFORM(gnFail) + ' FAIL' + CHR(13) + CHR(10), gcErrLog, 1)
STRTOFILE('end (eroare) ' + TRANSFORM(DATETIME()) + CHR(13) + CHR(10), gcErrLog, 1)
QUIT
ENDPROC
*==============================================================================================
* MockGoExecutorS10Cablare: captureaza fiecare lcSql trimis prin oExecute()/oExecuta(), fara sa
* execute NIMIC in Oracle. oExecuta cu alias de cursor creeaza un cursor GOL (0 randuri) cu acel
* nume - StergeDocumentFacturare (ofacturare_rutare_scriere.prg:344) citeste doar Reccount() pe
* cursoarele intoarse, niciodata continutul lor, deci 0 randuri il duce corect pe ramura
* "sterge_factura" (fara nota contabila de reversat) - ramura simpla, un singur oExecuta in plus,
* tot mockat.
*==============================================================================================
DEFINE CLASS MockGoExecutorS10Cablare AS Custom
cSqlCapturat = ''
nApeluri = 0
cEroare = ''
FUNCTION oExecute(tcSql)
THIS.nApeluri = THIS.nApeluri + 1
LOCAL lcDiagCrs
IF USED('crsfactura')
lcDiagCrs = ' [DIAG crsfactura: RECNO=' + TRANSFORM(RECNO('crsfactura')) + ' RECCOUNT=' + TRANSFORM(RECCOUNT('crsfactura')) + ' EOF=' + TRANSFORM(EOF('crsfactura')) + ' ALIAS()=' + ALIAS() + ']'
ELSE
lcDiagCrs = ' [DIAG crsfactura: NEUSED]'
ENDIF
THIS.cSqlCapturat = THIS.cSqlCapturat + '>>>APEL ' + TRANSFORM(THIS.nApeluri) + ' (oExecute) VARTYPE(tcSql)=' + VARTYPE(m.tcSql) + lcDiagCrs + CHR(13) + CHR(10) + TRANSFORM(m.tcSql) + CHR(13) + CHR(10)
RETURN 1
ENDFUNC
FUNCTION oExecuta(tcSql, tcCursor)
THIS.nApeluri = THIS.nApeluri + 1
THIS.cSqlCapturat = THIS.cSqlCapturat + '>>>APEL ' + TRANSFORM(THIS.nApeluri) + ' (oExecuta)' + CHR(13) + CHR(10) + TRANSFORM(m.tcSql) + CHR(13) + CHR(10)
IF VARTYPE(m.tcCursor) = 'C' AND !EMPTY(m.tcCursor)
IF USED(m.tcCursor)
USE IN (m.tcCursor)
ENDIF
CREATE CURSOR (m.tcCursor) (xdummy I)
ENDIF
RETURN .T.
ENDFUNC
FUNCTION oPrelucrareEroare()
RETURN 'MockGoExecutorS10Cablare: ' + THIS.cEroare
ENDFUNC
ENDDEFINE