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
This commit is contained in:
236
programe/anulare_lot_ef.prg
Normal file
236
programe/anulare_lot_ef.prg
Normal file
@@ -0,0 +1,236 @@
|
||||
*!* 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
|
||||
Reference in New Issue
Block a user