Files
comun/utile/Teste/editare_factura/test_s7_rotunjire.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

350 lines
13 KiB
Plaintext

* test_s7_rotunjire.prg
* S7 - rotunjirea la reeditare: verifica_total_document (PACK_FACTURARE.pck) insereaza o linie de
* corectie in ACT_TEMP cand totalul documentului difera de suma din note. Criteriul din plan:
* trei editari consecutive nu trebuie sa lase trei linii de corectie in nota activa.
*
* Reproduce TREI reeditari consecutive, fara nicio modificare de continut (acelasi tipar ca
* trecerea 2 din test_s5_scriere_reala.prg, repetat de trei ori), pe acelasi document
* id_vanzare = 1049. Fiecare trecere ruleaza lantul real (OSCRIE_IN_FISIERE(2)/(0),
* finalizeaza_modificare_nota, ScrieArticoleFacturaEditate), in tranzactie proprie, cu COMMIT.
*
* Dupa fiecare COMMIT, numara in ACT (nu ACT_TEMP - GTT SYS$TRANSACTION, golita la fiecare COMMIT):
* - randurile active (STERS=0) pe COD-ul curent al documentului;
* - liniile de corectie: perechi (scd,scc,nract,dataact,explicatia) cu 2+ randuri si suma diferita
* - semnatura exacta a INSERT-ului din verifica_total_document (PACK_FACTURARE.pck:16353-16460,
* 16467-16574), confirmata pe un caz real din productie (id_fact=8008816, cod=1140709).
*
* Harness, nu UI: acelasi tipar ca test_s5_scriere_reala.prg (buton=1 fortat, do_deschide/inchide
* tranzactie reproduse inline). CONSUMA DATE DE TEST: VANZARI.COD se realoca la fiecare trecere.
* 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_s7_rotunjire_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()
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', 2026, 8
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
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
PUBLIC gnIdVanzareTest
gnIdVanzareTest = 1049
STRTOFILE('gnAn=' + TRANSFORM(gnAn) + ' gnLuna=' + TRANSFORM(gnLuna) + ' gnIdUtil=' + TRANSFORM(gnIdUtil) + CHR(13) + CHR(10), lcLog, 1)
DO ruleaza_trecere_s7 WITH gnIdVanzareTest, 1, lcLog
DO ruleaza_trecere_s7 WITH gnIdVanzareTest, 2, lcLog
DO ruleaza_trecere_s7 WITH gnIdVanzareTest, 3, 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
PROCEDURE ExecSel
LPARAMETERS tcSql, tcCursor
LOCAL lnQ
IF USED(tcCursor)
USE IN (tcCursor)
ENDIF
lnQ = goExecutor.oExecute(tcSql, tcCursor)
RETURN lnQ
ENDPROC
*-- numara, pentru cod-ul dat, randurile active si liniile de corectie (semnatura verifica_total_document)
PROCEDURE NumaraCorectii
LPARAMETERS tnCod, tnAn, tnLuna, tcLog
LOCAL lcSql, lnQ, lnRanduriActive, lnLiniiCorectie
lcSql = [select count(*) as nr from act where cod = ] + TRANSFORM(tnCod) + ;
[ and an = ] + TRANSFORM(tnAn) + [ and luna = ] + TRANSFORM(tnLuna) + [ and sters = 0]
lnQ = ExecSel(lcSql, 'v_nract')
lnRanduriActive = IIF(lnQ > 0, v_nract.nr, -1)
IF USED('v_nract')
USE IN v_nract
ENDIF
*-- semnatura verifica_total_document (PACK_FACTURARE.pck:16353-16460, 16467-16574): un rand nou
*-- cu ACELASI (scd,scc,nract,dataact,explicatia) ca randul original, dar SUMA = diferenta de
*-- rotunjire, deci mica (delta < 5) si diferita de suma originala - nu orice pereche duplicata
*-- de (scd,scc): documentul poate avea legitim doua linii de detaliu cu acelasi cont contabil
*-- (delta mare sau delta = 0 intre ele, verificat pe 1140900-1140903 - fals pozitiv prins la runda 1)
lcSql = [select count(*) as nr from ( ] + ;
[ select scd, scc, nract, dataact, explicatia, count(*) c, min(suma) smin, max(suma) smax ] + ;
[ from act where cod = ] + TRANSFORM(tnCod) + [ and an = ] + TRANSFORM(tnAn) + ;
[ and luna = ] + TRANSFORM(tnLuna) + [ and sters = 0 ] + ;
[ group by scd, scc, nract, dataact, explicatia ] + ;
[ having count(*) > 1 and max(suma) <> min(suma) and abs(max(suma) - min(suma)) < 5) ]
lnQ = ExecSel(lcSql, 'v_ncor')
lnLiniiCorectie = IIF(lnQ > 0, v_ncor.nr, -1)
IF USED('v_ncor')
USE IN v_ncor
ENDIF
STRTOFILE(' cod=' + TRANSFORM(tnCod) + ' randuri active in ACT=' + TRANSFORM(lnRanduriActive) + ;
' linii de corectie (semnatura verifica_total_document)=' + TRANSFORM(lnLiniiCorectie) + CHR(13) + CHR(10), tcLog, 1)
RETURN lnLiniiCorectie
ENDPROC
PROCEDURE ruleaza_trecere_s7
LPARAMETERS tnIdVanzare, tnNrTrecere, tcLog
PRIVATE pnAn, pnLuna, lnCod, lnIdFact
LOCAL lnSters, llEProforma, lnIdSet, lnIdFactD, lnSucces, llGasitRand
LOCAL lcSql, lnQ, lnCodInainte, lnCodDupa, lnLiniiCorectie
STRTOFILE(CHR(13) + CHR(10) + '========== TRECEREA ' + TRANSFORM(tnNrTrecere) + ' - reeditare fara nicio modificare (id_vanzare=' + ;
TRANSFORM(tnIdVanzare) + ') ==========' + CHR(13) + CHR(10), tcLog, 1)
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(tnIdVanzare)
lnQ = ExecSel(lcSql, 'v_vz_inainte')
IF lnQ <= 0 OR RECCOUNT('v_vz_inainte') <> 1
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': 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
USE IN v_vz_inainte
STRTOFILE(' VANZARI inainte: cod=' + TRANSFORM(lnCod) + ' sters=' + TRANSFORM(lnSters) + ' id_fact=' + TRANSFORM(lnIdFact) + CHR(13) + CHR(10), tcLog, 1)
IF lnSters = 1 OR llEProforma
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': document editabil (nesters, neproforma)', .F., 'sters=' + TRANSFORM(lnSters)
RETURN
ENDIF
IF (pnAn*12) + pnLuna <> (gnAn*12) + gnLuna
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': document din luna curenta', .F., TRANSFORM(pnAn) + '/' + TRANSFORM(pnLuna)
RETURN
ENDIF
IF ReferinteDocumenteNota(pnAn, pnLuna, lnCod) OR EsteInEFactura(lnIdFact)
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': document fara referinte / netrimis in eFactura', .F., 'blocat de garda'
RETURN
ENDIF
IF !IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.)
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': IncarcaCursoareModificareNota', .F., 'a esuat'
RETURN
ENDIF
IF RECCOUNT('actactan') = 0
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': 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
IF !IncarcaVanzareDinNota('tact')
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': IncarcaVanzareDinNota', .F., 'nu a gasit randul din VANZARI'
RETURN
ENDIF
IncarcaArticoleFactura(tnIdVanzare, 'tvd')
*-- nicio modificare pe tvd - reeditare pura
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
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 'trecerea ' + TRANSFORM(tnNrTrecere) + ': 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 USED('tvd')
USE IN tvd
ENDIF
IF USED('tvanz')
USE IN tvanz
ENDIF
IF lnSucces <= 0
STRTOFILE(' scrierea nu s-a produs - fara numarare de corectii' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
lcSql = [select cod from vanzari where id_vanzare = ] + TRANSFORM(tnIdVanzare)
lnQ = ExecSel(lcSql, 'v_vz_dupa')
lnCodDupa = IIF(lnQ > 0, v_vz_dupa.cod, -1)
IF USED('v_vz_dupa')
USE IN v_vz_dupa
ENDIF
STRTOFILE(' VANZARI.cod: ' + TRANSFORM(lnCodInainte) + ' -> ' + TRANSFORM(lnCodDupa) + CHR(13) + CHR(10), tcLog, 1)
lnLiniiCorectie = NumaraCorectii(lnCodDupa, pnAn, pnLuna, tcLog)
*-- criteriul din plan: trei editari consecutive nu lasa trei linii de corectie in nota ACTIVA.
*-- verifica_total_document insereaza cel mult 2 linii pe generatie (una pentru ftva, una pentru
*-- tva; a treia doar pentru ntip in (48,49), nu e cazul aici) - nota activa nu poate contine mai
*-- mult decat atat, indiferent de numarul de editari anterioare (blocul vechi e integral STERS=1).
DO asserteaza WITH 'trecerea ' + TRANSFORM(tnNrTrecere) + ': linii de corectie in nota activa nu creste cu numarul de treceri (<= 2)', ;
lnLiniiCorectie >= 0 AND lnLiniiCorectie <= 2, ;
'linii de corectie=' + TRANSFORM(lnLiniiCorectie) + ' dupa ' + TRANSFORM(tnNrTrecere) + ' treceri'
ENDPROC
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
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 test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC