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:
2026-09-09 21:35:07 +03:00
parent 8e022d332e
commit 940bb39701
48 changed files with 10602 additions and 519 deletions

236
programe/anulare_lot_ef.prg Normal file
View 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

View File

@@ -0,0 +1,508 @@
* coada_contabilizare_ef.prg
*!* 08.09.2026
*!* marius.mutu
*!* coada ghidata de contabilizare eFactura: eligibilitate calculata dinainte (CIF ambiguu in ROA
*!* sau linii cu lipsuri de completat blocheaza lotul, partener negasit sau inactiv doar
*!* atentioneaza - se rezolva la contabilizare), rutare automata contabilitate/gestiune dupa
*!* liniile facturii, antet de progres si raport final, contor local pe cursorul bifat.
DEFINE CLASS CoadaContabilizareEF AS Custom
*!* Plafon de facturi bifate pe o rulare a cozii
nPlafon = 50
*!* Calculeaza eligibilitatea fiecarui rand din cursorul de facturi (id, id_fact, cod_fiscal,
*!* numar_act, eligibil_lot, motiv_lot, ales trebuie sa existe deja in alias). Randurile neeligibile sunt
*!* debifate; cele eligibile pot primi in motiv_lot un text de atentionare (partener nou sau
*!* inactiv), fara sa blocheze. O singura interogare Oracle (parteneri grupati dupa codul fiscal
*!* normalizat, activi si inactivi), fara interogari per rand.
PROCEDURE MarcheazaEligibilitate
LPARAMETERS tcAlias, tlLunaInchisa
LOCAL lcSelect, lcSql, llSucces, lcAlias, lcCf, lnActivi, lnInactivi, lcMotiv, lcAtentionare
lcSelect = SELECT()
lcAlias = m.tcAlias
lcSql = "select cf_bare," + ;
" sum(case when inactiv = 0 then 1 else 0 end) as n_activi," + ;
" sum(case when inactiv <> 0 then 1 else 0 end) as n_inactivi" + ;
" from (select inactiv," + ;
" case when replace(upper(cod_fiscal),' ','') like 'RO%'" + ;
" then substr(replace(upper(cod_fiscal),' ',''), 3)" + ;
" else replace(upper(cod_fiscal),' ','') end as cf_bare" + ;
" from nom_parteneri where sters = 0) t" + ;
" group by cf_bare"
llSucces = goExecutor.oExecuta(m.lcSql, 'cCoadaParteneri')
IF !m.llSucces
SELECT (m.lcSelect)
RETURN .F.
ENDIF
SELECT cCoadaParteneri
INDEX ON cf_bare TAG cf_bare
SELECT (m.lcAlias)
SCAN
lcCf = ALLTRIM(STRTRAN(UPPER(NVL(cod_fiscal,'')),' ',''))
IF LEFT(m.lcCf, 2) == 'RO'
lcCf = SUBSTR(m.lcCf, 3)
ENDIF
lnActivi = 0
lnInactivi = 0
IF !EMPTY(m.lcCf) AND SEEK(m.lcCf, 'cCoadaParteneri', 'cf_bare')
lnActivi = NVL(cCoadaParteneri.n_activi, 0)
lnInactivi = NVL(cCoadaParteneri.n_inactivi, 0)
ENDIF
lcMotiv = This.EligibilRand(id_fact, m.lcCf, m.lnActivi, m.lnInactivi, m.tlLunaInchisa, numar_act)
lcAtentionare = IIF(EMPTY(m.lcMotiv), This.TextAtentionarePartener(m.lnActivi, m.lnInactivi), '')
REPLACE eligibil_lot WITH IIF(EMPTY(m.lcMotiv), 1, 0), ;
motiv_lot WITH IIF(EMPTY(m.lcMotiv), m.lcAtentionare, m.lcMotiv) IN (m.lcAlias)
IF !EMPTY(m.lcMotiv)
REPLACE ales WITH 0 IN (m.lcAlias)
ENDIF
ENDSCAN
USE IN (SELECT('cCoadaParteneri'))
SELECT (m.lcSelect)
RETURN .T.
ENDPROC
*!* Motivul pentru care un document nu poate intra in coada, sau sir gol daca e eligibil.
*!* tnActivi/tnInactivi = cati parteneri are ROA pe codul fiscal (ambele variante RO); un CIF
*!* negasit sau gasit doar inactiv nu mai blocheaza - partenerul se creeaza sau se foloseste
*!* inactiv la contabilizare (RezolvarePartenerEF), doar atentioneaza (TextAtentionarePartener).
PROCEDURE EligibilRand
LPARAMETERS tnIdFact, tcCodFiscal, tnActivi, tnInactivi, tlLunaInchisa, tcNumarAct
IF m.tlLunaInchisa
RETURN 'luna este inchisa'
ENDIF
IF !EMPTY(NVL(m.tnIdFact, 0))
RETURN 'factura este deja importata in contabilitate'
ENDIF
IF EMPTY(ALLTRIM(NVL(m.tcCodFiscal, '')))
RETURN 'eFactura nu are cod fiscal, nu se poate identifica partenerul'
ENDIF
IF NVL(m.tnActivi, 0) > 1 OR (NVL(m.tnActivi, 0) = 0 AND NVL(m.tnInactivi, 0) > 1)
RETURN 'CIF ambiguu in ROA, alegeti partenerul manual'
ENDIF
IF EMPTY(This.NrActDinNumarAct(m.tcNumarAct))
RETURN 'numarul documentului nu se poate deduce din ' + ALLTRIM(NVL(m.tcNumarAct, '')) + ', completati-l manual'
ENDIF
RETURN ''
ENDPROC
*!* Text de atentionare pentru un rand eligibil (nu blocheaza), cand partenerul nu e o
*!* potrivire activa simpla: gol daca exista exact un partener activ pe CIF
PROCEDURE TextAtentionarePartener
LPARAMETERS tnActivi, tnInactivi
IF NVL(m.tnActivi, 0) = 0 AND NVL(m.tnInactivi, 0) = 0
RETURN 'partener nou in ROA, se creeaza automat la contabilizare'
ENDIF
IF NVL(m.tnActivi, 0) = 0 AND NVL(m.tnInactivi, 0) = 1
RETURN 'partenerul gasit este inactiv in ROA'
ENDIF
RETURN ''
ENDPROC
*!* Numarul de document dedus din numarul eFacturii: primul grup de cifre de la dreapta
*!* ('ZZT-A1-C' -> 1, 'F1234' -> 1234, 'FACTURA' -> 0). 0 inseamna ca nu s-a putut deduce.
PROCEDURE NrActDinNumarAct
LPARAMETERS tcNumarAct
LOCAL lcText, lcCifre, lnI, llInGrup
lcText = ALLTRIM(NVL(m.tcNumarAct, ''))
lcCifre = ''
llInGrup = .F.
FOR lnI = LEN(m.lcText) TO 1 STEP -1
IF ISDIGIT(SUBSTR(m.lcText, m.lnI, 1))
lcCifre = SUBSTR(m.lcText, m.lnI, 1) + m.lcCifre
llInGrup = .T.
ELSE
IF m.llInGrup
EXIT
ENDIF
ENDIF
ENDFOR
RETURN INT(VAL(RIGHT(m.lcCifre, 14)))
ENDPROC
*!* Textul lipsurilor facturii al carei cursor de linii e deschis (tcAliasDetalii), calculat
*!* local (cont/gestiune) plus o interogare pe vplcont_ANALITIC per cont distinct fara acont
*!* (doar daca tcAliasDetalii are coloana acont), cu TextDeCompletat.
*!* tnGestiuneImplicita = optiunea EFACTURA_ID_GESTIUNE_P, citita de apelant
PROCEDURE LipsuriDetalii
LPARAMETERS tcAliasDetalii, tnGestiuneImplicita
LOCAL lcSelect, lnRecno, lnArticole, lnGestiuni, lnAnalitic, llAreAcont, lcListaCont, lcSql, lcContx
lcSelect = SELECT()
lnArticole = 0
lnGestiuni = 0
lnAnalitic = 0
llAreAcont = (TYPE(m.tcAliasDetalii + '.acont') <> 'U')
IF m.llAreAcont
lcListaCont = cursor2listac(m.tcAliasDetalii, 'cont', ',', "!EMPTY(NVL(cont,'')) AND EMPTY(NVL(acont,''))")
IF !EMPTY(m.lcListaCont)
lcSql = "select distinct cont from vplcont_ANALITIC where inactiv = 0 and an = ?gnAn and cont in (" + m.lcListaCont + ")"
llAreAcont = goExecutor.oExecuta(m.lcSql, 'cCoadaAnaliticLipsuri')
ELSE
llAreAcont = .F.
ENDIF
ENDIF
SELECT (m.tcAliasDetalii)
lnRecno = RECNO()
SCAN
IF EMPTY(ALLTRIM(NVL(cont, '')))
lnArticole = lnArticole + 1
ENDIF
IF NVL(in_stoc, 0) = 1 AND EMPTY(NVL(id_gestiune, 0)) AND EMPTY(NVL(m.tnGestiuneImplicita, 0))
lnGestiuni = lnGestiuni + 1
ENDIF
IF m.llAreAcont AND !EMPTY(ALLTRIM(NVL(cont, ''))) AND EMPTY(ALLTRIM(NVL(acont, '')))
lcContx = ALLTRIM(cont)
SELECT cCoadaAnaliticLipsuri
LOCATE FOR cont = m.lcContx
IF FOUND()
lnAnalitic = lnAnalitic + 1
ENDIF
SELECT (m.tcAliasDetalii)
ENDIF
ENDSCAN
TRY
GO m.lnRecno
CATCH
GO TOP
ENDTRY
IF USED('cCoadaAnaliticLipsuri')
USE IN cCoadaAnaliticLipsuri
ENDIF
SELECT (m.lcSelect)
RETURN This.TextDeCompletat(m.lnArticole, m.lnGestiuni, m.lnAnalitic)
ENDPROC
*!* Compune textul scurt din numarul de linii fara cont, fara gestiune si fara analitic, pentru
*!* coloana de grid
PROCEDURE TextDeCompletat
LPARAMETERS tnArticole, tnGestiuni, tnAnalitic
LOCAL lcCont, lcGest, lcAnalitic, lcText
lcCont = IIF(NVL(m.tnArticole, 0) = 0, '', ALLTRIM(STR(m.tnArticole)) + ' cont')
lcGest = IIF(NVL(m.tnGestiuni, 0) = 0, '', ALLTRIM(STR(m.tnGestiuni)) + ' gest.')
lcAnalitic = IIF(NVL(m.tnAnalitic, 0) = 0, '', ALLTRIM(STR(m.tnAnalitic)) + ' analitic')
lcText = m.lcCont
IF !EMPTY(m.lcGest)
lcText = IIF(EMPTY(m.lcText), m.lcGest, m.lcText + ' ' + m.lcGest)
ENDIF
IF !EMPTY(m.lcAnalitic)
lcText = IIF(EMPTY(m.lcText), m.lcAnalitic, m.lcText + ' ' + m.lcAnalitic)
ENDIF
RETURN m.lcText
ENDPROC
*!* Aplica pe tot cursorul de facturi lipsurile calculate in lot de RecunoastereArticolEF.LipsuriLista
*!* (tcAliasLipsuri, indexat pe id_efactura). Numarul de conturi lipsa e fara_cont_orice cand
*!* tlCompleteazaCont, altfel fara_cont_catalog; devine 0 daca tcContImplicit e nevid (umple toate
*!* liniile neconditionat, ca la completeazadetaliifactura:12040). Numarul de gestiuni lipsa devine 0
*!* daca tnGestiuneImplicita e nevida (:12041, neconditionat de tlCompleteazaGestiune); altfel, cand
*!* tlCompleteazaGestiune e oprit propunerea per linie a cascadei nu se aplica niciodata (:12010/:12028
*!* cer flagul), deci raman lipsa toate liniile stocabile (stoc_total), nu doar cele fara propunere
*!* (stoc_fara_gestiune). Numarul de analitice lipsa e fara_analitic, neconditionat de tlCompleteazaCont/
*!* tcContImplicit (linii care deja au un cont din cascada, indiferent de completarea implicita).
*!* O factura absenta din tcAliasLipsuri (fara linii) nu are nimic de completat.
*!* Regula de rand: identica cu ActualizeazaLipsuriRandCurent (anaf_efactura.vc2) - lipsuri nevide pe
*!* rand inca eligibil blocheaza si debifeaza; lipsuri vide pe rand blocat DIN acest motiv il redeschid,
*!* fara sa atinga alte motive puse de MarcheazaEligibilitate. Pastreaza pozitia in tcAliasFacturi
PROCEDURE AplicaLipsuriLista
LPARAMETERS tcAliasFacturi, tcAliasLipsuri, tcContImplicit, tnGestiuneImplicita, tlCompleteazaCont, tlCompleteazaGestiune
LOCAL lcSelect, lnRecno, llGasit, lnArticole, lnGestiuni, lnAnalitic, lcLipsuri, llEraLipsuri
IF !USED(m.tcAliasFacturi) OR !USED(m.tcAliasLipsuri)
RETURN .F.
ENDIF
lcSelect = SELECT()
SELECT (m.tcAliasFacturi)
lnRecno = RECNO()
SCAN
llGasit = SEEK(id, m.tcAliasLipsuri, 'idefact')
lnArticole = 0
lnGestiuni = 0
lnAnalitic = 0
IF m.llGasit
IF m.tlCompleteazaCont
lnArticole = EVALUATE(m.tcAliasLipsuri + '.fara_cont_orice')
ELSE
lnArticole = EVALUATE(m.tcAliasLipsuri + '.fara_cont_catalog')
ENDIF
IF EMPTY(NVL(m.tnGestiuneImplicita, 0))
IF m.tlCompleteazaGestiune
lnGestiuni = EVALUATE(m.tcAliasLipsuri + '.stoc_fara_gestiune')
ELSE
lnGestiuni = EVALUATE(m.tcAliasLipsuri + '.stoc_total')
ENDIF
ENDIF
lnAnalitic = EVALUATE(m.tcAliasLipsuri + '.fara_analitic')
ENDIF
IF !EMPTY(ALLTRIM(NVL(m.tcContImplicit, '')))
lnArticole = 0
ENDIF
SELECT (m.tcAliasFacturi)
lcLipsuri = This.TextDeCompletat(m.lnArticole, m.lnGestiuni, m.lnAnalitic)
llEraLipsuri = (LEFT(ALLTRIM(NVL(motiv_lot,'')), 13) == 'de completat:')
REPLACE de_completat WITH m.lcLipsuri IN (m.tcAliasFacturi)
REPLACE gest WITH IIF(m.llGasit AND EVALUATE(m.tcAliasLipsuri + '.stoc_total') > 0, 'G', '') IN (m.tcAliasFacturi)
IF !EMPTY(m.lcLipsuri)
IF NVL(eligibil_lot,1) = 1
REPLACE eligibil_lot WITH 0, ales WITH 0, motiv_lot WITH 'de completat: ' + m.lcLipsuri IN (m.tcAliasFacturi)
ENDIF
ELSE
IF NVL(eligibil_lot,1) = 0 AND m.llEraLipsuri
REPLACE eligibil_lot WITH 1, motiv_lot WITH '' IN (m.tcAliasFacturi)
ENDIF
ENDIF
ENDSCAN
TRY
GO m.lnRecno IN (m.tcAliasFacturi)
CATCH
GO TOP IN (m.tcAliasFacturi)
ENDTRY
SELECT (m.lcSelect)
RETURN .T.
ENDPROC
*!* Decide ruta documentului dupa liniile lui deja completate: 1 = Import contabilitate
*!* (ImportGeneral, doar note), 2 = Import gestiune (ImportModifica, note + rulaje), daca
*!* exista cel putin o linie de articol gestionabil (in_stoc = 1)
PROCEDURE Ruta
LPARAMETERS tcAliasDetalii
LOCAL lcSelect, lnGestionabile, lnRecno
lcSelect = SELECT()
lnGestionabile = 0
SELECT (m.tcAliasDetalii)
lnRecno = RECNO()
COUNT FOR NVL(in_stoc, 0) = 1 TO lnGestionabile
TRY
GO m.lnRecno
CATCH
GO TOP
ENDTRY
SELECT (m.lcSelect)
RETURN IIF(m.lnGestionabile > 0, 2, 1)
ENDPROC
*!* Textul antetului permanent afisat cat ruleaza coada
PROCEDURE AntetProgres
LPARAMETERS tnCurent, tnTotal, tcFurnizor, tcNrAct, tnSuma
LOCAL lcSuma
lcSuma = ALLTRIM(TRANSFORM(NVL(m.tnSuma, 0), '999,999,999.99'))
RETURN 'Factura ' + ALLTRIM(STR(m.tnCurent)) + ' din ' + ALLTRIM(STR(m.tnTotal)) + ' - ' + ;
ALLTRIM(NVL(m.tcFurnizor, '')) + ' - ' + ALLTRIM(NVL(m.tcNrAct, '')) + ' - ' + m.lcSuma + ' lei' + ;
' (ESC opreste coada dupa documentul curent)'
ENDPROC
*!* Mesajul de refuz cand numarul de facturi bifate eligibile depaseste plafonul
PROCEDURE MesajPlafon
LPARAMETERS tnTotal
RETURN 'Sunt bifate ' + ALLTRIM(STR(m.tnTotal)) + ' facturi eligibile, peste plafonul de ' + ;
ALLTRIM(STR(This.nPlafon)) + ' facturi pe o rulare a cozii.' + CHR(13) + ;
'Debifati o parte din facturi si porniti coada din nou.'
ENDPROC
*!* Mesajul de confirmare inainte de a porni coada pe N facturi
PROCEDURE MesajConfirmare
LPARAMETERS tnTotal
RETURN 'Se vor contabiliza ' + ALLTRIM(STR(m.tnTotal)) + ' facturi, una dupa alta.' + CHR(13) + ;
'Fiecare document va fi aratat pentru confirmare inainte de scriere.' + CHR(13) + ;
'Se poate opri coada cu ESC intre facturi sau la intrebarea de dupa un document nereusit. Continuati?'
ENDPROC
*!* Linia de raport cand operatorul a oprit coada, cu numarul de facturi ramase neprocesate
*!* tcCauza: cum s-a oprit coada; implicit ESC, apasat intre doua documente
PROCEDURE MesajOprire
LPARAMETERS tnRamase, tcCauza
RETURN 'operatorul a oprit coada ' + IIF(EMPTY(NVL(m.tcCauza, '')), 'cu ESC', ALLTRIM(m.tcCauza)) + ;
' - ' + ALLTRIM(STR(m.tnRamase)) + ' facturi bifate raman neprocesate'
ENDPROC
*!* Intrebarea pusa operatorului dupa un document nereusit, singura cale de a opri lotul cat
*!* timp un formular modal de introducere consuma tastatura (ESC nu ajunge la bucla cozii)
PROCEDURE MesajContinuare
LPARAMETERS tcMotiv, tnRamase
RETURN 'Documentul nu a fost creat: ' + ALLTRIM(NVL(m.tcMotiv, '')) + CHR(13) + CHR(10) + CHR(13) + CHR(10) + ;
'Continuati cu celelalte ' + ALLTRIM(STR(m.tnRamase)) + ' facturi bifate?'
ENDPROC
PROCEDURE CreeazaRaport
IF USED('crsCoadaRaport')
USE IN crsCoadaRaport
ENDIF
CREATE CURSOR crsCoadaRaport (id_efactura N(20), numar_act V(30), furnizor V(200), stare V(10), motiv V(200))
ENDPROC
PROCEDURE AdaugaRaport
LPARAMETERS tnIdEfactura, tcNumarAct, tcFurnizor, tcStare, tcMotiv
LOCAL lcSelect
IF !USED('crsCoadaRaport')
RETURN .F.
ENDIF
lcSelect = SELECT()
INSERT INTO crsCoadaRaport (id_efactura, numar_act, furnizor, stare, motiv) ;
VALUES (m.tnIdEfactura, ALLTRIM(NVL(m.tcNumarAct, '')), ALLTRIM(NVL(m.tcFurnizor, '')), m.tcStare, NVL(m.tcMotiv, ''))
SELECT (m.lcSelect)
RETURN .T.
ENDPROC
*!* Raport final pe document, ramane deschis dupa ce coada s-a terminat
PROCEDURE AfiseazaRaport
IF !USED('crsCoadaRaport')
RETURN .F.
ENDIF
AMESSAGEBOX(This.MesajRaport(), 0+64, _screen.Caption)
RETURN .T.
ENDPROC
*!* Textul rezumatului cozii, compus pe crsCoadaRaport (randuri OK/SARIT/ESEC pe documente,
*!* randul OPRIT cu id_efactura=0 e marcaj de intrerupere, nu document). Plafon 15 documente
*!* listate la problemele SARIT/ESEC, apoi un rand "... si inca N."
PROCEDURE MesajRaport
LOCAL lcSelect, lnOk, lnSarit, lnEsec, lnListate, lcOprit, laLinii[200], lnL, lcText, lnI
IF !USED('crsCoadaRaport')
RETURN ''
ENDIF
lcSelect = SELECT()
SELECT crsCoadaRaport
lnOk = 0
lnSarit = 0
lnEsec = 0
lnListate = 0
lcOprit = ''
lnL = 0
SCAN
DO CASE
CASE ALLTRIM(stare) == 'OK'
lnOk = lnOk + 1
CASE ALLTRIM(stare) == 'SARIT' OR ALLTRIM(stare) == 'ESEC'
IF ALLTRIM(stare) == 'SARIT'
lnSarit = lnSarit + 1
ELSE
lnEsec = lnEsec + 1
ENDIF
IF lnListate < 15
lnL = lnL + 1
laLinii[m.lnL] = ALLTRIM(NVL(numar_act,'')) + ' / ' + ALLTRIM(NVL(furnizor,''))
IF !EMPTY(ALLTRIM(NVL(motiv,'')))
lnL = lnL + 1
laLinii[m.lnL] = ' ' + ALLTRIM(NVL(motiv,''))
ENDIF
lnListate = lnListate + 1
ENDIF
CASE ALLTRIM(stare) == 'OPRIT'
lcOprit = ALLTRIM(NVL(motiv,''))
ENDCASE
ENDSCAN
SELECT (m.lcSelect)
lcText = 'Coada de contabilizare - ' + ALLTRIM(STR(m.lnOk + m.lnSarit + m.lnEsec)) + ' facturi' + CHR(13) + CHR(10) + CHR(13) + CHR(10) + ;
'Contabilizate : ' + ALLTRIM(STR(m.lnOk)) + CHR(13) + CHR(10) + ;
'Sarite : ' + ALLTRIM(STR(m.lnSarit)) + CHR(13) + CHR(10) + ;
'Nereusite : ' + ALLTRIM(STR(m.lnEsec))
IF m.lnSarit + m.lnEsec > 0
lcText = m.lcText + CHR(13) + CHR(10) + CHR(13) + CHR(10) + 'Nu s-au contabilizat:'
FOR lnI = 1 TO m.lnL
lcText = m.lcText + CHR(13) + CHR(10) + laLinii[m.lnI]
ENDFOR
IF m.lnSarit + m.lnEsec > m.lnListate
lcText = m.lcText + CHR(13) + CHR(10) + '... si inca ' + ALLTRIM(STR(m.lnSarit + m.lnEsec - m.lnListate)) + '.'
ENDIF
ENDIF
IF !EMPTY(m.lcOprit)
lcText = m.lcText + CHR(13) + CHR(10) + CHR(13) + CHR(10) + m.lcOprit
ENDIF
RETURN m.lcText
ENDPROC
*!* Contoare pentru bara de lot, calculate local pe cursorul deja incarcat (fara interogare
*!* Oracle): total bifate si suma lor, cate intra in Import N bifate (eligibile, neimportate),
*!* cate in Anuleaza N documente (deja au document), cate raman doar pentru import individual
*!* (bifate, neeligibile lot, neimportate inca); nGata/nTotal = "gata de import: N din M" pe tot
*!* cursorul afisat, indiferent de bifa (eligibile si neimportate / toate randurile)
PROCEDURE ContorBifate
LPARAMETERS tcAlias
LOCAL lcSelect, lnRecno, loContor
lcSelect = SELECT()
loContor = CREATEOBJECT('Empty')
ADDPROPERTY(loContor, 'nBifate', 0)
ADDPROPERTY(loContor, 'nSuma', 0)
ADDPROPERTY(loContor, 'nIndividual', 0)
ADDPROPERTY(loContor, 'nImport', 0)
ADDPROPERTY(loContor, 'nAnulare', 0)
ADDPROPERTY(loContor, 'nGata', 0)
ADDPROPERTY(loContor, 'nTotal', 0)
ADDPROPERTY(loContor, 'nGestiune', 0)
SELECT (m.tcAlias)
lnRecno = RECNO()
loContor.nTotal = RECCOUNT()
SCAN FOR NVL(eligibil_lot,1) = 1 AND NVL(id_fact,0) = 0
loContor.nGata = loContor.nGata + 1
ENDSCAN
SELECT (m.tcAlias)
SCAN FOR !EMPTY(NVL(gest,''))
loContor.nGestiune = loContor.nGestiune + 1
ENDSCAN
SELECT (m.tcAlias)
SCAN FOR ales = 1
loContor.nBifate = loContor.nBifate + 1
loContor.nSuma = loContor.nSuma + NVL(total_cu_tva, 0)
IF NVL(id_fact, 0) <> 0
loContor.nAnulare = loContor.nAnulare + 1
ELSE
IF NVL(eligibil_lot, 1) = 1
loContor.nImport = loContor.nImport + 1
ELSE
loContor.nIndividual = loContor.nIndividual + 1
ENDIF
ENDIF
ENDSCAN
TRY
GO m.lnRecno
CATCH
GO TOP
ENDTRY
SELECT (m.lcSelect)
RETURN loContor
ENDPROC
ENDDEFINE
*!* Culoarea celulei de analitic (grid detalii eFactura): rosu daca contul cere analitic activ si acont e gol,
*!* apoi tiparul existent ISTORIC/APROX/alb; foloseste cursorul cAnaliticCerut deschis de forma, daca exista.
PROCEDURE CuloareAnaliticLipsaEF
LPARAMETERS tcCont, tcAcont, tcSursaCont
IF !EMPTY(NVL(m.tcCont,'')) AND EMPTY(NVL(m.tcAcont,'')) AND USED('cAnaliticCerut') AND INDEXSEEK(m.tcCont,.F.,'cAnaliticCerut','cont')
RETURN RGB(255,205,205)
ENDIF
IF NVL(m.tcSursaCont,'') == 'ISTORIC'
RETURN RGB(255,228,196)
ENDIF
IF NVL(m.tcSursaCont,'') == 'APROX'
RETURN RGB(255,255,240)
ENDIF
RETURN RGB(255,255,255)
ENDPROC

