#6 editare factura emisa: S5 - scrierea sumelor editate in Oracle

La salvarea unei facturi deja emise, modificarile facute liniilor de articole
se scriu acum real in VANZARI_DETALII, in aceeasi tranzactie cu restul salvarii,
si totalurile documentului se recalculeaza din liniile efectiv salvate.

- ofacturare_editare.prg: helper nou ScrieArticoleFacturaEditate. Idiomul e
  "marcheaza tot sters, invie ce ramane", nu delta, pentru ca
  actualizeaza_vanzari face UPDATE ... SET STERS = 0 pe tot documentul, fara
  garda; o scriere delta ar lasa liniile sterse sa reinvie la fiecare salvare.
  Cursor gol = no-op, ca o eroare la incarcare sa nu goleasca factura.
- comun.vc2, ofacturare_comun.vc2: agatarea apelului dupa
  finalizeaza_modificare_nota si inainte de inchiderea tranzactiei, in ambele
  puncte de intrare.
- omodificari.vc2: coloana Pret achizitie in grid, editabila doar pe liniile
  noi; liniile de set devin needitabile, cu marcaj; cinci validari la salvare.
- teste: cinci suite noi (validari, grid UI, scriere reala, discount/valuta,
  rollback, al doilea punct de intrare) si asteptari actualizate in
  test_page3_articole.
- docs: oracle_export.md - exportul all_source cere linesize 32767, altfel
  rupe liniile lungi prin mijlocul identificatorilor; scripturi-migrare-db.md -
  UpdateVersiune adauga singur extensia .sql.

Cere scripturile ff_2026_08_09_01 (PACK_FACTURARE) si ff_2026_08_09_02
(VVANZARI_ARTICOLE).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
This commit is contained in:
2026-08-10 01:37:12 +03:00
parent b9eba29ebe
commit 1c42ae0af4
13 changed files with 3408 additions and 60 deletions

View File

