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
625 lines
26 KiB
Plaintext
625 lines
26 KiB
Plaintext
* 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
|