View File

@@ -38,7 +38,7 @@ PROCEDURE vizImportEFactura
ldData1 = GOMONTH(DATE(m.gnAn, m.gnLuna, 1), 1)
lcData2 = '01' + PADL(MONTH(m.ldData1),2,'0') + ALLTRIM(STR(YEAR(m.ldData1)))
TEXT To lcSchema Noshow
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), partener C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal C(30) null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4) null, descriere M null, detalii_plata M null, diferenta N(16,4) null, procesat N(1), SerieActRoa V(10) Null, NrActRoa N(14) Null, IdPartRoa N(10) Null, PartenerRoa V(100) null, codFiscalROA V(20), idValutaROA N(5) null,numeValutaROA V(5) null, cursROA N(16,6) null,Cont c(4) Null,ACont c(4) Null,TVAIncasare N(1),Fdoc V(20) null,Id_Fdoc N(5) Null,Nrord V(100) null,Id_Lucrare I Null,Contract V(100) Null,Id_Ctr I Null,Sectie V(100) null,Id_Sectie I Null,dst_chlt V(100) null, Id_venchelt I NUll, nresp V(100) null, Id_responsabil I NUll , completat N(1), completatdet N(1), creditnote N(1), explicatiaROA V(100) null
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), partener C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal C(30) null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4) null, descriere M null, detalii_plata M null, diferenta N(16,4) null, procesat N(1), SerieActRoa V(10) Null, NrActRoa N(14) Null, IdPartRoa N(10) Null, PartenerRoa V(100) null, codFiscalROA V(20), idValutaROA N(5) null,numeValutaROA V(5) null, cursROA N(16,6) null,Cont c(4) Null,ACont c(4) Null,TVAIncasare N(1),Fdoc V(20) null,Id_Fdoc N(5) Null,Nrord V(100) null,Id_Lucrare I Null,Contract V(100) Null,Id_Ctr I Null,Sectie V(100) null,Id_Sectie I Null,dst_chlt V(100) null, Id_venchelt I NUll, nresp V(100) null, Id_responsabil I NUll , completat N(1), completatdet N(1), creditnote N(1), explicatiaROA V(100) null, eligibil_lot N(1), motiv_lot V(120), eroare_lot N(1), de_completat V(80), gest c(1), part_inactiv N(1)
ENDTEXT
*!* diferenta ramane goala cand factura nu e in Registrul TVA sau e in valuta si tine cont de semnul notei de credit, ca la borderou
@@ -46,7 +46,7 @@ ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xf
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, partener, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, case when jtotctva is null then null when NVL(nume_valuta,'RON') <> 'RON' then null else decode(creditnote,0,1,-1) * NVL(total_cu_tva,0.00) - (NVL(jtotctva,0.00) - NVL(jtva_ti,0.00)) end as diferenta, procesat,
'' as SerieActRoa, CAST(null as Number(14)) as NrActRoa, CAST(null as Number(20)) as idPartRoa, '' as PartenerRoa, '' as codFiscalROA, CAST(null as Number(10)) as idValutaROA, '' as numeValutaROA, CAST(null as Number(16,6)) as cursROA,
'' as Cont, '' as acont, 0 as TVAIncasare, '' as Fdoc, CAST(0 as Number(5)) as Id_Fdoc, '' as Nrord, CAST(0 as Number(10)) as id_Lucrare, '' as Contract, CAST(null as Number(10)) as id_ctr,
'' Sectie, CAST(0 as Number(10)) as id_Sectie, '' as dst_chlt, CAST(0 as Number(10)) as id_Venchelt, '' as nresp, CAST(0 as Number(10)) as id_responsabil, 0 as completat, 0 as completatdet, creditnote, '' as explicatiaROA
'' Sectie, CAST(0 as Number(10)) as id_Sectie, '' as dst_chlt, CAST(0 as Number(10)) as id_Venchelt, '' as nresp, CAST(0 as Number(10)) as id_responsabil, 0 as completat, 0 as completatdet, creditnote, '' as explicatiaROA, 1 as eligibil_lot, '' as motiv_lot, 0 as eroare_lot, '' as de_completat, '' as gest, 0 as part_inactiv
FROM <<m.lcTabel>>
ENDTEXT
@@ -64,10 +64,10 @@ SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclien
* DETALII FACTURI PRIMITE/TRIMISE/EMISE
TEXT To lcSchema Noshow
distribuie N(1), id_tip N(10) null, id_articol N(20) null, id_gestiune N(20) null, cont C(4) null, acont C(4) null, id N(20), id_efactura N(20), nr N(5), articol V(250), descriere V(250), detalii M, cantitate N(18,6), um V(20), um_iso V(50), um_roa V(50), pret N(20,6), proctva N(7,2), tiptva V(2), valoarefaratva N(20,6), discountfaratva N(20,6), in_stoc N(1), articol_roa V(250), codmat_roa V(50), codbare V(50), codclient V(100), codfurnizor V(100), codcpv V(50), codnc8 V(50), nume_gestiune V(50), cgest V(20), tva N(20,6), pretv N(20,6), tvav N(20,6), pretvtva N(20,6)
distribuie N(1), id_tip N(10) null, id_articol N(20) null, id_gestiune N(20) null, cont C(4) null, acont C(4) null, sursa_cont V(10) null, id N(20), id_efactura N(20), nr N(5), articol V(250), descriere V(250), detalii M, cantitate N(18,6), um V(20), um_iso V(50), um_roa V(50), pret N(20,6), proctva N(7,2), tiptva V(2), valoarefaratva N(20,6), discountfaratva N(20,6), in_stoc N(1), articol_roa V(250), codmat_roa V(50), codbare V(50), codclient V(100), codfurnizor V(100), codcpv V(50), codnc8 V(50), nume_gestiune V(50), cgest V(20), tva N(20,6), pretv N(20,6), tvav N(20,6), pretvtva N(20,6)
ENDTEXT
TEXT To lcSelect Noshow
select 0 as distribuie, CAST(0 as number(10)) as id_tip, id_articol, id_gestiune, cont, acont, id, id_efactura, nr, articol, descriere, detalii, cantitate, um, um_iso, um_roa, pret, proctva, tiptva, valoarefaratva, discountfaratva, in_stoc, articol_roa, codmat_roa, codbare, codclient, codfurnizor, codcpv, codnc8, nume_gestiune, cgest, 0 as tva, 0 as pretv, 0 as tvav, 0 as pretvtva from anaf_vefactura_detalii
select 0 as distribuie, CAST(0 as number(10)) as id_tip, id_articol, id_gestiune, cont, acont, sursa_cont, id, id_efactura, nr, articol, descriere, detalii, cantitate, um, um_iso, um_roa, pret, proctva, tiptva, valoarefaratva, discountfaratva, in_stoc, articol_roa, codmat_roa, codbare, codclient, codfurnizor, codcpv, codnc8, nume_gestiune, cgest, 0 as tva, 0 as pretv, 0 as tvav, 0 as pretvtva from anaf_vefactura_detalii
ENDTEXT
lcOrder = [nr]
lcgroup = []
@@ -188,13 +188,13 @@ PROCEDURE UpdateEFacturaArticolROA
LPARAMETERS tnIdEFactura
Local lcSql, llSucces, lcSelect
PRIVATE pnIdArticol, pnId, pnIdGestiune, pcCont
PRIVATE pnIdArticol, pnId, pnIdGestiune, pcCont, pcAcont, pcSursaCont
lcSelect = SELECT()
lcSql = "update anaf_efactura_detalii set id_articol = ?pnIdArticol, id_gestiune = ?pnIdGestiune, cont = ?pcCont, acont = ?pcAcont where id = ?pnId"
lcSql = "update anaf_efactura_detalii set id_articol = ?pnIdArticol, id_gestiune = ?pnIdGestiune, cont = ?pcCont, acont = ?pcAcont, sursa_cont = ?pcSursaCont where id = ?pnId"
llSucces = .T.
SELECT id, id_articol, id_gestiune, cont, acont FROM crsDetaliiFacturi INTO CURSOR cArticoleTemp
SELECT id, id_articol, id_gestiune, cont, acont, sursa_cont FROM crsDetaliiFacturi INTO CURSOR cArticoleTemp
SELECT cArticoleTemp
SCAN
@@ -203,7 +203,8 @@ PROCEDURE UpdateEFacturaArticolROA
pnIdGestiune = IIF(EMPTY(NVL(id_gestiune, 0)), null, id_gestiune)
pcCont = ALLTRIM(NVL(cont, ''))
pcAcont = ALLTRIM(NVL(acont, ''))
pcSursaCont = ALLTRIM(NVL(sursa_cont, ''))
llSucces = goExecutor.oExecuta(m.lcSql)
IF !m.llSucces
EXIT
@@ -236,4 +237,27 @@ PROCEDURE UpdateEFacturaIdFact
SELECT (m.lcSelect)
RETURN m.llSucces
ENDPROC && UpdateEFacturaIdFact
ENDPROC && UpdateEFacturaIdFact
**********************
* Reseteaza anaf_efactura.id_fact dupa anularea in bloc a documentului, doar daca valoarea
* curenta e cea asteptata (evita sa reseteze o legatura noua scrisa intre timp)
**********************
PROCEDURE ResetEFacturaIdFact
LPARAMETERS tnIdEFactura, tnIdFact
Local lcSql, llSucces, lcSelect
PRIVATE pnId, pnIdFact
lcSelect = SELECT()
lcSql = "update anaf_efactura set id_fact = null where id = ?pnId and id_fact = ?pnIdFact"
llSucces = .T.
pnId = m.tnIdEfactura
pnIdFact = m.tnIdFact
llSucces = goExecutor.oExecuta(m.lcSql)
SELECT (m.lcSelect)
RETURN m.llSucces
ENDPROC && ResetEFacturaIdFact

