* test_s5_scriere_reala.prg * Test REAL de scriere in VANZARI_DETALII pentru lantul de editare a unei facturi emise - * APROBAT explicit de Marius (09.08.2026) sa scrie in schema de dev MARIUSM_AUTO@ROA_CENTRAL. * * Ce dovedeste, si nu poate fi dovedit headless: pack_facturare.actualizeaza_vanzari (apelata din * pack_contafin.finalizeaza_modificare_nota) face UPDATE VANZARI_DETALII SET STERS = 0 pe TOT * documentul, deci INVIE liniile sterse la o editare anterioara. Idiomul "marcheaza tot sters, * invie ce ramane" din ScrieArticoleFacturaEditate (ofacturare_editare.prg), apelat DUPA * finalizeaza_modificare_nota si in aceeasi tranzactie, trebuie sa corecteze ambele consecinte. * * Ordinea testata (o singura tranzactie manuala), copiata din ofacturare_comun.vc2:3799-3837: * do_deschide_tranzactie -> OSCRIE_IN_FISIERE(2) -> OSCRIE_IN_FISIERE(0) -> * finalizeaza_modificare_nota -> ScrieArticoleFacturaEditate -> do_inchide_tranzactie * * Doua treceri pe acelasi document: * TRECEREA 1 - o linie stearsa, o linie cu cantitatea schimbata, o linie noua adaugata. * TRECEREA 2 - reeditare fara nicio modificare; singura care dovedeste ca linia stearsa la * trecerea 1 RAMANE stearsa (consecinta 2 a resetului). * * In interiorul tranzactiei, dupa finalizeaza_modificare_nota si inainte de scrierea liniilor, * se citeste starea necomisa a lui VANZARI_DETALII (aceeasi conexiune) - proba directa ca resetul * STERS = 0 chiar ruleaza inainte, si ca scrierea liniilor il corecteaza dupa. * * Harness, nu UI: frm_modific2024 e ocolit (se blocheaza headless pe un dialog nativ - capcana j din * testare-ui-vfp.md), buton=1 e fortat direct, deci inainte_de_do_termin NU se executa. * do_deschide_tranzactie/do_inchide_tranzactie sunt reproduse inline dupa _frm_base.vc2:252-302. * OSCRIE_IN_FISIERE, finalizeaza_modificare_nota si ScrieArticoleFacturaEditate ruleaza reale. * * CONSUMA DATE DE TEST: VANZARI.COD se realoca la fiecare salvare, iar liniile sterse raman sterse. * Documentul e id_vanzare = 1049 (nu 1050, cel ales de descopera_caz_test pentru FACTURA_ARTICOLE). * Nu modifica cod de aplicatie, nu atinge .PJX/.exe. QUIT la final. SET SAFETY OFF SET TALK OFF LOCAL lcLog lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_s5_scriere_reala_log.txt' STRTOFILE('start ' + TTOC(DATETIME()) + CHR(13) + CHR(10), lcLog) PUBLIC gcErrLog, gcTestLog, gnPass, gnFail gcErrLog = lcLog gcTestLog = lcLog gnPass = 0 gnFail = 0 ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() *-- mock amessagebox incarcat PRIMUL, inaintea lantului real (la nume duplicat castiga primul gasit) SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg ADDITIVE DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT' IF gnHandle <= 0 STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1) QUIT ENDIF LOCAL lnVerifMock lnVerifMock = amessagebox('verificare mock', 4+32, 'test') STRTOFILE('verificare mock amessagebox = ' + TRANSFORM(lnVerifMock) + ; IIF(lnVerifMock = 6, ' (OK, mock activ)', ' (ATENTIE: amessagebox real, risc de blocaj)') + CHR(13) + CHR(10), lcLog, 1) SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\oscrie_in_fisiere.prg ADDITIVE *-- garda de referinte din do_editare_factura sta in odocumente.prg, care nu e in mediul de test SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\odocumente.prg ADDITIVE IF TYPE('gnPC') <> 'N' PUBLIC gnPC gnPC = 2 ENDIF PUBLIC gcMockUltimMesaj, gnMockUltimTip gcMockUltimMesaj = '' gnMockUltimTip = 0 STRTOFILE('gnAn=' + TRANSFORM(gnAn) + ' gnLuna=' + TRANSFORM(gnLuna) + ' gnIdUtil=' + TRANSFORM(gnIdUtil) + CHR(13) + CHR(10), lcLog, 1) *-- valorile alese pentru linia noua; pret_achizitie distinctiv, ca sa se poata urmari peste treceri PUBLIC gnPretAchNou, gnCantNoua, gnPretNou gnPretAchNou = 77.77 gnCantNoua = 3 gnPretNou = 50 PUBLIC gnIdVanzareTest gnIdVanzareTest = 1049 *-- liniile urmarite peste ambele treceri: la trecerea 2 documentul se reincarca din Oracle, iar *-- linia stearsa nu mai e in tvd - identitatea ei trebuie pastrata din trecerea 1 PUBLIC gnDetModificat, gnDetSters, gnDetNou gnDetModificat = 0 gnDetSters = 0 gnDetNou = 0 *-- starea de plecare, inainte de orice scriere DO LogStareLinii WITH 'STARE INITIALA', gnIdVanzareTest, lcLog DO ruleaza_trecere WITH gnIdVanzareTest, 'TRECEREA 1 - sterge o linie, schimba o cantitate, adauga o linie', .T., lcLog DO ruleaza_trecere WITH gnIdVanzareTest, 'TRECEREA 2 - reeditare fara nicio modificare', .F., lcLog STRTOFILE(CHR(13) + CHR(10) + 'REZULTAT: ' + TRANSFORM(gnPass) + ' PASS / ' + TRANSFORM(gnFail) + ' FAIL' + CHR(13) + CHR(10), lcLog, 1) STRTOFILE('done ' + TTOC(DATETIME()) + CHR(13) + CHR(10), lcLog, 1) QUIT PROCEDURE asserteaza LPARAMETERS tcNume, tlConditie, tcValoare IF m.tlConditie gnPass = gnPass + 1 STRTOFILE('PASS ' + m.tcNume + ' [' + m.tcValoare + ']' + CHR(13) + CHR(10), gcTestLog, 1) ELSE gnFail = gnFail + 1 STRTOFILE('FAIL ' + m.tcNume + ' [' + m.tcValoare + ']' + CHR(13) + CHR(10), gcTestLog, 1) ENDIF ENDPROC *-- executa SELECT-ul prin goExecutor si intoarce codul de succes; cursorul vechi se inchide intai PROCEDURE ExecSel LPARAMETERS tcSql, tcCursor LOCAL lnQ IF USED(tcCursor) USE IN (tcCursor) ENDIF lnQ = goExecutor.oExecute(tcSql, tcCursor) RETURN lnQ ENDPROC *-- logheaza starea tuturor liniilor documentului (inclusiv cele sterse); folosit si INTRE pasii *-- tranzactiei manuale - citirea merge pe aceeasi conexiune, deci vede si ce nu e inca comis PROCEDURE LogStareLinii LPARAMETERS tcEticheta, tnIdVanzare, tcLog LOCAL lcSql, lnQ, lcRand lcSql = [select id_vanzare_det, nvl(sters,0) as sters, nvl(cantitate,0) as cantitate, ] + ; [nvl(pret,0) as pret, nvl(pret_achizitie,0) as pret_achizitie ] + ; [from vanzari_detalii where id_vanzare = ] + TRANSFORM(tnIdVanzare) + [ order by id_vanzare_det] lnQ = ExecSel(lcSql, 'v_stare') IF lnQ <= 0 STRTOFILE(' [' + tcEticheta + '] EROARE citire linii: ' + ALLTRIM(TRANSFORM(NVL(goExecutor.cEroare, ''))) + CHR(13) + CHR(10), tcLog, 1) RETURN ENDIF lcRand = ' [' + tcEticheta + '] linii:' + CHR(13) + CHR(10) SELECT v_stare SCAN lcRand = lcRand + ' det=' + TRANSFORM(id_vanzare_det) + ' sters=' + TRANSFORM(sters) + ; ' cant=' + TRANSFORM(cantitate) + ' pret=' + TRANSFORM(pret) + ' pret_ach=' + TRANSFORM(pret_achizitie) + CHR(13) + CHR(10) ENDSCAN STRTOFILE(lcRand, tcLog, 1) USE IN v_stare ENDPROC *-- citeste STERS de pe o linie anume, direct din Oracle (si necomis, in tranzactie); -1 = eroare/lipsa PROCEDURE CitesteSters LPARAMETERS tnIdVanzareDet LOCAL lcSql, lnQ, lnRez lnRez = -1 lcSql = [select nvl(sters,0) as sters from vanzari_detalii where id_vanzare_det = ] + TRANSFORM(tnIdVanzareDet) lnQ = ExecSel(lcSql, 'v_unsters') IF lnQ > 0 AND RECCOUNT('v_unsters') = 1 lnRez = v_unsters.sters ENDIF IF USED('v_unsters') USE IN v_unsters ENDIF RETURN lnRez ENDPROC *-- reproduce _frm_base.vc2:252-265 (do_deschide_tranzactie), fara sa instantieze niciun formular PROCEDURE MyDeschideTranzactie LOCAL llReturn, lnSuccesLocal IF TYPE('goExecutor') = 'O' goExecutor.oExecuta([select * from dual]) ENDIF lnSuccesLocal = SQLSetprop(gnHandle, "Transactions", 2) llReturn = IIF(lnSuccesLocal < 0, .F., .T.) RETURN llReturn ENDPROC *-- reproduce _frm_base.vc2:279-302 (do_inchide_tranzactie), fara sa instantieze niciun formular PROCEDURE MyInchideTranzactie LPARAMETERS tnTip LOCAL llReturn, lnSuccesLocal IF tnTip = 1 lnSuccesLocal = SQLCOMMIT(gnHandle) ELSE lnSuccesLocal = SQLROLLBACK(gnHandle) ENDIF IF lnSuccesLocal < 0 llReturn = .F. ELSE lnSuccesLocal = SQLSetprop(gnHandle, "Transactions", 1) llReturn = IIF(lnSuccesLocal < 0, .F., .T.) ENDIF RETURN llReturn ENDPROC PROCEDURE ruleaza_trecere LPARAMETERS tnIdVanzare, tcEticheta, tlAplicaModificari, tcLog *-- pnAn/pnLuna/lnCod/lnIdFact PRIVATE (nu LOCAL), ca in ofacturare_comun.vc2:3730 - *-- finalizeaza_modificare_nota le foloseste ca bind-variabile ?pnLuna/?pnAn in josul stivei PRIVATE pnAn, pnLuna, lnCod, lnIdFact LOCAL lnSters, llEProforma, lnIdSet, lnIdFactD, lnSucces, llGasitRand LOCAL lcSql, lnQ, lnI LOCAL lnDetModificat, lnDetSters, lnDetPastrat, lnCantVecheMod, lnPretAchMod LOCAL lnMaxDetInainte, lnNrActiveInainte LOCAL lnCodInainte, lnTotFtvaInainte, lnTotTvaInainte, lnTotCtvaInainte LOCAL lnStersProbaDupaFinalizeaza, lnStersProbaDupaScriere LOCAL lnCodDupa, lnStersDupa, lnTotFtvaDupa, lnTotTvaDupa, lnTotCtvaDupa LOCAL lnDetNou, lnPretAchNouDupa, lnCantModDupa, lnPretAchModDupa, lnStersModDupa LOCAL lnNrActiveDupa, lnBrutAsteptat, lnStersNouUrmarit, lnPretAchNouUrmarit STRTOFILE(CHR(13) + CHR(10) + '========== ' + tcEticheta + ' (id_vanzare=' + TRANSFORM(tnIdVanzare) + ') ==========' + CHR(13) + CHR(10), tcLog, 1) *-- 1) starea documentului din VANZARI (cod-ul se realoca la fiecare salvare) lcSql = [select cod, sters, id_fact, eproforma, total_fara_tva, total_tva, total_cu_tva, discount, ] + ; [extract(year from data_act) as anact, extract(month from data_act) as lunaact ] + ; [from vanzari where id_vanzare = ] + TRANSFORM(tnIdVanzare) lnQ = ExecSel(lcSql, 'v_vz_inainte') IF lnQ <= 0 OR RECCOUNT('v_vz_inainte') <> 1 DO asserteaza WITH tcEticheta + ': VANZARI citit', .F., 'lnQ=' + TRANSFORM(lnQ) RETURN ENDIF SELECT v_vz_inainte lnCod = cod lnSters = sters lnIdFact = id_fact llEProforma = (NVL(eproforma, 0) = 1) pnAn = anact pnLuna = lunaact lnCodInainte = cod lnTotFtvaInainte = total_fara_tva lnTotTvaInainte = total_tva lnTotCtvaInainte = total_cu_tva USE IN v_vz_inainte STRTOFILE(' VANZARI inainte: cod=' + TRANSFORM(lnCod) + ' sters=' + TRANSFORM(lnSters) + ' id_fact=' + TRANSFORM(lnIdFact) + ; ' an/luna=' + TRANSFORM(pnAn) + '/' + TRANSFORM(pnLuna) + ' total_ftva=' + TRANSFORM(lnTotFtvaInainte) + ; ' total_tva=' + TRANSFORM(lnTotTvaInainte) + ' total_ctva=' + TRANSFORM(lnTotCtvaInainte) + CHR(13) + CHR(10), tcLog, 1) *-- 2) garzile din do_editare_factura (ofacturare_comun.vc2:3742-3767), fara UI IF lnSters = 1 OR llEProforma DO asserteaza WITH tcEticheta + ': document editabil (nesters, neproforma)', .F., 'sters=' + TRANSFORM(lnSters) RETURN ENDIF IF (pnAn*12) + pnLuna <> (gnAn*12) + gnLuna DO asserteaza WITH tcEticheta + ': document din luna curenta', .F., TRANSFORM(pnAn) + '/' + TRANSFORM(pnLuna) RETURN ENDIF IF ReferinteDocumenteNota(pnAn, pnLuna, lnCod) OR EsteInEFactura(lnIdFact) DO asserteaza WITH tcEticheta + ': document fara referinte / netrimis in eFactura', .F., 'blocat de garda' RETURN ENDIF *-- 3) instantaneul liniilor inainte de editare lcSql = [select count(*) as nr, max(id_vanzare_det) as maxdet from vanzari_detalii where id_vanzare = ] + TRANSFORM(tnIdVanzare) lnQ = ExecSel(lcSql, 'v_max') lnMaxDetInainte = IIF(lnQ > 0, NVL(v_max.maxdet, 0), 0) IF USED('v_max') USE IN v_max ENDIF *-- 4) cursoarele notei, exact ca do_editare_factura IF !IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.) DO asserteaza WITH tcEticheta + ': IncarcaCursoareModificareNota', .F., 'a esuat' RETURN ENDIF IF RECCOUNT('actactan') = 0 DO asserteaza WITH tcEticheta + ': exista nota contabila', .F., 'Reccount(actactan)=0' RETURN ENDIF SELECT actactan llGasitRand = .F. IF lnIdFact > 0 LOCATE FOR NVL(id_fact, 0) = lnIdFact llGasitRand = FOUND() ENDIF IF !llGasitRand GO TOP lnIdFact = id_fact ENDIF lnIdSet = id_set lnIdFactD = NVL(id_factd, 0) SELECT a.*, IIF(NVL(id_jtva_coloana, 0) = 0, 0, 1) AS cu_Tva FROM tact a INTO CURSOR tact READWRITE *-- 5) tvanz + tvd, cursoarele pe care le lasa calea reala inainte de Createobject(frm_modific2024) IF !IncarcaVanzareDinNota('tact') DO asserteaza WITH tcEticheta + ': IncarcaVanzareDinNota', .F., 'nu a gasit randul din VANZARI' RETURN ENDIF IncarcaArticoleFactura(tnIdVanzare, 'tvd') lnNrActiveInainte = RECCOUNT('tvd') STRTOFILE(' tvd incarcat cu ' + TRANSFORM(lnNrActiveInainte) + ' linii active; tvanz.id_vanzare=' + TRANSFORM(tvanz.id_vanzare) + ; ' discount=' + TRANSFORM(NVL(tvanz.discount, 0)) + CHR(13) + CHR(10), tcLog, 1) IF lnNrActiveInainte < 3 DO asserteaza WITH tcEticheta + ': documentul are cel putin 3 linii active', .F., TRANSFORM(lnNrActiveInainte) RETURN ENDIF *-- 6) editarile utilizatorului, aplicate pe tvd exact cum le lasa pagina de articole: *-- randul 1 primeste cantitate dubla, randul 2 e marcat sters (sters=1, ramane in cursor), *-- randul 3 ramane neatins, plus o linie noua cu id_vanzare_det = 0 lnDetPastrat = 0 lnCantVecheMod = 0 lnPretAchMod = 0 IF tlAplicaModificari SELECT tvd GO TOP gnDetModificat = id_vanzare_det lnCantVecheMod = NVL(cantitate, 0) lnPretAchMod = NVL(pret_achizitie, 0) SKIP gnDetSters = id_vanzare_det SKIP lnDetPastrat = id_vanzare_det ELSE *-- linia stearsa la trecerea 1 nu mai e in tvd; identitatile vin din trecerea 1 SELECT tvd LOCATE FOR id_vanzare_det = gnDetModificat IF !FOUND() DO asserteaza WITH tcEticheta + ': linia editata la trecerea 1 e reincarcata', .F., 'det=' + TRANSFORM(gnDetModificat) RETURN ENDIF lnCantVecheMod = NVL(cantitate, 0) lnPretAchMod = NVL(pret_achizitie, 0) ENDIF lnDetModificat = gnDetModificat lnDetSters = gnDetSters IF tlAplicaModificari SELECT tvd GO TOP REPLACE cantitate WITH lnCantVecheMod * 2, lmodificat WITH .T. SKIP REPLACE sters WITH 1, lmodificat WITH .T. *-- linia noua: coloanele care conteaza pentru INSERT se iau de pe prima linie, ca sa fie *-- coerenta cu documentul (cota TVA, jurnal, valuta, cont); gestiunea e cea a adaugarii *-- din dialog (gnScadereStoc = 0 -> id_gestiune = -1000) LOCAL lnArtNou, lnPretCuTvaNou, lnProcTvavNou, lnIdValNou, lnJtvaNou, lnTaxcodeNou, lcContNou SELECT tvd GO TOP lnArtNou = id_articol lnPretCuTvaNou = NVL(pret_cu_tva, 0) lnProcTvavNou = NVL(proc_tvav, 1) lnIdValNou = id_valuta lnJtvaNou = id_jtva_coloana lnTaxcodeNou = taxcode lcContNou = NVL(cont, '') APPEND BLANK IN tvd REPLACE id_vanzare WITH tnIdVanzare, id_vanzare_det WITH 0, id_articol WITH lnArtNou, ; cantitate WITH gnCantNoua, pret WITH gnPretNou, pret_cu_tva WITH lnPretCuTvaNou, ; proc_tvav WITH lnProcTvavNou, discount_unitar WITH 0, id_gestiune WITH -1000, ; cont WITH lcContNou, id_valuta WITH lnIdValNou, id_jtva_coloana WITH lnJtvaNou, ; taxcode WITH lnTaxcodeNou, sters WITH 0, pret_achizitie WITH gnPretAchNou, ; lmodificat WITH .T. IN tvd STRTOFILE(' editari in tvd: det=' + TRANSFORM(lnDetModificat) + ' cantitate ' + TRANSFORM(lnCantVecheMod) + ; ' -> ' + TRANSFORM(lnCantVecheMod * 2) + ' (pret_achizitie ramane ' + TRANSFORM(lnPretAchMod) + ')' + CHR(13) + CHR(10) + ; ' det=' + TRANSFORM(lnDetSters) + ' marcata stearsa (tvd.sters=1)' + CHR(13) + CHR(10) + ; ' det=' + TRANSFORM(lnDetPastrat) + ' neatinsa' + CHR(13) + CHR(10) + ; ' linie noua: id_articol=' + TRANSFORM(lnArtNou) + ' cantitate=' + TRANSFORM(gnCantNoua) + ; ' pret=' + TRANSFORM(gnPretNou) + ' pret_achizitie=' + TRANSFORM(gnPretAchNou) + CHR(13) + CHR(10), tcLog, 1) ELSE STRTOFILE(' tvd nemodificat: det ' + TRANSFORM(lnDetModificat) + ' / ' + TRANSFORM(lnDetSters) + ' / ' + ; TRANSFORM(lnDetPastrat) + ' (linia stearsa la trecerea 1 nici nu mai e incarcata)' + CHR(13) + CHR(10), tcLog, 1) ENDIF *-- 7) frm_modific2024 ocolit, buton=1 fortat (inainte_de_do_termin NU se executa) buton = 1 *-- 8) ramura buton=1 din do_editare_factura (ofacturare_comun.vc2:3799-3837), copiata identic; *-- do_deschide/inchide_tranzactie sunt reproduse inline (MyDeschide/MyInchideTranzactie) lnSucces = 0 lnStersProbaDupaFinalizeaza = -1 lnStersProbaDupaScriere = -1 TRY IF MyDeschideTranzactie() SELECT actactan lnSucces = OSCRIE_IN_FISIERE(2, .T., .T.) STRTOFILE(' OSCRIE_IN_FISIERE(2,...) => ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1) IF lnSucces > 0 IF USED('actactan') USE IN actactan ENDIF SELECT tact REPLACE id_jtva_coloana WITH NULL, proc_tva WITH 0 FOR cu_Tva = 0 SELECT * FROM tact INTO CURSOR actactan READWRITE REPLACE ALL id_util WITH gnIdUtil, sters WITH 0 IF USED('rul_temp') USE IN rul_temp ENDIF SELECT * FROM trul INTO CURSOR RUL_TEMP READWRITE REPLACE ALL id_util WITH gnIdUtil, sters WITH 0 IF USED('rul_temp_obinv') USE IN rul_temp_obinv ENDIF SELECT * FROM trul_obinv INTO CURSOR RUL_TEMP_OBINV READWRITE REPLACE ALL id_util WITH gnIdUtil, sters WITH 0 lnSucces = OSCRIE_IN_FISIERE(0, .T., .T.) STRTOFILE(' OSCRIE_IN_FISIERE(0,...) => ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1) ENDIF IF lnSucces > 0 lcSql = [begin pack_contafin.finalizeaza_modificare_nota(?pnLuna,?pnAn,Null,] + ALLTRIM(STR(lnIdSet)) + [,] + ; ALLTRIM(STR(lnCod)) + [,] + ALLTRIM(STR(lnIdFact)) + [,] + ALLTRIM(STR(lnIdFactD)) + [,?gnIdUtil); end;] lnSucces = IIF(goExecutor.oExecuta(lcSql), 1, -1) STRTOFILE(' finalizeaza_modificare_nota => ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1) ENDIF *-- PROBA DE ORDONARE: starea necomisa, dupa finalizeaza_modificare_nota si INAINTE de *-- scrierea liniilor - aici se vede resetul STERS = 0 din actualizeaza_vanzari IF lnSucces > 0 DO LogStareLinii WITH 'IN TRANZACTIE, dupa finalizeaza_modificare_nota', tnIdVanzare, tcLog IF lnDetSters > 0 lnStersProbaDupaFinalizeaza = CitesteSters(lnDetSters) ENDIF ENDIF *-- blocul nou, identic cu ofacturare_comun.vc2:3828-3830 si comun.vc2:2491 IF lnSucces > 0 AND "OFACTURARE_EDITARE" $ UPPER(SET("Procedure")) AND USED('tvanz') AND RECCOUNT('tvanz') = 1 lnSucces = IIF(ScrieArticoleFacturaEditate(tvanz.id_vanzare), 1, -1) STRTOFILE(' ScrieArticoleFacturaEditate => ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1) ELSE STRTOFILE(' ATENTIE: blocul ScrieArticoleFacturaEditate NU s-a executat' + CHR(13) + CHR(10), tcLog, 1) ENDIF IF lnSucces > 0 DO LogStareLinii WITH 'IN TRANZACTIE, dupa ScrieArticoleFacturaEditate', tnIdVanzare, tcLog IF lnDetSters > 0 lnStersProbaDupaScriere = CitesteSters(lnDetSters) ENDIF ENDIF IF MyInchideTranzactie(IIF(lnSucces < 0, 2, 1)) STRTOFILE(' tranzactie inchisa cu ' + IIF(lnSucces < 0, 'ROLLBACK', 'COMMIT') + CHR(13) + CHR(10), tcLog, 1) ELSE STRTOFILE(' FAIL la inchiderea tranzactiei' + CHR(13) + CHR(10), tcLog, 1) ENDIF ELSE STRTOFILE(' FAIL: deschiderea tranzactiei a esuat' + CHR(13) + CHR(10), tcLog, 1) ENDIF CATCH TO loExc STRTOFILE(' EXCEPTIE in lantul de scriere: ' + TRANSFORM(loExc.ErrorNo) + ' [' + loExc.Message + '] ' + ; loExc.Procedure + ':' + TRANSFORM(loExc.LineNo) + ' -> ROLLBACK' + CHR(13) + CHR(10), tcLog, 1) lnSucces = -99 MyInchideTranzactie(2) ENDTRY DO asserteaza WITH tcEticheta + ': lantul de scriere a mers pana la capat (lnSucces>0, COMMIT)', ; lnSucces > 0, 'lnSucces=' + TRANSFORM(lnSucces) IF USED('actactan') USE IN actactan ENDIF IF USED('tact') USE IN tact ENDIF IF USED('rul_temp') USE IN rul_temp ENDIF IF USED('trul') USE IN trul ENDIF IF USED('rul_temp_obinv') USE IN rul_temp_obinv ENDIF IF USED('trul_obinv') USE IN trul_obinv ENDIF IF lnSucces <= 0 STRTOFILE(' scrierea nu s-a produs - fara verificari dupa' + CHR(13) + CHR(10), tcLog, 1) RETURN ENDIF *-- 9) verificarile de dupa commit DO LogStareLinii WITH 'DUPA COMMIT', tnIdVanzare, tcLog *-- proba de ordonare, singura care nu poate fi obtinuta din afara tranzactiei DO asserteaza WITH tcEticheta + ': resetul STERS=0 din actualizeaza_vanzari a rulat inainte de scrierea liniilor', ; lnStersProbaDupaFinalizeaza = 0, 'sters pe det=' + TRANSFORM(lnDetSters) + ' dupa finalizeaza = ' + TRANSFORM(lnStersProbaDupaFinalizeaza) *-- starea liniilor dupa commit lcSql = [select id_vanzare_det, nvl(sters,0) as sters, nvl(cantitate,0) as cantitate, ] + ; [nvl(pret,0) as pret, nvl(pret_achizitie,0) as pret_achizitie ] + ; [from vanzari_detalii where id_vanzare = ] + TRANSFORM(tnIdVanzare) + [ order by id_vanzare_det] lnQ = ExecSel(lcSql, 'v_dupa') IF lnQ <= 0 DO asserteaza WITH tcEticheta + ': citirea liniilor dupa commit', .F., 'lnQ=' + TRANSFORM(lnQ) RETURN ENDIF lnStersModDupa = -1 lnCantModDupa = -1 lnPretAchModDupa = -1 lnDetNou = 0 lnPretAchNouDupa = -1 lnStersNouUrmarit = -1 lnPretAchNouUrmarit = -1 lnNrActiveDupa = 0 lnBrutAsteptat = 0 SELECT v_dupa SCAN IF sters = 0 lnNrActiveDupa = lnNrActiveDupa + 1 lnBrutAsteptat = lnBrutAsteptat + ROUND(cantitate * pret, 2) ENDIF IF id_vanzare_det = lnDetModificat lnStersModDupa = sters lnCantModDupa = cantitate lnPretAchModDupa = pret_achizitie ENDIF IF id_vanzare_det > lnMaxDetInainte lnDetNou = id_vanzare_det lnPretAchNouDupa = pret_achizitie ENDIF *-- linia adaugata la trecerea 1, urmarita si la trecerea 2 (acolo e deja linie existenta) IF gnDetNou > 0 AND id_vanzare_det = gnDetNou lnStersNouUrmarit = sters lnPretAchNouUrmarit = pret_achizitie ENDIF ENDSCAN USE IN v_dupa *-- linia marcata stearsa: STERS=1 dupa ce s-a intors finalizeaza_modificare_nota LOCAL lnStersDetSters lnStersDetSters = CitesteSters(lnDetSters) DO asserteaza WITH tcEticheta + ': linia marcata stearsa are STERS=1 in VANZARI_DETALII', ; lnStersDetSters = 1, 'det=' + TRANSFORM(lnDetSters) + ' sters=' + TRANSFORM(lnStersDetSters) *-- si dovada ca scrierea liniilor e cea care a corectat resetul DO asserteaza WITH tcEticheta + ': ScrieArticoleFacturaEditate a re-marcat linia stearsa in aceeasi tranzactie', ; lnStersProbaDupaScriere = 1, 'sters pe det=' + TRANSFORM(lnDetSters) + ' dupa scriere = ' + TRANSFORM(lnStersProbaDupaScriere) *-- liniile pastrate raman active, cu cantitatea editata DO asserteaza WITH tcEticheta + ': linia pastrata e activa cu cantitatea editata', ; lnStersModDupa = 0 AND ABS(lnCantModDupa - IIF(tlAplicaModificari, lnCantVecheMod * 2, lnCantVecheMod)) < 0.001, ; 'det=' + TRANSFORM(lnDetModificat) + ' sters=' + TRANSFORM(lnStersModDupa) + ' cant=' + TRANSFORM(lnCantModDupa) *-- PRET_ACHIZITIE pe linia existenta ramane neatins (omis din SET-ul de UPDATE) DO asserteaza WITH tcEticheta + ': PRET_ACHIZITIE pe linia existenta editata a ramas neatins', ; ABS(lnPretAchModDupa - lnPretAchMod) < 0.0001, ; 'det=' + TRANSFORM(lnDetModificat) + ' inainte=' + TRANSFORM(lnPretAchMod) + ' dupa=' + TRANSFORM(lnPretAchModDupa) IF tlAplicaModificari *-- linia noua a intrat prin INSERT, cu ID_VANZARE_DET alocat de trigger DO asserteaza WITH tcEticheta + ': linia noua a fost inserata cu ID_VANZARE_DET alocat de trigger', ; lnDetNou > lnMaxDetInainte, 'det nou=' + TRANSFORM(lnDetNou) + ' (max inainte=' + TRANSFORM(lnMaxDetInainte) + ')' DO asserteaza WITH tcEticheta + ': linia noua are PRET_ACHIZITIE exact valoarea tastata', ; ABS(lnPretAchNouDupa - gnPretAchNou) < 0.0001, 'pret_achizitie=' + TRANSFORM(lnPretAchNouDupa) + ' (tastat ' + TRANSFORM(gnPretAchNou) + ')' DO asserteaza WITH tcEticheta + ': documentul are 3 linii active (una stearsa, una noua)', ; lnNrActiveDupa = 3, 'active=' + TRANSFORM(lnNrActiveDupa) gnDetNou = lnDetNou ELSE DO asserteaza WITH tcEticheta + ': nicio linie noua nu a fost inserata', ; lnDetNou = 0, 'det peste maximul dinainte=' + TRANSFORM(lnDetNou) DO asserteaza WITH tcEticheta + ': numarul de linii active nu s-a schimbat', ; lnNrActiveDupa = lnNrActiveInainte, 'active=' + TRANSFORM(lnNrActiveDupa) + ' (erau ' + TRANSFORM(lnNrActiveInainte) + ')' DO asserteaza WITH tcEticheta + ': linia adaugata la trecerea 1 e activa si la reeditare', ; lnStersNouUrmarit = 0, 'det=' + TRANSFORM(gnDetNou) + ' sters=' + TRANSFORM(lnStersNouUrmarit) DO asserteaza WITH tcEticheta + ': PRET_ACHIZITIE al liniei adaugate la trecerea 1 a ramas neatins', ; ABS(lnPretAchNouUrmarit - gnPretAchNou) < 0.0001, ; 'det=' + TRANSFORM(gnDetNou) + ' pret_achizitie=' + TRANSFORM(lnPretAchNouUrmarit) + ' (tastat ' + TRANSFORM(gnPretAchNou) + ')' ENDIF *-- totalurile din VANZARI dupa recalculeaza_totaluri_vanzari lcSql = [select cod, nvl(sters,0) as sters, total_fara_tva, total_tva, total_cu_tva from vanzari where id_vanzare = ] + TRANSFORM(tnIdVanzare) lnQ = ExecSel(lcSql, 'v_vz_dupa') IF lnQ <= 0 OR RECCOUNT('v_vz_dupa') <> 1 DO asserteaza WITH tcEticheta + ': VANZARI citit dupa commit', .F., 'lnQ=' + TRANSFORM(lnQ) RETURN ENDIF SELECT v_vz_dupa lnCodDupa = cod lnStersDupa = sters lnTotFtvaDupa = total_fara_tva lnTotTvaDupa = total_tva lnTotCtvaDupa = total_cu_tva USE IN v_vz_dupa STRTOFILE(' VANZARI dupa: cod=' + TRANSFORM(lnCodDupa) + ' (era ' + TRANSFORM(lnCodInainte) + ') sters=' + TRANSFORM(lnStersDupa) + ; ' total_ftva=' + TRANSFORM(lnTotFtvaDupa) + ' total_tva=' + TRANSFORM(lnTotTvaDupa) + ; ' total_ctva=' + TRANSFORM(lnTotCtvaDupa) + ' (brut din linii active=' + TRANSFORM(lnBrutAsteptat) + ')' + CHR(13) + CHR(10), tcLog, 1) DO asserteaza WITH tcEticheta + ': VANZARI.COD realocat, documentul ramane activ', ; lnCodDupa <> lnCodInainte AND lnStersDupa = 0, TRANSFORM(lnCodInainte) + ' -> ' + TRANSFORM(lnCodDupa) DO asserteaza WITH tcEticheta + ': totalurile din VANZARI sunt coerente (fara_tva + tva = cu_tva)', ; ABS((lnTotFtvaDupa + lnTotTvaDupa) - lnTotCtvaDupa) < 0.01, ; TRANSFORM(lnTotFtvaDupa) + ' + ' + TRANSFORM(lnTotTvaDupa) + ' = ' + TRANSFORM(lnTotCtvaDupa) *-- toate liniile documentului au preturile cu TVA (pret_cu_tva=1), deci totalul brut al *-- documentului e suma cantitate*pret pe liniile active - relatie verificata si inainte de editare DO asserteaza WITH tcEticheta + ': total_cu_tva corespunde liniilor active dupa recalcul', ; ABS(lnTotCtvaDupa - lnBrutAsteptat) < 0.01, ; 'total_cu_tva=' + TRANSFORM(lnTotCtvaDupa) + ' suma linii active=' + TRANSFORM(lnBrutAsteptat) IF USED('tvd') USE IN tvd ENDIF IF USED('tvanz') USE IN tvanz ENDIF STRTOFILE(' REZUMAT ' + tcEticheta + ': cod ' + TRANSFORM(lnCodInainte) + ' -> ' + TRANSFORM(lnCodDupa) + CHR(13) + CHR(10), tcLog, 1) ENDPROC PROCEDURE test_error_handler LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1) ENDPROC