@@ -0,0 +1,816 @@
* test_s5_discount_valuta.prg
* Inchide cele doua goluri declarate de test_s5_scriere_reala: parametrul de discount al procedurii
* pack_facturare.recalculeaza_totaluri_vanzari (decizia 41) si documentele in valuta.
*
* Contractul verificat: recalculeaza_totaluri_vanzari(V_ID_VANZARE, V_DISCOUNT DEFAULT NULL), cu
* NULL = "pastreaza valoarea curenta". Cazul periculos e al doilea: daca NULL ar zeroa tacit
* discountul, orice salvare ulterioara a documentului l-ar sterge.
*
* BLOCUL A - contractul pe un document in RON (id_vanzare = 1049, in_valuta = 0). Patru apeluri
* succesive in aceeasi tranzactie, cu citirea starii necomise intre ele:
* NULL pe discount 0 -> recalculul reproduce exact starea persistata (idempotent)
* valoare nenula -> ajunge in VANZARI.DISCOUNT si scade totalurile
* NULL peste ea -> VERDICTUL: pastreaza sau zeroeaza
* 0 -> readuce documentul la starea de plecare
* Tranzactia se inchide cu ROLLBACK, deci blocul NU consuma date.
*
* BLOCUL B - acelasi contract pe un document REAL in valuta (id_vanzare = 1037, in_valuta = 1,
* id_valuta = 2, curs = 5.2688, cu rand in VANZARI_CURSURI). Aici se exercita ramura
* decode(in_valuta, 1, ROUND(curs * discount / multiplicator, PPRETV), discount) din procedura -
* discountul e exprimat in valuta si se converteste la RON prin cursul documentului. Se verifica
* si perechea valval/tvaval/totval. Documentul e din 05.2026 (arhiva), deci tranzactia se inchide
* obligatoriu cu ROLLBACK: nimic nu se modifica in el.
*
* BLOCUL C - lantul real de salvare pe un document cu discount NENUL (id_vanzare = 1049). Singurul
* bloc care scrie: pune discountul prin procedura (COMMIT), ruleaza lantul complet de editare fara
* nicio modificare de linii (COMMIT) si verifica ca discountul supravietuieste salvarii - adica
* tvanz.discount (citit din VANZARI de IncarcaVanzareNota) ajunge inapoi in procedura prin
* ScrieArticoleFacturaEditate. La final restaureaza discount = 0 si totalurile initiale (COMMIT).
* CONSUMA UN COD: VANZARI.COD se realoca la salvare.
*
* Harness identic cu test_s5_scriere_reala.prg: frm_modific2024 ocolit, buton = 1 fortat,
* do_deschide/inchide_tranzactie reproduse inline dupa _frm_base.vc2:252-302. Nu atinge cod de
* aplicatie, nu modifica PACK_FACTURARE. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_s5_discount_valuta_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
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
*-- documentele de test si valorile de discount folosite
PUBLIC gnIdRon, gnIdValuta, gnDiscRon, gnDiscValuta, gnPPretV
gnIdRon = 1049
gnIdValuta = 1037
gnDiscRon = 12.5
gnDiscValuta = 10
gnPPretV = 2
*-- capul documentului citit de CitesteCap
PUBLIC gnCapCod, gnCapSters, gnCapInValuta, gnCapDisc, gnCapDiscNul, gnCapDiscTva
PUBLIC gnCapVA, gnCapFtva, gnCapTva, gnCapCtva, gnCapValval, gnCapTvaval, gnCapTotval
PUBLIC gnCapIdValuta, gnCapCurs, gnCapMult
STRTOFILE('gnAn=' + TRANSFORM(gnAn) + ' gnLuna=' + TRANSFORM(gnLuna) + ' gnIdUtil=' + TRANSFORM(gnIdUtil) + CHR(13) + CHR(10), lcLog, 1)
*-- precizia de pret in valuta, din optiunile firmei - intra in formula de conversie a discountului
IF ExecSel([select to_number(pack_sesiune.getOptiuneFirma('PPRETV')) as ppretv from dual], 'v_opt') > 0
gnPPretV = NVL(v_opt.ppretv, 2)
USE IN v_opt
ENDIF
STRTOFILE('PPRETV = ' + TRANSFORM(gnPPretV) + CHR(13) + CHR(10), lcLog, 1)
DO bloc_a_discount_ron WITH lcLog
DO bloc_b_valuta WITH lcLog
DO bloc_c_lant_real WITH 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
*-- citeste capul documentului in variabilele gnCap*; citirea merge pe aceeasi conexiune, deci vede
*-- si starea necomisa din interiorul tranzactiei. Intoarce .F. daca randul nu exista.
PROCEDURE CitesteCap
LPARAMETERS tnId
LOCAL lcSql, lnQ
lcSql = [select cod, nvl(sters,0) as sters, nvl(in_valuta,0) as in_valuta, ] + ;
[nvl(discount,0) as discount, nvl2(discount,0,1) as disc_nul, nvl(discount_tva,0) as discount_tva, ] + ;
[nvl(valoare_achizitie,0) as valoare_achizitie, nvl(total_fara_tva,0) as total_fara_tva, ] + ;
[nvl(total_tva,0) as total_tva, nvl(total_cu_tva,0) as total_cu_tva, ] + ;
[nvl(valval,0) as valval, nvl(tvaval,0) as tvaval, nvl(totval,0) as totval, ] + ;
[nvl(id_valuta,0) as id_valuta, nvl(curs,0) as curs, nvl(multiplicator,0) as multiplicator ] + ;
[from vanzari where id_vanzare = ] + TRANSFORM(tnId)
lnQ = ExecSel(lcSql, 'v_cap')
IF lnQ <= 0 OR RECCOUNT('v_cap') <> 1
RETURN .F.
ENDIF
SELECT v_cap
gnCapCod = cod
gnCapSters = sters
gnCapInValuta = in_valuta
gnCapDisc = discount
gnCapDiscNul = disc_nul
gnCapDiscTva = discount_tva
gnCapVA = valoare_achizitie
gnCapFtva = total_fara_tva
gnCapTva = total_tva
gnCapCtva = total_cu_tva
gnCapValval = valval
gnCapTvaval = tvaval
gnCapTotval = totval
gnCapIdValuta = id_valuta
gnCapCurs = curs
gnCapMult = multiplicator
USE IN v_cap
RETURN .T.
ENDPROC
PROCEDURE LogCap
LPARAMETERS tcEticheta, tcLog
STRTOFILE(' [' + tcEticheta + '] cod=' + TRANSFORM(gnCapCod) + ' in_valuta=' + TRANSFORM(gnCapInValuta) + ;
' discount=' + TRANSFORM(gnCapDisc) + IIF(gnCapDiscNul = 1, ' (NULL in baza)', '') + ;
' discount_tva=' + TRANSFORM(gnCapDiscTva) + ' val_ach=' + TRANSFORM(gnCapVA) + CHR(13) + CHR(10) + ;
' ftva=' + TRANSFORM(gnCapFtva) + ' tva=' + TRANSFORM(gnCapTva) + ' ctva=' + TRANSFORM(gnCapCtva) + ;
' | valval=' + TRANSFORM(gnCapValval) + ' tvaval=' + TRANSFORM(gnCapTvaval) + ' totval=' + TRANSFORM(gnCapTotval) + ;
' | id_valuta=' + TRANSFORM(gnCapIdValuta) + ' curs=' + TRANSFORM(gnCapCurs) + ' mult=' + TRANSFORM(gnCapMult) + ;
CHR(13) + CHR(10), tcLog, 1)
ENDPROC
*-- apeleaza procedura de recalcul; tcDiscount e literalul SQL ('NULL' sau o valoare)
PROCEDURE ApelRecalc
LPARAMETERS tnId, tcDiscount, tcLog
LOCAL lcSql, llOk
lcSql = [begin pack_facturare.recalculeaza_totaluri_vanzari(] + ALLTRIM(STR(tnId)) + [,] + tcDiscount + [); end;]
llOk = goExecutor.oExecuta(lcSql)
STRTOFILE(' APEL ' + lcSql + ' => ' + IIF(llOk, 'OK', 'ESEC [' + ALLTRIM(TRANSFORM(NVL(goExecutor.cEroare, ''))) + ']') + CHR(13) + CHR(10), tcLog, 1)
RETURN llOk
ENDPROC
*-- cota de TVA maxima de pe liniile active - intra in formula discountului de TVA din procedura
PROCEDURE CotaMaxima
LPARAMETERS tnId
LOCAL lcSql, lnQ, lnRez
lnRez = 0
lcSql = [select nvl(max(proc_tvav),0) as tvavmax from vanzari_detalii where id_vanzare = ] + ;
TRANSFORM(tnId) + [ and sters = 0]
lnQ = ExecSel(lcSql, 'v_tvav')
IF lnQ > 0 AND RECCOUNT('v_tvav') = 1
lnRez = v_tvav.tvavmax
ENDIF
IF USED('v_tvav')
USE IN v_tvav
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
*=====================================================================================
*-- BLOCUL A: contractul parametrului de discount, pe document in RON, cu ROLLBACK la final
*=====================================================================================
PROCEDURE bloc_a_discount_ron
LPARAMETERS tcLog
LOCAL lnBaseDisc, lnBaseDiscTva, lnBaseVA, lnBaseFtva, lnBaseTva, lnBaseCtva
LOCAL lnP1Disc, lnP1Ftva, lnP1Tva, lnP1Ctva, lnP1DiscTva, lnP1VA
LOCAL lnTvavMax, lnAstFtva, lnAstDiscTva, llOk, lcEt
lcEt = 'A'
STRTOFILE(CHR(13) + CHR(10) + '========== BLOCUL A - contractul de discount pe document in RON (id_vanzare=' + ;
TRANSFORM(gnIdRon) + ') ==========' + CHR(13) + CHR(10), tcLog, 1)
IF !CitesteCap(gnIdRon)
DO asserteaza WITH lcEt + ': documentul in RON exista', .F., 'id_vanzare=' + TRANSFORM(gnIdRon)
RETURN
ENDIF
DO LogCap WITH 'STARE INITIALA', tcLog
IF gnCapInValuta <> 0
DO asserteaza WITH lcEt + ': documentul ales e in RON (in_valuta=0)', .F., TRANSFORM(gnCapInValuta)
RETURN
ENDIF
lnBaseDisc = gnCapDisc
lnBaseDiscTva = gnCapDiscTva
lnBaseVA = gnCapVA
lnBaseFtva = gnCapFtva
lnBaseTva = gnCapTva
lnBaseCtva = gnCapCtva
lnTvavMax = CotaMaxima(gnIdRon)
STRTOFILE(' cota TVA maxima pe liniile active = ' + TRANSFORM(lnTvavMax) + CHR(13) + CHR(10), tcLog, 1)
IF !MyDeschideTranzactie()
DO asserteaza WITH lcEt + ': tranzactia s-a deschis', .F., 'SQLSetprop a esuat'
RETURN
ENDIF
TRY
*-- PASUL 1: NULL peste discountul curent (0) - recalculul trebuie sa reproduca exact starea
llOk = ApelRecalc(gnIdRon, 'NULL', tcLog)
DO asserteaza WITH lcEt + '1: apelul cu NULL a mers', llOk, 'llOk=' + TRANSFORM(llOk)
IF llOk AND CitesteCap(gnIdRon)
DO LogCap WITH 'dupa recalc(NULL) pe discount 0', tcLog
DO asserteaza WITH lcEt + '1: recalculul reproduce exact totalurile persistate (idempotent)', ;
ABS(gnCapFtva - lnBaseFtva) < 0.005 AND ABS(gnCapTva - lnBaseTva) < 0.005 ;
AND ABS(gnCapCtva - lnBaseCtva) < 0.005 AND ABS(gnCapVA - lnBaseVA) < 0.005, ;
'ftva ' + TRANSFORM(lnBaseFtva) + '->' + TRANSFORM(gnCapFtva) + ' tva ' + TRANSFORM(lnBaseTva) + ;
'->' + TRANSFORM(gnCapTva) + ' ctva ' + TRANSFORM(lnBaseCtva) + '->' + TRANSFORM(gnCapCtva)
DO asserteaza WITH lcEt + '1: NULL nu schimba discountul (0 ramane 0)', ;
ABS(gnCapDisc - lnBaseDisc) < 0.0001, TRANSFORM(lnBaseDisc) + ' -> ' + TRANSFORM(gnCapDisc)
ENDIF
*-- PASUL 2: valoare nenula - trebuie sa ajunga in VANZARI.DISCOUNT si sa scada totalurile.
*-- pe document in RON procedura ia discountul ca atare (decode(in_valuta,1,...,discount))
lnAstFtva = lnBaseFtva - gnDiscRon
lnAstDiscTva = ROUND(gnDiscRon * (lnTvavMax - 1), gnPPretV)
llOk = ApelRecalc(gnIdRon, ALLTRIM(STR(gnDiscRon, 18, 4)), tcLog)
DO asserteaza WITH lcEt + '2: apelul cu valoare nenula a mers', llOk, 'llOk=' + TRANSFORM(llOk)
IF !llOk OR !CitesteCap(gnIdRon)
MyInchideTranzactie(2)
RETURN
ENDIF
DO LogCap WITH 'dupa recalc(' + TRANSFORM(gnDiscRon) + ')', tcLog
DO asserteaza WITH lcEt + '2: valoarea nenula ajunge in VANZARI.DISCOUNT', ;
ABS(gnCapDisc - gnDiscRon) < 0.0001, 'discount=' + TRANSFORM(gnCapDisc) + ' (cerut ' + TRANSFORM(gnDiscRon) + ')'
DO asserteaza WITH lcEt + '2: total_fara_tva scade exact cu discountul', ;
ABS(gnCapFtva - lnAstFtva) < 0.005, 'ftva=' + TRANSFORM(gnCapFtva) + ' asteptat ' + TRANSFORM(lnAstFtva)
DO asserteaza WITH lcEt + '2: DISCOUNT_TVA = discount * (cota - 1), rotunjit', ;
ABS(gnCapDiscTva - lnAstDiscTva) < 0.011, 'discount_tva=' + TRANSFORM(gnCapDiscTva) + ' asteptat ' + TRANSFORM(lnAstDiscTva)
DO asserteaza WITH lcEt + '2: total_tva scade cu TVA-ul discountului', ;
ABS(gnCapTva - (lnBaseTva - lnAstDiscTva)) < 0.011, ;
'tva=' + TRANSFORM(gnCapTva) + ' asteptat ' + TRANSFORM(lnBaseTva - lnAstDiscTva)
DO asserteaza WITH lcEt + '2: totalurile raman coerente (fara_tva + tva = cu_tva)', ;
ABS((gnCapFtva + gnCapTva) - gnCapCtva) < 0.01, ;
TRANSFORM(gnCapFtva) + ' + ' + TRANSFORM(gnCapTva) + ' = ' + TRANSFORM(gnCapCtva)
DO asserteaza WITH lcEt + '2: VALOARE_ACHIZITIE nu depinde de discount', ;
ABS(gnCapVA - lnBaseVA) < 0.005, TRANSFORM(lnBaseVA) + ' -> ' + TRANSFORM(gnCapVA)
lnP1Disc = gnCapDisc
lnP1Ftva = gnCapFtva
lnP1Tva = gnCapTva
lnP1Ctva = gnCapCtva
lnP1DiscTva = gnCapDiscTva
lnP1VA = gnCapVA
*-- PASUL 3: VERDICTUL. NULL peste un discount nenul - pastreaza sau zeroeaza?
llOk = ApelRecalc(gnIdRon, 'NULL', tcLog)
DO asserteaza WITH lcEt + '3: apelul cu NULL peste discount nenul a mers', llOk, 'llOk=' + TRANSFORM(llOk)
IF !llOk OR !CitesteCap(gnIdRon)
MyInchideTranzactie(2)
RETURN
ENDIF
DO LogCap WITH 'VERDICT - dupa recalc(NULL) peste discount ' + TRANSFORM(lnP1Disc), tcLog
DO asserteaza WITH lcEt + '3: VERDICT - NULL PASTREAZA discountul curent, nu-l zeroeaza', ;
ABS(gnCapDisc - lnP1Disc) < 0.0001, ;
'discount inainte=' + TRANSFORM(lnP1Disc) + ' dupa NULL=' + TRANSFORM(gnCapDisc)
DO asserteaza WITH lcEt + '3: NULL lasa toate totalurile neschimbate', ;
ABS(gnCapFtva - lnP1Ftva) < 0.0001 AND ABS(gnCapTva - lnP1Tva) < 0.0001 ;
AND ABS(gnCapCtva - lnP1Ctva) < 0.0001 AND ABS(gnCapDiscTva - lnP1DiscTva) < 0.0001 ;
AND ABS(gnCapVA - lnP1VA) < 0.0001, ;
'ftva=' + TRANSFORM(gnCapFtva) + ' tva=' + TRANSFORM(gnCapTva) + ' ctva=' + TRANSFORM(gnCapCtva)
*-- PASUL 4: 0 explicit - readuce documentul la starea de plecare
llOk = ApelRecalc(gnIdRon, '0', tcLog)
DO asserteaza WITH lcEt + '4: apelul cu 0 a mers', llOk, 'llOk=' + TRANSFORM(llOk)
IF llOk AND CitesteCap(gnIdRon)
DO LogCap WITH 'dupa recalc(0)', tcLog
DO asserteaza WITH lcEt + '4: 0 explicit zeroeaza discountul (spre deosebire de NULL)', ;
ABS(gnCapDisc - 0) < 0.0001, 'discount=' + TRANSFORM(gnCapDisc)
DO asserteaza WITH lcEt + '4: totalurile revin exact la starea de plecare', ;
ABS(gnCapFtva - lnBaseFtva) < 0.005 AND ABS(gnCapTva - lnBaseTva) < 0.005 ;
AND ABS(gnCapCtva - lnBaseCtva) < 0.005, ;
'ftva=' + TRANSFORM(gnCapFtva) + ' tva=' + TRANSFORM(gnCapTva) + ' ctva=' + TRANSFORM(gnCapCtva)
ENDIF
CATCH TO loExc
STRTOFILE(' EXCEPTIE in blocul A: ' + TRANSFORM(loExc.ErrorNo) + ' [' + loExc.Message + '] ' + ;
loExc.Procedure + ':' + TRANSFORM(loExc.LineNo) + CHR(13) + CHR(10), tcLog, 1)
ENDTRY
*-- blocul A nu consuma date: tot ce s-a scris mai sus se anuleaza
IF MyInchideTranzactie(2)
STRTOFILE(' tranzactie inchisa cu ROLLBACK' + CHR(13) + CHR(10), tcLog, 1)
ELSE
STRTOFILE(' FAIL la ROLLBACK' + CHR(13) + CHR(10), tcLog, 1)
ENDIF
IF CitesteCap(gnIdRon)
DO LogCap WITH 'DUPA ROLLBACK', tcLog
DO asserteaza WITH lcEt + '5: ROLLBACK-ul a lasat documentul exact cum era (blocul nu consuma date)', ;
ABS(gnCapDisc - lnBaseDisc) < 0.0001 AND ABS(gnCapFtva - lnBaseFtva) < 0.0001 ;
AND ABS(gnCapTva - lnBaseTva) < 0.0001 AND ABS(gnCapCtva - lnBaseCtva) < 0.0001 ;
AND ABS(gnCapDiscTva - lnBaseDiscTva) < 0.0001 AND ABS(gnCapVA - lnBaseVA) < 0.0001, ;
'discount=' + TRANSFORM(gnCapDisc) + ' ftva=' + TRANSFORM(gnCapFtva) + ' tva=' + TRANSFORM(gnCapTva)
ENDIF
ENDPROC
*=====================================================================================
*-- BLOCUL B: acelasi contract pe un document REAL in valuta, cu ROLLBACK la final
*=====================================================================================
PROCEDURE bloc_b_valuta
LPARAMETERS tcLog
LOCAL lnBaseDisc, lnBaseDiscTva, lnBaseVA, lnBaseFtva, lnBaseTva, lnBaseCtva
LOCAL lnBaseValval, lnBaseTvaval, lnBaseTotval, lnBaseIdVal, lnBaseCurs, lnBaseMult
LOCAL lnP1Disc, lnP1Ftva, lnP1Tva, lnP1Valval, lnP1Tvaval
LOCAL lnTvavMax, lnDiscRon, lnAstDiscTvaVal, llOk, lcEt, lnNrCursuri
lcEt = 'B'
STRTOFILE(CHR(13) + CHR(10) + '========== BLOCUL B - document REAL in valuta (id_vanzare=' + ;
TRANSFORM(gnIdValuta) + ') ==========' + CHR(13) + CHR(10), tcLog, 1)
IF !CitesteCap(gnIdValuta)
DO asserteaza WITH lcEt + ': documentul in valuta exista', .F., 'id_vanzare=' + TRANSFORM(gnIdValuta)
RETURN
ENDIF
DO LogCap WITH 'STARE INITIALA', tcLog
DO asserteaza WITH lcEt + '0: documentul ales e chiar in valuta (in_valuta=1, cu id_valuta si curs)', ;
gnCapInValuta = 1 AND gnCapIdValuta > 0 AND gnCapCurs > 0 AND gnCapMult > 0, ;
'in_valuta=' + TRANSFORM(gnCapInValuta) + ' id_valuta=' + TRANSFORM(gnCapIdValuta) + ;
' curs=' + TRANSFORM(gnCapCurs) + ' mult=' + TRANSFORM(gnCapMult)
IF gnCapInValuta <> 1 OR gnCapCurs <= 0
RETURN
ENDIF
*-- fara rand in VANZARI_CURSURI, join-ul din procedura da NULL si agregatele se golesc (riscul R5)
lnNrCursuri = 0
IF ExecSel([select count(*) as nr from vanzari_cursuri where id_vanzare = ] + TRANSFORM(gnIdValuta), 'v_crs') > 0
lnNrCursuri = v_crs.nr
USE IN v_crs
ENDIF
DO asserteaza WITH lcEt + '0: documentul are rand in VANZARI_CURSURI (altfel recalculul da NULL)', ;
lnNrCursuri > 0, 'randuri=' + TRANSFORM(lnNrCursuri)
lnBaseDisc = gnCapDisc
lnBaseDiscTva = gnCapDiscTva
lnBaseVA = gnCapVA
lnBaseFtva = gnCapFtva
lnBaseTva = gnCapTva
lnBaseCtva = gnCapCtva
lnBaseValval = gnCapValval
lnBaseTvaval = gnCapTvaval
lnBaseTotval = gnCapTotval
lnBaseIdVal = gnCapIdValuta
lnBaseCurs = gnCapCurs
lnBaseMult = gnCapMult
lnTvavMax = CotaMaxima(gnIdValuta)
STRTOFILE(' cota TVA maxima pe liniile active = ' + TRANSFORM(lnTvavMax) + CHR(13) + CHR(10), tcLog, 1)
IF !MyDeschideTranzactie()
DO asserteaza WITH lcEt + ': tranzactia s-a deschis', .F., 'SQLSetprop a esuat'
RETURN
ENDIF
TRY
*-- PASUL 1: recalcul cu NULL pe un document in valuta emis normal - trebuie sa reproduca
*-- exact totalurile persistate, si in RON si in valuta (proba ca agregarea si conversia
*-- prin curs sunt corecte pe un document real, nu doar pe unul simulat in VFP)
llOk = ApelRecalc(gnIdValuta, 'NULL', tcLog)
DO asserteaza WITH lcEt + '1: apelul cu NULL a mers pe documentul in valuta', llOk, 'llOk=' + TRANSFORM(llOk)
IF !llOk OR !CitesteCap(gnIdValuta)
MyInchideTranzactie(2)
RETURN
ENDIF
DO LogCap WITH 'dupa recalc(NULL)', tcLog
DO asserteaza WITH lcEt + '1: totalurile in RON sunt reproduse exact pe documentul in valuta', ;
ABS(gnCapFtva - lnBaseFtva) < 0.005 AND ABS(gnCapTva - lnBaseTva) < 0.005 ;
AND ABS(gnCapCtva - lnBaseCtva) < 0.005, ;
'ftva ' + TRANSFORM(lnBaseFtva) + '->' + TRANSFORM(gnCapFtva) + ' tva ' + TRANSFORM(lnBaseTva) + ;
'->' + TRANSFORM(gnCapTva) + ' ctva ' + TRANSFORM(lnBaseCtva) + '->' + TRANSFORM(gnCapCtva)
DO asserteaza WITH lcEt + '1: totalurile in valuta (valval/tvaval/totval) sunt reproduse exact', ;
ABS(gnCapValval - lnBaseValval) < 0.005 AND ABS(gnCapTvaval - lnBaseTvaval) < 0.005 ;
AND ABS(gnCapTotval - lnBaseTotval) < 0.005, ;
'valval ' + TRANSFORM(lnBaseValval) + '->' + TRANSFORM(gnCapValval) + ' tvaval ' + ;
TRANSFORM(lnBaseTvaval) + '->' + TRANSFORM(gnCapTvaval) + ' totval ' + TRANSFORM(lnBaseTotval) + ;
'->' + TRANSFORM(gnCapTotval)
DO asserteaza WITH lcEt + '1: valuta documentului (id_valuta/curs/multiplicator) e pastrata', ;
gnCapIdValuta = lnBaseIdVal AND ABS(gnCapCurs - lnBaseCurs) < 0.00001 AND ABS(gnCapMult - lnBaseMult) < 0.00001, ;
'id_valuta=' + TRANSFORM(gnCapIdValuta) + ' curs=' + TRANSFORM(gnCapCurs) + ' mult=' + TRANSFORM(gnCapMult)
DO asserteaza WITH lcEt + '1: NULL nu schimba discountul documentului in valuta', ;
ABS(gnCapDisc - lnBaseDisc) < 0.0001, TRANSFORM(lnBaseDisc) + ' -> ' + TRANSFORM(gnCapDisc)
*-- PASUL 2: discount nenul pe document in valuta. Discountul e exprimat in valuta:
*-- in RON se scade ROUND(curs * discount / multiplicator, PPRETV), in valuta se scade brut.
lnDiscRon = ROUND(lnBaseCurs * gnDiscValuta / lnBaseMult, gnPPretV)
lnAstDiscTvaVal = ROUND(gnDiscValuta * (lnTvavMax - 1), gnPPretV)
STRTOFILE(' discount ' + TRANSFORM(gnDiscValuta) + ' in valuta => ' + TRANSFORM(lnDiscRon) + ' RON (curs ' + ;
TRANSFORM(lnBaseCurs) + ' / mult ' + TRANSFORM(lnBaseMult) + ')' + CHR(13) + CHR(10), tcLog, 1)
llOk = ApelRecalc(gnIdValuta, ALLTRIM(STR(gnDiscValuta, 18, 4)), tcLog)
DO asserteaza WITH lcEt + '2: apelul cu valoare nenula a mers pe documentul in valuta', llOk, 'llOk=' + TRANSFORM(llOk)
IF !llOk OR !CitesteCap(gnIdValuta)
MyInchideTranzactie(2)
RETURN
ENDIF
DO LogCap WITH 'dupa recalc(' + TRANSFORM(gnDiscValuta) + ')', tcLog
DO asserteaza WITH lcEt + '2: valoarea nenula ajunge in VANZARI.DISCOUNT (document in valuta)', ;
ABS(gnCapDisc - gnDiscValuta) < 0.0001, 'discount=' + TRANSFORM(gnCapDisc) + ' (cerut ' + TRANSFORM(gnDiscValuta) + ')'
DO asserteaza WITH lcEt + '2: total_fara_tva scade cu discountul CONVERTIT prin cursul documentului', ;
ABS(gnCapFtva - (lnBaseFtva - lnDiscRon)) < 0.011, ;
'ftva=' + TRANSFORM(gnCapFtva) + ' asteptat ' + TRANSFORM(lnBaseFtva - lnDiscRon)
DO asserteaza WITH lcEt + '2: valval scade cu discountul BRUT, in valuta', ;
ABS(gnCapValval - (lnBaseValval - gnDiscValuta)) < 0.011, ;
'valval=' + TRANSFORM(gnCapValval) + ' asteptat ' + TRANSFORM(lnBaseValval - gnDiscValuta)
DO asserteaza WITH lcEt + '2: DISCOUNT_TVA pastreaza TVA-ul discountului in valuta', ;
ABS(gnCapDiscTva - lnAstDiscTvaVal) < 0.011, ;
'discount_tva=' + TRANSFORM(gnCapDiscTva) + ' asteptat ' + TRANSFORM(lnAstDiscTvaVal)
DO asserteaza WITH lcEt + '2: tvaval scade cu TVA-ul discountului in valuta', ;
ABS(gnCapTvaval - (lnBaseTvaval - lnAstDiscTvaVal)) < 0.011, ;
'tvaval=' + TRANSFORM(gnCapTvaval) + ' asteptat ' + TRANSFORM(lnBaseTvaval - lnAstDiscTvaVal)
DO asserteaza WITH lcEt + '2: totalurile in RON raman coerente (fara_tva + tva = cu_tva)', ;
ABS((gnCapFtva + gnCapTva) - gnCapCtva) < 0.01, ;
TRANSFORM(gnCapFtva) + ' + ' + TRANSFORM(gnCapTva) + ' = ' + TRANSFORM(gnCapCtva)
DO asserteaza WITH lcEt + '2: totalurile in valuta raman coerente (valval + tvaval = totval)', ;
ABS((gnCapValval + gnCapTvaval) - gnCapTotval) < 0.01, ;
TRANSFORM(gnCapValval) + ' + ' + TRANSFORM(gnCapTvaval) + ' = ' + TRANSFORM(gnCapTotval)
lnP1Disc = gnCapDisc
lnP1Ftva = gnCapFtva
lnP1Tva = gnCapTva
lnP1Valval = gnCapValval
lnP1Tvaval = gnCapTvaval
*-- PASUL 3: verdictul pe NULL, repetat pe calea de valuta
llOk = ApelRecalc(gnIdValuta, 'NULL', tcLog)
DO asserteaza WITH lcEt + '3: apelul cu NULL peste discount nenul a mers', llOk, 'llOk=' + TRANSFORM(llOk)
IF llOk AND CitesteCap(gnIdValuta)
DO LogCap WITH 'VERDICT valuta - dupa recalc(NULL) peste discount ' + TRANSFORM(lnP1Disc), tcLog
DO asserteaza WITH lcEt + '3: VERDICT - NULL pastreaza discountul si pe documentul in valuta', ;
ABS(gnCapDisc - lnP1Disc) < 0.0001, ;
'discount inainte=' + TRANSFORM(lnP1Disc) + ' dupa NULL=' + TRANSFORM(gnCapDisc)
DO asserteaza WITH lcEt + '3: NULL lasa neschimbate si totalurile in RON, si cele in valuta', ;
ABS(gnCapFtva - lnP1Ftva) < 0.0001 AND ABS(gnCapTva - lnP1Tva) < 0.0001 ;
AND ABS(gnCapValval - lnP1Valval) < 0.0001 AND ABS(gnCapTvaval - lnP1Tvaval) < 0.0001, ;
'ftva=' + TRANSFORM(gnCapFtva) + ' valval=' + TRANSFORM(gnCapValval)
ENDIF
CATCH TO loExc
STRTOFILE(' EXCEPTIE in blocul B: ' + TRANSFORM(loExc.ErrorNo) + ' [' + loExc.Message + '] ' + ;
loExc.Procedure + ':' + TRANSFORM(loExc.LineNo) + CHR(13) + CHR(10), tcLog, 1)
ENDTRY
*-- documentul e din arhiva (2026-05): ROLLBACK obligatoriu, nu se modifica nimic in el
IF MyInchideTranzactie(2)
STRTOFILE(' tranzactie inchisa cu ROLLBACK' + CHR(13) + CHR(10), tcLog, 1)
ELSE
STRTOFILE(' FAIL la ROLLBACK' + CHR(13) + CHR(10), tcLog, 1)
ENDIF
IF CitesteCap(gnIdValuta)
DO LogCap WITH 'DUPA ROLLBACK', tcLog
DO asserteaza WITH lcEt + '4: ROLLBACK-ul a lasat documentul din arhiva exact cum era', ;
ABS(gnCapDisc - lnBaseDisc) < 0.0001 AND ABS(gnCapFtva - lnBaseFtva) < 0.0001 ;
AND ABS(gnCapTva - lnBaseTva) < 0.0001 AND ABS(gnCapCtva - lnBaseCtva) < 0.0001 ;
AND ABS(gnCapValval - lnBaseValval) < 0.0001 AND ABS(gnCapTvaval - lnBaseTvaval) < 0.0001 ;
AND ABS(gnCapTotval - lnBaseTotval) < 0.0001 AND ABS(gnCapVA - lnBaseVA) < 0.0001, ;
'discount=' + TRANSFORM(gnCapDisc) + ' ftva=' + TRANSFORM(gnCapFtva) + ' valval=' + TRANSFORM(gnCapValval)
ENDIF
ENDPROC
*=====================================================================================
*-- BLOCUL C: lantul real de salvare pe un document cu discount NENUL. Singurul care comite.
*=====================================================================================
PROCEDURE bloc_c_lant_real
LPARAMETERS 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 lnBaseDisc, lnBaseFtva, lnBaseTva, lnBaseCtva, lnBaseVA, lnBaseDiscTva
LOCAL lnCodInainte, lnSters, llEProforma, lnIdSet, lnIdFactD, lnSucces, llGasitRand
LOCAL lcSql, lnQ, lcEt, llOk, lnDiscTvaAst, lnTvavMax, lnNrLinii
lcEt = 'C'
STRTOFILE(CHR(13) + CHR(10) + '========== BLOCUL C - lantul real de salvare pe document cu discount nenul (id_vanzare=' + ;
TRANSFORM(gnIdRon) + ') ==========' + CHR(13) + CHR(10), tcLog, 1)
IF !CitesteCap(gnIdRon)
DO asserteaza WITH lcEt + ': documentul exista', .F., 'id_vanzare=' + TRANSFORM(gnIdRon)
RETURN
ENDIF
DO LogCap WITH 'STARE INITIALA', tcLog
lnBaseDisc = gnCapDisc
lnBaseDiscTva = gnCapDiscTva
lnBaseVA = gnCapVA
lnBaseFtva = gnCapFtva
lnBaseTva = gnCapTva
lnBaseCtva = gnCapCtva
lnTvavMax = CotaMaxima(gnIdRon)
lnDiscTvaAst = ROUND(gnDiscRon * (lnTvavMax - 1), gnPPretV)
*-- 1) pregatirea: documentul primeste un discount nenul, comis, prin chiar procedura testata
IF !MyDeschideTranzactie()
DO asserteaza WITH lcEt + '0: tranzactia de pregatire s-a deschis', .F., 'SQLSetprop a esuat'
RETURN
ENDIF
llOk = ApelRecalc(gnIdRon, ALLTRIM(STR(gnDiscRon, 18, 4)), tcLog)
IF !llOk
MyInchideTranzactie(2)
DO asserteaza WITH lcEt + '0: pregatirea documentului cu discount nenul', .F., 'apelul a esuat'
RETURN
ENDIF
MyInchideTranzactie(1)
IF !CitesteCap(gnIdRon)
RETURN
ENDIF
DO LogCap WITH 'PREGATIT, comis - discount nenul pe document', tcLog
DO asserteaza WITH lcEt + '0: documentul are acum discount nenul, comis', ;
ABS(gnCapDisc - gnDiscRon) < 0.0001, 'discount=' + TRANSFORM(gnCapDisc)
*-- 2) lantul real de editare, fara nicio modificare de linii
lcSql = [select cod, sters, id_fact, eproforma, ] + ;
[extract(year from data_act) as anact, extract(month from data_act) as lunaact ] + ;
[from vanzari where id_vanzare = ] + TRANSFORM(gnIdRon)
lnQ = ExecSel(lcSql, 'v_vz')
IF lnQ <= 0 OR RECCOUNT('v_vz') <> 1
DO asserteaza WITH lcEt + '1: VANZARI citit', .F., 'lnQ=' + TRANSFORM(lnQ)
RETURN
ENDIF
SELECT v_vz
lnCod = cod
lnCodInainte = cod
lnSters = sters
lnIdFact = id_fact
llEProforma = (NVL(eproforma, 0) = 1)
pnAn = anact
pnLuna = lunaact
USE IN v_vz
IF lnSters = 1 OR llEProforma OR (pnAn * 12) + pnLuna <> (gnAn * 12) + gnLuna
DO asserteaza WITH lcEt + '1: document editabil, din luna curenta', .F., ;
'sters=' + TRANSFORM(lnSters) + ' an/luna=' + TRANSFORM(pnAn) + '/' + TRANSFORM(pnLuna)
DO restaureaza_discount WITH tcLog, lnBaseDisc, lnBaseFtva, lnBaseTva, lnBaseCtva
RETURN
ENDIF
IF ReferinteDocumenteNota(pnAn, pnLuna, lnCod) OR EsteInEFactura(lnIdFact)
DO asserteaza WITH lcEt + '1: document fara referinte / netrimis in eFactura', .F., 'blocat de garda'
DO restaureaza_discount WITH tcLog, lnBaseDisc, lnBaseFtva, lnBaseTva, lnBaseCtva
RETURN
ENDIF
IF !IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.) OR RECCOUNT('actactan') = 0
DO asserteaza WITH lcEt + '1: IncarcaCursoareModificareNota', .F., 'a esuat sau nota e goala'
DO restaureaza_discount WITH tcLog, lnBaseDisc, lnBaseFtva, lnBaseTva, lnBaseCtva
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
IF !IncarcaVanzareDinNota('tact')
DO asserteaza WITH lcEt + '1: IncarcaVanzareDinNota', .F., 'nu a gasit randul din VANZARI'
DO restaureaza_discount WITH tcLog, lnBaseDisc, lnBaseFtva, lnBaseTva, lnBaseCtva
RETURN
ENDIF
IncarcaArticoleFactura(gnIdRon, 'tvd')
lnNrLinii = RECCOUNT('tvd')
*-- proba cheie a caii VFP: discountul documentului ajunge in cursorul pe care se sprijina helperul
DO asserteaza WITH lcEt + '2: tvanz.discount aduce discountul nenul din VANZARI in cursorul de lucru', ;
!ISNULL(tvanz.discount) AND ABS(NVL(tvanz.discount, 0) - gnDiscRon) < 0.0001, ;
'tvanz.discount=' + TRANSFORM(NVL(tvanz.discount, 0)) + ' (in VANZARI ' + TRANSFORM(gnDiscRon) + ')'
STRTOFILE(' tvd incarcat cu ' + TRANSFORM(lnNrLinii) + ' linii active; tvanz.discount=' + ;
TRANSFORM(NVL(tvanz.discount, 0)) + CHR(13) + CHR(10), tcLog, 1)
*-- frm_modific2024 ocolit, buton=1 fortat (inainte_de_do_termin NU se executa)
buton = 1
lnSucces = 0
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
*-- starea necomisa a discountului dupa realinierea COD-ului: actualizeaza_vanzari nu-l atinge
IF lnSucces > 0 AND CitesteCap(gnIdRon)
DO LogCap WITH 'IN TRANZACTIE, dupa finalizeaza_modificare_nota', tcLog
DO asserteaza WITH lcEt + '3: finalizeaza_modificare_nota nu atinge DISCOUNT', ;
ABS(gnCapDisc - gnDiscRon) < 0.0001, 'discount=' + TRANSFORM(gnCapDisc)
ENDIF
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 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 lcEt + '4: lantul de salvare 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 USED('tvd')
USE IN tvd
ENDIF
IF USED('tvanz')
USE IN tvanz
ENDIF
*-- 3) verificarile de dupa commit: discountul a supravietuit salvarii complete
IF CitesteCap(gnIdRon)
DO LogCap WITH 'DUPA COMMIT', tcLog
DO asserteaza WITH lcEt + '5: discountul nenul supravietuieste salvarii complete a documentului', ;
ABS(gnCapDisc - gnDiscRon) < 0.0001, ;
'discount=' + TRANSFORM(gnCapDisc) + ' (era ' + TRANSFORM(gnDiscRon) + ')'
DO asserteaza WITH lcEt + '5: VANZARI.COD realocat, documentul ramane activ', ;
gnCapCod <> lnCodInainte AND gnCapSters = 0, TRANSFORM(lnCodInainte) + ' -> ' + TRANSFORM(gnCapCod)
DO asserteaza WITH lcEt + '5: totalurile de dupa salvare tin cont de discount', ;
ABS(gnCapFtva - (lnBaseFtva - gnDiscRon)) < 0.011 AND ABS(gnCapDiscTva - lnDiscTvaAst) < 0.011, ;
'ftva=' + TRANSFORM(gnCapFtva) + ' asteptat ' + TRANSFORM(lnBaseFtva - gnDiscRon) + ;
' discount_tva=' + TRANSFORM(gnCapDiscTva)
DO asserteaza WITH lcEt + '5: totalurile raman coerente dupa salvare', ;
ABS((gnCapFtva + gnCapTva) - gnCapCtva) < 0.01, ;
TRANSFORM(gnCapFtva) + ' + ' + TRANSFORM(gnCapTva) + ' = ' + TRANSFORM(gnCapCtva)
ENDIF
*-- 4) restaurarea: documentul se intoarce la discount 0 si la totalurile de plecare
DO restaureaza_discount WITH tcLog, lnBaseDisc, lnBaseFtva, lnBaseTva, lnBaseCtva
ENDPROC
*-- readuce documentul de lucru la discountul si totalurile de plecare, comis
PROCEDURE restaureaza_discount
LPARAMETERS tcLog, tnBaseDisc, tnBaseFtva, tnBaseTva, tnBaseCtva
LOCAL llOk
IF !MyDeschideTranzactie()
DO asserteaza WITH 'C6: tranzactia de restaurare s-a deschis', .F., 'SQLSetprop a esuat'
RETURN
ENDIF
llOk = ApelRecalc(gnIdRon, ALLTRIM(STR(tnBaseDisc, 18, 4)), tcLog)
IF llOk
MyInchideTranzactie(1)
ELSE
MyInchideTranzactie(2)
ENDIF
DO asserteaza WITH 'C6: restaurarea discountului initial a mers', llOk, 'llOk=' + TRANSFORM(llOk)
IF CitesteCap(gnIdRon)
DO LogCap WITH 'DUPA RESTAURARE', tcLog
DO asserteaza WITH 'C6: documentul e readus la discountul si totalurile de plecare', ;
ABS(gnCapDisc - tnBaseDisc) < 0.0001 AND ABS(gnCapFtva - tnBaseFtva) < 0.005 ;
AND ABS(gnCapTva - tnBaseTva) < 0.005 AND ABS(gnCapCtva - tnBaseCtva) < 0.005, ;
'discount=' + TRANSFORM(gnCapDisc) + ' ftva=' + TRANSFORM(gnCapFtva) + ;
' tva=' + TRANSFORM(gnCapTva) + ' ctva=' + TRANSFORM(gnCapCtva)
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)
ENDPROC