View File

@@ -52,8 +52,10 @@
*!* 03.09.2024
*!* ProcentTva2IdJtva - tratare procent TVA 0 si taxare inversa (eFactura)
*!* 05.12.2024
*!* GetArticolEFByPartDenumire - caut si articolele fara id_articol, in caz ca sunt servicii, nu articole gestionabile ROA
*!* 03.09.2026
*!* marius.mutu
*!* GetArticolEFByPartDenumire - invelis peste RecunoastereArticolEF: cascada text exact ->
*!* cheie normalizata in istoricul furnizorului, plus parametrul de iesire tcSursa (EXACT/APROX)
*!* 15.01.2025
*!* GetDocumentByContPartenerAct - se cauta comanda si in IREG_PARTENERI.EXPLICATIA
@@ -7335,61 +7337,46 @@ ENDPROC && GetArticolById
**************************************
*** Intoarce un obiect din ANAF_VEFACTURA_DETALII/id_articol dupa cod fiscal furnizor/client si denumire
*** Cauta in articolele furnizorului/clientului, ultima aparitie a articolului respectiv
*** Cauta in istoricul furnizorului/clientului cascada RecunoastereArticolEF.PotrivesteArticol
*** (text exact, apoi cheie normalizata), ultima aparitie a articolului respectiv
*** lnIdArticol = GetArticolEFByPartDenumire("cod fiscal", "articol", .T.)
*** loArticol = GetArticolByCodDenumire("articol", "cod bare", "cod furnizor", "cod client", IdPart, .F.)
**************************************
Procedure GetArticolEFByPartDenumire
lParameters tcCodFiscal, tlPrimite, tcDenumire, tlReturnId, tnIdEfactura
lParameters tcCodFiscal, tlPrimite, tcDenumire, tlReturnId, tnIdEfactura, tcSursa
* tcCodFiscal : cod fiscal client/furnizor
* tlPrimite: facturi primite / emise
* tcDenumire: denumire articol
* tlReturnId: .T. = intoarce id_articol, .F. = intoarce obiect
* tlReturnId: .T. = intoarce id_articol, .F. = intoarce obiect
* tnIdEfactura: id_efactura curenta. sa nu caut articolul in factura curenta, ci in facturile anterioare
Private pcDenumire, pcCodBare, pcCodFurnizor, pcCodCLient, pnIdPart, pnIdEfactura
Local lcSql, lnSucces, lcSelect, loArticol, loReturn, lcColoanaCodFiscal
* tcSursa: parametru de iesire optional (@tcSursa) - 'EXACT'/'APROX' la gasire, '' cand nu s-a gasit nimic
Local lcSelect, loArticol, loReturn, loRecunoastere, lcSursa
lcSelect = SELECT()
loArticol = null
loReturn = Null
pcDenumire = UPPER(Alltrim(NVL(m.tcDenumire, '')))
pcCodFiscal = UPPER(ALLTRIM(NVL(m.tcCodFiscal, '')))
pnIdArticol = 0
pnIdEfactura = IIF(!EMPTY(NVL(tnIdEfactura, 0)), m.tnIdEfactura, 0)
lcColoanaCodFiscal = IIF(m.tlPrimite, "e.cod_fiscal_emitent", "e.cod_fiscal_beneficiar")
TEXT TO lcSql TEXTMERGE NOSHOW
SELECT * FROM (SELECT d.* FROM ANAF_VEFACTURA_DETALII d LEFT JOIN ANAF_EFACTURA e ON (e.id = d.id_efactura)
WHERE <<m.lcColoanaCodFiscal>> = ?pcCodFiscal AND TRIM(UPPER(d.articol)) = ?pcDenumire and id_articol is not null ORDER BY d.id desc) WHERE rownum = 1
ENDTEXT
loReturn = Null
llSucces = goExecutor.oSelecteaza2Object(m.lcSql, @loArticol)
loRecunoastere = Createobject('RecunoastereArticolEF')
loArticol = loRecunoastere.PotrivesteArticol(m.tcCodFiscal, m.tlPrimite, m.tcDenumire, m.tnIdEfactura, @lcSursa)
tcSursa = m.lcSursa
If m.llSucces
* Daca nu am gasit factura cu articol ROA (este posibil sa fie de servicii, fara articole gestionabile)
* Caut articolelele anterioare, fara id_articol
IF EMPTY(NVL(loArticol.id_articol,0)) AND !EMPTY(NVL(m.tnIdEfactura,0))
TEXT TO lcSql TEXTMERGE NOSHOW
SELECT * FROM (SELECT d.* FROM ANAF_VEFACTURA_DETALII d LEFT JOIN ANAF_EFACTURA e ON (e.id = d.id_efactura)
WHERE <<m.lcColoanaCodFiscal>> = ?pcCodFiscal AND TRIM(UPPER(d.articol)) = ?pcDenumire and e.id <> ?pnIdEFactura ORDER BY d.id desc) WHERE rownum = 1
ENDTEXT
IF ISNULL(m.loArticol)
* obiect cu proprietatile ANAF_VEFACTURA_DETALII la valoarea implicita a tipului, nu NULL, cand cascada nu gaseste nimic
loArticol = loRecunoastere.oGol
IF ISNULL(m.loArticol)
* cascada s-a oprit pe eroare de date, fara sa aduca structura
goExecutor.oSelecteaza2Object("SELECT * FROM ANAF_VEFACTURA_DETALII WHERE 1 = 0", @loArticol)
ENDIF
ENDIF
llSucces = goExecutor.oSelecteaza2Object(m.lcSql, @loArticol)
ENDIF
ENDIF
IF m.llSucces
IF m.tlReturnId
loReturn = loArticol.id_articol
ELSE
loReturn = loArticol
ENDIF
IF m.tlReturnId
loReturn = loArticol.id_articol
ELSE
loReturn = loArticol
ENDIF
SELECT (m.lcSelect)
Return loReturn
ENDPROC && GetArticolEFByPartDenumire

