Files
comun/programe/anulare_lot_ef.prg
Marius Mutu 940bb39701 Import eFactura in lot: borderou cu ce lipseste, coada de contabilizare, alegerea contului
Borderoul tine per factura ce mai are de completat si daca are articole de gestiune
(camp gest, coloana si filtru), coada contabilizeaza in serie facturile bifate si
incheie cu un rezumat, iar contul de furnizor/client se alege din planul de conturi.
Cheia normalizata de articol, rezolvarea automata a partenerului si anularea in bloc
intra tot aici. Pozitia in lista se pastreaza peste reaplicarea filtrului.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Aroafxp4z8bmM5oVECZRXY
2026-09-09 22:06:48 +03:00

237 lines
9.0 KiB
Plaintext

*!* 03.09.2026
*!* marius.mutu
*!* AnulareLotEF - anularea in bloc a documentelor generate din importul eFactura: pre-verifica
*!* lotul, separa acceptate/refuzate cu motiv, apoi sterge acceptatele intr-o singura tranzactie
*!* si reseteaza legatura eFactura
Define Class AnulareLotEF As Custom
cEroare = '' && mesajul ultimei erori; gol daca ultima operatie a reusit
cAvertismentRisc = '' && ce nu poate fi verificat automat (Init)
Procedure Init
This.cAvertismentRisc = 'Verificarea automata nu poate detecta doua situatii: nota a fost' + ;
' modificata manual dupa import, sau jurnalul de TVA in care intra a fost deja depus.' + ;
' Confirmati anularea doar dupa ce le-ati verificat manual.'
Endproc && Init
*!* Pre-verifica fiecare id din tcListaIdEfactura (anaf_efactura.id, separate prin virgula) si
*!* imparte lotul in acceptate/refuzate cu motiv, fara sa scrie nimic in baza. Lasa deschise
*!* CRSACCEPTATE si CRSREFUZATE (id_efactura, id_fact, cod, an, luna, numar_act, furnizor, suma
*!* [, motiv]), pentru ecranul de confirmare. La eroare: .F., mesajul in This.cEroare
Procedure Verifica
Lparameters tcListaIdEfactura
Local lcLista, lcSql, lnSucces, llLunaInchisa, lnIdFact, lcMotiv, llAreReferinte, lcSelect
This.cEroare = ''
lcSelect = Select()
This.CreeazaCursoareGoale()
lcLista = This.CurataLista(m.tcListaIdEfactura)
If Empty(m.lcLista)
This.cEroare = 'nu a fost primit niciun id de eFactura valid'
Select (m.lcSelect)
Return .F.
Endif
Text To lcSql Textmerge Noshow
WITH doc AS (
SELECT a.id_fact, a.cod, a.an, a.luna,
ROW_NUMBER() OVER (PARTITION BY a.id_fact ORDER BY a.cod DESC) rn
FROM ACT a
WHERE a.sters = 0 AND a.id_fact IN (SELECT id_fact FROM ANAF_EFACTURA WHERE id IN (<<m.lcLista>>) AND NVL(id_fact,0) <> 0)
)
SELECT e.id AS id_efactura, NVL(e.id_fact,0) AS id_fact, d.cod, d.an, d.luna,
NVL(e.xnumar_act,'') AS numar_act, NVL(e.xfurnizor,'') AS furnizor, NVL(e.xtotal_cu_tva,0) AS suma
FROM ANAF_EFACTURA e
LEFT JOIN doc d ON (d.id_fact = e.id_fact AND d.rn = 1)
WHERE e.id IN (<<m.lcLista>>)
ORDER BY e.id
Endtext
lnSucces = goExecutor.oExecute(m.lcSql, 'crsCandidatiEF')
If m.lnSucces < 0
This.cEroare = Nvl(goExecutor.cEroare, 'eroare necunoscuta la verificarea lotului')
Select (m.lcSelect)
Return .F.
Endif
llLunaInchisa = (Type('glLunaInchisa') = 'L' And m.glLunaInchisa)
Select crsCandidatiEF
Scan
lnIdFact = crsCandidatiEF.id_fact
lcMotiv = ''
Do Case
Case Empty(m.lnIdFact)
lcMotiv = 'factura nu e importata in contabilitate (id_fact lipseste)'
Case Empty(Nvl(crsCandidatiEF.cod, 0))
lcMotiv = 'documentul nu mai exista (a fost deja anulat sau modificat)'
Case m.llLunaInchisa
lcMotiv = 'luna este inchisa'
Otherwise
llAreReferinte = ReferinteDocumenteNota(crsCandidatiEF.an, crsCandidatiEF.luna, crsCandidatiEF.cod)
If m.llAreReferinte
lcMotiv = 'documentul are incasari/plati atasate - anuleaza manual nota ' + Transform(crsCandidatiEF.cod) + ' din registrul jurnal'
Endif
Endcase
If Empty(m.lcMotiv)
Insert Into crsAcceptate Values (crsCandidatiEF.id_efactura, crsCandidatiEF.id_fact, crsCandidatiEF.cod, crsCandidatiEF.an, crsCandidatiEF.luna, crsCandidatiEF.numar_act, crsCandidatiEF.furnizor, crsCandidatiEF.suma)
Else
Insert Into crsRefuzate Values (crsCandidatiEF.id_efactura, crsCandidatiEF.id_fact, Nvl(crsCandidatiEF.cod, 0), Nvl(crsCandidatiEF.an, 0), Nvl(crsCandidatiEF.luna, 0), crsCandidatiEF.numar_act, crsCandidatiEF.furnizor, crsCandidatiEF.suma, m.lcMotiv)
Endif
Endscan
Use In (Select('crsCandidatiEF'))
Select (m.lcSelect)
Return .T.
Endproc && Verifica
*!* Scrie in log (goLog) lista completa acceptate+refuzate, inainte de executie si in afara tranzactiei.
*!* tcCursorAcceptate/tcCursorRefuzate: implicit CRSACCEPTATE/CRSREFUZATE
Procedure Logheaza
Lparameters tcCursorAcceptate, tcCursorRefuzate
Local lcCursor, lcLog, lcSelect
lcSelect = Select()
lcLog = 'AnulareLotEF, lot de anulare:'
lcCursor = Iif(Empty(m.tcCursorAcceptate), 'crsAcceptate', m.tcCursorAcceptate)
If Used(m.lcCursor)
Select (m.lcCursor)
Scan
lcLog = m.lcLog + Chr(13) + Chr(10) + ' ACCEPTAT id_efactura=' + Transform(id_efactura) + ' id_fact=' + Transform(id_fact) + ;
' cod=' + Transform(cod) + ' numar_act=' + Alltrim(Nvl(numar_act, '')) + ' furnizor=' + Alltrim(Nvl(furnizor, '')) + ' suma=' + Transform(suma)
Endscan
Endif
lcCursor = Iif(Empty(m.tcCursorRefuzate), 'crsRefuzate', m.tcCursorRefuzate)
If Used(m.lcCursor)
Select (m.lcCursor)
Scan
lcLog = m.lcLog + Chr(13) + Chr(10) + ' REFUZAT id_efactura=' + Transform(id_efactura) + ' id_fact=' + Transform(id_fact) + ;
' cod=' + Transform(cod) + ' numar_act=' + Alltrim(Nvl(numar_act, '')) + ' furnizor=' + Alltrim(Nvl(furnizor, '')) + ' motiv=' + Alltrim(Nvl(motiv, ''))
Endscan
Endif
goLog.Log(m.lcLog, 'AnulareLotEF')
Select (m.lcSelect)
Endproc && Logheaza
*!* Sterge documentele din tcCursorAcceptate (implicit CRSACCEPTATE, lasat de Verifica) intr-o
*!* singura tranzactie; la orice eroare face ROLLBACK pe tot lotul. Intoarce numarul de documente
*!* sterse, sau 0 la esec (motivul in This.cEroare)
Procedure Executa
Lparameters tcCursorAcceptate, tcCursorRefuzate
Local lcCursor, lnSterse, lcSelect, llSucces, llTranzactieManuala, lcSqlInit, lcSqlSterge
Local loEroare As Exception
Private pnCod, pnAn, pnLuna, pnIdEfactura, pnIdFact
This.cEroare = ''
lnSterse = 0
llSucces = .F.
llTranzactieManuala = .F.
lcSelect = Select()
lcCursor = Iif(Empty(m.tcCursorAcceptate), 'crsAcceptate', m.tcCursorAcceptate)
This.Logheaza(m.tcCursorAcceptate, m.tcCursorRefuzate)
If !Used(m.lcCursor) Or Reccount(m.lcCursor) = 0
Select (m.lcSelect)
Return 0
Endif
Try
If SQLSetprop(gnHandle, 'Transactions', 2) < 0
This.cEroare = 'nu s-a putut porni tranzactia manuala'
Else
llTranzactieManuala = .T.
lcSqlInit = [begin pack_contafin.init_scriere_act_rul_local(?gnIdUtil,?gnAn,?gnLuna, 1,0,?gnIdSucursala); end;]
llSucces = (goExecutor.oExecute(m.lcSqlInit) >= 0)
If !m.llSucces
This.cEroare = Nvl(goExecutor.cEroare, 'eroare necunoscuta la initializarea stergerii')
Endif
If m.llSucces
Select (m.lcCursor)
Scan
pnCod = cod
pnAn = an
pnLuna = luna
pnIdEfactura = id_efactura
pnIdFact = id_fact
* pnAn/pnLuna sunt ale documentului (nu gnAn/gnLuna ale sesiunii) - sterge_document(cod)
* cu un singur parametru cauta in ACT pe an/luna curente ale sesiunii Oracle si nu ar
* gasi nimic pentru un document dintr-o alta perioada, fara sa semnaleze eroare
lcSqlSterge = [begin pack_contafin.sterge_document(?pnCod,?pnAn,?pnLuna,?gnIdUtil); end;]
llSucces = (goExecutor.oExecute(m.lcSqlSterge) >= 0)
If !m.llSucces
This.cEroare = Nvl(goExecutor.cEroare, 'eroare necunoscuta la stergerea documentului cod=' + Transform(m.pnCod))
Exit
Endif
llSucces = ResetEFacturaIdFact(m.pnIdEfactura, m.pnIdFact)
If !m.llSucces
This.cEroare = 'documentul cod=' + Transform(m.pnCod) + ' a fost sters, dar resetarea legaturii eFactura a esuat'
Exit
Endif
lnSterse = lnSterse + 1
Endscan
Endif
Endif
Catch To loEroare
llSucces = .F.
This.cEroare = Iif(!Empty(This.cEroare), This.cEroare, loEroare.Message)
Finally
If m.llTranzactieManuala
If m.llSucces
goExecutor.oExecute('COMMIT')
Else
goExecutor.oExecute('ROLLBACK')
lnSterse = 0
Endif
SQLSetprop(gnHandle, 'Transactions', 1)
Endif
Endtry
Select (m.lcSelect)
Return m.lnSterse
Endproc && Executa
*!* Cursoare goale cu structura finala, folosite si la eroare - ecranul se poate deschide oricum
Procedure CreeazaCursoareGoale
If Used('crsAcceptate')
Use In (Select('crsAcceptate'))
Endif
Create Cursor crsAcceptate (id_efactura N(20), id_fact N(20), cod N(15), an N(4), luna N(2), numar_act C(30), furnizor C(250), suma N(20,4))
If Used('crsRefuzate')
Use In (Select('crsRefuzate'))
Endif
Create Cursor crsRefuzate (id_efactura N(20), id_fact N(20), cod N(15), an N(4), luna N(2), numar_act C(30), furnizor C(250), suma N(20,4), motiv C(200))
Endproc && CreeazaCursoareGoale
*!* Curata tcLista (anaf_efactura.id separate prin virgula) la un sir doar cu intregi valizi,
*!* separate prin virgula, gata de interpolat intr-un IN() SQL - elimina orice token nenumeric
Procedure CurataLista
Lparameters tcLista
Local lnN, lnI, lcVal, lcCurata
Local Array laId[1]
lcCurata = ''
lnN = Alines(laId, Nvl(m.tcLista, ''), 0, ',')
For lnI = 1 To m.lnN
lcVal = Alltrim(laId[m.lnI])
If !Empty(m.lcVal) And Empty(Chrtran(m.lcVal, '0123456789', ''))
lcCurata = m.lcCurata + Iif(Empty(m.lcCurata), '', ',') + m.lcVal
Endif
Endfor
Return m.lcCurata
Endproc && CurataLista
Enddefine