Files
vfp_roaauto/COMUN/programe/anaf_efactura.prg

3806 lines
147 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#DEFINE LF CHR(10)
#DEFINE CRLF CHR(13)+CHR(10)
#DEFINE CT_SUCCES 1
#DEFINE CT_INSUCCES -1
*!* 12.08.2024
*!* ParseEFactura - discount factura, discount linie
*!* 21.08.2024
*!* xml2PdfAnaf - tratare Invoice / CreditNote
*!* 03.12.2024
*!* AnafeFactura.RefreshToken, SaveToken apeleaza AnafeFacturaServer.RefreshToken, SaveToken
*!* AnafeFacturaServer.RefreshToken - automat daca data expirarii este mai mare sau egala, fara sa mai apara formularul de Actualizare
*!* astfel incat si pe server sa se apeleze automat daca expira tokenul
*!* 07.01.2025
*!* UpdateDbFactura - corectie double byte characters la mesaj_raspuns
*!* RefreshToken - tratare eroare cu Try Catch
*!* 26.03.2025
*!* SendEfactura - uploadb2c pentru persoane fizice len(codfiscal) = 13
*!* 20.05.2025
*!* DescarcareRaspunsuri - se afiseaza eroare daca nu sunt drepturi in spv
*!* 13.03.2026
*!* Validarea si xml2pdfanaf se fac cu serviciul autentificat cu token efactura api.anaf.ro in loc de serviciul neautentificat https://webservicesp.anaf.ro/
*!* serviciul neautentificat nu mai raspundea
*********************************
* Se apeleaza din ROACONT > Borderou eFactura
* Intoarce .T. daca descarcarea zip efactura si actualizarea efactura in baza de date s-au realizat cu succes
*********************************
PROCEDURE efactura_client
LPARAMETERS tnZile, tlFortareRaspunsuri, tlTest
LOCAL lnExitCode, lcHost, lcPassword, lcUser, lnIsServer, lnFortareRaspunsuri, lnZile, llSucces
Local loAnaf As 'AnafeFacturaServer'
Local lcErrorMessage, llFortareRaspunsuri, llServer, loEx, llTest
lcHost = ''
lcUser = IIF(TYPE('gcS') = 'C', m.gcS, '')
lcPassword = ''
llServer = .F.
lnZile = IIF(EMPTY(m.tnZile), 60, m.tnZile)
llFortareRaspunsuri = m.tlFortareRaspunsuri
llTest = m.tlTest
llSucces = .F.
TRY
loAnaf = Createobject('AnafeFacturaServer', m.llServer, m.lcHost, m.lcuser, m.lcPassword)
loAnaf.ltest = m.llTest
llSucces = loAnaf.Run(m.lnZile, m.llFortareRaspunsuri)
IF loAnaf.lError
goLog.Log(loAnaf.cErrorMessage)
ENDIF
CATCH TO loEx
lnExitCode = 1
lcErrorMessage = TTOC(DATETIME(),1) + ' Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut: ' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure
WAIT WINDOW m.lcErrorMessage NOWAIT
AMESSAGEBOX(m.lcErrorMessage)
This.Log(m.lcErrorMessage)
ENDTRY
RETURN m.llSucces
ENDPROC && efactura_client
Define Class AnafeFacturaServer As Custom
dLastRunDate1 = {} && dataora inceput pentru ultima citire a raspunsurilor
dLastRunDate2 = {} && dataora sfarsit pentru ultima citire a raspunsurilor
nLastRunDays = 0 && numarul de zile pentru citirea raspunsurilor
nLastRunSucces = 0 && succes la ultima citire a raspunsurilor
cLogFile = ''
cToken = ''
cRefreshToken = ''
dTokenGendate = {}
dTokenExpdate = {}
cTokenUrl = ''
cCodFiscal = '' && cod fiscal contribuabil fara atribut fiscal
lTest = .F. && .T. = transmite eFactura TEST
cResponsesPath = '' && Citire raspunsuri. Calea unde se salveaza fisierele xml primite, semnatura MFIN, pdf generat de ANAF: z:\e-factura\<an>\<luna> <an>\<furnizor>\<id_descarcare
nDaysResponses = 60
cSendPath = '' && cale unde sunt fisierele xml de trimis
cSendInvalidPath = '' && calea unde se muta fisierele invalide
cSendOkPath = '' && calea unde se muta fisierele trimise
cSaveFurnizoriPath = '' && cale template unde se copie xml, semnatura, generare pdf in ProcesCopiere
cSaveClientiPath = ''
cSaveFurnizoriFile = '' && nume fisier template pentru xml, semnatura, pdf
cSaveClientiFile = '' && nume fisier template pentru xml, semnatura, pdf
nSaveFile = 1 && 1 = se salveaza arhivele zip in calea template, 0 nu se salveaza
nSaveAnafPdfFile = 1 && 1 = se salveaza arhivele zip in calea template, 0 nu se salveaza
cSaveLogsPath = '' && directorul unde se salveaza fisierele cu raspunsuri de la ANAF descarcate (optional)
cServerPath = '' && directorul de pe server EFACTURA_SERVER_PATH
cNetworkPath = '' && directorul din retea accesibil de pe clienti, daca se ruleaza din ROACONT. EFACTURA_NETWORK_PATH
cErrorMessage = ''
lError = .F.
cDatabaseFileName = 'anaf_efactura.dbf'
cDatabaseFilePath = ''
lServer = .T.
cHost = ''
cUser = ''
cPassword = ''
lConnected = .F. && daca programul este deja conectat la baza de date si nu este necesar sa se conecteze/deconecteze
lZipDatabase = .T. && daca se salveaza zip efactura in baza de date
lTokenAutoRefresh = .F. && daca se actualizeaza automat tokenul cu 10 zile inainte de expirare
oAnafeFactura = null
Procedure Init
Lparameters tlServer, tcHost, tcUser, tcPassword
Local lcTest, llSucces, lcUser
This.cErrorMessage = ''
lcUser = tcUser
IF TYPE('tcUser') = 'C' AND !EMPTY(m.tcUser)
lcUser = m.tcUser
ELSE
lcUser = IIF(TYPE('gcS') = 'C', m.gcS, '')
ENDIF
this.lServer = m.tlServer
This.cHost = m.tcHost
this.cUser = m.lcUser
this.cPassword = m.tcPassword
* Initializare baza date
goConn.cHost = This.cHost
goConn.cUser = this.cUser
goConn.cPassword = this.cPassword
This.lConnected = This.IsConnected()
This.cLogFile = goLog.cLogFile
llSucces = This.ReadSettingsFromDb()
Endproc && Init
PROCEDURE Run
LPARAMETERS tnZile, tlFortareRaspunsuri
Local llSucces, lnZile, llFortareRaspunsuri
lnZile = m.tnZile
This.nDaysResponses = m.lnZile
llFortareRaspunsuri = m.tlFortareRaspunsuri
This.PreRun()
llSucces = This.InitDB(m.lnZile)
IF m.llSucces
llSucces = This.DescarcareRaspunsuri(m.lnZile, m.llFortareRaspunsuri)
IF !m.llSucces AND !This.lServer
AMESSAGEBOX(This.cErrorMessage,0+48, _SCREEN.Caption)
ENDIF
ENDIF
IF m.llSucces
llSucces = This.ProcesareRaspunsuri(m.llFortareRaspunsuri)
IF m.llSucces
llSucces = This.UpdateDb()
IF !m.llSucces AND !This.lServer AND !EMPTY(This.cErrorMessage)
AMESSAGEBOX(This.cErrorMessage,0+48, _SCREEN.Caption)
ENDIF
ELSE
IF !m.llSucces AND !This.lServer AND !EMPTY(This.cErrorMessage)
AMESSAGEBOX(This.cErrorMessage,0+48, _SCREEN.Caption)
ENDIF
ENDIF
ENDIF
This.PostRun(m.llSucces)
RETURN m.llSucces
ENDPROC && Run
*****************************
PROCEDURE PreRun
Local llSucces, lnHandle
This.dLastRunDate1 = DATETIME()
This.dLastRunDate2 = {//::}
This.nLastRunDays = This.nDaysResponses
This.nLastRunSucces = 0
lnHandle = This.ConnectROA()
llSucces = (m.lnHandle > 0)
IF m.llSucces
scrie_optiune('EFACTURA_LASTRUN_DATE1', ttoc(This.dLastRunDate1), 'Efactura data inceput cand au fost verificate raspunsurile SPV')
scrie_optiune('EFACTURA_LASTRUN_DATE2', ttoc(This.dLastRunDate2), 'Efactura data sfarsit cand au fost verificate raspunsurile SPV')
scrie_optiune('EFACTURA_LASTRUN_DAYS', ALLTRIM(STR(This.nLastRunDays)), 'Efactura cate zile de raspunsuri au fost verificate ultima data')
scrie_optiune('EFACTURA_LASTRUN_SUCCES', ALLTRIM(STR(This.nLastRunSucces)), 'Efactura succes la ultima verificare de raspunsuri SPV')
ENDIF
ENDPROC && PreRun
*****************************
PROCEDURE PostRun
LPARAMETERS tlSucces
Local llSucces, lnHandle
This.nLastRunSucces = IIF(m.llSucces, 1, 0)
This.dLastRunDate2 = DATETIME()
lnHandle = This.ConnectROA()
llSucces = (m.lnHandle > 0)
IF m.llSucces
scrie_optiune('EFACTURA_LASTRUN_SUCCES', ALLTRIM(STR(This.nLastRunSucces)), 'Efactura succes la ultima verificare de raspunsuri SPV')
scrie_optiune('EFACTURA_LASTRUN_DATE2', ttoc(This.dLastRunDate2), 'Efactura data sfarsit cand au fost verificate raspunsurile SPV')
scrie_optiune('EFACTURA_LASTRUN_SUCCES', IIF(m.tlSucces, "1", "0"), 'Efactura succes la ultima verificare de raspunsuri SPV')
ENDIF
ENDPROC && PostRun
*******************************
* Verifica daca programul este conectat la baza de date
*******************************
PROCEDURE IsConnected
LOCAL lcSql, llSucces
LOCAL loEx as Exception
Local lcErrorMessage
llSucces = .F.
lcSql = "SELECT sysdate FROM dual"
TRY
llSucces = goExecutor.oExecuta(m.lcSql)
CATCH TO loEx
lcErrorMessage = TTOC(DATETIME(),1) + ' Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure
This.cErrorMessage = m.lcErrorMessage
This.Log(m.lcErrorMessage)
ENDTRY
RETURN m.llSucces
ENDPROC && IsConnected
PROCEDURE ReadSettingsFromDb
Local lcSql, llSucces, lcCodFiscal
Local lcErrorMessage, lcFirma, lcLastRunDate1, lcLastRunDate2, lcPath, lnHandle, lnSucces
Local lnZipDatabase
*:Global gcFirma, gnAn, gnLuna
llSucces = .F.
TEXT TO lcSql TEXTMERGE NOSHOW
select MAX(cod_fiscal) as cod_fiscal, MAX(firma) AS firma from syn_v_nom_firme where UPPER(schema) = '<<UPPER(ALLTRIM(This.cUser))>>' AND STERS = 0 AND (E_MAMA = 1 OR (E_MAMA = 0 AND ID_MAMA IS NULL))
ENDTEXT
lnHandle = This.ConnectROA()
llSucces = (m.lnHandle > 0)
IF m.llSucces
lnSucces = actualizeaza_optiuni()
llSucces = (lnSucces = CT_SUCCES)
IF m.llSucces
lcCodFiscal = ''
lcFirma = ''
llSucces = goExecutor.oExecuta(m.lcSql, "cFirmaTemp")
IF m.llSucces
lcCodFiscal = ALLTRIM(NVL(cFirmaTemp.cod_fiscal, ''))
lcFirma = ALLTRIM(NVL(cFirmaTemp.firma, ''))
This.cCodFiscal = UPPER(ALLTRIM(GetNrFromString(NVL(m.lcCodFiscal,''))))
IF TYPE('gcFirma') = 'C' AND EMPTY(m.gcFirma)
gcFirma = m.lcFirma
ENDIF
ENDIF
USE IN (SELECT('cFirmaTemp'))
ENDIF
IF m.llSucces
IF TYPE('gnAn') = 'N' AND EMPTY(m.gnAn)
lcSql = "SELECT AN, LUNA FROM CALENDAR WHERE AN*12 + LUNA = (SELECT MAX(AN*12+LUNA) FROM CALENDAR)"
llSucces = goExecutor.oExecuta(m.lcSql, 'cCalendarTemp')
IF m.llSucces
gnAn = cCalendarTemp.an
gnLuna = cCalendarTemp.luna
ENDIF
USE IN (SELECT('cCalendarTemp'))
ENDIF
ENDIF
lnSucces = This.DisconnectROA()
llSucces = (lnSucces = CT_SUCCES)
ENDIF
IF m.llSucces
This.cResponsesPath = ADDBS(ALLTRIM(NVL(citeste_optiune("EFACTURA_RESPONSESPATH"), ''))) && RASPUNSURI && <path>\<firma>\raspunsuri\
This.cSendPath = ADDBS(ALLTRIM(NVL(citeste_optiune("EFACTURA_SENDPATH"),''))) && FACTURI DE TRIMIS && <path>\<firma>\emise\
This.cSaveFurnizoriPath = ADDBS(ALLTRIM(NVL(citeste_optiune("EFACTURA_SAVE_FURNIZORI_PATH"), ''))) && <path>\<firma>\furnizori\<an>\<luna> <an>\<furnizor>\<id_descarcare>
This.cSaveFurnizoriFile = ALLTRIM(citeste_optiune("EFACTURA_SAVE_FURNIZORI_FILE")) && <id_incarcare>_<datafact>_<furnizor>
This.cSaveClientiPath = Addbs(ALLTRIM(NVL(citeste_optiune("EFACTURA_SAVE_CLIENTI_PATH"), ''))) && <path>\<firma>\clienti\<an>\<luna> <an>\<client>\<id_descarcare>
This.cSaveClientiFile = ALLTRIM(citeste_optiune("EFACTURA_SAVE_CLIENTI_FILE")) && <id_incarcare>_<id_descarcare>_<datafact>_<client>
This.nSaveFile = INT(VAL(ALLTRIM(citeste_optiune("EFACTURA_SAVE")))) && 1
This.nSaveAnafPdfFile = INT(VAL(ALLTRIM(citeste_optiune("EFACTURA_SAVE_ANAF_PDF")))) && 1
This.cServerPath = ADDBS(ALLTRIM(NVL(citeste_optiune("EFACTURA_SERVER_PATH"),''))) && C:\ROA-EFACTURA\
This.cNetworkPath = ADDBS(ALLTRIM(NVL(citeste_optiune("EFACTURA_NETWORK_PATH"),''))) && W:\
lcPath = IIF(This.lServer, this.cServerPath, this.cNetworkPath)
This.cSaveFurnizoriPath = STRTRAN(STRTRAN(This.cSaveFurnizoriPath, '<path>', m.lcPath, 1, 1, 1), '\\', '\', 1, 10, 1)
This.cSaveClientiPath = STRTRAN(STRTRAN(This.cSaveClientiPath, '<path>', m.lcPath, 1, 1, 1), '\\', '\', 1, 10, 1)
This.cResponsesPath = ADDBS(ALLTRIM(NVL(citeste_optiune("EFACTURA_RESPONSESPATH"),''))) && RASPUNSURI && <firma>\raspunsuri\
This.cSendPath = ADDBS(ALLTRIM(NVL(citeste_optiune("EFACTURA_SENDPATH"),''))) && FACTURI DE TRIMIS && <firma>\emise\
This.cResponsesPath = STRTRAN(STRTRAN(This.cResponsesPath, '<path>', m.lcPath, 1, 1, 1), '\\', '\', 1, 10, 1)
This.cResponsesPath = STRTRAN(This.cResponsesPath,'<firma>', UPPER(This.cUser),1,1,1)
This.cResponsesPath = This.cResponsesPath + IIF(this.lTest, 'test\', '')
This.cSaveLogsPath = This.cResponsesPath + 'logs\'
This.cSendPath = STRTRAN(STRTRAN(This.cSendPath, '<path>', m.lcPath, 1, 1, 1), '\\', '\', 1, 10, 1)
This.cSendPath = STRTRAN(This.cSendPath,'<firma>', UPPER(This.cUser),1,1,1)
This.cSendPath = This.cSendPath + IIF(this.lTest, 'test\', '')
This.cSendInvalidPath = This.cSendPath + 'invalid\'
This.cSendOkPath = This.cSendPath + 'ok\'
lnZipDatabase = INT(VAL(ALLTRIM(citeste_optiune("EFACTURA_ZIP_DATABASE")))) && 1
This.lZipDatabase = (m.lnZipDatabase = 1)
lcLastRunDate1 = ALLTRIM(NVL(citeste_optiune("EFACTURA_LASTRUN_DATE1"), ''))
This.dLastRunDate1 = Iif(!Empty(m.lcLastRunDate1), CTOT(m.lcLastRunDate1), {//::})
lcLastRunDate2 = ALLTRIM(NVL(citeste_optiune("EFACTURA_LASTRUN_DATE2"), ''))
This.dLastRunDate2 = Iif(!Empty(m.lcLastRunDate2), CTOT(m.lcLastRunDate2), {//::})
This.nLastRunDays = INT(VAL(ALLTRIM(NVL(citeste_optiune("EFACTURA_LASTRUN_DAYS"), ''))))
This.nLastRunSucces = INT(VAL(ALLTRIM(NVL(citeste_optiune("EFACTURA_LASTRUN_SUCCES"), ''))))
************
* Actualizeaza Token automat si citeste Token din baza de date
* This.GetToken()
This.RefreshTokenAuto()
ELSE
lcErrorMessage = 'ReadSettingsFromDb Eroare la initializarea setarilor'
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
ENDIF
This.Log('This.nSaveFile ' + TRANSFORM(This.nSaveFile) + CHR(13) + CHR(10) + ;
'This.nSaveAnafPdfFile ' + TRANSFORM(This.nSaveAnafPdfFile ) + CHR(13) + CHR(10) + ;
'This.cServerPath ' + ALLTRIM(This.cServerPath) + CHR(13) + CHR(10) + ;
'This.cNetworkPath ' + ALLTRIM(This.cNetworkPath) + CHR(13) + CHR(10) + ;
'This.cSaveFurnizoriPath ' + ALLTRIM(This.cSaveFurnizoriPath ) + CHR(13) + CHR(10) + ;
'This.cSaveClientiPath ' + ALLTRIM(This.cSaveClientiPath ) + CHR(13) + CHR(10) + ;
'This.cResponsesPath ' + ALLTRIM(This.cResponsesPath ) + CHR(13) + CHR(10) + ;
'This.cSaveLogsPath ' + ALLTRIM(This.cSaveLogsPath ))
RETURN m.llSucces
ENDPROC && ReadSettingsFromDb
*********************
*
*********************
PROCEDURE InitDB
LPARAMETERS tnZile
* tnZile: cate zile de raspunsuri se descarca, pentru a se verifica si cu baza de date cu tnZile de raspunsuri
LOCAL llSucces, lnZile
lnZile = IIF(EMPTY(m.tnZile), 60, m.tnZile) + 10 && adaug 10 zile pentru precautie
lnHandle = This.ConnectROA()
llSucces = (m.lnHandle > 0)
IF m.llSucces
pdData2 = DATE()+1
pdData1 = DATE() - m.lnZile
TEXT TO lcSql NOSHOW
select a.*, cast(NULL as varchar2(1000)) as factura_detalii, 0 as modificat
from anaf_efactura a
where a.data_raspuns between ?pdData1 and ?pdData2
ENDTEXT
llSucces = goExecutor.oExecuta(m.lcSql,"anaf_efactura")
IF m.llSucces
SELECT anaf_efactura
INDEX on id_incarcare TAG id_inc
INDEX on id_descarcare TAG id_desc
ENDIF
lnSucces = This.DisconnectROA()
ENDIF && lnSucces
RETURN m.llSucces
ENDPROC && InitDB
PROCEDURE ConnectROA
Local lnSucces
IF This.lConnected
* Nu ma conectez la baza de date daca sunt deja conectat (ex: Daca se apeleaza programul din ROACONT si sunt deja conectat la baza de date)
lnSucces = CT_SUCCES
ELSE
lnSucces = IIF(goConn.Connect() > 0, CT_SUCCES, CT_INSUCCES)
ENDIF
Return lnSucces
ENDPROC
PROCEDURE DisconnectROA
Local lnSucces
IF This.lConnected
lnSucces = CT_SUCCES
ELSE
lnSucces = goConn.Disconnect()
ENDIF
RETURN m.lnSucces
ENDPROC && DisconnectROA
Procedure Log
Lparameters tcText, tcProgram
IF TYPE('goLog') = 'O'
goLog.Log(tcText, tcProgram)
ELSE
lcText = Ttoc(Datetime(),3) + ' ' + IIF(!EMPTY(m.tcProgram), m.tcProgram + ' ', '') + m.tcText + CRLF
Strtofile(m.lcText, This.cLogFile, 1)
ENDIF
Endproc && Log
*******************************************************************
* Actualizare automata Token
*******************************************************************
FUNCTION RefreshTokenAuto
This.GetToken()
IF (This.lTokenAutoRefresh AND !EMPTY(NVL(This.cToken,'')) AND !EMPTY(NVL(This.cRefreshToken, ''))) AND (This.dTokenExpdate <= DATE())
This.RefreshToken()
ENDIF
This.GetToken()
ENDFUNC
************************************************************************
Function GetToken
Local lcRefreshToken, lcToken, lcTokenExpDate, lcTokenGenDate, ldTokenExpDate, ldTokenGenDate
lnTokenAutoRefresh = INT(VAL(ALLTRIM(citeste_optiune("ANAF_TOKEN_AUTO_REFRESH")))) && 1
This.lTokenAutoRefresh = (m.lnTokenAutoRefresh = 1)
* TokenJWT are dimensiunea mai mare. Il salvez in optiuni.varvalue2
lcToken = Alltrim(Nvl(citeste_optiune('ANAF_TOKEN', .T.), ''))
lcRefreshToken = Alltrim(Nvl(citeste_optiune('ANAF_REFRESH_TOKEN', .T.), ''))
lcTokenGenDate = Alltrim(Nvl(citeste_optiune('ANAF_TOKEN_GENDATE'), ''))
ldTokenGenDate = Iif(!Empty(m.lcTokenGenDate), Ctod(m.lcTokenGenDate), {})
lcTokenExpDate = Alltrim(Nvl(citeste_optiune('ANAF_TOKEN_EXPDATE'), ''))
ldTokenExpDate = Iif(!Empty(m.lcTokenExpDate), Ctod(m.lcTokenExpDate), {})
ldTokenExpDate = Iif(!Empty(m.ldTokenExpDate), m.ldTokenExpDate, m.ldTokenGenDate + 90)
lcTokenURL = Alltrim(Nvl(citeste_optiune('ANAF_URL_TOKEN'), ''))
This.cToken = m.lcToken
This.cRefreshToken = m.lcRefreshToken
This.dTokenGendate = m.ldTokenGenDate
This.dTokenExpdate = m.ldTokenExpDate
This.cTokenUrl = m.lcTokenURL
Do Case
Case Empty(m.lcToken)
This.Log('Token nu este configurat.')
Case m.ldTokenExpDate <= Date()
This.Log('Token expirat.')
Endcase
Return This.cToken
Endfunc
***************************
* Salveaza tokenul in baza de date optiuni firma
***************************
Procedure SaveToken
scrie_optiune('ANAF_TOKEN', This.cToken, 'ANAF Token SPV eFactura', .T.)
scrie_optiune('ANAF_REFRESH_TOKEN', This.cRefreshToken, 'ANAF Refresh Token SPV eFactura', .T.)
scrie_optiune('ANAF_TOKEN_GENDATE', Dtoc(This.dTokenGendate), 'ANAF Token SPV eFactura data generare')
scrie_optiune('ANAF_TOKEN_EXPDATE', Dtoc(This.dTokenExpdate), 'ANAF Token SPV eFactura data expirare')
Endproc && SaveToken
* Intoarce tokenul de acces la ANAF (eFactura) daca este salvat sau obtine un nou token
* Se apeleaza din formularul anaf_token.do_executa
Function newToken
Local lcTokenURL
This.Log('Introduceti in calculator tokenul USB cu semnatura electronica' + LF + ;
'Se va deschide pagina ANAF de generare token. Introduceti PIN-ul pentru semnatura electronica.' + LF + ;
'Copiati codurile "Token" si "Refresh Token" afisate si completati-le in ' + m.gcGeneralIniFile)
lcTokenURL = This.cTokenUrl
open_default_app(m.gcGeneralIniFile)
open_default_app(m.lcTokenURL)
Endfunc
* Actualizeaza data expirarii tokenului ANAF eFactura
* Se apeleaza din formularul anaf_token.do_executa
Function refreshToken
LPARAMETERS tcMesaj
* tcMesaj (OUT)
Local loHTTP As 'winHTTP.winHTTPrequest.5.1'
Local lcRefreshToken, lcResponse, lcURL, llSucces, loJson
llSucces = .F.
lcRefreshToken = Alltrim(This.cRefreshToken)
tcMesaj = ''
If Empty(m.lcRefreshToken)
tcMesaj = 'Completati Refresh Token'
This.Log(m.tcMesaj)
Else
lcURL = This.cTokenUrl
TRY
loHTTP = Createobject('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('POST', lcURL, .F.)
loHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
loHTTP.Send([refresh_token=] + m.lcRefreshToken)
CATCH
loHTTP = Createobject('MSXML2.XMLHTTP.6.0')
loHTTP.Open('POST', lcURL, .F.)
loHTTP.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
loHTTP.Send([refresh_token=] + m.lcRefreshToken)
ENDTRY
llSucces = (TYPE('loHTTP') = 'O')
IF m.llSucces
lcResponse = loHTTP.ResponseText
llSucces = (loHTTP.Status = 200)
ENDIF
If !m.llSucces
lcResponse = loHTTP.StatusText
Endif
If m.llSucces
TRY
loJson = nfjsonread(m.lcResponse)
CATCH TO loEx
llSucces = .F.
tcMesaj = 'Refresh token - eroare extragere raspuns json: ' + loEx.message + CRLF + m.lcResponse
this.Log(m.tcMesaj)
ENDTRY
If Type('loJson.expires_in') <> 'U' And Type('loJson.access_token') <> 'U' And Type('loJson.refresh_token') <> 'U'
This.dTokenExpdate = Date() + Int(Val(Transform(loJson.expires_in)) / 24 / 3600) && 90 zile
This.dTokenGendate = Date()
This.cToken = loJson.access_token
This.cRefreshToken = loJson.refresh_token
This.SaveToken()
tcMesaj = 'S-a regenerat token-ul, cu valabilitate pana la ' + Dtoc(This.dTokenExpdate)
This.Log(m.tcMesaj)
ELSE
tcMesaj ='Nu s-a regenerat token-ul! Generati un token nou!' + LF + m.lcResponse
This.Log(m.tcMesaj)
Endif
ELSE
tcMesaj = 'Nu s-a regenerat token-ul! Status = ' + Transform(loHTTP.Status) + CRLF + m.lcResponse
This.Log(m.tcMesaj, 0 + 48, _Screen.Caption)
Endif
Endif
Return m.llSucces
Endfunc
*********************
* Trimite fisiere xml eFactura in SPV
*********************
PROCEDURE VizeFacturaXml
CREATE CURSOR cXmlFiles (ales N(1), filepath c(250), procesat N(1), stare c(100), mesaj c(250), extern N(1))
loXmlFiles = CREATEOBJECT("anaf_efactura_xml", This)
loXmlFiles.Show(1)
USE IN (SELECT('cXmlFiles'))
ENDPROC && VizeFacturaXml
********************************
* Genereaza xml efactura, valideaza xml si trimite la API ANAF
* parseaza un director cu xml efactura si le trimite la API ANAF
********************************
Procedure TrimiteFacturaXML
LPARAMETERS tcFile, tlValidare, tlValidareOnline, tlNuTrimiteEFacturaANAF, tlExtern
Local loXmlEFactura As 'ExportEFactura'
Local lcErrorMessage, lcExecutionStatus, lcFile, lcIndexIncarcare, lcMesaj, llSucces, llValid, loEx
Local loXML, lcMesajValidare, llExtern, lcToken
PRIVATE pcIdIncarcare, pcMesajTrimis, pnTrimis
LOCAL loReturn
lcFile = m.tcFile
lcMesaj = ''
lcMesajValidare = ''
lcToken = This.cToken
loReturn = Createobject("empty")
AddProperty(loReturn, "lSucces", .F.)
AddProperty(loReturn, "cFile", '')
AddProperty(loReturn, "cResponse", '')
AddProperty(loReturn, "nStatus", 0)
llExtern = m.tlExtern
llValid = .T.
IF m.tlValidare
llSilentios = .T.
loXmlEFactura = CREATEOBJECT('ExportEFactura', m.llSilentios, m.lcToken)
llValid = loXmlEFactura.ValidareEFactura(m.lcFile, @lcMesajValidare, m.tlValidareOnline)
ENDIF
IF m.llValid AND !m.tlNuTrimiteEFacturaANAF
loReturn = This.SendEfactura(m.lcFile, m.llExtern)
llSucces = loReturn.lSucces
AddProperty(loReturn, "cIdIncarcare", '')
AddProperty(loReturn, "cMesaj", '')
If m.llSucces
pcMesajTrimis = Iif(This.lTest, 'TEST ', '')
loXML = Null
Try
loXML = nfxmlread(loReturn.cResponse)
Catch To loEx
lcErrorMessage = loEx.Message
Endtry
lcExecutionStatus = ''
lcIndexIncarcare = ''
lcErrorMessage = ''
If Type('loxml.header._attr_.executionstatus') <> 'U'
lcExecutionStatus = loXML.Header._attr_.executionstatus
Endif
If Type('loxml.header._attr_.index__incarcare') <> 'U'
lcIndexIncarcare = loXML.Header._attr_.index__incarcare
Endif
If Type('loxml.header.errors._attr_.errorMessage') <> 'U'
lcErrorMessage = loXML.Header.errors._attr_.ErrorMessage
Endif
Do Case
Case lcExecutionStatus = "0"
pcIdIncarcare = m.lcIndexIncarcare
pnTrimis = 1
pcMesajTrimis = m.pcMesajTrimis + 'Transmis cu succes. Index incarcare = ' + m.pcIdIncarcare
loReturn.cIdIncarcare = m.pcIdIncarcare
loReturn.lSucces = .T.
Case !Empty(m.lcErrorMessage)
pcIdIncarcare = ''
pnTrimis = 1
pcMesajTrimis = m.pcMesajTrimis + Iif(This.lTest, 'TEST ', '') + 'Eroare. ' + m.lcErrorMessage
Case [VALID] $ Upper(loReturn.cResponse)
pcIdIncarcare = ''
pnTrimis = 0
pcMesajTrimis = m.pcMesajTrimis + loReturn.cResponse
Otherwise
pcMesajTrimis = m.pcMesajTrimis + Iif(This.lTest, 'TEST ', '') + 'Eroare. ' + m.lcErrorMessage
pcIdIncarcare = ''
pnTrimis = 1
Endcase
loReturn.cMesaj = m.pcMesajTrimis + ' ' + m.lcMesajValidare
Else
pcMesajTrimis = ' Eroare transmitere - Http Status: ' + Transform(loReturn.nStatus) + ' Http Response: ' + Alltrim(Transform(loReturn.cResponse)) + ' ' + loReturn.cResponse
loReturn.cResponse = pcMesajTrimis
loReturn.cMesaj = m.pcMesajTrimis + ' ' + m.lcMesajValidare
This.Log(loReturn.cResponse)
ENDIF
ELSE
AddProperty(loReturn, "cIdIncarcare", '')
AddProperty(loReturn, "cMesaj", '')
pcMesajTrimis = '. Nu s-a trimis fisierul la ANAF.'
loReturn.cResponse = m.pcMesajTrimis
IF m.llValid
loReturn.cMesaj = 'Nu s-a trimis fisierul. ' + m.lcMesajValidare
loReturn.lSucces = .T.
llSucces = .T.
ELSE
loReturn.cMesaj = 'Eroare validare. Nu s-a trimis fisierul: ' + m.lcMesajValidare
loReturn.lSucces = .F.
llSucces = .F.
ENDIF
ENDIF
RETURN loReturn
Endproc && TrimiteFacturaXML
* Genereaza xml eFactura, valideaza xml si trimite la ANAF
Function SendEfactura
Lparameters tcFile, tlExtern, tlMesaj
* tcFile: calea catre fisierul xml efactura / sau xml mesaj
* tlExtern: daca se apeleaza cu parametrul Extern=DA (pentru clientii externi)
* tlMesaj: daca mesajul este o factura sau un mesaj catre furnizor
Local loEx As Exception
Local loHTTP As 'winHTTP.winHTTPrequest.5.1'
Local loReturn As "empty"
Local lcCodFiscal, lcExtern, lcFile, lcSend, lcServer, lcToken, llOk, llTest, llB2C
LOCAL lcCustomer, lcPartyLegal, lcCodFiscalClient
loReturn = Createobject("empty")
AddProperty(loReturn, "lSucces", .F.)
AddProperty(loReturn, "cFile", '')
AddProperty(loReturn, "cResponse", '')
AddProperty(loReturn, "nStatus", 0)
lcToken = This.cToken
lcCodFiscal = ALLTRIM(This.cCodFiscal)
llTest = This.lTest
llOk = .F.
lcFile = ''
lcFile = Iif(Type('tcFile') = 'C' and !Empty(m.tcFile), m.tcFile, '')
loReturn.cFile = m.lcFile
lcExtern = Iif(m.tlExtern, '&extern=DA', '')
This.Log('SendEFactura: ' + m.lcFile)
If File(m.lcFile)
lcSend = Filetostr(m.lcFile)
* Verific daca clientul este persoana fizica si folosesc upload2bc in loc de upload
lcCustomer = STREXTRACT(lcSend, '<cac:AccountingCustomerParty>', '</cac:AccountingCustomerParty>',1,1)
lcPartyLegal = STREXTRACT(lcCustomer, '<cac:PartyLegalEntity>', '</cac:PartyLegalEntity>',1,1)
lcCodFiscalClient = ALLTRIM(STREXTRACT(m.lcPartyLegal, '<cbc:CompanyID>','</cbc:CompanyID>',1,1))
llB2C = (LEN(m.lcCodFiscalClient) = 13) && persoane fizice
TRY
IF !m.tlMesaj
lcServer = [https://api.anaf.ro/] + Iif(m.llTest, [test], [prod]) + [/FCTEL/rest/upload] + IIF(m.llB2C,'b2c','') + [?standard=UBL&cif=] + m.lcCodFiscal + m.lcExtern
ELSE
lcServer = [https://api.anaf.ro/] + Iif(m.llTest, [test], [prod]) + [/FCTEL/rest/upload] + IIF(m.llB2C,'b2c','') + [?standard=RASP&cif=] + m.lcCodFiscal
ENDIF
loHTTP = Createobject('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('POST', lcServer, .F.)
loHTTP.setRequestHeader("Content-Type", "application/xml;")
loHTTP.setRequestHeader('Authorization', 'Bearer ' + m.lcToken) && 9b1f44af738c16aa10c78347b9a064857f034b03a20704a03c131b99f019cee5
poLog.Log(m.lcServer)
loHTTP.Send(m.lcSend)
loReturn.nStatus = loHTTP.Status
loReturn.cResponse = loHTTP.ResponseText
loReturn.lSucces = (loHTTP.Status = 200)
CATCH TO loEx
loReturn.lSucces = .F.
loReturn.cResponse = '<errorMessage="' + loEx.message + '">'
ENDTRY
Else
loReturn.cResponse = '<errorMessage="Nu exista fisierul' + m.lcFile + '">'
loReturn.lSucces = .F.
ENDIF
This.Log('SendEFactura: ' + Transform(loReturn.nStatus) + ' ' + Transform(loReturn.lSucces) + ' ' + loReturn.cResponse)
Return loReturn
Endfunc
* Genereaza xml mesaj catre furnizor si trimite la ANAF
Function SendMesaj
Lparameters tnIdIncarcare, tcMesaj
LOCAL lnIdIncarcare, lcMesaj, llMesaj, loReturn, lcFile
lcFile = ADDBS(SYS(2023)) + FORCEEXT(SYS(2015), 'xml')
llMesaj = .T.
lcMesaj = Alltrim(XmlSpecialCharacters(RemoveCharacters(m.tcMesaj, .T.)))
lnIdIncarcare = ALLTRIM(NVL(m.tnIdIncarcare,''))
TEXT TO lcText TEXTMERGE NOSHOW
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<header xmlns="mfp:anaf:dgti:spv:reqMesaj:v1" index_incarcare="<<m.lnIdIncarcare>>" message="<<m.lcMesaj>>"/>
ENDTEXT
STRTOFILE(m.lcText, m.lcFile)
loReturn = This.SendEFactura(m.lcFile,,m.llMesaj)
IF FILE(m.lcFile)
DELETE FILE (m.lcFile)
ENDIF
RETURN loReturn
ENDFUNC
*************************
* Dezarhiveaza o arhiva si intoarce .T./.F.
*************************
Procedure UnzipFile
Lparameters tcZipFile, tcDir, tcErrorMessage
* tcZipFile: arhiva zip cu detaliile raspunsului unei eFactura
* tcDir: IN/OUT directorul cu fisierele dezarhivate
* tcErrorMessage: OUT mesaj de eroare
Local laZipTemp[1, 3], lcDir, lcFileName, llSucces, llSilent
tcErrorMessage = ''
llSilent = .T.
IF TYPE('tcDir') <> 'C' OR EMPTY(NVL(m.tcDir, ''))
tcDir = ADDBS(JUSTPATH(m.tcZipFile))
ENDIF
This.Log('UnzipFile ' + m.tcZipFile)
llSucces = MyUnzip(m.tcZipFile, @tcDir, @tcErrorMessage, m.llSilent)
Return m.llSucces
ENDPROC && UnzipFile
*********************************
* Proces ProcesCopiere: copiez arhiva zip intr-o structura de directoare, dezarhivez, transform xml in pdf
*********************************
PROCEDURE ProcesareRaspunsuri
LPARAMETERS tlFortareRaspunsuri
Local lcDir, lcDir2, lcErrorMessage, lcFile, lcFile2, lcFile2Semnatura, lcFilePdf, lcFileSemnatura
Local lcIdDescarcare, lcIdIncarcare, lcTipRaspuns, lcZipFile, llSucces, loEx, loFactura, llFortareRaspunsuri
llFortareRaspunsuri = m.tlFortareRaspunsuri
This.Log('Procesare Raspunsuri')
* procesez server si nu este descarcat sau client (borderou eFactura ROACONT) si nu este procesat (completat detalii)
SELECT id_incarcare, id_descarcare, tip_mesaj_raspuns, filepath, procesat ;
FROM anaf_efactura WITH (BUFFERING = .T.) ;
WHERE ((This.lServer AND (procesat_server = 0 OR procesat = 0)) OR (!This.lServer AND (procesat = 0 OR modificat = 1))) AND ;
!EMPTY(NVL(filepath,'')) ;
ORDER BY id_incarcare ;
INTO CURSOR cRaspunsuriTemp
This.Log('Procesare Raspunsuri ' + ALLTRIM(STR(RECCOUNT('cRaspunsuriTemp'))) + ' fisiere de procesat')
llSucces = .T.
SELECT cRaspunsuriTemp
SCAN
lcIdIncarcare = ALLTRIM(id_incarcare)
lcIdDescarcare = ALLTRIM(id_descarcare)
lcZipFile = ALLTRIM(filepath)
lcTipRaspuns = UPPER(ALLTRIM(tip_mesaj_raspuns))
lcText = 'ProcesareRaspunsuri ' + ALLTRIM(STR(RECNO())) + '/' + ALLTRIM(STR(RECCOUNT()))
WAIT WINDOW m.lcText NOWAIT
This.Log(m.lcText)
IF FILE(m.lcZipFile)
lcDir = ''
lcErrorMessage = ''
llSucces = This.UnzipFile(m.lcZipFile, @lcDir, @lcErrorMessage)
IF !m.llSucces
lcErrorMessage = 'ProcesareRaspunsuri Eroare dezarhivare detalii factura id_incarcare = ' + Alltrim(m.lcIdIncarcare) + '. ' + m.lcErrorMessage
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
WAIT WINDOW m.lcErrorMessage NOWAIT
This.Log(m.lcErrorMessage)
ELSE
TRY
lcFile = Addbs(m.lcDir) + m.lcIdIncarcare + '.xml'
lcFileSemnatura = Addbs(m.lcDir) + 'semnatura_' + m.lcIdIncarcare + '.xml'
* Completez xml dezarhivat in anaf_efactura
lcDetalii = FILETOSTR(m.lcFile)
llSucces = This.cUpdateDetalii(m.lcIdIncarcare, m.lcDetalii)
IF !m.llSucces
lcErrorMessage = 'ProcesareRaspunsuri Eroare actualizare detalii id_incarcare ' + m.lcIdIncarcare
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
WAIT WINDOW m.lcErrorMessage NOWAIT
This.Log(m.lcErrorMessage)
ENDIF
* Parsez doar FATURA PRIMITA/FACTURA TRIMISA
IF Inlist(m.lcTipRaspuns, 'FACTURA PRIMITA', 'FACTURA TRIMISA') AND FILE(m.lcFile)
loFactura = ParseEFactura(m.lcFile)
ADDPROPERTY(loFactura, 'cIdIncarcare', m.lcIdIncarcare)
ADDPROPERTY(loFactura, 'cIdDescarcare', m.lcIdDescarcare)
ADDPROPERTY(loFactura, 'tip_mesaj_raspuns', m.lcTipRaspuns)
llSucces = This.cUpdateFactura(loFactura)
* Pe server, copiez arhiva zip, generez pdf in structura directoare custom
IF (This.nSaveFile = 1) AND ((This.lServer AND !EMPTY(NVL(This.cServerPath,''))) OR (!This.lServer AND !EMPTY(NVL(This.cNetworkPath,''))))
lcFile2 = This.GetFacturaSavePath(loFactura, 'zip')
lcDir2 = ADDBS(JUSTPATH(m.lcFile2))
lcFilePdf = m.lcDir2 + Juststem(m.lcFile2) + '.pdf'
If !File(m.lcFile2)
llSucces = This.SaveFile(m.lcZipFile, .F., m.lcDir2, JUSTFNAME(m.lcFile2))
ENDIF
IF (this.nSaveAnafPdfFile = 1) AND !FILE(m.lcFilePdf)
lcFilePdf = This.xml2PdfAnaf(m.lcFile, m.lcFilePdf)
ENDIF
This.cUpdateProcesatServer(m.lcIdIncarcare)
ELSE
* Marchez procesat server si daca nu trece prin procesul de procesare, pentru ca altfel il procesez din nou si urmatoarea data (dezarhivare, copiere)
This.cUpdateProcesatServer(m.lcIdIncarcare)
ENDIF && This.nSaveFile = 1
ENDIF && lcTipRaspuns
DELETE FILE(m.lcFile)
DELETE FILE(m.lcFileSemnatura)
Catch To loEx
llSucces = .F.
lcErrorMessage = 'ProcesareRaspunsuri Eroare la salvarea datelor extrase din xml eFactura. ' + 'Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
WAIT WINDOW m.lcErrorMessage NOWAIT
This.Log(m.lcErrorMessage)
ENDTRY
ENDIF
ENDIF
ENDSCAN && cRaspunsuriTemp
USE IN (SELECT('cRaspunsuriTemp'))
RETURN m.llSucces
ENDPROC && ProcesareRaspunsuri
*********************************
* RASPUNSURI FACTURI
* Trebuie sa descarc ERORI FACTURI TRIMISE si FACTURI PRIMITE si sa citesc detalii (mesaj eroare, numar, data factura, detalii factura furnizor)
* Citesc lista de raspunsuri ANAF
* Descarc detaliile fiecarui raspuns neprocesat
* Salvez arhiva zip detalii in directorul zilei curente
*********************************
Procedure DescarcareRaspunsuri
Lparameters tnZile, tlFortareRaspunsuri
* tnZile : Cate zile de raspunsuri de la ANAF
* tlFortareRaspunsuri: .T. = se proceseaza si mesajele + detaliile deja salvate si procesate, default .F.
Local lcFile2, lcSelect, llSucces, lnMesaj, lnMesaje, lnRecno, lnZile, loAnafMesaj, loEx, loJson
Local loReturn, loMesaj, lnFortareRaspunsuri, loEx As Exception
llFortareRaspunsuri = Iif(Type('tlFortareRaspunsuri') = 'L', m.tlFortareRaspunsuri, .F.)
lcSelect = Select()
llSucces = .F.
*************************************************
Local loHTTP As 'winHTTP.winHTTPrequest.5.1'
Local loReturn As "empty"
Local lcServer, llTest, lcToken, lcCodFiscal, lnZile, lcText
llTest = This.lTest
lcToken = This.cToken
lcCodFiscal = This.cCodfiscal
lnZile = Iif(!Empty(m.tnZile), Min(m.tnZile, 60), 60)
ltEndTime = GetUtcTime(DATETIME()-60) && 60 de secunde in urma, ca sa fiu sigur? ca ceasul calculatorului nu este inainte fata de timpul serverului ANAF. Poate fi si cu mai mult de 1 minut
ltStartTime = ltEndTime - m.lnZile*24*60*60
lcStartTime = ALLTRIM(STR(Datetime2UnixTime(m.ltStartTime))) + '000'
lcEndTime = ALLTRIM(STR(Datetime2UnixTime(m.ltEndTime))) + '000'
loHTTP = Createobject('winHTTP.winHTTPrequest.5.1')
lnPagina = 1
lnNumarTotalPagini = 99999
DO WHILE m.lnPagina <= m.lnNumarTotalPagini
TEXT TO lcServer TEXTMERGE NOSHOW
https://api.anaf.ro/<<Iif(m.llTest, [test], [prod])>>/FCTEL/rest/listaMesajePaginatieFactura?startTime=<<lcStartTime>>&endTime=<<lcEndTime>>&cif=<<lcCodFiscal>>&pagina=<<lnPagina>>
ENDTEXT
lcText = 'Descarcare Raspunsuri ultimele ' + TRANSFORM(m.lnZile) + ' zile : ' + TTOC(m.ltStartTime,3) + '-' + TTOC(m.ltEndTime,3)
WAIT WINDOW m.lcText NOWAIT
This.Log(m.lcText + ' ' + m.lcServer)
loHTTP.Open('GET', lcServer, .F.)
loHTTP.setRequestHeader("Content-Type", "application/xml;")
loHTTP.setRequestHeader('Authorization', 'Bearer ' + m.lcToken)
loHTTP.Send()
llSucces = (loHttp.Status = 200)
IF !m.llSucces
lcErrorMessage = This.cUser + ' ' + 'DescarcareRaspunsuri Eroare la citirea raspunsurilor! Solutii: 1. Reincercati operatia cu o perioada mai mica. 2. Actualizati/Regenerati token-ul de acces daca este expirat.' + LF + loHTTP.ResponseText
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
EXIT
ENDIF
llSucces = This.SaveFile(loHttp.ResponseText, .T.,This.cSaveLogsPath,'response_json_' + TTOC(Datetime(),1) + '.txt')
TRY
loJson = nfjsonread(loHTTP.ResponseText)
CATCH TO loEx
llSucces = .F.
lcErrorMessage = This.cUser + ' ' + 'DescarcareRaspunsuri ' + LF + ' Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
ENDTRY
IF TYPE('loJson') <> 'O'
llSucces = .F.
lcErrorMessage = This.cUser + ' ' + 'DescarcareRaspunsuri ' + LF + ' Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
EXIT
ENDIF
If Type('loJson.numar_total_pagini') = 'N'
lnNumarTotalPagini = loJson.numar_total_pagini
ENDIF
If Type('loJson.eroare') = 'C' And !Empty(loJson.eroare)
llSucces = .F.
lcErrorMessage = This.cUser + LF + loJson.eroare
This.cErrorMessage = m.lcErrorMessage + ;
IIF(ATC('Nu exista mesaje in intervalul selectat', loJson.eroare) > 0, '', ;
LF + 'Posibile cauze/solutii: Token expirat (regenerati tokenul), semnatura electronica expirata (reinnoiti semnatura in SPV)' + ;
LF + ;
LF + 'Apasati pe butonul Chatbot (stanga) pentru alte solutii!')
This.lError = .T.
This.Log(m.lcErrorMessage)
EXIT
ENDIF
If Type('loJson.mesaje') = 'U'
llSucces = .F.
lcErrorMessage = This.cUser + ' ' + 'DescarcareRaspunsuri Eroare: Nu exista informatia [mesaje] in raspuns.' + LF + loHttp.ResponseText
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
EXIT
ENDIF
lnMesaje = Alen(loJson.mesaje)
For lnMesaj = 1 To m.lnMesaje
lcText = This.cUser + ' ' + 'DescarcareRaspunsuri Raspuns ' + Alltrim(Str(m.lnMesaj)) + '/' + Alltrim(Str(m.lnMesaje))
WAIT WINDOW m.lcText NOWAIT
This.Log(m.lcText)
loMesaj = loJson.mesaje[m.lnMesaj]
AddProperty(loMesaj, 'recno', m.lnMesaj)
AddProperty(loMesaj, 'recc', m.lnMesaje)
lcIdIncarcare = IIF(Type('loMesaj.id_solicitare') = 'C' And !Empty(Nvl(loMesaj.id_solicitare, '')), loMesaj.id_solicitare, '')
IF !EMPTY(m.lcIdIncarcare)
* Nu procesez mesajele deja descarcate, decat daca fortez procesarea tuturor mesajelor
IF m.llFortareRaspunsuri OR (This.lServer AND !This.cIsDescarcat(m.lcIdIncarcare)) OR (!This.lServer AND !This.cIsProcesat(m.lcIdIncarcare))
loAnafMesaj = This.ProceseazaMesaj(loMesaj)
llSucces = !loAnafMesaj.lEroare
IF loAnafMesaj.lEroare
This.lError = .T.
This.cErrorMessage = loAnafMesaj.cEroare
ENDIF
ENDIF
ELSE
llSucces = .F.
lcErrorMessage = This.cUser + ' ' + 'DescarcareRaspunsuri Eroare: EMPTY(loMesaj.id_solicitare) Mesaj ' + Alltrim(Str(m.lnMesaj)) + '/' + Alltrim(Str(m.lnMesaje))
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
EXIT
ENDIF && empty
Endfor && lnMesaj
lnPagina = m.lnPagina + 1
ENDDO && .T.
Select (m.lcSelect)
Return m.llSucces
Endproc && DescarcareRaspunsuri
*****************************
* Dezarhiveaza mesajul, parseaza xml efactura trimisa/primita si salveaza pe disk si in baza de date
* Intoarce un obiect AnafMesaj (cEroare, lEroare)
****************************
Procedure ProceseazaMesaj
Lparameters toMesaj
Local loDate As "empty"
Local lcDirectory, lcFile, lcTip, lcTipRaspuns, llSucces, lnAn, lnLuna, lnMin, lnOra, lnSec, lnZi
Local loAnafMesaj, loDetalii, lcFilePath
loAnafMesaj = This.NewMesaj()
With toMesaj
loAnafMesaj.cIdIncarcare = .id_solicitare
lnAn = Val(Substr(.data_creare, 1, 4))
lnLuna = Val(Substr(.data_creare, 5, 2))
lnZi = Val(Substr(.data_creare, 7, 2))
lnOra = Val(Substr(.data_creare, 9, 2))
lnMin = Val(Substr(.data_creare, 11, 2))
lnSec = Val(Substr(.data_creare, 13, 2))
loAnafMesaj.dDataRaspuns = Datetime(m.lnAn, m.lnLuna, m.lnZi, m.lnOra, m.lnMin, m.lnSec)
loAnafMesaj.cMesajRaspuns = .detalii
loAnafMesaj.cTipMesajRaspuns = .tip
loAnafMesaj.cIdDescarcare = .Id
loAnafMesaj.cCodFiscalEmitent = Strextract(.detalii, [cif_emitent=], [ ],1,1+2)
loAnafMesaj.cCodFiscalBeneficiar = Strextract(.detalii, [cif_beneficiar=], [ ],1,1+2)
loAnafMesaj.nTest = Iif(This.lTest, 1, 0) && server TEST ANAF
loAnafMesaj.nFacturaEmisa = IIF(UPPER(ALLTRIM(.tip)) = 'FACTURA PRIMITA', 0, 1)
lcTipRaspuns = Alltrim(Upper(loAnafMesaj.cTipMesajRaspuns))
* Adaug mesajul in cRaspunsuri
This.cAddMesaj(loAnafMesaj)
lcTip = Iif('ERORI'$m.lcTipRaspuns, 'ERORI', Iif('PRIMIT'$m.lcTipRaspuns, 'PRIMITE', Iif('TRIMIS'$m.lcTipRaspuns, 'TRIMISE', IIF('MESAJ CUMPARATOR TRANSMIS'$m.lcTipRaspuns, 'MESAJE', 'ALTELE'))))
lcFile = loAnafMesaj.cIdIncarcare + '_' + loAnafMesaj.cIdDescarcare + '.zip' && C:\EFACTURA\PRIMITE\20240112\1234_1234\
IF this.lServer
lcDirectory = This.cResponsesPath + m.lcTip + '\' + Dtos(Date()) + '\'
ELSE
lcDirectory = GetPdfPath('EFACTURA', m.lcTip)
ENDIF
lcFilePath = m.lcDirectory + m.lcFile
* Daca nu exista fisierul zip descarcat de alt program
IF !FILE(m.lcFilePath)
* Descarca detalii raspuns
loDetalii = This.DownloadDetaliiEFactura(loAnafMesaj.cIdDescarcare, ' Descarcare detalii factura ID: ' + loAnafMesaj.cIdDescarcare)
llSucces = loDetalii.lSucces
If !m.llSucces
loAnafMesaj.cEroare = 'Eroare descarcare detalii factura id_descarcare = ' + Alltrim(loAnafMesaj.cIdDescarcare) + ;
'. Cod eroare: ' + Alltrim(Transform(loDetalii.nStatus)) + ' ' + loDetalii.cErrorMessage
loAnafMesaj.lEroare = .T.
Else
If 'eroare' $ Lower(loDetalii.cResponse)
loAnafMesaj.cEroare = 'Eroare descarcare detalii raspuns id_descarcare = ' + Alltrim(loAnafMesaj.cIdDescarcare) + '. ' + loDetalii.cResponse
loAnafMesaj.lEroare = .T.
Endif && 'eroare' $ Lower(loDetalii.cResponse)
Endif && m.llSucces loDetalii.lSucces
IF loAnafMesaj.lEroare
This.Log('Proceseaza Mesaj ' + loAnafMesaj.cEroare)
ELSE
llSucces = This.SaveFile(loDetalii.cResponse, .T., m.lcDirectory, m.lcFile)
This.Log('Proceseaza Mesaj salvare fisier: ' + Transform(m.llSucces) + ' ' + m.lcFilePath)
ENDIF && lEroare
ENDIF && !file
ENDWITH && toMesaj
* Salvez arhiva pe disk
IF FILE(m.lcFilePath)
This.Log('Proceseaza Mesaj. Exista fisierul: ' + m.lcFilePath)
loAnafMesaj.lEroare = .F.
llSucces = .T.
* Actualizez cRaspunsuri.descarcat, filepath
lnDescarcatServer = IIF(this.lServer, 1, 0) && marchez descarcat doar daca am descarcat pe server
This.cUpdateDescarcat(loAnafMesaj.cIdIncarcare, m.lnDescarcatServer, m.lcFilePath)
ENDIF
Return loAnafMesaj
Endproc && ProceseazaMesaj
* Salveaza fisiere/variabile pe disk
Procedure SaveFile
Lparameters tcFile, tlVariable, tcDirectory, tcFileName
* tcFile: calea catre fisierul sursa
* tlVariable: .T. daca tcFile este o variabila cu continutul fisierului
* tcFileName: numele fisierului destinatie
Local lcFile2, llSucces, loEx As Exception
llSucces = .T.
lcFileName2 = Iif(!Empty(m.tcFileName), m.tcFileName, Justfname(m.tcFile))
lcFile2 = Addbs(m.tcDirectory) + m.lcFileName2
If !Empty(m.tcDirectory) And !Directory(m.tcDirectory)
Try
Md (m.tcDirectory)
Catch To loEx
llSucces = .F.
This.Log('SaveFile ' + 'Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure)
Endtry
Endif
If !Empty(m.tcDirectory) And Directory(m.tcDirectory)
Try
If m.tlVariable
Strtofile(m.tcFile, m.lcFile2)
Else
Copy File (m.tcFile) To (m.lcFile2)
ENDIF
This.Log('SaveFile ' + m.lcFile2)
llSucces = .T.
Catch To loEx
llSucces = .F.
This.Log('SaveFile ' + 'Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure)
Endtry
Endif
Return m.llSucces
Endproc && SaveFile
************
* Intoarce calea de salvare xml intr-un director comun, definit in baza de date OPTIUNI
************
Procedure GetFacturaSavePath
Lparameters toFactura, tcExt
* tcExt: optional, default xml
Local loReturn As "empty"
Local lcAn, lcDataAct, lcFile2, lcFile2Semnatura, lcFilePdf, lcFileSemnatura, lcFurnizor
Local lcIdDescarcare, lcIdIncarcare, lcLuna, lcLuna2, lcLuna3, lcNumarAct, lcSaveFile, lcSavePath
Local llSucces, lcExt, lcFirma
llSucces = .F.
lcExt = IIF(!EMPTY(m.tcExt), m.tcExt, 'xml')
lcTip = ALLTRIM(UPPER(toFactura.tip_mesaj_raspuns)) && FACTURI TRIMISE / FACTURI PRIMITE
llFurnizor = 'PRIMIT'$m.lcTip
IF m.llFurnizor
lcPartener = WindowsSpecialCharacters(toFactura.Furnizor)
lcSavePath = This.cSaveFurnizoriPath
lcSaveFile = This.cSaveFurnizoriFile
ELSE
lcPartener = WindowsSpecialCharacters(toFactura.Client)
lcSavePath = This.cSaveClientiPath
lcSaveFile = This.cSaveClientiFile
ENDIF
lcFirma = This.cUser
lcPartener = Alltrim(Left(Strtran(m.lcPartener, '.', '',1,100,1), 50))
lcAn = Alltrim(Str(Year(toFactura.dataact)))
lcLuna = c_luna(Month(toFactura.dataact))
lcLuna3 = cluna3(Month(toFactura.dataact))
lcLuna2 = Padl(Month(toFactura.dataact), 2, '0')
lcDataAct = Dtos(toFactura.dataact)
lcIdIncarcare = toFactura.cIdIncarcare
lcIdDescarcare = toFactura.cIdDescarcare
lcNumarAct = Alltrim(WindowsSpecialCharacters(toFactura.numaract))
lcSavePath = Strtran(m.lcSavePath, '<an>', m.lcAn, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<aaaa>', m.lcAn, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<id_incarcare>', m.lcIdIncarcare, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<id_descarcare>', m.lcIdDescarcare, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<luna>', m.lcLuna, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<lll>', m.lcLuna3, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<ll>', m.lcLuna2, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<yyyymmdd>', m.lcDataAct, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<datafact>', m.lcDataAct, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<furnizor>', m.lcPartener, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<client>', m.lcPartener, 1, 100, 1)
lcSavePath = Strtran(m.lcSavePath, '<firma>', m.lcFirma, 1, 100, 1)
lcSavePath = Addbs(m.lcSavePath)
If Empty(m.lcSaveFile)
lcFile2 = m.lcSavePath + m.lcIdIncarcare + '_' + m.lcIdDescarcare + '_' + m.lcDataAct + '_' + m.lcNumarAct + '.' + m.lcExt
Else
lcFile2 = m.lcSavePath + Strtran(m.lcSaveFile, '<id_incarcare>', m.lcIdIncarcare, 1, 100, 1)
lcFile2 = Strtran(m.lcFile2, '<id_descarcare>', m.lcIdDescarcare, 1, 100, 1)
lcFile2 = Strtran(m.lcFile2, '<datafact>', m.lcDataAct, 1, 100, 1)
lcFile2 = Strtran(m.lcFile2, '<furnizor>', m.lcPartener, 1, 100, 1)
lcFile2 = Strtran(m.lcFile2, '<client>', m.lcPartener, 1, 100, 1)
If EMPTY(Justext(Lower(m.lcFile2)))
lcFile2 = m.lcFile2 + '.' + m.lcExt
Endif
ENDIF
RETURN m.lcFile2
Endproc && GetFacturaSavePath
************************************
* Intoarce un obiect tip ANAF_EFACTURA, doar informatiile din mesajul ANAF, pentru salvarea in baza de date
************************************
Function NewMesaj
Local loMesaj
loMesaj= Createobject("empty")
AddProperty(loMesaj, 'nId', Null)
AddProperty(loMesaj, 'cIdIncarcare', Null)
AddProperty(loMesaj, 'cMesajRaspuns', Null)
AddProperty(loMesaj, 'dDataRaspuns', Null)
AddProperty(loMesaj, 'cMesajRaspuns', Null)
AddProperty(loMesaj, 'cTipMesajRaspuns', Null)
AddProperty(loMesaj, 'cIdDescarcare', Null)
AddProperty(loMesaj, 'cCodFiscalEmitent', Null)
AddProperty(loMesaj, 'cCodFiscalBeneficiar', Null)
AddProperty(loMesaj, 'cDetalii', Null)
AddProperty(loMesaj, 'nFacturaEmisa', Null)
AddProperty(loMesaj, 'nTest', 0)
AddProperty(loMesaj, 'lEroare', .F.)
AddProperty(loMesaj, 'cEroare', '')
Return loMesaj
Endfunc && NewMesaj
* Citeste raspunsuri eFactura de la ANAF
Function ReadResponseEFactura
Lparameters tnZile
Local loHTTP As 'winHTTP.winHTTPrequest.5.1'
Local loReturn As "empty"
Local lcServer, llTest, lcToken, lcCodFiscal, lnZile
llTest = This.lTest
lcToken = This.cToken
lcCodFiscal = This.cCodFiscal
lnZile = Iif(!Empty(m.tnZile), Min(m.tnZile, 60), 60)
This.Log('ReadResponseEfactura: Citire raspunsuri ANAF ultimele ' + Alltrim(Str(m.lnZile)) + '...')
Try
lcServer = [https://api.anaf.ro/] + Iif(m.llTest, [test], [prod]) + [/FCTEL/rest/listaMesajeFactura?zile=] + Alltrim(Str(m.lnZile)) + [&cif=] + m.lcCodFiscal && 1879855
This.Log(m.lcServer)
loHTTP = Createobject('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('GET', lcServer, .F.)
loHTTP.setRequestHeader("Content-Type", "application/xml;")
loHTTP.setRequestHeader('Authorization', 'Bearer ' + m.lcToken)
loHTTP.Send()
Catch To loEx
This.Log('ReadResponseEfactura ' + loEx.Message)
Endtry
loReturn = Createobject("empty")
AddProperty(loReturn, "lSucces", (loHTTP.Status = 200))
AddProperty(loReturn, "cResponse", loHTTP.ResponseText)
AddProperty(loReturn, "nStatus", loHTTP.Status)
If loHTTP.Status <> 200
loReturn.cResponse = loHTTP.StatusText && 403 Forbidden
Endif
This.Log('ReadResponseEfactura ' + Transform(loHTTP.Status))
Return loReturn
Endfunc
******************
* Citeste detalii factura eFactura de la ANAF
* Intoarce un obiect cu cResponse (continutul arhivei zip)
*****************
Function DownloadDetaliiEFactura
Lparameters tcIdDescarcare, tcWaitWindowText
* tcIdDescarcare: Id descarcare ANAF
* tcWaitWindowText: optional, text pentru wait window:
Local loHTTP As 'winHTTP.winHTTPrequest.5.1'
Local loReturn As "empty", loEx As Exception
Local lcServer, llTest, lcToken, lcCodFiscal, lcIdDescarcare, lcErrorMessage, lcWaitWindowText
llTest = This.lTest
lcToken = This.cToken
lcIdDescarcare = m.tcIdDescarcare
lcErrorMessage = ''
lcWaitWindowText = Iif(!Empty(m.tcWaitWindowText), m.tcWaitWindowText, 'Descarcare detalii factura ID: ' + m.tcIdDescarcare)
WAIT WINDOW m.lcWaitWindowText NOWAIT
Try
lcServer = [https://api.anaf.ro/] + Iif(m.llTest, [test], [prod]) + [/FCTEL/rest/descarcare?id=] + m.lcIdDescarcare
This.Log('DownloadDetaliieFactura ' + m.lcServer)
loHTTP = Createobject('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('GET', lcServer, .F.)
loHTTP.setRequestHeader("Content-Type", "application/xml;")
loHTTP.setRequestHeader('Authorization', 'Bearer ' + m.lcToken)
loHTTP.Send()
Catch To loEx
This.Log('DownloadDetaliieFactura ' + loEx.Message)
Endtry
loReturn = Createobject("empty")
AddProperty(loReturn, "lSucces", (loHTTP.Status = 200))
If 'eroare' $ Lower(loHTTP.ResponseText)
lcResponse = loHTTP.ResponseText
lcErrorMessage = m.lcResponse
Else
lcResponse = loHTTP.ResponseBody
Endif
AddProperty(loReturn, "cResponse", m.lcResponse) && arhiva zip sau json cu text eroare {'eroare' : 'Factura cu id 1112 nu exista'}
AddProperty(loReturn, "nStatus", loHTTP.Status)
AddProperty(loReturn, "cErrorMessage", m.lcErrorMessage)
This.Log('DownloadDetaliieFactura ' + Transform(loHTTP.Status) + ' ' + m.lcErrorMessage)
Return loReturn
Endfunc
*****************
* Adauga/actualizeaza datele si detaliile facturii in baza de date ANAF_EFACTURA
* Foloseste obiect returnat din ParseEFactura
* Intoarce SUCCES = .T.
*****************
Procedure cUpdateFactura
Parameters toFactura, tcCursor
*toFactura: obiect din ParseEFactura
* tcCursor: optional, anaf_efactura sau un cursor asemanator, temporar
LOCAL llSucces, lcSql, lcCursor
lcCursor = IIF(EMPTY(m.tcCursor), 'anaf_efactura', m.tcCursor)
UPDATE (m.lcCursor) ;
set xnumar_act = toFactura.NumarAct, ;
xdata_act = toFactura.DataAct, ;
xdata_scad = toFactura.DataScad, ;
xdescriere = toFactura.Detalii, ;
xdetalii_plata = Left(toFactura.Detaliiplata, 500), ;
xtotal_fara_tva = toFactura.TotalFaraTva, ;
xtotal_tva = toFactura.TotalTva, ;
xtotal_tva_ron = toFactura.TotalTvaRON, ;
xtotal_cu_tva = toFactura.TotalCuTva, ;
xdiscount_fara_tva = toFactura.DiscountFaraTVA, ;
xtaxe_fara_tva = toFactura.TaxeFaraTVA, ;
xvaloare_fara_tva = toFactura.ValoareFaraTVA, ;
xtotal_de_plata = toFactura.TotaldePlata, ;
xnume_valuta = toFactura.Valuta, ;
xfurnizor = toFactura.Furnizor, ;
xclient = toFactura.Client, ;
factura_detalii = toFactura.FacturaDetalii, ;
creditnote = toFactura.CreditNote, ;
cod_fiscal_emitent = IIF(EMPTY(NVL(cod_fiscal_emitent,'')), UPPER(ALLTRIM(GetNrFromString(NVL(toFactura.CodFiscalFurnizor,'')))), cod_fiscal_emitent), ;
cod_fiscal_beneficiar = IIF(EMPTY(NVL(cod_fiscal_beneficiar,'')), UPPER(ALLTRIM(GetNrFromString(NVL(toFactura.CodFiscalClient,'')))), cod_fiscal_beneficiar), ;
modificat = 1 ;
where id_incarcare = toFactura.cIdIncarcare
llSucces = .T.
TABLEUPDATE(1,.F., m.lcCursor)
RETURN m.llSucces
Endproc && cUpdateFactura
*****************
* Adauga/actualizeaza un raspuns FACTURA PRIMITA/TRIMISA/EROARE in ANAF_EFACTURA
* Mesajul intoarce ANAF_EFACTURA.ID
* Intoarce SUCCES = .T.
*****************
Procedure UpdateRaspuns
Parameters toMesaj
Private pnId
pnId = 0
TEXT TO lcSql NOSHOW
BEGIN
pack_anaf.UpdateRaspuns(?.cIdIncarcare,
?.dDataRaspuns,
?.cMesajRaspuns,
?.cTipMesajRaspuns,
?.cIdDescarcare,
?.cCodFiscalEmitent,
?.cCodFiscalBeneficiar,
?.cDetalii,
?.nTest,
?@pnId);
end;
ENDTEXT
With toMesaj
llSucces = goExecutor.oExecuta(m.lcSql)
Endwith
If m.llSucces
toMesaj.nId = m.pnId
Endif
Return m.llSucces
Endproc && UpdateRaspuns
*****************
* Actualizeaza un ANAF_EFACTURA.DETALII, DETALII_ZIP (arhiva xml efactura) dupa ce se descarca arhiva cu detaliile unui raspuns
* Intoarce SUCCES = .T.
*****************
Procedure UpdateRaspunsDetalii
Parameters pcIdDescarcare, pcDetalii, pcDetaliiZip
Local lcSql, llSucces
* Fac update direct pe tabela in loc de pack_anaf.UpdateRaspunsDetalii, pentru ca da cateaodata eroare (BUG oracle)
llSucces = goExecutor.oExecuta('update anaf_efactura set detalii = ?pcDetalii, detalii_zip = ?pcDetaliiZip where id_descarcare = ?pcIdDescarcare')
If .F. && am facut direct update pe tabela
lcSql = [BEGIN pack_anaf.UpdateRaspunsDetalii(?pcIdDescarcare, ?pcDetalii, ?pcDetaliiZip); end;]
llSucces = goExecutor.oExecuta(m.lcSql)
If !m.llSucces
* Da eroare cateodata, asa ca reincerc update direct pe tabela
If AMESSAGEBOX('Doriti sa reincercati actualizarea detaliilor?',4+32,_Screen.Caption) = 6
llSucces = goExecutor.oExecuta('update anaf_efactura set detalii = ?pcDetalii, detalii_zip = ?pcDetaliiZip where id_descarcare = ?pcIdDescarcare')
Endif
Endif
Endif
Return m.llSucces
Endproc && UpdateRaspunsDetalii
*****************
* Marcheaza ANAF_EFACTURA.PROCESAT = 1 ca sa nu se mai descarce arhiva cu detaliile raspunsului, daca mesajul a fost procesat
*****************
Procedure UpdateProcesat
Parameters tcIdDescarcare, tnProcesat
* tnIdEfactura: ANAF_EFACTURA.ID_DESCARCARE
* tnProcesat: OPTIONAL, DEFAULT (1)
Local lcSql, llSucces
Private pnProcesat
pnProcesat = Iif(!Empty(m.tnProcesat) And Type('tnProcesat') = 'N' And Inlist(m.tnProcesat,0,1), m.tnProcesat, 1)
lcSql = [BEGIN pack_anaf.UpdateProcesat(?tcIdDescarcare, ?pnProcesat); END;]
llSucces = goExecutor.oExecuta(m.lcSql)
Return m.llSucces
Endproc && UpdateProcesat
*****************
* Intoarce .T. daca un IdDescarcare a fost descarcat
*****************
Function cIsDescarcat
Parameters tcIdIncarcare
Local llDescarcat
IF SEEK(m.tcIdIncarcare, 'anaf_efactura', 'id_inc')
llDescarcat = (anaf_efactura.descarcat = 1)
ENDIF
RETURN m.llDescarcat
Endfunc && cIsDescarcat
*****************
* Intoarce .T. daca un IdIncarcare a fost procesat
*****************
Function cIsProcesat
Parameters tcIdIncarcare
Local llProcesat
IF SEEK(m.tcIdIncarcare, 'anaf_efactura', 'id_inc')
llProcesat = (anaf_efactura.procesat = 1)
ENDIF
RETURN m.llProcesat
Endfunc && cIsProcesat
*****************
* Completeaza raspunsuri.descarcat, filepath, dupa salvarea arhivei raspuns
*****************
PROCEDURE cAddMesaj
PARAMETERS toMesaj
LOCAL lcSql, llSucces
TEXT TO lcSql NOSHOW
merge into anaf_efactura a using dual b ON (a.id_incarcare = ?tcIdIncarcare)
when not matched then
INSERT (id_incarcare, id_descarcare) VALUES (?tcIdIncarcare, ?tcIdDescarcare)
ENDTEXT
*!* llSucces = goExecutor.oExecuta(m.lcSql)
*!* IF m.llSucces
WITH toMesaj
IF !SEEK(.cIdIncarcare,'anaf_efactura', 'id_inc')
INSERT INTO anaf_efactura (id_incarcare, id_descarcare,tip_mesaj_raspuns,mesaj_raspuns,data_raspuns,cod_fiscal_emitent,cod_fiscal_beneficiar,factura_emisa,test) ;
VALUES (.cIdIncarcare, .cIdDescarcare, .cTipMesajRaspuns,.cMesajRaspuns,.dDataRaspuns,.cCodFiscalEmitent,.cCodFiscalBeneficiar,.nFacturaEmisa,.nTest)
TABLEUPDATE(1,.F.,'ANAF_EFACTURA')
ENDIF
ENDWITH
llSucces = .T.
*!* ENDIF
RETURN m.llSucces
ENDPROC && AddMesaj
*****************
* Completeaza raspunsuri.descarcat, filepath, dupa salvarea arhivei raspuns
*****************
PROCEDURE cUpdateDescarcat
PARAMETERS tcIdIncarcare, tnDescarcat, tcFilePath
TEXT TO lcSql noshow
UPDATE anaf_efactura SET descarcat = ?tnDescarcat, filepath = ?tcFilePath WHERE id_incarcare = ?tcIdIncarcare
ENDTEXT
*!* llSucces = goExecutor.oExecuta(m.lcSql)
*!* IF m.llSucces
UPDATE anaf_efactura SET descarcat = m.tnDescarcat, filepath = m.tcFilePath, modificat = 1 WHERE id_incarcare = m.tcIdIncarcare
TABLEUPDATE(1,.F.,'ANAF_EFACTURA')
llSucces = .T.
*!* ENDIF
RETURN m.llSucces
ENDPROC
*****************
* Completeaza raspunsuri.descarcat, filepath, dupa salvarea arhivei raspuns
*****************
PROCEDURE cUpdateProcesat
PARAMETERS tcIdIncarcare
UPDATE anaf_efactura SET procesat = 1, modificat = 1 WHERE id_incarcare = m.tcIdIncarcare
TABLEUPDATE(1,.F.,'ANAF_EFACTURA')
llSucces = .T.
RETURN m.llSucces
ENDPROC
*****************
* Completeaza anaf_efactura.procesat_server = 1, dupa procesarea arhivei pe servers sau in directorul din retea
*****************
PROCEDURE cUpdateProcesatServer
PARAMETERS tcIdIncarcare
UPDATE anaf_efactura SET procesat_server = 1, modificat = 1 WHERE id_incarcare = m.tcIdIncarcare
TABLEUPDATE(1,.F.,'ANAF_EFACTURA')
llSucces = .T.
RETURN m.llSucces
ENDPROC
*****************
* Completeaza anaf_efactura.detalii (continutul fisierului xml din raspuns)
*****************
PROCEDURE cUpdateDetalii
PARAMETERS tcIdIncarcare, tcDetalii
UPDATE anaf_efactura SET detalii = m.tcDetalii, modificat = 1 WHERE id_incarcare = m.tcIdIncarcare
TABLEUPDATE(1,.F.,'ANAF_EFACTURA')
llSucces = .T.
RETURN m.llSucces
ENDPROC
*****************
* actualizeaza anaf_efactura
*****************
PROCEDURE UpdateDb
LPARAMETERS tcCursor
LOCAL lcSql, llSucces, lnSucces, lcSelect, lcCursor
lcSelect = SELECT()
lcCursor = IIF(EMPTY(m.tcCursor), 'anaf_efactura', m.tcCursor)
llSucces = .T.
lnSucces = This.ConnectROA()
IF m.lnSucces = CT_SUCCES
* Actualizez datele doar pentru facturile care nu au fost procesate (fie de catre server, fie de catre clienti)
SELECT * FROM (m.lcCursor) WITH (BUFFERING = .T.) WHERE modificat = 1 OR procesat = 0 INTO CURSOR crsUpdateTemp
SELECT crsUpdateTemp
SCAN
SCATTER NAME loRec MEMO
lcText = 'Actualizare baza de date ' + ALLTRIM(STR(RECNO())) + '/' + ALLTRIM(STR(RECCOUNT()))
WAIT WINDOW m.lcText NOWAIT
This.Log(m.lcText)
llSucces = This.UpdateDbFactura(loRec)
IF !m.llSucces
lcErrorMessage = This.cErrorMessage
IF LEN(m.lcErrorMessage) > 200
IF This.lServer
WAIT WINDOW LEFT(m.lcErrorMessage,200) NOWAIT
ELSE
AMESSAGEBOX(m.lcErrorMessage,0+48,_Screen.Caption)
ENDIF
ELSE
WAIT WINDOW m.lcErrorMessage NOWAIT
ENDIF
This.Log(m.lcErrorMessage)
IF !This.lServer
* daca imi da eroare la o factura, incerc sa le actualizez pe celelalte
IF AMESSAGEBOX('Continuati actualizarea celorlalte facturi in baza de date?',4+32,_screen.Caption) <> 6
EXIT
ENDIF
ENDIF
ENDIF
ENDSCAN
USE IN (SELECT('crsUpdateTemp'))
ENDIF && lnSucces
lnSucces = This.DisConnectROA()
SELECT (m.lcSelect)
RETURN m.llSucces
ENDPROC && UpdateDb
*****************
* actualizeaza o linie de factura in anaf_efactura
*****************
PROCEDURE UpdateDbFactura
LPARAMETERS toFactura
* toFactura : obiect din anaf_efactura
Local lcSql, llSucces, lcText
Local lcFacturaDetalii, lnIdEfactura, llZipDatabase
PRIVATE pcDetalii, pcDetaliiZip, pnId, pcDetaliiPlata
lcText = StripNonAscii(NVL(toFactura.xdetalii_plata,''), '')
lcText = RemoveCharactersDB(m.lcText, .T.)
lcText = LEFT(ALLTRIM(m.lcText), 495)
toFactura.xdetalii_plata = m.lcText && LEFT(ALLTRIM(StripNonAscii(NVL(toFactura.xdetalii_plata,''), '')), 495)
lcText = StripNonAscii(NVL(toFactura.xdescriere,''), '')
lcText = RemoveCharactersDB(m.lcText, .T.)
lcText = LEFT(ALLTRIM(m.lcText), 3995)
toFactura.xdescriere = m.lcText && LEFT(ALLTRIM(StripNonAscii(NVL(toFactura.xdescriere, ''), '')), 3995)
lcText = StripNonAscii(NVL(toFactura.mesaj_raspuns,''), '')
lcText = RemoveCharactersDB(m.lcText, .T.)
lcText = LEFT(ALLTRIM(m.lcText), 250)
toFactura.mesaj_raspuns = m.lcText
llZipDatabase = This.lZipDatabase && daca se salveaza zip efactura in baza de date
pnId = 0
* Nu mai actualizez anaf_detalii in pack_anaf.UpdateFactura, pentru ca da eroare cateodata (cand sunt prea multe linii?)
* Actualizez separat liniile
pcDetalii = toFactura.Detalii
pcDetaliiZip = ''
IF m.llZipDatabase AND TYPE('toFactura.filepath') = 'C' AND !EMPTY(NVL(toFactura.filepath,'')) AND FILE(NVL(toFactura.filepath,''))
pcDetaliiZip = FILETOSTR(ALLTRIM(NVL(toFactura.filepath,'')))
ENDIF
lcFacturaDetalii = NVL(toFactura.factura_detalii, '')
toFactura.xnumar_act = RIGHT(ALLTRIM(toFactura.xnumar_act), 30)
toFactura.procesat = 1 && sa se actualizeze anaf_efactura.procesat
llSucces = .F.
TEXT TO lcSql NOSHOW
begin
pack_anaf.AdaugaRaspunsFactura(v_id_incarcare => ?TRIM(.id_incarcare),
v_data_raspuns => ?.data_raspuns,
v_mesaj_raspuns => ?TRIM(.mesaj_raspuns),
v_tip_mesaj_raspuns => ?TRIM(.tip_mesaj_raspuns),
v_id_descarcare => ?TRIM(.id_descarcare),
v_cod_fiscal_emitent => ?TRIM(.cod_fiscal_emitent),
v_cod_fiscal_beneficiar => ?TRIM(.cod_fiscal_beneficiar),
v_detalii => ?.detalii,
v_test => ?.test,
v_numar_act => ?TRIM(.xnumar_act),
v_data_act => ?.xdata_act,
v_data_scad => ?.xdata_scad,
v_furnizor => ?TRIM(.xfurnizor),
v_client => ?TRIM(.xclient),
v_descriere => ?TRIM(LEFT(.xdescriere,3995)),
v_detalii_plata => ?.xdetalii_plata,
v_total_fara_tva => ?.xtotal_fara_tva,
v_total_tva => ?.xtotal_tva,
v_total_tva_ron => ?.xtotal_tva_ron,
v_total_cu_tva => ?.xtotal_cu_tva,
v_discount_fara_tva => ?.xdiscount_fara_tva,
v_taxe_fara_tva => ?.xtaxe_fara_tva,
v_valoare_fara_tva => ?.xvaloare_fara_tva,
v_total_de_plata => ?.xtotal_de_plata,
v_nume_valuta => ?TRIM(.xnume_valuta),
v_descarcat => ?.descarcat,
v_filepath => ?.filepath,
v_procesat_server => ?.procesat_server,
v_procesat => ?.procesat,
v_xmldetalii => ?.factura_detalii,
v_creditnote => ?.creditnote,
V_ID_EFACTURA => ?@pnId);
end;
ENDTEXT
* Daca len(FacturaDetalii) > 5000, da eroare si trebuie sa actualizez separat
IF LEN(m.lcFacturaDetalii) < 5000 AND LEN(m.pcDetalii) < 5000
WITH toFactura
lnSucces = goExecutor.oExecute(m.lcSql)
llSucces = (m.lnSucces = CT_SUCCES)
ENDWITH
IF !m.llSucces
SET STEP ON
This.lError = .T.
This.cErrorMessage = goExecutor.cEroare
ENDIF
IF m.llSucces AND m.llZipDatabase AND !EMPTY(m.pcDetaliiZip)
* Fac update direct pe tabela in loc de pack_anaf.UpdateRaspunsDetalii, pentru ca da cateodata eroare (BUG oracle)
lcSql = 'update anaf_efactura set detalii_zip = ?pcDetaliiZip where id = ?pnId'
lnSucces = goExecutor.oExecute(m.lcSql)
llSucces = (m.lnSucces = CT_SUCCES)
IF !m.llSucces
This.lError = .T.
This.cErrorMessage = goExecutor.cEroare
ENDIF
ENDIF
ENDIF && len
*********************************************
* Daca da eroare, mai incerc o data fara transmiterea detalii factura = lista articole.
* Articolele le salvez separat
IF !m.llSucces
* ORA-01460
toFactura.factura_detalii = ''
toFactura.detalii = ''
WITH toFactura
lnSucces = goExecutor.oExecute(m.lcSql)
llSucces = (m.lnSucces = CT_SUCCES)
ENDWITH
IF !m.llSucces
SET STEP ON
This.lError = .T.
This.cErrorMessage = goExecutor.cEroare
ELSE
* Adaug fiecare linie in anaf_efactura_detalii pentru ca cateodata se blocheaza Oracle BUG, daca este > 4.000 caractere
llSucces = This.UpdateFacturaDetalii(m.pnId, m.lcFacturaDetalii)
ENDIF
IF m.llSucces
* Fac update direct pe tabela in loc de pack_anaf.UpdateRaspunsDetalii, pentru ca da cateodata eroare (BUG oracle)
lcSql = 'update anaf_efactura set detalii = ?pcDetalii' + IIF(m.llZipDatabase and !EMPTY(m.pcDetaliiZip), ', detalii_zip = ?pcDetaliiZip', '') + ' where id = ?pnId'
lnSucces = goExecutor.oExecute(m.lcSql)
llSucces = (m.lnSucces = CT_SUCCES)
IF !m.llSucces
SET STEP ON
This.lError = .T.
This.cErrorMessage = goExecutor.cEroare
ENDIF
ENDIF
ENDIF
IF !m.llSucces
lcErrorMessage = 'UpdateDb Eroare la actualizarea datelor facturii pe server anaf_efactura.id = ' + TRANSFORM(m.pnId) + ' numar = ' + TRANSFORM(toFactura.xnumar_act) + CHR(13) + CHR(10) + ;
This.cErrorMessage
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
ENDIF
RETURN m.llSucces
ENDPROC && UpdateDb
*************************
*** Adaug linii una cate una, din cauza ca uneori are eroare la UpdateFactura cu toate detaliile, cand sunt prea multe linii poate?
*************************
Procedure UpdateFacturaDetalii
Parameters tnIdEfactura, tcFacturaDetalii
* tnIdEfactura: Id efactura
* tcFacturaDetalii: xml detalii factura
Local lcSql, llSucces, lnCount, lnRec, lnRecs
Private poRec
llSucces = .T.
lnCount = 0
* Verific daca exista deja introduse linii factura. Nu mai introduc
lcSql = "select count(*) from ANAF_EFACTURA_DETALII WHERE ID_EFACTURA = ?tnIdEfactura"
llSucces = goExecutor.oSelecteaza2Value(m.lcSql, @lnCount)
If Nvl(m.lnCount,0) > 0
Return m.llSucces
Endif
TEXT TO lcSql NOSHOW
INSERT INTO ANAF_EFACTURA_DETALII (ID_EFACTURA, NR, ARTICOL, DESCRIERE, DETALII, UM, CANTITATE, PRET, PROCTVA, TIPTVA, VALOAREFARATVA, DISCOUNTFARATVA)
VALUES (?tnIdEfactura, ?.NR, ?.ARTICOL, ?.DESCRIERE, ?.DETALII, ?.UM, ?.CANT, ?.PRET, ?.PROCTVA, ?.TIPTVA, ?.VALOAREFARATVA, ?.DISCOUNTFARATVA)
ENDTEXT
TRY
lnRecs = Xmltocursor(tcFacturaDetalii, "cFacturaDetaliiTemp")
Select cFacturaDetaliiTemp
Scan
Scatter Name poRec Memo
Wait Window 'eFactura ID ' + Alltrim(Str(m.tnIdEfactura)) + ' Salvare articol ' + Alltrim(Str(Recno())) + '/' + Alltrim(Str(m.lnRecs)) + ' ...' Nowait
With poRec
.descriere = RemoveCharactersDB(.descriere, .T.)
.descriere = LEFT(ALLTRIM(.descriere), 300)
.articol = RemoveCharactersDB(.articol, .T.)
.articol = LEFT(ALLTRIM(.articol), 300)
lnSucces = goExecutor.oExecute(m.lcSql)
llSucces = (m.lnSucces = CT_SUCCES)
If !m.llSucces
This.cErrorMessage = goExecutor.cEroare
This.lError = .T.
Exit
Endif
Endwith
Endscan
Use In (Select('cFacturaDetaliITemp'))
CATCH TO loEx
This.Log('tcFacturaDetalii ' + tcFacturaDetalii)
ENDTRY
Return m.llSucces
Endproc && UpdateFacturaDetalii
****************
* Genereaza pdf din xml eFactura pe serverul ANAF
****************
Procedure xml2PdfAnaf
Lparameters tcFile, tcFisierPdf, tlVariable
* tcXml: xml eFactura
* tcFisierPdf : (optional) calea catre fisierul Pdf generat. Altfel, se intreaba utilizatorul
* tlVariable: .T. daca tcFile este o variabila cu continutul xml efactura
Local loHTTP As 'winHTTP.winHTTPrequest.5.1'
Local loReturn As "empty"
Local lcMesaj, lcSend, lcServer, lcStare, llValid, lnBytes, lnMesaj, lnMesaje, loJson, loMessage, lcTip, lcToken
loReturn = Createobject("empty")
AddProperty(loReturn, "lSucces", .F.)
AddProperty(loReturn, "cFile", '')
AddProperty(loReturn, "cResponse", '')
AddProperty(loReturn, "cResponseBody", '')
AddProperty(loReturn, "nStatus", 0)
AddProperty(loReturn, "cFilePdf", '')
If !Empty(m.tcFisierPdf)
loReturn.cFilePdf = m.tcFisierPdf
Endif
lcSend = ''
If m.tlVariable
lcSend = m.tcFile
Else
If File(m.tcFile)
lcSend = Filetostr(m.tcFile)
Endif
ENDIF
lcTip = 'FACT1'
IF 'CreditNote'$m.lcSend
lcTip = 'FCN'
ENDIF
lcToken = This.cToken
*!* lcServer = [https://webservicesp.anaf.ro/prod/FCTEL/rest/transformare/] + m.lcTip + [/DA] && serviciu neautentificat
lcServer = [https://api.anaf.ro/prod/FCTEL/rest/transformare/] + m.lcTip + [/DA] && serviciu autentificat
loHTTP = Createobject('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('POST', lcServer, .F.)
loHTTP.setRequestHeader("Content-Type", "text/plain")
loHTTP.setRequestHeader('Authorization', 'Bearer ' + m.lcToken) && 9b1f44af738c16aa10c78347b9a064857f034b03a20704a03c131b99f019cee5
Try
This.Log(m.lcServer)
Catch
Endtry
* Elimin caracterele Chr(13), Chr(10)
* Da eroare la serviciul ANAF
lcSend = Strtran(m.lcSend, [&#x0D;], [])
* Sterg xsi:schemaLocation pentru ca poate da request rejected
* xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 ../../UBL-2.1(1)/xsd/maindoc/UBL-Invoice-2.1.xsd"
lcXsi = Strextract(lcSend, [xsi:schemaLocation="], [.xsd"], 1, 1)
lcSend = Strtran(m.lcSend, m.lcXsi, '', 1, 1, 1)
loHTTP.Send(m.lcSend)
loReturn.nStatus = loHTTP.Status
loReturn.cResponse = loHTTP.ResponseText
loReturn.cResponseBody = loHTTP.ResponseBody
loReturn.lSucces = (loHTTP.Status = 200)
lcMesaj = ''
If loReturn.lSucces
Do Case
Case ["stare"] $ Lower(loReturn.cResponse)
* Daca nu este valid xml
loJson = nfjsonread(loReturn.cResponse)
If Type('loJson.stare') = 'C' And !Empty(loJson.stare)
lcStare = Alltrim(Lower(loJson.stare))
llValid = (m.lcStare == 'ok')
If !m.llValid
If Type('loJson.messages_vfpsafe_') = 'U'
lcMesaj = 'Fisierul nu s-a validat. Nu exista informatia [messages] in raspuns. ' + Chr(13) + Chr(10) + loReturn.cResponse
Else
lnMesaje = Alen(loJson.messages_vfpsafe_)
lcMesaj = ''
For lnMesaj = 1 To m.lnMesaje
loMessage = loJson.messages_vfpsafe_[m.lnMesaj]
If Type('loMessage.message') = 'C'
lcMesaj = lcMesaj + loMessage.Message + Chr(13) + Chr(10)
Endif
Endfor
Endif && messages
Endif && llValid
Endif
If !Empty(m.lcMesaj)
lcErrorMessage = 'XML2PDFANAF ' + m.lcMesaj
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
Endif
Case 'request rejected' $ Lower(loReturn.cResponse)
lcErrorMessage = 'XML2PDFANAF Fisierul nu s-a validat.' + CRLF + loReturn.cResponse
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
Otherwise
* Daca este valid xml
If Empty(loReturn.cFilePdf)
loReturn.cFilePdf = Putfile('Fisier pdf', 'efactura.pdf', 'pdf')
Endif
Try
Delete File loReturn.cFilePdf
Endtry
lnBytes = Strtofile(loReturn.cResponseBody, loReturn.cFilePdf)
This.Log('XML2PDFANAF ' + loReturn.cFilePdf)
Endcase
Endif && loReturn.lSucces
Return loReturn.cFilePdf
Endproc && Xml2PdfAnaf
*********************
* Trimite fisiere xml eFactura in SPV
*********************
PROCEDURE VizSPV
* [{"id":"100000000","detalii":"recipisa pentru CIF 8000000000, tip D112, numar_inregistrare INTERNT-130000000-2017/20-12-2017, perioada raportare 11.2017","cif":"8000000000","data_creare":"20.12.2017 12:00:00","id_solicitare":null,"tip":"RECIPISA"}],"cnp":"1111111111118","cui":"8000000000,8000000001,8000000002","serial":"xxxxxxxxxxxxxxxxxxx"}
*!* CREATE CURSOR cMesajeSPV (ales N(1), id V(32), detalii V(250) null, cif V(20) null, data_creare T null, id_solicitare V(32) null, tip V(50) null, atasament W null, descarcat N(1), citit N(1), arhivat N(1))
*!* lcSql = [select id, cif, data_creare, detalii, id_solicitare, tip, '' as atasament, citit, arhivat, descarcat from anaf_spv ] + ;
*!* IIF(!EMPTY(m.tnArhivat) and m.tnArhivat = 1, "", "where arhivat=0")
*!* llSucces = goExecutor.oExecuta(m.lcSql, 'cMesajeSPVTemp')
*!* SELECT cMesajeSPV
*!* APPEND FROM DBF('cMesajeSPVTemp')
*!* INDEX on ID TAG Id DESCENDING
*!* USE IN (SELECT('cMesajeSPVTemp'))
Local loFrmSPV As "anaf_spv"
Local lcFiltru, lcFiltruOriginal, lcGroup, lcOrder, lcSchema, lcSelect, llAfisare, llModParam
PRIVATE poMesaje
lcSelect=[select 0 as ales, id, detalii, cif, data_creare, id_solicitare, tip, '' as atasament, citit, arhivat, descarcat from anaf_spv]
lcFiltru=[arhivat=0]
lcSchema=[ales N(1), id V(32), detalii V(250) null, cif V(20) null, data_creare T null, id_solicitare V(32) null, tip V(50) null, atasament W null, citit N(1), arhivat N(1), descarcat N(1)]
lcOrder=[data_creare desc]
llAfisare=.F.
lcGroup = []
llModParam = .T.
lcFiltruOriginal = []
poMesaje = null
gencursor('poMesaje','cMesajeSPV', m.lcSelect, m.lcFiltru, m.lcSchema, m.lcOrder, m.llAfisare, m.lcGroup, m.llModParam, m.lcFiltruOriginal)
poMesaje.ca_baza1.afisare()
SELECT cMesajeSPV
loFrmSPV = CREATEOBJECT("anaf_spv", This)
loFrmSPV.Show(1)
USE IN (SELECT('cMesajeSPV '))
ENDPROC && VizSPV
*****************
* Citeste lista de mesaje din SPV si salveaza in baza de date
*****************
PROCEDURE GetSPV
Local loHTTP As "MSXML2.XMLHTTP"
Local lcCIF, lcDetaliiMesaj, lcErrorMessage, lcIdMesaj, lcIdSolicitare, lcMesaj, lcResponse, lcTip
Local llSucces, loEx, loJson, loMesaj, ltDataCreare
LOCAL lcCodFiscal, lcURL, lnZile, lcZile, loEx as Exception
DECLARE INTEGER InternetSetOption IN "wininet.dll" ;
INTEGER hInternet, INTEGER dwOption, STRING lpBuffer, INTEGER dwBufferLength
#DEFINE INTERNET_OPTION_END_BROWSER_SESSION 42
* Clear SSL cache by ending the browser session
=InternetSetOption(0, INTERNET_OPTION_END_BROWSER_SESSION, 0, 0)
lnZile = 1000
lcZile = ALLTRIM(STR(m.lnZile))
lcCodFiscal = ALLTRIM(NVL(This.cCodFiscal, ''))
lcURL = "https://webserviced.anaf.ro/SPVWS2/rest/listaMesaje?zile=" + m.lcZile + "&cif=" + m.lcCodFiscal
llSucces = .F.
TRY
loHTTP = Createobject("MSXML2.XMLHTTP")
loHTTP.Open("GET", lcURL , .F.)
loHTTP.setRequestHeader("content-type", "text/plain")
loHTTP.Send()
llSucces = .T.
CATCH TO loEx
This.cErrorMessage = loEx.message
This.lError = .T.
ENDTRY
llSucces = .T.
lcMesaj = ''
* Verificam statusul raspunsului
IF TYPE('loHttp') = 'O' AND loHttp.Status <> 200
* Daca cererea HTTP a esuat
lcMesaj = "Eroare la conectarea la server: " + TRANSFORM(loHttp.Status)
This.cErrorMessage = m.lcMesaj
This.lError = .T.
llSucces = .F.
ENDIF
* Preluam raspunsul JSON
IF m.llSucces
lcResponse = loHttp.ResponseText
IF ATC('<head>', m.lcResponse) > 0
llSucces = .F.
DO CASE
CASE ATC('utilizator neautorizat', m.lcResponse) > 0
lcMesaj = 'Utilizator neautorizat. Posibile cauze: parola eronata sau certificat fara drepturi.'
CASE ATC('certificatul nu a fost prezentat', m.lcResponse) > 0
lcMesaj = 'Certificatul nu a fost prezentat.'
OTHERWISE
lcMesaj = 'Eroare certificat'
ENDCASE
This.cErrorMessage = m.lcMesaj
This.lError = .T.
ENDIF
ENDIF
IF m.llSucces
* Transformam raspunsul JSON <20>ntr-un obiect FoxPro
TRY
loJson = nfjsonread(m.lcResponse)
CATCH TO loEx
llSucces = .F.
lcErrorMessage = 'GetSPV ' + LF + ' Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure
This.cErrorMessage = m.lcErrorMessage
This.lError = .T.
This.Log(m.lcErrorMessage)
ENDTRY
* Verificam daca exista mesaje disponibile
IF TYPE("loJson.mesaje") <> "U"
* Daca avem mesaje, le salvam <20>ntr-un array
*!* laMesaje = loJson.mesaje
*!* lnMesajeCount = ALEN(laMesaje, 1)
* Iteram prin lista de mesaje si descarcam fiecare mesaj
lnMesaje = 0
FOR EACH loMesaj IN loJson.mesaje
lnMesaje = lnMesaje + 1
*i = 1 TO lnMesajeCount
*!* lcIdMesaj = laMesaje[i].id
*!* lcDetaliiMesaj = laMesaje[i].detalii
lcIdMesaj = loMesaj.id
lcDetaliiMesaj = loMesaj.detalii
lcTip = loMesaj.tip
lcCIF = loMesaj.cif
ltDataCreare = CTOT(loMesaj.data_creare)
lcIdSolicitare = loMesaj.id_solicitare
WAIT WINDOW 'Mesaj: ' + ALLTRIM(STR(m.lnMesaje)) + ' ' + m.lcTip NOWAIT
llSucces = This.UpdateDbSPV(m.loMesaj)
*!* IF !SEEK(m.lcIdMesaj, 'cMesajeSPV', 'id')
*!*
*!* INSERT INTO cMesajeSPV (id, detalii, tip, cif, data_creare, id_solicitare) VALUES (m.lcIdMesaj, m.lcDetaliiMesaj, m.lcTip, m.lcCIF, m.ltDataCreare, m.lcIdSolicitare)
*!* SELECT cMesajeSPV
*!* IF SEEK(m.lcIdMesaj)
*!* SCATTER NAME loMesaj MEMO
*!* llSucces = This.UpdateDbSPV(m.loMesaj)
*!* ENDIF
*!* ENDIF
ENDFOR
*!* GO TOP IN cMesajeSPV
WAIT WINDOW ALLTRIM(STR(m.lnMesaje)) + ' mesaje verificate/adaugate' NOWAIT
ELSE
* Daca nu exista mesaje
lcMesaj = "Nu exista mesaje disponibile in ultimele " + lcZile + " zile."
ENDIF
ENDIF && llSucces
IF !This.lServer AND !EMPTY(This.cErrorMessage)
AMESSAGEBOX(This.cErrorMessage, 0+48, _screen.Caption)
ENDIF
RETURN m.llSucces
ENDPROC && GetSPV
***************************
* Salveaza un mesaj SPV in baza de date anaf_spv
***************************
PROCEDURE UpdateDbSPV
LPARAMETERS toMesaj
Local lcSql, llSucces
PRIVATE pcCIF, pcDetalii, pcId, pcIdSolicitare, pcTip, ptDataCreare
TEXT TO lcSql NOSHOW
merge into anaf_spv a using dual b ON (a.id = ?pcId)
when not matched then
INSERT (id, detalii, tip, cif, data_creare, id_solicitare) VALUES (?pcId, ?pcDetalii, ?pcTip, ?pcCIF, ?ptDataCreare, ?pcIdSolicitare)
ENDTEXT
WITH toMesaj
pcId = ALLTRIM(.id)
pcDetalii = ALLTRIM(.detalii)
pcTip = ALLTRIM(.tip)
pcCIF = ALLTRIM(.cif)
ptDataCreare = CTOT(.data_creare)
pcIdSolicitare = ALLTRIM(.id_solicitare)
ENDWITH
llSucces = goExecutor.oExecuta(m.lcSql)
IF !m.llSucces
goLog.Log(NVL(pcId, '') + ' ' + NVL(pcTip, '') + ' ' + NVL(pcCIF, '') + ' ' + TRANSFORM(NVL(ptDataCreare, {})) + ' ' + NVL(pcIdSolicitare, '') + ' ' + NVL(pcDetalii, ''))
SET STEP ON
ENDIF
RETURN m.llSucces
ENDPROC && UpdateDbSPV
***************************
* Salveaza atasamentul pentru un mesaj SPV in baza de date anaf_spv
***************************
PROCEDURE UpdateDbSPVFile
PARAMETERS tcIdMesaj, tcContinut, tcFileName
* tcIdMesaj: Id mesaj SPV
* tcContinut: continutul pdf/zip mesaj
Local lcSql, llSucces
lcSql = [UPDATE anaf_spv SET atasament = ?tcContinut, filename = ?tcFileName, descarcat = 1 WHERE id = ?tcIdMesaj]
llSucces = goExecutor.oExecuta(m.lcSql)
IF !m.llSucces
goLog.Log(TRANSFORM(NVL(tcContinut, '')) + ' ' + TRANSFORM(NVL(tcIdMesaj, '')) + ' ' + TRANSFORM(m.tcFileName))
SET STEP ON
ENDIF
RETURN m.llSucces
ENDPROC && UpdateDbSPVFile
****************
* Actualizeaza anaf_spv.citit, descarcat, arhivat
****************
PROCEDURE UpdateSPV
LPARAMETERS tcIdMesaj, tcAtribut, tnValoare
lcSql = [update anaf_spv set ] + m.tcAtribut + [ = ] + ALLTRIM(STR(m.tnValoare)) + [ where id = ] + ALLTRIM(m.tcIdMesaj)
llSucces = goExecutor.oExecuta(m.lcSql)
RETURN m.llSucces
ENDPROC
*****************
* Descarca atasamentul pdf al unui mesaj din SPV si il salveaza pe disc
*****************
PROCEDURE DescarcaDetaliiSPV
LPARAMETERS tcIdMesaj
* tnIdMesaj (optional): Id mesaj, altfel se descarca mesajele cMesajeSPV.ales = 1
* ttDataCreare, tcTip (optional): pentru numele fisierului
Local loHTTP As "MSXML2.XMLHTTP"
Local lcDirectory, lcIdMesaj, lcPdfData, lcPdfFileName, lcRecc, lcUrlDescarcare
Local lcData, lcDataCreare, lcExtensie, lcFileName, lcFiltru, lcTip, llSucces, lcIdMesaj
lcIdMesaj = IIF(!EMPTY(m.tcIdMesaj), ALLTRIM(m.tcIdMesaj), '')
*!* ******************
*!* DECLARE INTEGER InternetSetOption IN "wininet.dll" ;
*!* INTEGER hInternet, INTEGER dwOption, STRING lpBuffer, INTEGER dwBufferLength
*!* #DEFINE INTERNET_OPTION_END_BROWSER_SESSION 42
*!* * Clear SSL cache by ending the browser session
*!* =InternetSetOption(0, INTERNET_OPTION_END_BROWSER_SESSION, 0, 0)
*!* ******************
IF this.lServer
lcDirectory = This.cResponsesPath + 'SPV' + '\' + Dtos(Date()) + '\'
ELSE
lcDirectory = GetPdfPath('SPV')
ENDIF
lcFiltru = 'descarcat = 0'
DO CASE
CASE !EMPTY(m.lcIdMesaj)
lcFiltru = 'id = lcIdMesaj'
OTHERWISE
SELECT * FROM cMesajeSPV WHERE ales = 1 INTO CURSOR cMesajeSelectateTemp
IF _tally > 0
lcFiltru = 'ales = 1'
ENDIF
USE IN (SELECT('cMesajeSelectateTemp'))
ENDCASE
SELECT * FROM cMesajeSPV WHERE &lcFiltru INTO CURSOR cMesajeTemp NOFILTER
lcRecc = TRANSFORM(RECCOUNT('cMesajeTemp'))
llSucces = .F.
TRY
loHTTP = Createobject("MSXML2.XMLHTTP")
llSucces = .T.
CATCH TO loEx
This.cErrorMessage = loEx.message
This.lError = .T.
IF !This.lServer
AMESSAGEBOX('Eroare ' + This.cErrorMessage,0+48, _Screen.Caption)
ENDIF
ENDTRY
IF m.llSucces AND TYPE('loHttp') = 'O'
This.lError = .F.
SELECT cMesajeTemp
SCAN
lcIdMesaj = ALLTRIM(id)
lcDataCreare = TTOC(data_creare,1)
lcTip = ALLTRIM(tip)
lcDetalii = ALLTRIM(detalii)
llSucces = .T.
WAIT WINDOW TRANSFORM(RECNO()) + '/' + m.lcRecc NOWAIT
* Construim URL-ul pentru descarcarea mesajului
lcUrlDescarcare = "https://webserviced.anaf.ro/SPVWS2/rest/descarcare?id=" + m.lcIdMesaj
* Facem cererea pentru descarcarea mesajului PDF
llSucces = .F.
TRY
loHttp.Open("GET", m.lcUrlDescarcare, .F.)
loHttp.Send()
llSucces = .T.
CATCH TO loEx
This.cErrorMessage = loEx.message
This.lError = .T.
IF !This.lServer
AMESSAGEBOX('Eroare ' + This.cErrorMessage,0+48, _Screen.Caption)
ENDIF
ENDTRY
* Verificam statusul descarcarii
IF m.llSucces AND loHttp.Status = 200
* Verific daca raspunsul contine un mesaj de eroare in html
lcResponse = loHttp.ResponseText
DO CASE
CASE ATC('<head>', m.lcResponse) > 0
llSucces = .F.
DO CASE
CASE ATC('utilizator neautorizat', m.lcResponse) > 0
lcMesaj = 'Utilizator neautorizat. Posibile cauze: parola eronata sau certificat fara drepturi.'
CASE ATC('certificatul nu a fost prezentat', m.lcResponse) > 0
lcMesaj = 'Certificatul nu a fost prezentat.'
OTHERWISE
lcMesaj = 'Eroare certificat'
ENDCASE
This.cErrorMessage = m.lcMesaj
This.lError = .T.
WAIT WINDOW "Eroare la descarcarea mesajului " + m.lcIdMesaj + ' : ' + m.lcMesaj NOWAIT
IF !This.lServer
AMESSAGEBOX("Eroare la descarcarea mesajului " + m.lcIdMesaj + ' : ' + m.lcMesaj + '!',0+48,_Screen.Caption)
EXIT
ENDIF
CASE LEFT(m.lcResponse, 1) = "{"
*!* {"titlu":"Descarcare mesaj","eroare":"A aparut o eroare tehnica. Cod: 2000"}
lcMesaj = GetRegExp(m.lcResponse, '(?<="eroare":")[^"]+', 1)
This.cErrorMessage = m.lcMesaj
This.lError = .T.
WAIT WINDOW "Eroare la descarcarea mesajului " + m.lcIdMesaj + ' : ' + m.lcMesaj NOWAIT
IF !This.lServer
AMESSAGEBOX("Eroare la descarcarea mesajului " + m.lcIdMesaj + ' : ' + m.lcMesaj + '!',0+48,_Screen.Caption)
EXIT
ENDIF
OTHERWISE
* Obtinem continutul PDF/ZIP
lcResponse = loHttp.ResponseBody
ENDCASE
* Salvam fisierul PDF/zip pe disc
*detalii: recipisa pentru CIF 1879855, tip D300, numar_inregistrare INTERNT-767970463-2024/16-08-2024, perioada raportare 7.2024
lcTipD = GetRegExp(m.lcDetalii, ", tip ([^,]+)", 1) && obtin Tip declaratie ",tip D300,"
lcTipD = ALLTRIM(STRTRAN(m.lcTipD, ", tip", "",1,1,1))
lcTipD = IIF(!EMPTY(m.lcTipD), '_' + ALLTRIM(m.lcTipD), '')
lcPerioadaR = GetRegExp(m.lcDetalii, "perioada raportare (\d+\.\d+)", 1) && perioada raportare "7.2024"
lcPerioadaR = ALLTRIM(STRTRAN(m.lcPerioadaR, "perioada raportare", "",1,1,1))
lcPerioadaR = IIF(!EMPTY(m.lcPerioadaR), '_' + ALLTRIM(m.lcPerioadaR), '')
lcExtensie = IIF(This.lError, 'html', IIF(LOWER(LEFT(loHttp.responseText, 4)) = '%pdf', 'pdf', 'zip'))
lcFileName = m.lcDirectory + "mesaj_spv_" + m.lcIdMesaj + "_" + m.lcDataCreare + "_" + m.lcTip + m.lcTipD + m.lcPerioadaR + "." + m.lcExtensie
STRTOFILE(m.lcResponse, m.lcFileName, 0)
IF m.llSucces
* Salvez atasamentul in baza de date
llSucces = This.UpdateDbSPVFile(m.lcIdMesaj, m.lcResponse, JUSTFNAME(m.lcFileName))
ENDIF
IF m.llSucces
UPDATE cMesajeSPV SET descarcat = 1 WHERE id = m.lcIdMesaj
ENDIF
* Afisam un mesaj de succes
WAIT WINDOW "Mesajul " + m.lcIdMesaj + " descarcat cu succes: " + m.lcFileName NOWAIT
ELSE
* Daca apare o eroare la descarcare, afisam mesajul de eroare
WAIT WINDOW "Eroare la descarcarea mesajului " + m.lcIdMesaj NOWAIT
ENDIF
ENDSCAN && cMesajeTemp
ENDIF && llSucces
USE IN (SELECT('cMesajeTemp'))
IF !This.lServer
open_default_app(m.lcDirectory)
ENDIF
ENDPROC && DescarcaDetaliiSPV
*************
* Deschide directorul cu atasamente SPV si atasamentul dorit, dupa id mesaj
*************
PROCEDURE DeschideAtasamentSPV
LPARAMETERS tcIdMesaj
PRIVATE pcIdMesaj
Local laFiles[1], lcDirectory, lcFile, lcFileSkeleton, lcFiltru, lcFiltruOriginal, lcFisier, lcId
Local lcOrder, lcSchema, lcSelect, lcgroup, llAfiseaza, llModParam, lnFile, lnFiles
pcIdMesaj = tcIdMesaj
IF this.lServer
lcDirectory = This.cResponsesPath + 'SPV' + '\' + Dtos(Date()) + '\'
ELSE
lcDirectory = GetPdfPath('SPV')
ENDIF
lcDirectory = ADDBS(m.lcDirectory)
lcFileSkeleton = m.lcDirectory + '*' + ALLTRIM(m.tcIdMesaj) + '*.*'
lnFiles = ADIR(laFiles, m.lcFileSkeleton)
IF m.lnFiles > 0
open_default_app(m.lcDirectory)
FOR lnFile = 1 TO m.lnFiles
lcFile = m.lcDirectory + laFiles[m.lnFile,1]
IF FILE(m.lcFile)
open_default_app(m.lcFile)
ENDIF
ENDFOR
ELSE
* daca nu sunt fisiere pe disk, descarc din baza de date
PRIVATE poDetaliiZip
poDetaliiZip = null
lcSchema = [id V(36), fisier W, filename V(100)]
lcSelect = [select id, atasament, filename from anaf_spv where id = ?pcIdMesaj]
lcOrder = []
lcgroup = []
lcFiltru = []
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poDetaliiZip','cRegFisierTemp', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poDetaliiZip.ca_baza1.afisare()
If Used('cRegFisierTemp')
lcId= ALLTRIM(NVL(id, ''))
lcFisier = fisier
lcFileName = IIF(!EMPTY(NVL(filename, '')), ALLTRIM(NVL(filename, '')), m.pcIdMesaj + '.pdf')
Use In (Select('cRegFisierTemp'))
lcFile = PUTFILE('Fisier', m.lcFileName, JUSTEXT(m.lcFileName))
IF !EMPTY(m.lcFile)
Strtofile(lcFisier, m.lcFile)
open_default_app(JUSTPATH(m.lcFile))
open_default_app(m.lcFile)
ENDIF
Endif
ENDIF
ENDPROC && DeschideAtasamentSPV
Enddefine && ANAFeFacturaServer
Procedure viz_borderou_efactura
LOCAL loAnafeFactura
If !m.glEfactura
AMESSAGEBOX('Trebuie activata functionalitatea eFactura!', 0 + 48, _Screen.Caption)
Return
Endif
* gcAcces = [1;2;3;4;5;6]
loAnafeFactura = Createobject("ANAFeFactura")
loAnafeFactura.vizeFactura()
ENDPROC
*****************************
PROCEDURE viz_efactura_xml
LOCAL loAnafeFactura
loAnafeFactura = CREATEOBJECT("AnafeFacturaServer")
loAnafeFactura.vizeFacturaXml()
ENDPROC && viz_efactura_xml
*****************************
PROCEDURE viz_spv
LOCAL loAnafeFactura
loAnafeFactura = CREATEOBJECT("AnafeFacturaServer")
loAnafeFactura.VizSPV()
ENDPROC && viz_spv
Define Class ANAFeFactura As Custom
AnafeFacturaServer = null
token = ''
refresh_token = ''
token_gendate = {}
token_expdate = {}
codfiscal = '' && cod fiscal contribuabil fara atribut fiscal
lTest = .F. && .T. = transmite eFactura TEST
cResponsesPath = ''
Procedure Init
this.AnafeFacturaServer = Createobject('AnafeFacturaServer')
This.codfiscal = IIF(TYPE('goFirma') = 'O', gofirma.codfiscalfro, '')
This.cResponsesPath = GetPdfPath('EFACTURA') && ADDBS(m.gcEFACTURA_RESPONSESPATH) && RASPUNSURI daca se descarca automat cu ROAEFACTURA
Endproc && Init
Procedure vizeFactura
Local lcToken
Local loFrmBorderou As "frm_borderou_efactura"
Local lcFiltru, lcFiltruOriginal, lcOrder, lcSchema, lcSelect, lcgroup, llAfiseaza, llModParam, lcData1, lnInregistrariAfisare
Local lcSqlCount, llSucces
Private poFacturiEmise, poFacturiPrimite, poFacturiTrimise, poFacturiDetalii, pnRecCnt
poFacturiEmise = Null
poFacturiPrimite = Null
poFacturiTrimise = Null
poFacturiDetalii = Null
lcToken = This.getToken()
If Empty(m.lcToken)
AMESSAGEBOX('Nu s-a obtinut token-ul eFactura!', 0 + 48, _Screen.Caption)
Endif
* La facturi primite/trimise aduc 0 inregistrari.
* Afisez inregistrarile la prima activare a paginilor Trimise/Primite din Borderou
* Nu aduc coloana ANAF_EFACTURA.DETALII (xml efactura) pentru ca este prea mult trafic de date si merge greu pentru multe inregistrari. Aduc detalii doar pentru cate o factura
* FACTURI PRIMITE
lcData1 = '01' + PADL(INT(m.gnLuna),2,'0') + ALLTRIM(STR(m.gnAn))
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), 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_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), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
Endtext
Text To lcSelect Noshow
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, 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, decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-NVL(jtotctva, 0.00) as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_primit
Endtext
lcOrder = [data_act,numar_act,data_raspuns]
lcgroup = []
* Aduc inregistrarile cand se activeaza prima data pagina cu facturi primite
lcFiltru = [1=2] && [(extract(year from data_act) = ?gnAn and extract(month from data_act) = ?gnLuna) or (data_act is null and data_raspuns >= to_date('] + m.lcData1 + [','ddmmyyyy'))]
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poFacturiPrimite', 'crsFacturiPrimite', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiPrimite.ca_baza1.afisare()
Select crsFacturiPrimite
Go Top
* FACTURI TRIMISE
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), id_incarcare C(36), id_descarcare c(36) null, mesaj_trimis C(250) 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_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), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
Endtext
Text To lcSelect Noshow
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, mesaj_trimis, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, 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, decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-NVL(jtotctva, 0.00) as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_trimis
Endtext
lcOrder = [data_act,numar_act,data_trimis,data_raspuns]
lcgroup = []
* Aduc inregistrarile cand se activeaza prima data pagina cu facturi trimise
lcFiltru = [1=2] && [(extract(year from data_act) = ?gnAn and extract(month from data_act) = ?gnLuna) or (data_act is null and data_raspuns >= to_date('] + m.lcData1 + [','ddmmyyyy'))]
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poFacturiTrimise', 'crsFacturiTrimise', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiTrimise.ca_baza1.afisare()
Select crsFacturiTrimise
Go Top
* FACTURI EMISE
Text To lcSchema Noshow
ales N(1), id N(20), id_fact N(20), id_vanzare N(10), data_act D, numar_act N(14), in_valuta N(1) null, curs N(10,4) null, valval N(16,2), tvaval N(16,2),totval N(16,2), total_fara_tva N(16,2), total_tva N(16,2), total_cu_tva N(16,2), nume_valuta C(5) null, client C(100), id_client N(10), cod_fiscal C(30), tip_persoana N(1) null, trimis N(1) null, data_trimis T null, stare C(100) null, id_incarcare C(36) null, mesaj_trimis C(250) null, id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, xfurnizor C(200), xclient C(200), xdata_act D, xnumar_act C(30), xtotal_fara_tva N(16,4), xtotal_tva N(16,4), xtotal_tva_ron N(16,4), xtotal_cu_tva N(16,4), xdiscount_fara_tva N(16,4), xtaxe_fara_tva N(16,4), xvaloare_fara_tva N(16,4), xtotal_de_plata N(16,4), xnume_valuta C(5), test N(1) null, id_util N(10), utilizator C(100), jtotctva N(16,4), diferenta N(16,4), procesat N(1), procesat_server N(1), creditnote N(1)
Endtext
Text To lcSelect Noshow
SELECT 0 as ales, id, id_fact, id_vanzare, data_act, numar_act, in_valuta, curs, valval, tvaval, totval, total_fara_tva, total_tva,total_cu_tva, nume_valuta, client, id_client, cod_fiscal, NVL(tip_persoana,1) as tip_persoana, NVL(trimis,0) as trimis, data_trimis, stare, id_incarcare, mesaj_trimis, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, xfurnizor, xclient, xdata_act, xnumar_act, xtotal_fara_tva, xtotal_tva, xtotal_tva_ron, xtotal_cu_tva, xdiscount_fara_tva, xtaxe_fara_tva, xvaloare_fara_tva, xtotal_de_plata, xnume_valuta, test, id_util, utilizator, jtotctva, decode(creditnote,0,1,-1) * ROUND(NVL(xtotal_cu_tva , 0.00) * decode(in_valuta,1,curs,1), 2)-NVL(jtotctva, 0.00) as diferenta, procesat, procesat_server,creditnote FROM anaf_vefactura_emis
Endtext
lcOrder = [data_act,numar_act]
lcgroup = []
lcFiltru = [(extract(year from data_act)=?gnAn and extract(month from data_act)=?gnLuna) OR (trimis = 1 and tip_mesaj_raspuns is null and extract(year from data_act) >=2023)]
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
* Afisez toate facturile emise, ca sa le pot vizualiza pe cele netrimise sau trimise cu starea lor (trimis, eroare etc.)
gencursor('poFacturiEmise', 'crsFacturiEmise', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiEmise.ca_baza1.afisare()
* DETALII FACTURI PRIMITE/TRIMISE/EMISE
Text To lcSchema Noshow
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), pret N(20,6), proctva N(7,2), valoarefaratva N(20,6), discountfaratva N(20,6)
Endtext
Text To lcSelect Noshow
select id, id_efactura, nr, articol, descriere, detalii, cantitate, um, pret, proctva, valoarefaratva, discountfaratva from anaf_vefactura_detalii
Endtext
lcOrder = [nr]
lcgroup = []
lcFiltru = [1=2] && IIF(!EMPTY(NVL(crsFacturiPrimite.id,0)), [id_efactura=] + ALLTRIM(STR(crsFacturiPrimite.id)), [1=2])
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poFacturiDetalii', 'crsDetaliiFacturi', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiDetalii.ca_baza1.afisare()
Select crsFacturiEmise
loFrmBorderou = Createobject("anaf_efactura", This)
* Do Form anaf_efactura Name loFrmBorderou Linked With this Noshow
loFrmBorderou.Show(1)
Use In (Select('crsFacturiEmise'))
Use In (Select('crsFacturiTrimise'))
Use In (Select('crsFacturiPrimite'))
Use In (Select('crsDetaliiFacturi'))
Endproc && vizeFactura
Function getToken
Lparameters tlShow
* tlShow: .T. arata formularul chiar daca este generat Token si nu este expirat 90 zile
Private poToken
Local loFrmToken As "anaf_token"
Local lcToken, lcRefreshToken, lcTokenGenDate, ldTokenGenDate, loServer
loServer = This.AnafeFacturaServer
* TokenJWT are dimensiunea mai mare. Il salvez in optiuni.varvalue2
IF .F.
lcToken = Alltrim(Nvl(citeste_optiune('ANAF_TOKEN', .T.), ''))
lcRefreshToken = Alltrim(Nvl(citeste_optiune('ANAF_REFRESH_TOKEN', .T.), ''))
lcTokenGenDate = Alltrim(Nvl(citeste_optiune('ANAF_TOKEN_GENDATE'), ''))
ldTokenGenDate = Iif(!Empty(m.lcTokenGenDate), Ctod(m.lcTokenGenDate), {})
lcTokenExpDate = Alltrim(Nvl(citeste_optiune('ANAF_TOKEN_EXPDATE'), ''))
ldTokenExpDate = Iif(!Empty(m.lcTokenExpDate), Ctod(m.lcTokenExpDate), {})
ldTokenExpDate = Iif(!Empty(m.ldTokenExpDate), m.ldTokenExpDate, m.ldTokenGenDate + 90)
ELSE
lcToken = loServer.cToken
lcRefreshToken = loServer.cRefreshToken
ldTokenGenDate = loServer.dTokenGendate
ldTokenExpDate = loServer.dTokenExpdate
ENDIF
This.token = m.lcToken
This.refresh_token = m.lcRefreshToken
This.token_gendate = m.ldTokenGenDate
This.token_expdate = m.ldTokenExpDate
If m.tlShow Or Empty(m.lcToken) Or m.ldTokenExpDate <= Date()
loFrmToken = Createobject("anaf_token", This)
loFrmToken.Show(1)
If m.lcToken <> loServer.cToken
loServer.dTokenGendate = Date()
loServer.dTokenExpdate = Date() + 90
Endif
This.SaveToken()
Endif
Return loServer.cToken
Endfunc
***************************
* Salveaza tokenul in baza de date optiuni firma
***************************
Procedure SaveToken
LOCAL loServer
loServer = This.AnafeFacturaServer
loServer.SaveToken()
Endproc && SaveToken
* Intoarce tokenul de acces la ANAF (eFactura) daca este salvat sau obtine un nou token
* Se apeleaza din formularul anaf_token.do_executa
Function newToken
AMESSAGEBOX('Introduceti in calculator tokenul USB cu semnatura electronica' + Chr(13) + Chr(10) + ;
'Se va deschide pagina ANAF de generare token. Introduceti PIN-ul pentru semnatura electronica.' + Chr(13) + Chr(10) + ;
'Copiati codurile "Token" si "Refresh Token" afisate si completati-le in ROA.', 0 + 64, _Screen.Caption)
lcURL = [https://romfast.ro/oauth2/]
open_default_app(m.lcURL)
Endfunc
* Actualizeaza data expirarii tokenului ANAF eFactura
* Se apeleaza din formularul anaf_token.do_executa
Function refreshToken
LOCAL loServer, lcMesaj, llSucces
llSucces = .F.
loServer = This.AnafeFacturaServer
lcMesaj = ''
llSucces = loServer.RefreshToken(@lcMesaj)
AMESSAGEBOX(m.lcMesaj, 0 + 48, _Screen.Caption)
Return m.llSucces
Endfunc
********************************
* Bifeaza Trimis o factura trimisa manual la ANAF
********************************
Procedure BifeazaTrimisManual
Lparameters tnIdFact, tnTrimis
Private pnIdFact, pnTrimis
pnIdFact = m.tnIdFact
pnTrimis = m.tnTrimis
pnTest = IIF(This.lTest, 1, 0) && server TEST ANAF
lcSql = 'begin pack_anaf.BifeazaEFactTrimisManual(?pnIdFact, ?pnTrimis, ?pnTest, ?gnIdUtil); end;'
llSucces = goExecutor.oExecuta(m.lcSql)
Return m.llSucces
Endproc && BifeazaTrimisManual
********************************
* Suprascrie Id Incarcare manual, in caz ca pe factura este un Id Incarcare al trimiterilor ulterioare care au primit raspuns Eroare factura duplicata
* Este posibil si ca la prima incarcare anaf.ro sa dea timeout si sa nu intoarca Id Incarcare si sa se trimita din nou factura. Se primeste id incarcare, dar mesajul de descarcare este EROARE factura duplicata.
********************************
Procedure SuprascrieIdIncarcare
Lparameters tnIdFact, tcIdIncarcare
Private pnIdFact, pcIdIncarcare
pnIdFact = m.tnIdFact
pcIdIncarcare = m.tcIdIncarcare
pnTest = IIF(This.lTest, 1, 0) && server TEST ANAF
lcSql = 'begin pack_anaf.SuprascrieIdIncarcare(?pnIdFact, ?pcIdIncarcare, ?pnTest, ?gnIdUtil); end;'
llSucces = goExecutor.oExecuta(m.lcSql)
Return m.llSucces
Endproc && SuprascrieIdIncarcare
********************************
* Genereaza xml efactura, valideaza xml si trimite la API ANAF
********************************
Procedure TrimiteFacturi
Lparameters tlNuTrimiteEFacturaANAF
Local lcTip, llSucces, lnValoare, lnRecno, loEx as Exception
Local lcFilter, lcSql, lnIdVanzare
Local lcRecc, lcRecno, ldDataFact, lnNumarFact, loReturn, lnTrimis
Local lcMesaj
Local lcErrorMessage, lcExecutionStatus, lcIndexIncarcare, loXML
Private pnIdFact, pnValoare, pcMesajTrimis, pnTrimis, pcIdIncarcare, pnTest
llSucces = .F.
pnIdFact = crsFacturiEmise.id_fact
pnTest = IIF(This.lTest, 1, 0) && server TEST ANAF
lnRecno = Recno('crsFacturiEmise')
lcFilter = "id_fact = " + Alltrim(Str(m.pnIdFact))
Select crsFacturiEmise
Locate For ales = 1
If !Found()
Locate For id_fact = m.pnIdFact
Else
lcFilter = "ales = 1"
Endif
If Empty(m.pnIdFact)
Return m.llSucces
Endif
lcSql = 'begin pack_anaf.BifeazaEFactTrimis(?pnIdFact, ?pnTrimis, ?pcMesajTrimis, ?pcIdIncarcare, ?pnTest, ?gnIdUtil); end;'
Select crsFacturiEmise
lcRecc = Alltrim(Str(Reccount()))
Scan For &lcFilter
pnIdFact = id_fact
lnIdVanzare = id_vanzare
lnNumarFact = crsFacturiEmise.numar_act
ldDataFact = crsFacturiEmise.data_act
pnTrimis = Nvl(trimis, 0)
lnTrimis = Nvl(trimis, 0)
pcIdIncarcare = Nvl(id_incarcare, '')
lcRecno = Alltrim(Str(Recno()))
Wait Window 'Factura ' + Alltrim(Str(m.lnNumarFact)) + ' / ' + Dtoc(m.ldDataFact) + ' ' + m.lcRecno + '/' + m.lcRecc Nowait
loReturn = This.TrimiteEfactura(m.lnIdVanzare, m.tlNuTrimiteEFacturaANAF)
llSucces = loReturn.lSucces
If m.llSucces
pcMesajTrimis = Iif(This.lTest, 'TEST ', '')
loXML = NULL
IF !m.tlNuTrimiteEFacturaANAF
TRY
loXML = nfxmlread(loReturn.cResponse)
CATCH TO loEx
lcErrorMessage = loEx.Message
ENDTRY
ENDIF
lcExecutionStatus = ''
lcIndexIncarcare = ''
lcErrorMessage = ''
IF TYPE('loxml.header._attr_.executionstatus') <> 'U'
lcExecutionStatus = loxml.header._attr_.executionstatus
ENDIF
IF TYPE('loxml.header._attr_.index__incarcare') <> 'U'
lcIndexIncarcare = loxml.header._attr_.index__incarcare
ENDIF
IF TYPE('loxml.header.errors._attr_.errorMessage') <> 'U'
lcErrorMessage = loxml.header.errors._attr_.errorMessage
ENDIF
Do Case
Case lcExecutionStatus = "0"
pcIdIncarcare = m.lcIndexIncarcare
pnTrimis = 1
pcMesajTrimis = m.pcMesajTrimis + 'Transmis cu succes. Index incarcare = ' + m.pcIdIncarcare
Case !EMPTY(m.lcErrorMessage)
pcIdIncarcare = ''
pnTrimis = 1
pcMesajTrimis = m.pcMesajTrimis + Iif(This.lTest, 'TEST ', '') + 'Eroare. ' + m.lcErrorMessage
Case [VALID] $ Upper(loReturn.cResponse)
pcIdIncarcare = ''
pnTrimis = 0
pcMesajTrimis = m.pcMesajTrimis + loReturn.cResponse
Otherwise
pcMesajTrimis = m.pcMesajTrimis + Iif(This.lTest, 'TEST ', '') + 'Eroare. ' + m.lcErrorMessage
pcIdIncarcare = ''
pnTrimis = 1
Endcase
* Completez doar cu raspunsul de la trimiterea la ANAF, nu si de la validare
If !m.tlNuTrimiteEFacturaANAF
pcMesajTrimis = LEFT(m.pcMesajTrimis,250)
llSucces = goExecutor.oExecuta(m.lcSql)
Endif
If [VALID] $ Upper(loReturn.cResponse) And m.lnTrimis = 0
Replace trimis With m.pnTrimis, id_incarcare With m.pcIdIncarcare, data_trimis With Datetime(), mesaj_trimis With m.pcMesajTrimis, ales With 0, ;
id_descarcare WITH '', data_raspuns WITH null, tip_mesaj_raspuns WITH '', mesaj_raspuns WITH null ;
In crsFacturiEmise
Else
Replace trimis With m.pnTrimis, id_incarcare With m.pcIdIncarcare, data_trimis With Datetime(), mesaj_trimis With m.pcMesajTrimis, ales With 0, ;
id_descarcare WITH '', data_raspuns WITH null, tip_mesaj_raspuns WITH '', mesaj_raspuns WITH null ;
In crsFacturiEmise
Endif
ELSE
lcMesaj = 'Eroare transmitere factura ' + Alltrim(Str(m.lnNumarFact)) + ' / ' + Dtoc(m.ldDataFact) + Chr(13) + Chr(10) + ;
'Fisier xml: ' + Alltrim(Transform(loReturn.cFile)) + Chr(13) + Chr(10) + ;
'ANAF Http Status: ' + Transform(loReturn.nStatus) + Chr(13) + Chr(10) + ;
IIF(loReturn.nStatus = 403, 'Acces interzis. Token-ul a expirat si trebuie regenerat.' + Chr(13) + Chr(10), '') + ;
'ANAF Http Response: ' + Alltrim(Transform(loReturn.cResponse))
poLog.Log(m.lcMesaj)
If AMESSAGEBOX(m.lcMesaj + Chr(10) + ;
'Doriti sa continuati?', 4 + 32, _Screen.Caption) <> 6
Exit
Endif
Endif
Endscan
Select crsFacturiEmise
Try
If m.lnRecno > 0
Goto m.lnRecno
Else
Go Top
Endif
Catch
Go Top
Endtry
Endproc && TrimiteFacturi
* Genereaza xml eFactura, valideaza xml si trimite la ANAF
FUNCTION TrimiteEfactura
Lparameters tnIdVanzare, tlNuTrimiteEFacturaANAF
PRIVATE pcTokenEfactura
LOCAL loReturn
loReturn = Createobject("empty")
AddProperty(loReturn, "lSucces", .F.)
AddProperty(loReturn, "cFile", '')
AddProperty(loReturn, "cResponse", '')
AddProperty(loReturn, "nStatus", 0)
* Genereaza xml eFactura
llSilent = .T.
llJustPDF = .F.
lcTipDocument = 'FACTURA'
llEFactura = .T.
llOk = .F.
lcFile = ''
lcMesaj = ''
pcTokenEfactura = This.Token && variabila privata pentru getxmlefactura > ValidareEFacturaAnaf
loDate = listeaza_formular(m.tnIdVanzare, m.llSilent, m.llJustPDF, m.lcTipDocument, m.llEFactura)
loInfo = loDate.oInfoEFactura
If Type('loInfo.cFile') = 'C'
lcFile = Iif(Type('loInfo.cFile') = 'C', loInfo.cFile, '')
llOk = loInfo.lOk
lcMesaj = loInfo.cMesaj
Endif
loReturn.cFile = m.lcFile
lcCodTara = 'RO'
IF TYPE('loDate.oClient.cod_tara') <> 'U'
lcCodTara = ALLTRIM(NVL(loDate.oClient.cod_tara, ''))
IF EMPTY(m.lcCodTara)
lcCodTara = 'RO'
ENDIF
ENDIF
llAtributFiscalRO = .F.
IF TYPE('loDate.oClient.cod_fiscal') <> 'U'
llAtributFiscalRO = 'RO'$UPPER(ALLTRIM(NVL(loDate.oClient.cod_fiscal, '')))
ENDIF
llExtern = (m.lcCodTara <> 'RO' AND !m.llAtributFiscalRO) && sa aiba sediul fiscal extern si sa nu fie inregistrat TVA in Romania
lcExtern = IIF(m.llExtern, '&extern=DA', '')
If m.llOk And !Empty(m.lcFile) And Type('lcFile') = 'C' And File(m.lcFile)
If !m.tlNuTrimiteEFacturaANAF
loReturn = This.AnafeFacturaServer.SendEfactura(m.lcFile, m.llExtern)
Else
loReturn.cResponse = Iif(!Empty(m.lcMesaj), m.lcMesaj + Chr(13) + Chr(10), '') + 'VALID. Nu s-a trimis fisierul la ANAF.'
loReturn.lSucces = .T.
Endif
Else
loReturn.cResponse = m.lcMesaj + Chr(13) + Chr(10) + '<errorMessage="Nu s-a trimis fisierul la ANAF">'
loReturn.lSucces = .F.
Endif
RETURN m.loReturn
ENDFUNC && TrimiteEfactura
****************
* Parseaza un xml efactura si actualizeaza ANAF_EFACTURA
****************
PROCEDURE Detalii2UpdateFactura
LPARAMETERS tnId, tcDetalii
LOCAL llVariable
llVariable = .T.
TRY
loFactura = ParseEFactura(m.tcDetalii, m.llVariable)
loFactura.nId = m.tnId
lcSql = [select a.*, 1 as modificat, to_clob(null) as factura_detalii from anaf_efactura a where id = ] + ALLTRIM(STR(m.tnId))
llSucces = goExecutor.oExecuta(m.lcSql, 'cAnafEfacturaTemp')
IF m.llSucces
ADDPROPERTY(loFactura, 'cIdIncarcare', cAnafEfacturaTemp.id_incarcare)
ADDPROPERTY(loFactura, 'cIdDescarcare', cAnafEfacturaTemp.id_incarcare)
llSucces = This.AnafeFacturaServer.cUpdateFactura(loFactura, 'cAnafEfacturaTemp')
IF m.llSucces
llSucces = This.AnafeFacturaServer.UpdateDb('cAnafEfacturaTemp')
ENDIF
ENDIF
USE IN (SELECT('cAnafEfacturaTemp'))
Catch To loEx
llSucces = .F.
ENDTRY
RETURN m.llSucces
ENDPROC && Detalii2UpdateFactura
* Salveaza pe disk arhiva cu detalii ANAF_EFACTURA.DETALII_ZIP
FUNCTION DownloadDetaliiZip
LPARAMETERS tnIdeFactura
PRIVATE poDetaliiZip
poDetaliiZip = null
lcSchema = [id_incarcare V(36), fisier W]
lcSelect = [select id_incarcare, detalii_zip from anaf_efactura where id = ] + Alltrim(Str(tnIdeFactura))
lcOrder = []
lcgroup = []
lcFiltru = []
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poDetaliiZip','cRegFisierTemp', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poDetaliiZip.ca_baza1.afisare()
If Used('cRegFisierTemp')
lcIdIncarcare = ALLTRIM(NVL(id_incarcare, ''))
lcFisier = fisier
Use In (Select('cRegFisierTemp'))
lcFile = PUTFILE('Fisier', m.lcIdIncarcare, 'zip')
IF !EMPTY(m.lcFile)
Strtofile(lcFisier, m.lcFile)
open_default_app(JUSTPATH(m.lcFile))
ENDIF
Endif
ENDFUNC && DownloadDetaliiZip
ENDDEFINE && ANAFeFactura
*********************
* Parseaza xml efactura si intoarce obiect VFP cu datele facturii xml cu detaliile facturii
*********************
Procedure ParseEFactura
Lparameters tcFile, tlVariable
* tcFile: fisier sau variabila care contine xml eFactura
* tlVariable: .T. daca tcFile este o variabila care contine xml eFactura
Local lcFileText, lcDetalii, lcFacturaDetalii, loEx As Exception, loReturn
Local laLinii[1], laLiniiDisc[1], laDetalii[1], laDetaliiLinie[1], laDetaliiPlata[1], laCommodityClassification[1]
Local lcDataFactura, lcDataScad, lcDetaliiLinie, lcUM, lcValuta, lnAn, lnCant, lnDetalii
Local lnDetaliiLinie, lnDetaliu, lnDetaliuLinie, lnLinie, lnLinii, lnLuna, lnNr, lnPret, lnProcTva
Local lnZi, loFactura, loLinie, lcArticol, lcDetaliu
Local lcArticolDescriere, lcBanca, lcCodClient, lcCodFurnizor, lcTip, lcCod, lcCodBare, lcCodCPV, lcCodNC8
Local lcCodPlata, lcContBanca, lcPrefixInvoice, llCreditNote
Local lnCommodityClassification, lnCommodityClassifications, lnValoareFaraTVA
Local loCommodityClassification, loDetaliu, loItemClassificationCode
Local lnDiscount, lnDiscountLinie, lnValoareTVA, loTaxTotal
*!* IF '4114569629'$lcfile
*!* SET STEP ON
*!* ENDIF
loReturn = Createobject("empty")
AddProperty(loReturn, "nId", "") && ANAF_EFACTURA.ID
AddProperty(loReturn, "NumarAct", "")
AddProperty(loReturn, "DataAct", {})
AddProperty(loReturn, "DataScad", {})
AddProperty(loReturn, "Furnizor", "")
AddProperty(loReturn, "CodTaraFurnizor", "")
AddProperty(loReturn, "CodJudetFurnizor", "")
AddProperty(loReturn, "LocalitateFurnizor", "")
AddProperty(loReturn, "StradaFurnizor", "")
AddProperty(loReturn, "CodFiscalFurnizor", "")
AddProperty(loReturn, "Client", "")
AddProperty(loReturn, "CodTaraClient", "")
AddProperty(loReturn, "CodJudetClient", "")
AddProperty(loReturn, "LocalitateClient", "")
AddProperty(loReturn, "StradaClient", "")
AddProperty(loReturn, "CodFiscalClient", "")
AddProperty(loReturn, "TotalFaraTva", 0.00)
AddProperty(loReturn, "TotalTva", 0.00)
AddProperty(loReturn, "TotalTvaRON", 0.00)
AddProperty(loReturn, "TotalCuTva", 0.00)
AddProperty(loReturn, "TaxeFaraTVA", 0.00)
AddProperty(loReturn, "DiscountFaraTVA", 0.00)
AddProperty(loReturn, "ValoareFaraTVA", 0.00) && suma valoare articole
AddProperty(loReturn, "TotaldePlata", 0.00)
AddProperty(loReturn, "Valuta", "")
AddProperty(loReturn, "Detalii", "") && note factura
AddProperty(loReturn, "DetaliiPlata", "") && detalii plata (conturi bancare)
AddProperty(loReturn, "FacturaDetalii", "") && liniile facturii
AddProperty(loReturn, "FacturaDetaliiDisc", "") && linii discount la nivel de factura
AddProperty(loReturn, "Eroare", .F.) && daca a aparut o eroare la parsarea facturii
AddProperty(loReturn, "CreditNote", 0) && 1 = CreditNote, 0 = Invoice
Create Cursor cFacturaDetaliiTemp(nr I, cant N(16, 6), um V(20), articol V(250), descriere V(250), detalii M, Pret N(16, 6), proctva N(10, 2), tiptva V(2), valoarefaratva N(16,4), discountfaratva N(16,4), codfurnizor V(100), codclient V(100), codbare V(50), codcpv V(50), codnc8 V(50))
CREATE CURSOR cFacturaDetaliiDisc(valoare N(20,6), procentTVA N(5,2), tiptva V(10), discount N(1), motivdiscount V(200), motivdiscountcod V(50))
If m.tlVariable
lcFileText = m.tcFile
Else
lcFileText = Iif(File(m.tcFile), Filetostr(m.tcFile), '')
Endif
If Empty(m.lcFileText)
loReturn.eroare = .T.
Return loReturn
Endif
* CreditNote to Invoice
llCreditNote = 'CreditNote' $ lcFileText
loReturn.CreditNote = IIF(m.llCreditNote, 1, 0)
lcFileText = Strtran(lcFileText, 'CreditNote', 'Invoice', 1, 100000, 1)
lcFileText = Strtran(lcFileText, 'Credited', 'Invoiced', 1, 100000, 1)
* Scot cbc: cac:
* Unele fisiere nu au, altele au. Le scot din toate
lcFileText = Strtran(lcFileText, 'cac:', '', 1, 1000000, 1)
lcFileText = Strtran(lcFileText, 'cbc:', '', 1, 1000000, 1)
lcPrefixInvoice = STREXTRACT(m.lcFileText, [<], [Invoice],1,1) && un prefix custom la Invoice <p:Invoice xlmns...
IF LEN(m.lcPrefixInvoice) > 10 && caut prefixul la a doua aparitie a <
lcPrefixInvoice = STREXTRACT(m.lcFileText, [<], [Invoice],2,1) && un prefix custom la Invoice <p:Invoice xlmns...
ENDIF
IF !EMPTY(m.lcPrefixInvoice)
lcFileText = Strtran(lcFileText, m.lcPrefixInvoice, '', 1, 100000, 1) && elimin prefixul custom Invoice
ENDIF
* elimin prefixuri custom: n2:, n3:
lcPattern = [<\/.{1,6}:Amount>] && [<n3:Amount ]
lcPrefix = GetRegExp(m.lcFileText, m.lcPattern)
lcPrefix = STREXTRACT(NVL(m.lcPrefix, ''), [</], [Amount],1,1)
IF !EMPTY(m.lcPrefix)
lcFileText = Strtran(lcFileText, m.lcPrefix, '', 1, 100000, 1) && elimin prefixul custom
ENDIF
lcPattern = [<\/.{1,6}:AccountingSupplierParty>]
lcPrefix = GetRegExp(m.lcFileText, m.lcPattern)
lcPrefix = STREXTRACT(NVL(m.lcPrefix, ''), [</], [AccountingSupplierParty],1,1)
IF !EMPTY(m.lcPrefix)
lcFileText = Strtran(lcFileText, m.lcPrefix, '', 1, 100000, 1) && elimin prefixul custom
ENDIF
lcPattern = [<\/.{1,6}:LineExtensionAmount>]
lcPrefix = GetRegExp(m.lcFileText, m.lcPattern)
lcPrefix = STREXTRACT(NVL(m.lcPrefix, ''), [</], [LineExtensionAmount],1,1)
IF !EMPTY(m.lcPrefix)
lcFileText = Strtran(lcFileText, m.lcPrefix, '', 1, 100000, 1) && elimin prefixul custom
ENDIF
TRY
* Nu prea functioneaza transformarea in array-uri a tag-urilor care apar o singura data
loFactura = nfxmlread(m.lcFileText)
*!* MESSAGEBOX(lofactura.invoice.cac_legalmonetarytotal.cbc_taxinclusiveamount._attr_.currencyid)
*!* MESSAGEBOX(lofactura.invoice.cac_legalmonetarytotal.cbc_taxinclusiveamount._nodetext_)
*!* loNrFacturaPrimit = nfxmlread(m.pcDetalii, '.Invoice.cac:InvoiceLine[]', '//Invoice/cbc:ID' )
*!* loDataFacturaPrimit = nfxmlread(m.pcDetalii, '.Invoice.cac:InvoiceLine[]', '//Invoice/cbc:IssueDate' ) && 2022-09-30
*!* loDataFacturaPrimit = nfxmlread(m.pcDetalii, '.Invoice.cac:InvoiceLine[]', '//Invoice/cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount' ) && 2022-09-30
DO CASE
CASE Type('loFactura.invoice.id') = 'C'
loReturn.numaract = loFactura.Invoice.id
CASE Type('loFactura.invoice.id._nodetext_') = 'C'
loReturn.numaract = loFactura.Invoice.id._nodetext_
ENDCASE
If Type('loFactura.invoice.issuedate') = 'C'
lcDataFactura = loFactura.Invoice.issuedate
Else
If Type('loFactura.invoice.issuedate._nodetext_ ') = 'C'
lcDataFactura = loFactura.Invoice.issuedate._nodetext_
Endif
Endif
If !Empty(m.lcDataFactura)
lnAn = Int(Val(Substr(m.lcDataFactura, 1, 4)))
lnLuna = Int(Val(Substr(m.lcDataFactura, 6, 2)))
lnZi = Int(Val(Substr(m.lcDataFactura, 9, 2)))
loReturn.dataact = Date(m.lnAn, m.lnLuna, m.lnZi)
Endif
If Type('loFactura.invoice.duedate') = 'C'
lcDataScad = loFactura.Invoice.duedate
Else
If Type('loFactura.invoice.duedate._nodetext_') = 'C'
lcDataScad = loFactura.Invoice.duedate._nodetext_
Endif
Endif
If !Empty(m.lcDataScad)
lnAn = Int(Val(Substr(m.lcDataScad, 1, 4)))
lnLuna = Int(Val(Substr(m.lcDataScad, 6, 2)))
lnZi = Int(Val(Substr(m.lcDataScad, 9, 2)))
loReturn.datascad = Date(m.lnAn, m.lnLuna, m.lnZi)
Endif
If Type('lofactura.invoice.legalmonetarytotal.LineExtensionAmount._nodetext_') = 'C'
loReturn.valoarefaratva = Val(loFactura.Invoice.legalmonetarytotal.LineExtensionAmount._nodetext_)
Endif
If Type('lofactura.invoice.legalmonetarytotal.taxinclusiveamount._nodetext_') = 'C'
loReturn.totalcutva = Val(loFactura.Invoice.legalmonetarytotal.taxinclusiveamount._nodetext_)
Endif
If Type('lofactura.invoice.legalmonetarytotal.taxinclusiveamount._attr_.currencyid') = 'C'
loReturn.valuta = loFactura.Invoice.legalmonetarytotal.taxinclusiveamount._attr_.currencyid
Endif
If Type('lofactura.invoice.legalmonetarytotal.TaxExclusiveAmount._nodetext_') = 'C'
loReturn.totalfaratva = Val(loFactura.Invoice.legalmonetarytotal.TaxExclusiveAmount._nodetext_)
Endif
loReturn.totaltva = loReturn.totalcutva - loReturn.totalfaratva
If Type('lofactura.invoice.legalmonetarytotal.AllowanceTotalAmount._nodetext_') = 'C'
loReturn.discountfaratva = Val(loFactura.Invoice.legalmonetarytotal.AllowanceTotalAmount._nodetext_)
Endif
If Type('lofactura.invoice.legalmonetarytotal.ChargeTotalAmount._nodetext_') = 'C'
* Transport trecut ca valoare totala pe document, in loc de o linie din factura
loReturn.taxefaratva = Val(loFactura.Invoice.legalmonetarytotal.ChargeTotalAmount._nodetext_)
Endif
If Type('lofactura.invoice.legalmonetarytotal.PayableAmount._nodetext_') = 'C'
loReturn.totaldeplata = Val(loFactura.Invoice.legalmonetarytotal.PayableAmount._nodetext_)
Endif
* Daca moneda facturii este in valuta <> RON, atunci extrag valoare tva in RON
* Sunt 2 TaxTotal, una in valuta facturii si una in RON
*!* <cac:TaxTotal>
*!* <cbc:TaxAmount currencyID="RON">0.00</cbc:TaxAmount>
*!* </cac:TaxTotal>
IF UPPER(ALLTRIM(loReturn.valuta)) <> 'RON'
If Type('loFactura.Invoice.TaxTotal') <> 'U'
If Type('loFactura.Invoice.TaxTotal', 1) = 'A'
FOR EACH loTaxTotal IN loFactura.Invoice.TaxTotal
IF TYPE('loTaxTotal.TaxAmount._attr_.CurrencyId') = 'C' AND TYPE('loTaxTotal.TaxAmount._nodetext_') = 'C' AND loTaxTotal.TaxAmount._attr_.CurrencyId = "RON"
loReturn.TotalTVARON = VAL(loTaxTotal.TaxAmount._nodetext_)
ENDIF
ENDFOR
ELSE
IF TYPE('loFactura.Invoice.TaxTotal') = 'O'
loTaxTotal = loFactura.Invoice.TaxTotal
IF TYPE('loTaxTotal.TaxAmount._attr_') = 'C' AND TYPE('loTaxTotal.TaxAmount._nodetext_') = 'C' AND loTaxTotal.TaxAmount._attr_.CurrencyId = "RON"
loReturn.TotalTVARON = VAL(loTaxTotal.TaxAmount._nodetext_)
ENDIF
ENDIF
ENDIF
ENDIF && <> U
ELSE
loReturn.TotalTVARON = loReturn.totaltva
ENDIF && <> RON
loReturn.detalii = ""
If Type('loFactura.Invoice.note') <> 'U'
If Type('loFactura.Invoice.note', 1) = 'A'
Acopy(loFactura.Invoice.note, laDetalii)
ELSE
IF TYPE('loFactura.Invoice.note') = 'C'
laDetalii[1] = loFactura.Invoice.note
ELSE
IF TYPE('loFactura.Invoice.note._nodetext_') = 'C'
laDetalii[1] = loFactura.Invoice.note._nodetext_
ENDIF
ENDIF
Endif
lnDetalii = Alen(laDetalii)
For lnDetaliu = 1 To m.lnDetalii
lcDetaliu = ''
IF TYPE('laDetalii[m.lnDetaliu]') = 'C'
lcDetaliu = laDetalii[m.lnDetaliu]
ELSE
IF TYPE('laDetalii[m.lnDetaliu]._nodetext_') = 'C'
lcDetaliu = laDetalii[m.lnDetaliu]._nodetext_
ENDIF
ENDIF
loReturn.detalii = loReturn.detalii + Iif(m.lnDetaliu > 1, " ", "") + m.lcDetaliu
Endfor
Endif
* Detalii plata = conturi bancare plata
loReturn.detaliiplata = ""
If Type('loFactura.Invoice.paymentmeans') <> 'U'
If Type('loFactura.Invoice.paymentmeans', 1) = 'A'
Acopy(loFactura.Invoice.paymentmeans, laDetaliiPlata)
Else
laDetaliiPlata[1] = loFactura.Invoice.paymentmeans
Endif
lnDetalii = Alen(laDetaliiPlata)
For lnDetaliu = 1 To m.lnDetalii
loDetaliu = laDetaliiPlata[m.lnDetaliu]
lcCodPlata = ''
lcContBanca = ''
lcBanca = ''
If Type('loDetaliu.paymentmeanscode') = 'C'
lcCodPlata = loDetaliu.paymentmeanscode
Else
If Type('loDetaliu.paymentmeanscode._nodetext_') = 'C'
lcCodPlata = loDetaliu.paymentmeanscode._nodetext_
Endif
Endif
If !Empty(m.lcCodPlata)
Do Case
Case lcCodPlata = '10'
lcCodPlata = lcCodPlata + ' Numerar'
Case lcCodPlata = '20'
lcCodPlata = lcCodPlata + ' CEC'
Case lcCodPlata = '31'
lcCodPlata = lcCodPlata + ' Transfer'
Case lcCodPlata = '42'
lcCodPlata = lcCodPlata + ' OP'
Case lcCodPlata = '48'
lcCodPlata = lcCodPlata + ' Card'
Case lcCodPlata = '60'
lcCodPlata = lcCodPlata + ' BO'
Case lcCodPlata = '68'
lcCodPlata = lcCodPlata + ' Online'
Case lcCodPlata = '97'
lcCodPlata = lcCodPlata + ' Compensare'
Endcase
Endif
If Type('loDetaliu.payeefinancialaccount.id') = 'C'
lcContBanca = loDetaliu.payeefinancialaccount.id
Else
If Type('loDetaliu.payeefinancialaccount.id._nodetext_') = 'C'
lcContBanca = loDetaliu.payeefinancialaccount.id._nodetext_
Endif
Endif
If Type('loDetaliu.payeefinancialaccount.name') = 'C'
lcBanca = loDetaliu.payeefinancialaccount.name
Else
If Type('loDetaliu.payeefinancialaccount.name._nodetext_') = 'C'
lcBanca = loDetaliu.payeefinancialaccount.name._nodetext_
Endif
Endif
loReturn.detaliiplata = loReturn.detaliiplata + Iif(m.lnDetaliu > 1, "; ", "") + ;
Iif(Empty(m.lcCodPlata), '', 'Tip: ' + m.lcCodPlata) + ;
Iif(Empty(m.lcContBanca), '', Iif(!Empty(m.lcCodPlata), ',', '') + ' IBAN: ' + m.lcContBanca) + ;
Iif(Empty(m.lcBanca), '', Iif(!Empty(m.lcContBanca), ',', '') + ' Banca: ' + m.lcBanca)
Endfor
Endif
* Furnizor Denumire
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity.RegistrationName') = 'C'
loReturn.Furnizor = Alltrim(loFactura.Invoice.AccountingSupplierParty.Party.PartyLegalEntity.RegistrationName)
Else
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity.RegistrationName._nodetext_') = 'C'
loReturn.Furnizor = Alltrim(loFactura.Invoice.AccountingSupplierParty.Party.PartyLegalEntity.RegistrationName._nodetext_)
ELSE
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity[1].RegistrationName') = 'C'
loReturn.Furnizor = Alltrim(loFactura.Invoice.AccountingSupplierParty.Party.PartyLegalEntity[1].RegistrationName)
ELSE
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity[2].RegistrationName') = 'C'
loReturn.Furnizor = Alltrim(loFactura.Invoice.AccountingSupplierParty.Party.PartyLegalEntity[2].RegistrationName)
ENDIF
ENDIF
Endif
ENDIF
* Cod fiscal Furnizor
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyTaxScheme.CompanyId') = 'C'
loReturn.CodFiscalFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PartyTaxScheme.CompanyId)
Else
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyTaxScheme.CompanyId._nodetext_') = 'C'
loReturn.CodFiscalFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PartyTaxScheme.CompanyId._nodetext_)
ELSE
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity.CompanyId') = 'C'
loReturn.CodFiscalFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity.CompanyId)
Else
If Type('lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity.CompanyId._nodetext_') = 'C'
loReturn.CodFiscalFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PartyLegalEntity.CompanyId._nodetext_)
Endif
ENDIF
ENDIF
ENDIF
* Furnizor Cod Tara
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.Country.IdentificationCode') = 'C'
loReturn.CodTaraFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.Country.IdentificationCode)
Else
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.Country.IdentificationCode._nodetext_') = 'C'
loReturn.CodTaraFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.Country.IdentificationCode._nodetext_)
Endif
ENDIF
* Furnizor Cod Judet
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CountrySubentity') = 'C'
loReturn.CodJudetFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CountrySubentity)
Else
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CountrySubentity._nodetext_') = 'C'
loReturn.CodJudetFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CountrySubentity._nodetext_)
Endif
Endif
* Furnizor Localitate
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CityName') = 'C'
loReturn.LocalitateFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CityName)
Else
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CityName._nodetext_') = 'C'
loReturn.LocalitateFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.CityName._nodetext_)
Endif
ENDIF
* Furnizor Strada
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.StreetName') = 'C'
loReturn.StradaFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.StreetName)
Else
If Type('lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.StreetName._nodetext_') = 'C'
loReturn.StradaFurnizor = Alltrim(lofactura.invoice.AccountingSupplierParty.Party.PostalAddress.StreetName._nodetext_)
Endif
ENDIF
* Client Denumire
If Type('lofactura.invoice.AccountingCustomerParty.Party.PartyLegalEntity.RegistrationName') = 'C'
loReturn.client = Alltrim(loFactura.Invoice.AccountingCustomerParty.Party.PartyLegalEntity.RegistrationName)
Else
If Type('lofactura.invoice.AccountingCustomerParty.Party.PartyLegalEntity.RegistrationName._nodetext_') = 'C'
loReturn.client = Alltrim(loFactura.Invoice.AccountingCustomerParty.Party.PartyLegalEntity.RegistrationName._nodetext_)
Endif
ENDIF
* Cod fiscal Client
If Type('lofactura.invoice.AccountingCustomerParty.Party.PartyTaxScheme.CompanyId') = 'C'
loReturn.CodFiscalClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PartyTaxScheme.CompanyId)
Else
If Type('lofactura.invoice.AccountingCustomerParty.Party.PartyTaxScheme.CompanyId._nodetext_') = 'C'
loReturn.CodFiscalClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PartyTaxScheme.CompanyId._nodetext_)
ELSE
If Type('lofactura.invoice.AccountingCustomerParty.Party.PartyLegalEntity.CompanyId') = 'C'
loReturn.CodFiscalClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PartyLegalEntity.CompanyId)
Else
If Type('lofactura.invoice.AccountingCustomerParty.Party.PartyLegalEntity.CompanyId._nodetext_') = 'C'
loReturn.CodFiscalClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PartyLegalEntity.CompanyId._nodetext_)
Endif
ENDIF
ENDIF
ENDIF
* Client Cod Tara
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.Country.IdentificationCode') = 'C'
loReturn.CodTaraClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.Country.IdentificationCode)
Else
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.Country.IdentificationCode._nodetext_') = 'C'
loReturn.CodTaraClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.Country.IdentificationCode._nodetext_)
Endif
ENDIF
* Client Cod Judet
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CountrySubentity') = 'C'
loReturn.CodJudetClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CountrySubentity)
Else
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CountrySubentity._nodetext_') = 'C'
loReturn.CodJudetClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CountrySubentity._nodetext_)
Endif
Endif
* Client Localitate
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CityName') = 'C'
loReturn.LocalitateClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CityName)
Else
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CityName._nodetext_') = 'C'
loReturn.LocalitateClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.CityName._nodetext_)
Endif
ENDIF
* Client Strada
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.StreetName') = 'C'
loReturn.StradaClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.StreetName)
Else
If Type('lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.StreetName._nodetext_') = 'C'
loReturn.StradaClient = Alltrim(lofactura.invoice.AccountingCustomerParty.Party.PostalAddress.StreetName._nodetext_)
Endif
ENDIF
* Cursor linii factura
If Type('lofactura.invoice.invoiceline', 1) = 'A'
Acopy(loFactura.Invoice.invoiceline, laLinii)
Else
laLinii[1] = loFactura.Invoice.invoiceline
Endif
Try
lnLinii = Alen(laLinii)
For lnLinie = 1 To m.lnLinii
loLinie = laLinii[m.lnLinie]
lnNr = 0
If Type('loLinie.id') = 'C'
lnNr = Int(Val(loLinie.id))
Else
If Type('loLinie.id._nodetext_') = 'C'
lnNr = Int(Val(loLinie.id._nodetext_))
Endif
ENDIF
lnValoareFaraTVA = 0
If Type('loLinie.LineExtensionAmount._nodetext_') = 'C'
lnValoareFaraTVA = Val(loLinie.LineExtensionAmount._nodetext_)
Endif
lcArticol = ''
If Type('loLinie.item.name') = 'C'
lcArticol = Alltrim(loLinie.item.name)
Else
If Type('loLinie.item.name._nodetext_') = 'C'
lcArticol = Alltrim(loLinie.item.name._nodetext_)
Endif
Endif
lcArticolDescriere = ''
If Type('loLinie.item.description') = 'C'
lcArticolDescriere = Alltrim(loLinie.item.description)
Else
If Type('loLinie.item.description._nodetext_') = 'C'
lcArticolDescriere = Alltrim(loLinie.item.description._nodetext_)
Endif
Endif
lcDetaliiLinie = ''
If Type('loLinie.note') <> 'U'
If Type('loLinie.note', 1) = 'A'
Acopy(loLinie.note, laDetaliiLinie)
Else
If Type('loLinie.note') = 'C'
laDetaliiLinie[1] = loLinie.note
Else
If Type('loLinie.note._nodetext_') = 'C'
laDetaliiLinie[1] = loLinie.note._nodetext_
Endif
Endif
Endif
lnDetaliiLinie = Alen(laDetaliiLinie)
For lnDetaliuLinie = 1 To m.lnDetaliiLinie
lcDetaliiLinie = m.lcDetaliiLinie + Iif(m.lnDetaliuLinie > 1, " ", "") + laDetaliiLinie[m.lnDetaliuLinie]
Endfor
ENDIF
* Cod articol cumparator/client
lcCodClient = ''
If Type('loLinie.item.BuyersItemIdentification.ID') = 'C'
lcCodClient = Alltrim(loLinie.item.BuyersItemIdentification.ID)
Else
If Type('loLinie.item.BuyersItemIdentification.ID._nodetext_') = 'C'
lcCodClient = Alltrim(loLinie.item.BuyersItemIdentification.ID._nodetext_)
Endif
ENDIF
* Cod articol vanzator/furnizor
lcCodFurnizor = ''
If Type('loLinie.item.SellersItemIdentification.ID') = 'C'
lcCodFurnizor = Alltrim(loLinie.item.SellersItemIdentification.ID)
Else
If Type('loLinie.item.SellersItemIdentification.ID._nodetext_') = 'C'
lcCodFurnizor = Alltrim(loLinie.item.SellersItemIdentification.ID._nodetext_)
Endif
ENDIF
* Cod de bare articol
lcCodBare = ''
If Type('loLinie.item.StandardItemIdentification.ID') = 'C'
lcCodBare = Alltrim(loLinie.item.StandardItemIdentification.ID)
Else
If Type('loLinie.item.StandardItemIdentification.ID._nodetext_') = 'C'
lcCodBare = Alltrim(loLinie.item.StandardItemIdentification.ID._nodetext_)
Endif
ENDIF
lcCodCPV = ''
lcCodNC8 = ''
If Type('loLinie.item.CommodityClassification') <> 'U'
If Type('loLinie.item.CommodityClassification', 1) = 'A'
Acopy(loLinie.item.CommodityClassification, laCommodityClassification)
Else
If Type('loLinie.item.CommodityClassification') = 'O'
laCommodityClassification[1] = loLinie.item.CommodityClassification
Endif
Endif
lnCommodityClassifications = Alen(laCommodityClassification)
For lnCommodityClassification = 1 To m.lnCommodityClassifications
loCommodityClassification = laCommodityClassification[lnCommodityClassification]
IF TYPE('loCommodityClassification.ItemClassificationCode') = 'O'
loItemClassificationCode = loCommodityClassification.ItemClassificationCode
IF TYPE('loItemClassificationCode._attr_.listid') = 'C' AND TYPE('loItemClassificationCode._nodetext_') = 'C'
lcTip = UPPER(ALLTRIM(loItemClassificationCode._attr_.listid))
lcCod = ALLTRIM(loItemClassificationCode._nodetext_)
DO CASE
CASE m.lcTip = 'EN' AND EMPTY(m.lcCodBare)&& cod bare
lcCodBare = m.lcCod
CASE m.lcTip = 'STI' && cod CPV
lcCodCPV = m.lcCod
CASE m.lcTip = 'TSP' && cod NC8
lcCodNC8 = m.lcCod
ENDCASE
ENDIF && type
ENDIF && type
Endfor
ENDIF
lnCant = Val(loLinie.invoicedquantity._nodetext_)
lcUM = loLinie.invoicedquantity._attr_.unitcode
lnPret = Val(loLinie.price.priceamount._nodetext_)
lcValuta = loLinie.price.priceamount._attr_.currencyid
lnDiscountLinie = 0
IF TYPE('loLinie.AllowanceCharge.Amount._nodetext_') = 'C'
lnDiscountLinie = Val(loLinie.AllowanceCharge.Amount._nodetext_)
ENDIF
lnProcTva = 0
If Type('loLinie.item.ClassifiedTaxCategory.percent') = 'C'
lnProcTva = Val(loLinie.item.ClassifiedTaxCategory.percent)
Else
If Type('loLinie.item.ClassifiedTaxCategory.percent._nodetext_') = 'C'
lnProcTva = Val(loLinie.item.ClassifiedTaxCategory.percent._nodetext_)
Endif
ENDIF
lcTipTVA = "" && S standard/Z neplatitor TVA/AE taxare inversa
If Type('loLinie.item.ClassifiedTaxCategory.ID') = 'C'
lcTipTva = loLinie.item.ClassifiedTaxCategory.ID
Else
If Type('loLinie.item.ClassifiedTaxCategory.ID._nodetext_') = 'C'
lcTipTva = loLinie.item.ClassifiedTaxCategory.ID._nodetext_
Endif
Endif
* Tip CreditNote am vazut ca nu are cantitate si pret negative pe linie, dar are valoare fara tva negativ!!!
If m.llCreditNote And m.lnCant > 0 And m.lnPret > 0 And m.lnValoareFaraTVA< 0
lnCant = -1 * m.lnCant
Endif
Insert Into cFacturaDetaliiTemp(nr, cant, um, articol, descriere, detalii, Pret, proctva, tiptva, valoarefaratva, discountfaratva, codfurnizor, codclient, codbare, codcpv, codnc8) Values (m.lnNr, m.lnCant, m.lcUM, m.lcArticol, m.lcArticolDescriere, m.lcDetaliiLinie, m.lnPret, lnProcTva, m.lcTipTva, m.lnValoareFaraTVA, m.lnDiscountLinie, m.lcCodFurnizor, m.lcCodClient, m.lcCodBare, m.lcCodCPV, m.lcCodNC8)
Endfor
Catch To loEx
loReturn.eroare = .T.
goLog.Log('Eroare la salvarea datelor extrase din xml eFactura. ' + 'Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure)
Set Step On
Endtry
Cursortoxml("cfacturadetaliitemp", "lcFacturaDetalii", 1, 0 + 8, 0, "1")
loReturn.facturadetalii = m.lcFacturaDetalii
USE IN (SELECT('cFacturaDetaliiTemp'))
* cursor linii discount/taxe la nivel de factura
IF TYPE('lofactura.invoice.AllowanceCharge') <> 'U'
If Type('lofactura.invoice.AllowanceCharge', 1) = 'A'
Acopy(loFactura.Invoice.AllowanceCharge, laLiniiDisc)
Else
laLiniiDisc[1] = loFactura.Invoice.AllowanceCharge
Endif
Try
lnLinii = Alen(laLiniiDisc)
For lnLinie = 1 To m.lnLinii
loLinie = laLiniiDisc[m.lnLinie]
lnDiscount = 1
If Type('loLinie.ChargeIndicator') = 'C'
lnDiscount = IIF(LOWER(ALLTRIM(loLinie.ChargeIndicator)) = 'false', 1, 0) && discount = false, taxe = true
Else
If Type('loLinie.ChargeIndicator._nodetext_') = 'C'
lnDiscount = IIF(LOWER(ALLTRIM(loLinie.ChargeIndicator._nodetext_)) = 'false', 1, 0)
Endif
ENDIF
lcMotivDiscount = ''
If Type('loLinie.AllowanceChargeReason') = 'C'
lcMotivDiscount = ALLTRIM(loLinie.AllowanceChargeReason)
Else
If Type('loLinie.AllowanceChargeReason._nodetext_') = 'C'
lcMotivDiscount = ALLTRIM(loLinie.AllowanceChargeReason._nodetext_)
Endif
ENDIF
lcMotivDiscountCod = ''
If Type('loLinie.AllowanceChargeReasonCode') = 'C'
lcMotivDiscountCod = ALLTRIM(loLinie.AllowanceChargeReasonCode)
Else
If Type('loLinie.AllowanceChargeReasonCode._nodetext_') = 'C'
lcMotivDiscountCod = ALLTRIM(loLinie.AllowanceChargeReasonCode._nodetext_)
Endif
ENDIF
lnValoare = 0
If Type('loLinie.Amount._nodetext_') = 'C'
lnValoare = Val(loLinie.Amount._nodetext_)
ENDIF
lnProcTva = 0
If Type('loLinie.TaxCategory.Percent') = 'C'
lnProcTva = val(loLinie.TaxCategory.Percent)
Else
If Type('loLinie.TaxCategory.Percent._nodetext_') = 'C'
lnProcTva = val(loLinie.TaxCategory.Percent._nodetext_)
Endif
ENDIF
lcTipTVA = "" && S standard/Z neplatitor TVA/AE taxare inversa
If Type('loLinie.item.ClassifiedTaxCategory.ID') = 'C'
lcTipTva = loLinie.item.ClassifiedTaxCategory.ID
Else
If Type('loLinie.item.ClassifiedTaxCategory.ID._nodetext_') = 'C'
lcTipTva = loLinie.item.ClassifiedTaxCategory.ID._nodetext_
Endif
Endif
Insert Into cFacturaDetaliiDisc(valoare, procenttva, tiptva, discount, motivdiscount, motivdiscountcod) Values (m.lnValoare, m.lnProcTva, m.lcTipTVA, m.lnDiscount, m.lcMotivDiscount, m.lcMotivDiscountCod)
Endfor
Catch To loEx
loReturn.eroare = .T.
goLog.Log('Eroare la salvarea datelor extrase din xml eFactura. ' + 'Eroare: ' + TRANSFORM(loEx.ErrorNo) + ' ' + loEx.Message + ' Continut:' + loEx.LineContents + + ' Linia: ' + TRANSFORM(loEx.LineNo) + ' Program: ' + loEx.Procedure)
Set Step On
Endtry
Cursortoxml("cFacturaDetaliiDisc", "lcFacturaDetaliiDisc", 1, 0 + 8, 0, "")
loReturn.facturadetaliiDisc = m.lcFacturaDetaliiDisc
USE IN (SELECT('cFacturaDetaliiTVA'))
ENDIF && TYPE('lofactura.invoice.AllowanceCharge') <> 'U'
Catch To loEx
loReturn.eroare = .T.
AMESSAGEBOX(loEx.Message)
Set Step On
Endtry
Return loReturn
Endproc && ParseEFactura
******************************
PROCEDURE TestParseEFactura
Local loEfactura As "ExportEFactura"
Local lcFile, loFactura
*:Global pcDetaliiXML, pcFurnizorXML, pcNumarActXML, pcNumeValutaXML, pcXMLFacturaDetalii
*:Global pdDataActXML, pdDataScadXML, pnDiscountFaraTVAXML, pnTaxeFaraTVAXML, pnTotalCuTVAXML
*:Global pnTotalFaraTVAXML, pnTotalTVAXML, pnTotaldePlataXML, pnValoareFaraTVAXML
lcSetProcedure = LOWER(SET("Procedure"))
lcSetClasslib = LOWER(SET("Classlib"))
* json read
IF !'nfxmlread'$lcSetProcedure
SET PROCEDURE TO 'd:\roa\roacont\comun\utile\nfxml\nfxmlread.prg' ADDITIVE
ENDIF
* amessagebox
IF !'oproceduri_comune'$lcSetProcedure
SET PROCEDURE TO 'd:\roa\roacont\comun\programe\oproceduri_comune.prg' ADDITIVE
ENDIF
SET STEP ON
lcFile = GETFILE('xml','Fisier xml','Deschide', 0, "Fisier xml eFactura")
IF EMPTY(m.lcFile)
RETURN
ENDIF
TRY
loFactura = ParseEfactura(m.lcFile)
pcNumarActXML = loFactura.numaract
pdDataActXML = loFactura.dataact
pdDataScadXML = loFactura.datascad
pcFurnizorXML = loFactura.furnizor
pcDetaliiXML = loFactura.detalii
pcDetaliiPlataXML = loFactura.DetaliiPlata
pnTotalFaraTVAXML = loFactura.TotalFaraTva
pnTotalTVAXML = loFactura.TotalTva
pnTotalTVARONXML = loFactura.TotalTvaRON && daca factura este in valuta, se completeaza TotalTVARON
pnTotalCuTVAXML = loFactura.TotalCuTva
pnDiscountFaraTVAXML = loFactura.DiscountFaraTVA
pnTaxeFaraTVAXML = loFactura.TaxeFaraTVA
pnValoareFaraTVAXML = loFactura.ValoareFaraTVA && suma valoare fara tva articole
pnTotaldePlataXML = loFactura.TotaldePlata
pcNumeValutaXML = loFactura.valuta
pcXMLFacturaDetalii = loFactura.FacturaDetalii
XMLTOCURSOR(m.pcXmlFacturaDetalii, "factura_detalii")
Catch To loEx
MESSAGEBOX(loEx.message)
ENDTRY
ENDPROC && TestParseEFactura