View File

@@ -691,7 +691,7 @@ Function lans
*----------------------------------------------
Procedure introducere_compacta
Parameters tcFis, tcscd, tcscc, tl_calcTVA, tl_plata, tctitlu, tctva, tn_idset, tl_acont, tnDeducere, tlCursorCreat, tnTotcTVA
Parameters tcFis, tcscd, tcscc, tl_calcTVA, tl_plata, tctitlu, tctva, tn_idset, tl_acont, tnDeducere, tlCursorCreat, tnTotcTVA, tnTop
Local llVerificaAcont, llSucces, llN50, llN100, llNeexigibil, llCursorCreat
llCursorCreat = .F.
llVerificaAcont = .T.
@@ -708,6 +708,7 @@ Procedure introducere_compacta
*!* tnDeducere = 0/1 - daca se scriu notele pentru cheltuieli deductibile 50%
*!* tlCursorCreat (optional) = .T. daca cursorul cnote_contabile este creat anterior (Ex: import din eFactura)
*!* tnTotcTVA (optional) = Valoarea cu TVA import eFactura
*!* tnTop (optional) = pozitia Top cat timp ruleaza lotul de import eFactura
If Pcount() >= 9
llVerificaAcont = tl_acont
@@ -1070,7 +1071,7 @@ Procedure introducere_compacta
obj.titlufrumos1.Caption = tctitlu
obj.Show(1)
obj.Show(1, tnTop)
USE IN (SELECT('crsTaxTable'))
USE IN (SELECT('crsjtva'))

View File

@@ -0,0 +1,655 @@
*!* 08.09.2026
*!* marius.mutu
*!* RecunoastereArticolEF - cascada de potrivire cont/acont/id_articol/id_gestiune pentru liniile de
*!* eFactura, calculata intr-o singura interogare per factura (PotrivesteFactura): catalogul ROA
*!* (denumire/codbare/codmat/codmatf/cod partener), apoi text exact, apoi cheie normalizata in
*!* istoricul propriu al furnizorului, apoi articolul contat oriunde in firma pe aceeasi cheie (ultima
*!* factura), apoi contul sintetic dominant al furnizorului din ACT, apoi contul majoritar al
*!* celorlalte linii ale facturii; id_articol/id_gestiune vin doar din catalog/istoric propriu/articol
*!* firma-wide, niciodata din furnizor/factura
Define Class RecunoastereArticolEF As Custom
nNormalizat = 1 && EFACTURA_ART_NORMALIZAT: 0 = doar text exact
nPrefix = 12 && lungimea cheii normalizate comparate, fixa - indexul functional de pe
&& ANAF_EFACTURA_DETALII e creat pe exact aceasta lungime, nu mai e configurabila din optiuni
nIstoric = 1 && EFACTURA_ART_ISTORIC: 0 = fara treapta pe cont sintetic din istoricul furnizorului
oGol = Null && ultimul obiect gol produs de cascada, pentru apelantii care asteapta obiect, nu NULL
Procedure Init
This.IncarcaOptiuni()
Endproc && Init
Procedure IncarcaOptiuni
Local lcVal
This.nNormalizat = 1
This.nIstoric = 1
Try
lcVal = citeste_optiune('EFACTURA_ART_NORMALIZAT')
If Type('lcVal') = 'C' And !Empty(Alltrim(m.lcVal))
This.nNormalizat = Int(Val(m.lcVal))
Endif
lcVal = citeste_optiune('EFACTURA_ART_ISTORIC')
If Type('lcVal') = 'C' And !Empty(Alltrim(m.lcVal))
This.nIstoric = Int(Val(m.lcVal))
Endif
Catch
Endtry
Endproc && IncarcaOptiuni
*!* Fragmentul SQL al cheii normalizate (cifre si separatori scosi, trunchiata la nPrefix caractere),
*!* aplicat identic pe coloana din tabela si pe valoarea cautata - functia Oracle FN_EFACT_ARTNORM
*!* si nPrefix sunt cele de pe indexul functional IDX_EFACT_DET_ARTNORM; REGEXP_REPLACE nu poate fi
*!* indexat direct (ORA-01743), de-aia expresia sta intr-o functie deterministica in Oracle
Procedure CheieSql
Lparameters tcColoana
Return "FN_EFACT_ARTNORM(" + m.tcColoana + "," + Transform(This.nPrefix) + ")"
Endproc && CheieSql
*!* Fragmentul SQL al ferestrei de istoric (ultimele 24 de luni)
Procedure FereastraIstoricSql
Lparameters tcColoanaData
Return m.tcColoanaData + " >= ADD_MONTHS(TRUNC(SYSDATE,'MM'), -24)"
Endproc && FereastraIstoricSql
*!* Cascada pentru o singura denumire de articol, in istoricul aceluiasi furnizor/client din
*!* ultimele 24 de luni (exclude factura curenta). tcSursa (referinta): 'EXACT'/'APROX' la gasire,
*!* '' altfel. Intoarce obiectul gasit (campurile ANAF_VEFACTURA_DETALII) sau NULL cand nu s-a gasit nimic.
Procedure PotrivesteArticol
Lparameters tcCodFiscal, tlPrimite, tcDenumire, tnIdEfactura, tcSursa
Local lcSql, llSucces, loArticol, lcColoanaCodFiscal, lcCheieCol, lcCheieVal, lcIst, lcFereastra
Private pcDenumire, pcCodFiscal, pnIdEfactura
This.oGol = Null
tcSursa = ''
loArticol = Null
pcDenumire = Upper(Alltrim(Nvl(m.tcDenumire, '')))
pcCodFiscal = Upper(Alltrim(Nvl(m.tcCodFiscal, '')))
pnIdEfactura = Iif(!Empty(Nvl(m.tnIdEfactura, 0)), m.tnIdEfactura, 0)
lcColoanaCodFiscal = Iif(m.tlPrimite, "e.cod_fiscal_emitent", "e.cod_fiscal_beneficiar")
lcCheieCol = This.CheieSql('articol')
lcCheieVal = This.CheieSql('?pcDenumire')
lcFereastra = This.FereastraIstoricSql('e.xdata_act')
Text To lcIst Textmerge Noshow
WITH ist AS (SELECT /*+ MATERIALIZE */ d.*, TRIM(UPPER(d.articol)) a_ex, <<m.lcCheieCol>> a_no
FROM ANAF_VEFACTURA_DETALII d LEFT JOIN ANAF_EFACTURA e ON (e.id = d.id_efactura)
WHERE <<m.lcColoanaCodFiscal>> = ?pcCodFiscal AND e.id <> ?pnIdEfactura AND <<m.lcFereastra>>)
Endtext
Text To lcSql Textmerge Noshow
<<m.lcIst>>
SELECT * FROM (SELECT * FROM ist WHERE a_ex = ?pcDenumire AND id_articol IS NOT NULL ORDER BY id DESC) WHERE ROWNUM = 1
Endtext
llSucces = goExecutor.oSelecteaza2Object(m.lcSql, @loArticol)
If !m.llSucces
Return Null
Endif
If !Empty(Nvl(loArticol.id_articol, 0))
tcSursa = 'EXACT'
Return loArticol
Endif
Text To lcSql Textmerge Noshow
<<m.lcIst>>
SELECT * FROM (SELECT * FROM ist WHERE a_ex = ?pcDenumire ORDER BY id DESC) WHERE ROWNUM = 1
Endtext
llSucces = goExecutor.oSelecteaza2Object(m.lcSql, @loArticol)
If !m.llSucces
Return Null
Endif
If !Empty(Nvl(loArticol.cont, ''))
tcSursa = 'EXACT'
Return loArticol
Endif
* pasii 3-4 (cheie normalizata) au comutatorul lor; treapta 5 de mai jos are alt comutator
If This.nNormalizat # 0
Text To lcSql Textmerge Noshow
<<m.lcIst>>
SELECT * FROM (SELECT * FROM ist WHERE LENGTH(<<m.lcCheieVal>>) >= 3
AND a_no = <<m.lcCheieVal>> AND id_articol IS NOT NULL ORDER BY id DESC) WHERE ROWNUM = 1
Endtext
llSucces = goExecutor.oSelecteaza2Object(m.lcSql, @loArticol)
If !m.llSucces
Return Null
Endif
If !Empty(Nvl(loArticol.id_articol, 0))
tcSursa = 'APROX'
Return loArticol
Endif
Text To lcSql Textmerge Noshow
<<m.lcIst>>
SELECT * FROM (SELECT * FROM ist WHERE LENGTH(<<m.lcCheieVal>>) >= 3
AND a_no = <<m.lcCheieVal>> ORDER BY id DESC) WHERE ROWNUM = 1
Endtext
llSucces = goExecutor.oSelecteaza2Object(m.lcSql, @loArticol)
If !m.llSucces
Return Null
Endif
If !Empty(Nvl(loArticol.cont, ''))
tcSursa = 'APROX'
Return loArticol
Endif
Endif
If This.nIstoric # 0
Local loIstoric
Text To lcSql Textmerge Noshow
<<m.lcIst>>
SELECT cont FROM (SELECT cont FROM (SELECT TRIM(cont) AS cont FROM ist
WHERE cont IS NOT NULL AND TRIM(cont) IS NOT NULL ORDER BY id DESC) WHERE ROWNUM <= 5)
GROUP BY cont HAVING COUNT(*) = 5
Endtext
llSucces = goExecutor.oSelecteaza2Object(m.lcSql, @loIstoric)
If !m.llSucces
Return Null
Endif
If !Empty(Nvl(loIstoric.cont, ''))
loArticol.cont = Alltrim(loIstoric.cont)
tcSursa = 'ISTORIC'
Return loArticol
Endif
Endif
This.oGol = m.loArticol
Return Null
Endproc && PotrivesteArticol
*!* Cascada completa (catalog ROA, istoric propriu, articol firma-wide, cont dominant al
*!* furnizorului, cont majoritar al facturii) pentru toate liniile facturii tnIdEfactura, intr-o
*!* singura interogare Oracle. Lasa deschis cursorul CRSPOTRIVIRELINII (NR, ID_DETALIU, CONT,
*!* ACONT, ID_ARTICOL, ARTICOL_ROA, CODMAT_ROA, IN_STOC, ID_GESTIUNE, SURSA_CONT, IN_STOC_SUGERAT),
*!* pozitionat pe primul rand, sau fara randuri daca factura nu are linii. tnIdPart (optional):
*!* id_part ROA al furnizorului/clientului, pentru cautarea in codurile lui de articol
*!* (parteneri_articole_coduri) - fara el, acea sursa a catalogului nu propune nimic.
*!* Intoarce .T./.F. (goExecutor.cEroare)
Procedure PotrivesteFactura
Lparameters tnIdEfactura, tcCodFiscal, tlPrimite, tnIdPart
Local lcSql, lnSucces, lcColoanaCodFiscal, lcCheieColD, llNormalizat, lcX5, lcIst, lcFereastra
Local lcCat, lcS2, lcS1, lcEmisa, lcCodMatCol, lcCodMatFCol, lcCodMatPCol, lcCheieColDl, lcCheieColDFw
Local lcColPartener, lcColCredit, lcCod401, lcColDebit
Private pcCodFiscal, pnIdEfactura, pnIdPart
pcCodFiscal = Upper(Alltrim(Nvl(m.tcCodFiscal, '')))
pnIdEfactura = Iif(!Empty(Nvl(m.tnIdEfactura, 0)), m.tnIdEfactura, 0)
pnIdPart = Nvl(m.tnIdPart, 0)
lcColoanaCodFiscal = Iif(m.tlPrimite, "e.cod_fiscal_emitent", "e.cod_fiscal_beneficiar")
llNormalizat = (This.nNormalizat # 0)
lcCheieColD = This.CheieSql('articol')
*!* a_no pe linia curenta - NULL cand comutatorul e oprit, ca LENGTH(dl.a_no)>=3 sa dezactiveze
*!* singur x3/x4/fw (aceeasi garda folosita deja pentru cheia scurta)
lcCheieColDl = Iif(m.llNormalizat, m.lcCheieColD, "NULL")
*!* varianta calificata cu alias "d." - fw0 are si dl si d in FROM, ambele cu coloana articol
lcCheieColDFw = This.CheieSql('d.articol')
lcFereastra = This.FereastraIstoricSql('e.xdata_act')
lcEmisa = Iif(m.tlPrimite, '0', '1')
*!* codclient/codfurnizor pe linie, dupa acelasi tipar ca GetArticolByCodDenumire
*!* (oproceduri_comune.prg): primite = codClient pe codmat, codFurnizor pe codmatf;
*!* emise = codFurnizor pe codmat, codClient pe codul de partener
lcCodMatCol = Iif(m.tlPrimite, "dl.codclient", "dl.codfurnizor")
lcCodMatFCol = Iif(m.tlPrimite, "dl.codfurnizor", "CAST(NULL AS VARCHAR2(100))")
lcCodMatPCol = Iif(m.tlPrimite, "CAST(NULL AS VARCHAR2(100))", "dl.codclient")
*!* ACT: contul de furnizor/client (401/4111) identifica documentul, celalalt cont se agrega
lcColPartener = Iif(m.tlPrimite, "a.id_partc", "a.id_partd")
lcColCredit = Iif(m.tlPrimite, "a.scc", "a.scd")
lcCod401 = Iif(m.tlPrimite, "'401'", "'4111'")
lcColDebit = Iif(m.tlPrimite, "a.scd", "a.scc")
Text To lcIst Textmerge Noshow
ist AS (SELECT /*+ MATERIALIZE */ d.*, TRIM(UPPER(d.articol)) a_ex, <<m.lcCheieColD>> a_no
FROM ANAF_VEFACTURA_DETALII d JOIN ANAF_EFACTURA e ON (e.id = d.id_efactura)
WHERE <<m.lcColoanaCodFiscal>> = ?pcCodFiscal AND e.id <> ?pnIdEfactura AND <<m.lcFereastra>>),
ist2 AS (SELECT /*+ MATERIALIZE */ ist.*,
ROW_NUMBER() OVER (PARTITION BY a_ex ORDER BY id DESC) rn_ex,
ROW_NUMBER() OVER (PARTITION BY CASE WHEN id_articol IS NOT NULL THEN a_ex END ORDER BY id DESC) rn_ex_art,
ROW_NUMBER() OVER (PARTITION BY a_no ORDER BY id DESC) rn_no,
ROW_NUMBER() OVER (PARTITION BY CASE WHEN id_articol IS NOT NULL THEN a_no END ORDER BY id DESC) rn_no_art
FROM ist),
Endtext
If This.nIstoric # 0
Text To lcX5 Textmerge Noshow
x5c AS (SELECT cont FROM (SELECT cont FROM (SELECT TRIM(cont) cont FROM ist
WHERE cont IS NOT NULL AND TRIM(cont) IS NOT NULL
ORDER BY id DESC) WHERE ROWNUM <= 5) GROUP BY cont HAVING COUNT(*) = 5),
Endtext
Else
lcX5 = "x5c AS (SELECT NULL cont FROM DUAL WHERE 1 = 0),"
Endif
*!* Catalogul ROA (azi GetArticolByCodDenumire, o interogare per linie): cinci candidati
*!* egalitate, in ordinea denumire/codbare/codmat/codmatf/cod partener, alegere determinista
*!* (id_articol maxim) - inlocuieste OR-ul cu ROWNUM=1 arbitrar de azi. NOM_ARTICOLE direct
*!* (nu vnom_articole), catalogul intreg fiind ieftin de scanat si fara nevoie de coloanele lui
*!* in plus (grupa, tara origine, timp productie).
Text To lcCat Textmerge Noshow
catk AS (SELECT id_articol, denumire, codbare, codmat, codmatf, cont, acont, in_stoc,
ROW_NUMBER() OVER (PARTITION BY UPPER(denumire) ORDER BY id_articol DESC) rn_den,
ROW_NUMBER() OVER (PARTITION BY UPPER(codbare) ORDER BY id_articol DESC) rn_bare,
ROW_NUMBER() OVER (PARTITION BY UPPER(codmat) ORDER BY id_articol DESC) rn_mat,
ROW_NUMBER() OVER (PARTITION BY UPPER(codmatf) ORDER BY id_articol DESC) rn_matf
FROM NOM_ARTICOLE WHERE sters = 0 AND inactiv = 0),
catp AS (SELECT c.cod, a.id_articol, a.denumire, a.codmat, a.cont, a.acont, a.in_stoc,
ROW_NUMBER() OVER (PARTITION BY UPPER(c.cod) ORDER BY a.id_articol DESC) rn_p
FROM PARTENERI_ARTICOLE_CODURI c JOIN NOM_ARTICOLE a ON (a.id_part = c.id_part AND a.sters = 0 AND a.inactiv = 0)
WHERE c.id_part = ?pnIdPart AND c.sters = 0),
cat AS (SELECT dl.nr,
COALESCE(a1.id_articol, a2.id_articol, a3.id_articol, a4.id_articol, a5.id_articol) id_articol,
COALESCE(a1.denumire, a2.denumire, a3.denumire, a4.denumire, a5.denumire) articol_roa,
COALESCE(a1.codmat, a2.codmat, a3.codmat, a4.codmat, a5.codmat) codmat_roa,
COALESCE(a1.cont, a2.cont, a3.cont, a4.cont, a5.cont) cont,
COALESCE(a1.acont, a2.acont, a3.acont, a4.acont, a5.acont) acont,
COALESCE(a1.in_stoc, a2.in_stoc, a3.in_stoc, a4.in_stoc, a5.in_stoc) in_stoc
FROM dl
LEFT JOIN catk a1 ON (a1.rn_den = 1 AND UPPER(a1.denumire) = NULLIF(TRIM(UPPER(dl.articol)),''))
LEFT JOIN catk a2 ON (a2.rn_bare = 1 AND UPPER(a2.codbare) = NULLIF(TRIM(UPPER(dl.codbare)),''))
LEFT JOIN catk a3 ON (a3.rn_mat = 1 AND UPPER(a3.codmat) = NULLIF(TRIM(UPPER(<<m.lcCodMatCol>>)),''))
LEFT JOIN catk a4 ON (a4.rn_matf = 1 AND UPPER(a4.codmatf) = NULLIF(TRIM(UPPER(<<m.lcCodMatFCol>>)),''))
LEFT JOIN catp a5 ON (a5.rn_p = 1 AND UPPER(a5.cod) = NULLIF(TRIM(UPPER(<<m.lcCodMatPCol>>)),''))
),
Endtext
*!* Articolul contat oriunde in firma (ARTICOL): ultima linie, indiferent de furnizor, cu
*!* aceeasi cheie normalizata ca linia curenta, in aceeasi directie. Corelata pe cheile
*!* facturii curente (JOIN pe expresia indexului functional), nu materializata pe toata firma -
*!* ROWNUM=1 pe fereastra "ultima factura" e deja un singur candidat, garda de dominanta 70%
*!* nu are ce sa mai filtreze aici.
If m.llNormalizat
Text To lcS2 Textmerge Noshow
fw0 AS (SELECT /*+ USE_NL(d) INDEX(d IDX_EFACT_DET_ARTNORM) */ dl.nr, d.cont, d.acont, d.id_articol,
na.denumire articol_roa, na.codmat codmat_roa, na.in_stoc,
ROW_NUMBER() OVER (PARTITION BY dl.nr ORDER BY e.xdata_act DESC, d.id DESC) rn_fw
FROM dl
JOIN ANAF_EFACTURA_DETALII d ON (<<m.lcCheieColDFw>> = dl.a_no)
JOIN ANAF_EFACTURA e ON (e.id = d.id_efactura AND NVL(e.factura_emisa,0) = <<m.lcEmisa>>
AND e.id <> ?pnIdEfactura AND <<m.lcFereastra>>)
LEFT JOIN NOM_ARTICOLE na ON (na.id_articol = d.id_articol)
WHERE LENGTH(dl.a_no) >= 3 AND d.cont IS NOT NULL AND TRIM(d.cont) IS NOT NULL),
fw AS (SELECT nr, cont, acont, id_articol, articol_roa, codmat_roa, in_stoc FROM fw0 WHERE rn_fw = 1),
Endtext
Else
lcS2 = "fw AS (SELECT NULL nr, NULL cont, NULL acont, NULL id_articol, NULL articol_roa, NULL codmat_roa, NULL in_stoc FROM DUAL WHERE 1 = 0),"
Endif
*!* Contul sintetic dominant al furnizorului (FURNIZOR): ultimele 3 documente in care apare
*!* creditat pe 401/4111, majoritar 90% peste liniile lor de debit (exclus 442). Cautat o
*!* singura data per factura (toate liniile au acelasi furnizor), prin IDX_PARTC/IDX_PARTD -
*!* partenerul se rezolva intai separat (s1part), REGEXP_REPLACE nu intra in join-ul cu ACT.
Text To lcS1 Textmerge Noshow
efact AS (SELECT xdata_act FROM ANAF_EFACTURA WHERE id = ?pnIdEfactura),
s1part AS (SELECT id_part FROM NOM_PARTENERI
WHERE NVL(sters,0) = 0 AND REGEXP_REPLACE(UPPER(cod_fiscal),'[^0-9]','') = REGEXP_REPLACE(?pcCodFiscal,'[^0-9]','')),
s1doc AS (SELECT cod FROM (SELECT a.cod, MIN(a.dataact) d
FROM ACT a JOIN s1part p ON p.id_part = <<m.lcColPartener>>
WHERE NVL(a.sters,0) = 0 AND SUBSTR(<<m.lcColCredit>>,1,3) = <<m.lcCod401>>
AND a.dataact < (SELECT xdata_act FROM efact)
GROUP BY a.cod ORDER BY MIN(a.dataact) DESC) WHERE ROWNUM <= 3),
s1line AS (SELECT TRIM(<<m.lcColDebit>>) c FROM ACT a JOIN s1doc s ON s.cod = a.cod
WHERE NVL(a.sters,0) = 0 AND <<m.lcColDebit>> IS NOT NULL AND TRIM(<<m.lcColDebit>>) IS NOT NULL
AND SUBSTR(<<m.lcColDebit>>,1,3) <> '442'),
s1agg AS (SELECT c, COUNT(*) cnt, SUM(COUNT(*)) OVER () tot FROM s1line GROUP BY c),
s1top AS (SELECT c s1_cont FROM
(SELECT c, cnt FROM (SELECT c, cnt FROM s1agg ORDER BY cnt DESC, c) WHERE ROWNUM = 1) t,
(SELECT tot FROM s1agg WHERE ROWNUM = 1) tt
WHERE t.cnt/tt.tot >= 0.9),
Endtext
*!* pre: rezultatul S0+catalog+S2+S1 per linie. id_gestiune ramane a aceluiasi rand cu
*!* id_articol (nu se amesteca daca vine din catalog). S3 (contul majoritar al facturii) se
*!* calculeaza o singura data pe rezultatul de aici (s3syn/s3full), nu per linie ramasa goala.
Text To lcSql Textmerge Noshow
WITH <<m.lcIst>>
<<m.lcX5>>
dl AS (SELECT dd.*, TRIM(UPPER(dd.articol)) a_ex, <<m.lcCheieColDl>> a_no FROM ANAF_VEFACTURA_DETALII dd WHERE dd.id_efactura = ?pnIdEfactura),
<<m.lcCat>>
<<m.lcS2>>
<<m.lcS1>>
pre AS (SELECT dl.nr, dl.id id_detaliu,
NVL(cat.cont, NVL(x1.cont, NVL(x2.cont, NVL(x3.cont, NVL(x4.cont, NVL(x5.cont, NVL(x6.cont, s1top.s1_cont))))))) cont_full,
NVL(cat.acont, NVL(x1.acont, NVL(x2.acont, NVL(x3.acont, NVL(x4.acont, x6.acont))))) acont,
NVL(cat.id_articol, NVL(x1.id_articol, NVL(x3.id_articol, x6.id_articol))) id_articol,
NVL(cat.articol_roa, NVL(x1.articol_roa, NVL(x3.articol_roa, x6.articol_roa))) articol_roa,
NVL(cat.codmat_roa, NVL(x1.codmat_roa, NVL(x3.codmat_roa, x6.codmat_roa))) codmat_roa,
NVL(cat.in_stoc, NVL(x1.in_stoc, NVL(x3.in_stoc, x6.in_stoc))) in_stoc,
CASE WHEN cat.id_articol IS NOT NULL THEN NULL
WHEN x1.id_articol IS NOT NULL THEN x1.id_gestiune
WHEN x3.id_articol IS NOT NULL THEN x3.id_gestiune END id_gestiune,
CASE WHEN cat.cont IS NOT NULL THEN 'CATALOG'
WHEN x1.cont IS NOT NULL OR x2.cont IS NOT NULL THEN 'EXACT'
WHEN x3.cont IS NOT NULL OR x4.cont IS NOT NULL THEN 'APROX'
WHEN x5.cont IS NOT NULL THEN 'ISTORIC'
WHEN x6.cont IS NOT NULL THEN 'ARTICOL'
WHEN s1top.s1_cont IS NOT NULL THEN 'FURNIZOR' END sursa_cont
FROM dl
LEFT JOIN ist2 x1 ON (x1.a_ex = dl.a_ex AND x1.id_articol IS NOT NULL AND x1.rn_ex_art = 1)
LEFT JOIN ist2 x2 ON (x2.a_ex = dl.a_ex AND x2.rn_ex = 1)
LEFT JOIN ist2 x3 ON (LENGTH(dl.a_no) >= 3 AND x3.a_no = dl.a_no AND x3.id_articol IS NOT NULL AND x3.rn_no_art = 1)
LEFT JOIN ist2 x4 ON (LENGTH(dl.a_no) >= 3 AND x4.a_no = dl.a_no AND x4.rn_no = 1)
LEFT JOIN x5c x5 ON (1 = 1)
LEFT JOIN fw x6 ON (x6.nr = dl.nr)
LEFT JOIN cat ON (cat.nr = dl.nr)
LEFT JOIN s1top ON (1 = 1)
),
s3syn AS (SELECT syn FROM (SELECT SUBSTR(cont_full,1,3) syn, COUNT(*) cnt FROM pre WHERE cont_full IS NOT NULL
GROUP BY SUBSTR(cont_full,1,3) ORDER BY COUNT(*) DESC, SUBSTR(cont_full,1,3)) WHERE ROWNUM = 1),
s3full AS (SELECT cont_full FROM (SELECT o.cont_full, COUNT(*) cnt FROM pre o, s3syn s
WHERE SUBSTR(o.cont_full,1,3) = s.syn GROUP BY o.cont_full ORDER BY COUNT(*) DESC, o.cont_full) WHERE ROWNUM = 1)
SELECT p.nr, p.id_detaliu,
NVL(p.cont_full, s3.cont_full) AS cont,
CASE WHEN p.cont_full IS NOT NULL THEN p.acont END AS acont,
p.id_articol, p.articol_roa, p.codmat_roa, p.in_stoc, p.id_gestiune,
CASE WHEN p.cont_full IS NOT NULL THEN p.sursa_cont
WHEN s3.cont_full IS NOT NULL THEN 'FACTURA' END AS sursa_cont,
CAST(NULL AS NUMBER(1)) AS in_stoc_sugerat
FROM pre p
LEFT JOIN s3full s3 ON (1 = 1)
ORDER BY p.nr
Endtext
lnSucces = goExecutor.oExecute(m.lcSql, 'crsPotrivireLinii')
If m.lnSucces >= 0
This.SugereazaInStoc(m.tlPrimite)
Endif
Return (m.lnSucces >= 0)
Endproc && PotrivesteFactura
*!* Sirul de ID-uri (virgula) din campul id al cursorului de facturi, pentru clauza IN a
*!* interogarii de lot. Nu repozitioneaza cursorul
*!* ponytail: fara chunking, plafon Oracle IN ~1000 - de spart pe loturi daca lista afisata creste peste atat
Procedure ListaIdFacturi
Lparameters tcAliasFacturi
Local lcSelect, lcLista, lnRecno
lcSelect = Select()
Select (m.tcAliasFacturi)
lnRecno = Recno()
lcLista = ''
Scan
lcLista = m.lcLista + Iif(Empty(m.lcLista), '', ',') + Transform(Nvl(id, 0))
Endscan
Try
Go m.lnRecno
Catch
Go Top
Endtry
Select (m.lcSelect)
Return m.lcLista
Endproc && ListaIdFacturi
*!* Varianta pe lista intreaga a cascadei din PotrivesteFactura, o singura interogare Oracle
*!* pentru toate facturile din tcAliasFacturi (campul id). Lasa deschis CRSLIPSURILISTA, indexat
*!* pe id_efactura, un rand per factura cu macar o linie de detaliu: ID_EFACTURA, LINII,
*!* FARA_CONT_CATALOG (linii ramase fara cont daca s-ar aplica doar sursa CATALOG),
*!* FARA_CONT_ORICE (linii ramase fara cont cu toata cascada), STOC_FARA_GESTIUNE (linii
*!* stocabile fara gestiune propusa de cascada, inclusiv in_stoc_sugerat din cTipArticoleP/E),
*!* FARA_ANALITIC (linii cu cont care cere analitic in vplcont_ANALITIC pe gnAn si acont gol).
*!* Intoarce .T./.F.; la esec Oracle nu arunca dialog (ruleaza si in lot)
Procedure LipsuriLista
Lparameters tcAliasFacturi, tlPrimite
Local lcSql, lnSucces, lcIdList, lcColFiscalCol, lcCheieColD, llNormalizat, lcX5, lcIst, lcFereastra
Local lcCat, lcS2, lcS1, lcEmisa, lcCodMatCol, lcCodMatFCol, lcCodMatPCol, lcCheieColDl, lcCheieColDFw
Local lcColPartener, lcColCredit, lcCod401, lcColDebit, lcSelect, lcTabelTip, lcContIst
If !Used(m.tcAliasFacturi)
Return .F.
Endif
lcSelect = Select()
lcIdList = This.ListaIdFacturi(m.tcAliasFacturi)
If Used('crsLipsuriLista')
Use In (Select('crsLipsuriLista'))
Endif
If Empty(m.lcIdList)
Create Cursor crsLipsuriLista (id_efactura N(20), linii N(6), fara_cont_catalog N(6), ;
fara_cont_orice N(6), stoc_fara_gestiune N(6), stoc_total N(6), n_istoric N(6), x5_cont C(20), fara_analitic N(6))
Index On id_efactura Tag idefact
Select (m.lcSelect)
Return .T.
Endif
llNormalizat = (This.nNormalizat # 0)
lcColFiscalCol = Iif(m.tlPrimite, "cod_fiscal_emitent", "cod_fiscal_beneficiar")
lcCheieColD = This.CheieSql('articol')
lcCheieColDl = Iif(m.llNormalizat, m.lcCheieColD, "NULL")
lcCheieColDFw = This.CheieSql('d.articol')
lcFereastra = This.FereastraIstoricSql('e.xdata_act')
lcEmisa = Iif(m.tlPrimite, '0', '1')
lcCodMatCol = Iif(m.tlPrimite, "dl.codclient", "dl.codfurnizor")
lcCodMatFCol = Iif(m.tlPrimite, "dl.codfurnizor", "CAST(NULL AS VARCHAR2(100))")
lcCodMatPCol = Iif(m.tlPrimite, "CAST(NULL AS VARCHAR2(100))", "dl.codclient")
lcColPartener = Iif(m.tlPrimite, "a.id_partc", "a.id_partd")
lcColCredit = Iif(m.tlPrimite, "a.scc", "a.scd")
lcCod401 = Iif(m.tlPrimite, "'401'", "'4111'")
lcColDebit = Iif(m.tlPrimite, "a.scd", "a.scc")
Text To lcIst Textmerge Noshow
lst AS (SELECT id, <<m.lcColFiscalCol>> AS cod_fiscal, xdata_act FROM ANAF_EFACTURA WHERE id IN (<<m.lcIdList>>)),
lstpart AS (SELECT lst_id, MIN(id_part) id_part FROM (
SELECT l.id lst_id, p.id_part FROM lst l JOIN NOM_PARTENERI p
ON (NVL(p.sters,0)=0 AND REGEXP_REPLACE(UPPER(p.cod_fiscal),'[^0-9]','') = REGEXP_REPLACE(l.cod_fiscal,'[^0-9]',''))
) GROUP BY lst_id),
dl AS (SELECT dd.*, TRIM(UPPER(dd.articol)) a_ex, <<m.lcCheieColDl>> a_no
FROM ANAF_VEFACTURA_DETALII dd WHERE dd.id_efactura IN (SELECT id FROM lst)),
ist AS (SELECT /*+ MATERIALIZE */ d.*, TRIM(UPPER(d.articol)) a_ex, <<m.lcCheieColD>> a_no, e.<<m.lcColFiscalCol>> lst_cod_fiscal
FROM ANAF_VEFACTURA_DETALII d JOIN ANAF_EFACTURA e ON (e.id = d.id_efactura)
WHERE e.<<m.lcColFiscalCol>> IN (SELECT DISTINCT cod_fiscal FROM lst) AND <<m.lcFereastra>>),
x1raw AS (SELECT dl.id id_detaliu, i.cont, i.acont, i.id_articol, i.id_gestiune, i.in_stoc,
ROW_NUMBER() OVER (PARTITION BY dl.id ORDER BY i.id DESC) rnk
FROM dl JOIN lst l ON (l.id = dl.id_efactura) JOIN ist i ON (i.lst_cod_fiscal = l.cod_fiscal AND i.a_ex = dl.a_ex
AND i.id_articol IS NOT NULL AND i.id_efactura <> dl.id_efactura)),
x1 AS (SELECT * FROM x1raw WHERE rnk = 1),
x2raw AS (SELECT dl.id id_detaliu, i.cont, i.acont,
ROW_NUMBER() OVER (PARTITION BY dl.id ORDER BY i.id DESC) rnk
FROM dl JOIN lst l ON (l.id = dl.id_efactura) JOIN ist i ON (i.lst_cod_fiscal = l.cod_fiscal AND i.a_ex = dl.a_ex
AND i.id_efactura <> dl.id_efactura)),
x2 AS (SELECT * FROM x2raw WHERE rnk = 1),
x3raw AS (SELECT dl.id id_detaliu, i.cont, i.acont, i.id_articol, i.id_gestiune, i.in_stoc,
ROW_NUMBER() OVER (PARTITION BY dl.id ORDER BY i.id DESC) rnk
FROM dl JOIN lst l ON (l.id = dl.id_efactura) JOIN ist i ON (i.lst_cod_fiscal = l.cod_fiscal AND LENGTH(dl.a_no) >= 3
AND i.a_no = dl.a_no AND i.id_articol IS NOT NULL AND i.id_efactura <> dl.id_efactura)),
x3 AS (SELECT * FROM x3raw WHERE rnk = 1),
x4raw AS (SELECT dl.id id_detaliu, i.cont, i.acont,
ROW_NUMBER() OVER (PARTITION BY dl.id ORDER BY i.id DESC) rnk
FROM dl JOIN lst l ON (l.id = dl.id_efactura) JOIN ist i ON (i.lst_cod_fiscal = l.cod_fiscal AND LENGTH(dl.a_no) >= 3
AND i.a_no = dl.a_no AND i.id_efactura <> dl.id_efactura)),
x4 AS (SELECT * FROM x4raw WHERE rnk = 1),
Endtext
If This.nIstoric # 0
Text To lcX5 Textmerge Noshow
x5rank AS (SELECT l.id lst_id, i.cont,
ROW_NUMBER() OVER (PARTITION BY l.id ORDER BY i.id DESC) rn
FROM lst l JOIN ist i ON (i.lst_cod_fiscal = l.cod_fiscal AND i.id_efactura <> l.id
AND i.cont IS NOT NULL AND TRIM(i.cont) IS NOT NULL)),
x5top5 AS (SELECT lst_id, TRIM(cont) cont FROM x5rank WHERE rn <= 5),
x5c AS (SELECT lst_id, cont FROM x5top5 GROUP BY lst_id, cont HAVING COUNT(*) = 5),
Endtext
Else
lcX5 = "x5c AS (SELECT NULL lst_id, NULL cont FROM DUAL WHERE 1 = 0),"
Endif
Text To lcCat Textmerge Noshow
catk AS (SELECT id_articol, denumire, codbare, codmat, codmatf, cont, acont, in_stoc,
ROW_NUMBER() OVER (PARTITION BY UPPER(denumire) ORDER BY id_articol DESC) rn_den,
ROW_NUMBER() OVER (PARTITION BY UPPER(codbare) ORDER BY id_articol DESC) rn_bare,
ROW_NUMBER() OVER (PARTITION BY UPPER(codmat) ORDER BY id_articol DESC) rn_mat,
ROW_NUMBER() OVER (PARTITION BY UPPER(codmatf) ORDER BY id_articol DESC) rn_matf
FROM NOM_ARTICOLE WHERE sters = 0 AND inactiv = 0),
catp AS (SELECT lp.lst_id, c.cod, a.id_articol, a.denumire, a.codmat, a.cont, a.acont, a.in_stoc,
ROW_NUMBER() OVER (PARTITION BY lp.lst_id, UPPER(c.cod) ORDER BY a.id_articol DESC) rn_p
FROM lstpart lp JOIN PARTENERI_ARTICOLE_CODURI c ON (c.id_part = lp.id_part AND c.sters = 0)
JOIN NOM_ARTICOLE a ON (a.id_part = c.id_part AND a.sters = 0 AND a.inactiv = 0)),
cat AS (SELECT dl.id id_detaliu,
COALESCE(a1.id_articol, a2.id_articol, a3.id_articol, a4.id_articol, a5.id_articol) id_articol,
COALESCE(a1.cont, a2.cont, a3.cont, a4.cont, a5.cont) cont,
COALESCE(a1.acont, a2.acont, a3.acont, a4.acont, a5.acont) acont,
COALESCE(a1.in_stoc, a2.in_stoc, a3.in_stoc, a4.in_stoc, a5.in_stoc) in_stoc
FROM dl
LEFT JOIN catk a1 ON (a1.rn_den = 1 AND UPPER(a1.denumire) = NULLIF(TRIM(UPPER(dl.articol)),''))
LEFT JOIN catk a2 ON (a2.rn_bare = 1 AND UPPER(a2.codbare) = NULLIF(TRIM(UPPER(dl.codbare)),''))
LEFT JOIN catk a3 ON (a3.rn_mat = 1 AND UPPER(a3.codmat) = NULLIF(TRIM(UPPER(<<m.lcCodMatCol>>)),''))
LEFT JOIN catk a4 ON (a4.rn_matf = 1 AND UPPER(a4.codmatf) = NULLIF(TRIM(UPPER(<<m.lcCodMatFCol>>)),''))
LEFT JOIN catp a5 ON (a5.lst_id = dl.id_efactura AND a5.rn_p = 1 AND UPPER(a5.cod) = NULLIF(TRIM(UPPER(<<m.lcCodMatPCol>>)),''))
),
Endtext
If m.llNormalizat
Text To lcS2 Textmerge Noshow
fw0 AS (SELECT /*+ USE_NL(d) INDEX(d IDX_EFACT_DET_ARTNORM) */ dl.id id_detaliu, d.cont, d.acont, d.id_articol, na.in_stoc,
ROW_NUMBER() OVER (PARTITION BY dl.id ORDER BY e.xdata_act DESC, d.id DESC) rn_fw
FROM dl
JOIN ANAF_EFACTURA_DETALII d ON (<<m.lcCheieColDFw>> = dl.a_no)
JOIN ANAF_EFACTURA e ON (e.id = d.id_efactura AND NVL(e.factura_emisa,0) = <<m.lcEmisa>>
AND e.id <> dl.id_efactura AND <<m.lcFereastra>>)
LEFT JOIN NOM_ARTICOLE na ON (na.id_articol = d.id_articol)
WHERE LENGTH(dl.a_no) >= 3 AND d.cont IS NOT NULL AND TRIM(d.cont) IS NOT NULL),
fw AS (SELECT id_detaliu, cont, acont, id_articol, in_stoc FROM fw0 WHERE rn_fw = 1),
Endtext
Else
lcS2 = "fw AS (SELECT NULL id_detaliu, NULL cont, NULL acont, NULL id_articol, NULL in_stoc FROM DUAL WHERE 1 = 0),"
Endif
Text To lcS1 Textmerge Noshow
efact AS (SELECT id lst_id, xdata_act, cod_fiscal FROM lst),
s1doc AS (SELECT lst_id, cod FROM (
SELECT ef.lst_id, a.cod, MIN(a.dataact) d,
ROW_NUMBER() OVER (PARTITION BY ef.lst_id ORDER BY MIN(a.dataact) DESC) rn3
FROM efact ef JOIN lstpart lp ON lp.lst_id = ef.lst_id
JOIN ACT a ON (<<m.lcColPartener>> = lp.id_part AND NVL(a.sters,0)=0 AND SUBSTR(<<m.lcColCredit>>,1,3)=<<m.lcCod401>>
AND a.dataact < ef.xdata_act)
GROUP BY ef.lst_id, a.cod
) WHERE rn3 <= 3),
s1line AS (SELECT s.lst_id, TRIM(<<m.lcColDebit>>) c FROM ACT a JOIN s1doc s ON s.cod = a.cod
WHERE NVL(a.sters,0)=0 AND <<m.lcColDebit>> IS NOT NULL AND TRIM(<<m.lcColDebit>>) IS NOT NULL AND SUBSTR(<<m.lcColDebit>>,1,3) <> '442'),
s1agg AS (SELECT lst_id, c, COUNT(*) cnt FROM s1line GROUP BY lst_id, c),
s1tot AS (SELECT lst_id, SUM(cnt) tot FROM s1agg GROUP BY lst_id),
s1top AS (SELECT a.lst_id, a.c s1_cont FROM (
SELECT lst_id, c, cnt, ROW_NUMBER() OVER (PARTITION BY lst_id ORDER BY cnt DESC, c) rnk
FROM s1agg) a JOIN s1tot t ON t.lst_id = a.lst_id
WHERE a.rnk = 1 AND a.cnt/t.tot >= 0.9),
Endtext
Text To lcSql Textmerge Noshow
WITH <<m.lcIst>>
<<m.lcX5>>
<<m.lcCat>>
<<m.lcS2>>
<<m.lcS1>>
pre AS (SELECT dl.id id_detaliu, dl.id_efactura, dl.cont dl_cont,
NVL(dl.cont, NVL(cat.cont, NVL(x1.cont, NVL(x2.cont, NVL(x3.cont, NVL(x4.cont, NVL(x5.cont, NVL(x6.cont, s1top.s1_cont)))))))) cont_full,
NVL(dl.acont, NVL(cat.acont, NVL(x1.acont, NVL(x2.acont, NVL(x3.acont, NVL(x4.acont, x6.acont)))))) acont,
NVL(dl.in_stoc, NVL(cat.in_stoc, NVL(x1.in_stoc, NVL(x3.in_stoc, x6.in_stoc)))) in_stoc,
NVL(dl.id_gestiune, CASE WHEN cat.id_articol IS NOT NULL THEN NULL
WHEN x1.id_articol IS NOT NULL THEN x1.id_gestiune
WHEN x3.id_articol IS NOT NULL THEN x3.id_gestiune END) id_gestiune,
CASE WHEN cat.cont IS NOT NULL THEN 'CATALOG'
WHEN x1.cont IS NOT NULL OR x2.cont IS NOT NULL THEN 'EXACT'
WHEN x3.cont IS NOT NULL OR x4.cont IS NOT NULL THEN 'APROX'
WHEN x5.cont IS NOT NULL THEN 'ISTORIC'
WHEN x6.cont IS NOT NULL THEN 'ARTICOL'
WHEN s1top.s1_cont IS NOT NULL THEN 'FURNIZOR' END sursa_cont,
x5.cont x5_cont
FROM dl
LEFT JOIN x1 ON (x1.id_detaliu = dl.id)
LEFT JOIN x2 ON (x2.id_detaliu = dl.id)
LEFT JOIN x3 ON (x3.id_detaliu = dl.id)
LEFT JOIN x4 ON (x4.id_detaliu = dl.id)
LEFT JOIN x5c x5 ON (x5.lst_id = dl.id_efactura)
LEFT JOIN fw x6 ON (x6.id_detaliu = dl.id)
LEFT JOIN cat ON (cat.id_detaliu = dl.id)
LEFT JOIN s1top ON (s1top.lst_id = dl.id_efactura)
),
s3synraw AS (SELECT id_efactura, SUBSTR(cont_full,1,3) syn, COUNT(*) cnt
FROM pre WHERE cont_full IS NOT NULL GROUP BY id_efactura, SUBSTR(cont_full,1,3)),
s3syn AS (SELECT id_efactura, syn FROM (
SELECT id_efactura, syn, ROW_NUMBER() OVER (PARTITION BY id_efactura ORDER BY cnt DESC, syn) rnk
FROM s3synraw) WHERE rnk = 1),
s3fullraw AS (SELECT o.id_efactura, o.cont_full, COUNT(*) cnt
FROM pre o JOIN s3syn s ON (s.id_efactura = o.id_efactura AND SUBSTR(o.cont_full,1,3) = s.syn)
GROUP BY o.id_efactura, o.cont_full),
s3full AS (SELECT id_efactura, cont_full FROM (
SELECT id_efactura, cont_full, ROW_NUMBER() OVER (PARTITION BY id_efactura ORDER BY cnt DESC, cont_full) rnk
FROM s3fullraw) WHERE rnk = 1),
final_pre AS (SELECT p.id_efactura,
NVL(p.cont_full, s3.cont_full) AS cont,
CASE WHEN p.cont_full IS NOT NULL THEN p.acont END AS acont,
NVL(p.in_stoc,0) in_stoc, p.id_gestiune, p.sursa_cont, p.x5_cont,
CASE WHEN p.dl_cont IS NOT NULL THEN 0
WHEN p.sursa_cont IS NULL OR p.sursa_cont <> 'CATALOG' THEN 1 ELSE 0 END fara_catalog
FROM pre p
LEFT JOIN s3full s3 ON (s3.id_efactura = p.id_efactura)
)
SELECT fp.id_efactura,
COUNT(*) linii,
SUM(fp.fara_catalog) fara_cont_catalog,
SUM(CASE WHEN fp.cont IS NULL THEN 1 ELSE 0 END) fara_cont_orice,
SUM(CASE WHEN fp.in_stoc = 1 AND fp.id_gestiune IS NULL THEN 1 ELSE 0 END) stoc_fara_gestiune,
SUM(CASE WHEN fp.in_stoc = 1 THEN 1 ELSE 0 END) stoc_total,
SUM(CASE WHEN fp.sursa_cont = 'ISTORIC' THEN 1 ELSE 0 END) n_istoric,
SUM(CASE WHEN fp.acont IS NULL AND EXISTS (SELECT 1 FROM vplcont_ANALITIC va
WHERE va.cont = fp.cont AND va.inactiv = 0 AND va.an = ?gnAn) THEN 1 ELSE 0 END) fara_analitic,
MAX(fp.x5_cont) x5_cont
FROM final_pre fp
GROUP BY fp.id_efactura
Endtext
lnSucces = goExecutor.oExecute(m.lcSql, 'crsLipsuriLista')
If m.lnSucces < 0
Select (m.lcSelect)
Return .F.
Endif
Select crsLipsuriLista
Index On id_efactura Tag idefact
*!* corectie in_stoc_sugerat: liniile propuse DOAR de treapta ISTORIC (fara id_articol, deci
*!* fara in_stoc/id_gestiune din cascada) - daca x5_cont e in cTipArticoleP/E cu in_stoc=1,
*!* se aduna n_istoric la stoc_fara_gestiune si stoc_total (acelasi cont pentru toata factura)
lcTabelTip = Iif(m.tlPrimite, 'cTipArticoleP', 'cTipArticoleE')
If Used(m.lcTabelTip)
Select crsLipsuriLista
Scan For n_istoric > 0 And !Empty(Nvl(x5_cont, ''))
lcContIst = Alltrim(x5_cont)
Select (m.lcTabelTip)
Locate For Alltrim(cont) = m.lcContIst
If Found() And in_stoc = 1
Select crsLipsuriLista
Replace stoc_fara_gestiune With stoc_fara_gestiune + n_istoric, ;
stoc_total With stoc_total + n_istoric
Endif
Select crsLipsuriLista
Endscan
Go Top
Endif
Select (m.lcSelect)
Return .T.
Endproc && LipsuriLista
*!* Completeaza IN_STOC_SUGERAT pe crsPotrivireLinii, doar pentru liniile propuse de treapta
*!* ISTORIC (fara id_articol), din cursorul cTipArticoleP/cTipArticoleE (cont -> in_stoc,
*!* import_efactura.prg:88-132). Nu deduce nimic daca acel cursor nu e deschis in contextul
*!* apelantei - propunerea ramane goala, nu o duplica
Procedure SugereazaInStoc
Lparameters tlPrimite
Local lcTabelTip, lcCont
lcTabelTip = Iif(m.tlPrimite, 'cTipArticoleP', 'cTipArticoleE')
If !Used('crsPotrivireLinii') Or !Used(m.lcTabelTip)
Return
Endif
Select crsPotrivireLinii
Scan For Upper(Alltrim(Nvl(sursa_cont, ''))) = 'ISTORIC' And !Empty(Nvl(cont, ''))
lcCont = Alltrim(cont)
Select (m.lcTabelTip)
Locate For Alltrim(cont) = m.lcCont
If Found()
Select crsPotrivireLinii
Replace in_stoc_sugerat With Evaluate(m.lcTabelTip + '.in_stoc')
Endif
Endscan
Select crsPotrivireLinii
Go Top
Endproc && SugereazaInStoc
Enddefine

View File

@@ -0,0 +1,151 @@
* rezolvare_partener_ef.prg
*!* 07.09.2026
*!* marius.mutu
*!* identifica partenerul ROA dupa codul fiscal din eFactura (o singura interogare pentru ambele
*!* variante, cu si fara prefix RO) si, daca nu exista deloc, il creeaza automat, refolosind
*!* maparea din But_nou1.Click (anaf_efactura.vc2). Fara UI: rezultatul e o structura pe care
*!* ecranul o consuma si decide singur ce arata utilizatorului.
DEFINE CLASS RezolvarePartenerEF AS Custom
*!* Cauta partenerul dupa codul fiscal (ambele variante RO) si, daca nu-l gaseste deloc, il
*!* creeaza automat din datele eFacturii. Intoarce un obiect: cStare (gasit/gasit_inactiv/
*!* mai_multi/inexistent/creat), nIdPartener (ales sau nou creat, 0 daca nu s-a decis),
*!* cAtentionare (text pentru utilizator, gol daca nu e cazul), nCandidati/aCandidati
*!* (nIdPart, cDenumire, cCodFiscal, lActiv) pentru starea mai_multi.
PROCEDURE Rezolva
LPARAMETERS tcCodFiscal, tcDenumire, tlPrimite
LOCAL loRezultat, lcSql, llSucces, lnActivi, lnInactivi, lnIdActiv, lnIdInactiv, lnIdNou
PRIVATE pcCifBare, pcCifRo
loRezultat = This.RezultatGol()
pcCifBare = This.CifBare(m.tcCodFiscal)
IF EMPTY(m.pcCifBare)
loRezultat.cAtentionare = 'eFactura nu are cod fiscal, nu se poate identifica partenerul'
RETURN loRezultat
ENDIF
pcCifRo = 'RO' + m.pcCifBare
lcSql = "select id_part, denumire, cod_fiscal, inactiv from nom_parteneri" + ;
" where sters = 0 and replace(upper(cod_fiscal),' ','') in (?pcCifBare, ?pcCifRo)"
llSucces = goExecutor.oExecuta(m.lcSql, 'cRezolvarePartener')
IF !m.llSucces
loRezultat.cAtentionare = 'eroare la cautarea partenerului: ' + goExecutor.cEroare
RETURN loRezultat
ENDIF
lnActivi = 0
lnInactivi = 0
lnIdActiv = 0
lnIdInactiv = 0
SELECT cRezolvarePartener
SCAN
This.AdaugaCandidat(loRezultat, id_part, denumire, cod_fiscal, NVL(inactiv, 0) = 0)
IF NVL(inactiv, 0) = 0
lnActivi = lnActivi + 1
lnIdActiv = id_part
ELSE
lnInactivi = lnInactivi + 1
lnIdInactiv = id_part
ENDIF
ENDSCAN
USE IN (SELECT('cRezolvarePartener'))
DO CASE
CASE m.lnActivi = 1
loRezultat.cStare = 'gasit'
loRezultat.nIdPartener = m.lnIdActiv
CASE m.lnActivi >= 2
loRezultat.cStare = 'mai_multi'
loRezultat.cAtentionare = 'CIF ambiguu in ROA: ' + TRANSFORM(m.lnActivi) + ' parteneri activi, alegeti partenerul'
CASE m.lnActivi = 0 AND m.lnInactivi = 1
loRezultat.cStare = 'gasit_inactiv'
loRezultat.nIdPartener = m.lnIdInactiv
loRezultat.cAtentionare = 'partenerul gasit este inactiv in ROA'
CASE m.lnActivi = 0 AND m.lnInactivi >= 2
loRezultat.cStare = 'mai_multi'
loRezultat.cAtentionare = 'CIF ambiguu in ROA: ' + TRANSFORM(m.lnInactivi) + ' parteneri inactivi, alegeti partenerul'
OTHERWISE
lnIdNou = This.CreeazaPartener(m.tcCodFiscal, m.tcDenumire, m.tlPrimite)
IF m.lnIdNou > 0
loRezultat.cStare = 'creat'
loRezultat.nIdPartener = m.lnIdNou
loRezultat.cAtentionare = 'partener nou, creat automat din eFactura'
ELSE
loRezultat.cStare = 'inexistent'
loRezultat.cAtentionare = 'partenerul nu exista in ROA si nu a putut fi creat automat'
ENDIF
ENDCASE
RETURN loRezultat
ENDPROC
*!* Normalizeaza codul fiscal la forma fara prefix RO (scoate doar prefixul, nu 'RO' oriunde in sir)
PROCEDURE CifBare
LPARAMETERS tcCodFiscal
LOCAL lcCif
lcCif = STRTRAN(UPPER(ALLTRIM(NVL(m.tcCodFiscal, ''))), ' ', '')
IF LEFT(m.lcCif, 2) == 'RO'
lcCif = SUBSTR(m.lcCif, 3)
ENDIF
RETURN ALLTRIM(m.lcCif)
ENDPROC
*!* Creeaza silentios partenerul, cu maparea folosita si de But_nou1.Click (anaf_efactura.vc2):
*!* denumire, cod_fiscal (exact cum vine din eFactura), id_tip_part (17 furnizor/16 client),
*!* tip_persoana din ValidCNP. Aici lSilentios = .T. (fara formular), spre deosebire de butonul
*!* manual. Intoarce id-ul noului partener sau 0 la esec.
PROCEDURE CreeazaPartener
LPARAMETERS tcCodFiscal, tcDenumire, tlPrimite
LOCAL loDate, loDate2, llCNP, lnTipPersoana, lnIdPartener
lnIdPartener = 0
llCNP = ValidCNP(m.tcCodFiscal)
lnTipPersoana = IIF(m.llCNP, 2, 1)
loDate = CREATEOBJECT('Empty')
* id_part = 0: nom_parteneri_nou scrie id-ul nou creat inapoi in aceasta proprietate,
* pe calea silentioasa trebuie sa existe deja pe obiect (altfel "Property ID_PART is not found")
ADDPROPERTY(loDate, 'id_part', 0)
ADDPROPERTY(loDate, 'denumire', ALLTRIM(NVL(m.tcDenumire, '')))
ADDPROPERTY(loDate, 'cod_fiscal', ALLTRIM(NVL(m.tcCodFiscal, '')))
ADDPROPERTY(loDate, 'id_tip_part', IIF(m.tlPrimite, 17, 16))
* creare silentioasa (cus_odata_parteneri.make_sql) citeste tip_partener, nu id_tip_part
ADDPROPERTY(loDate, 'tip_partener', IIF(m.tlPrimite, 17, 16))
ADDPROPERTY(loDate, 'lSilentios', .T.)
loDate2 = nom_parteneri_nou(, , , m.lnTipPersoana, , m.loDate)
IF TYPE('loDate2') = 'O' AND TYPE('loDate2.id_part') = 'N'
lnIdPartener = NVL(loDate2.id_part, 0)
ENDIF
RETURN m.lnIdPartener
ENDPROC
PROCEDURE RezultatGol
LOCAL loRezultat
loRezultat = CREATEOBJECT('Empty')
ADDPROPERTY(loRezultat, 'cStare', 'inexistent')
ADDPROPERTY(loRezultat, 'nIdPartener', 0)
ADDPROPERTY(loRezultat, 'cAtentionare', '')
ADDPROPERTY(loRezultat, 'nCandidati', 0)
ADDPROPERTY(loRezultat, 'aCandidati[1]')
RETURN loRezultat
ENDPROC
PROCEDURE AdaugaCandidat
LPARAMETERS toRezultat, tnIdPart, tcDenumire, tcCodFiscal, tlActiv
LOCAL loCandidat, lnN
loCandidat = CREATEOBJECT('Empty')
ADDPROPERTY(loCandidat, 'nIdPart', m.tnIdPart)
ADDPROPERTY(loCandidat, 'cDenumire', ALLTRIM(NVL(m.tcDenumire, '')))
ADDPROPERTY(loCandidat, 'cCodFiscal', ALLTRIM(NVL(m.tcCodFiscal, '')))
ADDPROPERTY(loCandidat, 'lActiv', m.tlActiv)
lnN = toRezultat.nCandidati + 1
DIMENSION toRezultat.aCandidati(m.lnN)
toRezultat.aCandidati(m.lnN) = m.loCandidat
toRezultat.nCandidati = m.lnN
ENDPROC
ENDDEFINE