SET STEP ON
Test1()
Test2()
Procedure Test1
Local loRar As "RarAutoPass"
Local lcXMLComenzi, llTestMode
* Creare instanta
loRar = Createobject("RarAutoPass")
* Setare credentiale - pentru test
llTestMode = .T.
loRar.SetCredentials(m.llTestMode)
* Actualizare nomenclator
loRar.UpdateNomenclator()
TEXT TO lcXMLComenzi NOSHOW
COM001
2024-02-04
VF1234567890
B01AAA
150000
0
Test prezentare
SCHIMB_VITEZOMETRU
Schimbare vitezometru
REPARATIE_BORD
Reparatie instrumente bord
ENDTEXT
* Procesare fisier XML cu comenzi
If !loRar.ProcessXMLComenzi("comenzi.xml")
? "Eroare: " + loRar.ErrorMsg
Endif
Endproc && Test1
***********************************
Procedure Test2
Local loRar As "RarAutoPass"
Local llTestMode
* Creare instanta si setare mediu
loRar = Createobject("RarAutoPass")
* Pentru test
llTestMode = .T.
loRar.SetCredentials(m.llTestMode)
* SAU pentru productie
* loRar.SetCredentials("email@service.ro", "parola", .F.)
* Actualizare nomenclator (fortat)
If !loRar.UpdateNomenclator(.T.)
? "Eroare actualizare nomenclator: " + loRar.ErrorMsg
Return
Endif
* Adaugare mapari operatii
Use mapare_prestatii
Append Blank
Replace cod_op_service With "SCHIMB_VITEZOMETRU", ;
descr_op_service With "Schimbare vitezometru/instrumente bord", ;
cod_prestatie_rar With "OE-1", ;
auto_send With .T., ;
data_actualizare With Date()
* Procesare comenzi din XML
If !loRar.ProcessXMLComenzi("comenzi.xml")
? "Eroare procesare comenzi: " + loRar.ErrorMsg
* Verificam log-ul pentru detalii
Select rar_log
Browse
Endif
* Sau trimitere prezentare individuala
If !loRar.SendPrezentare(;
"2024-02-04", ; && Data prestatie
"B01AAA", ; && Nr inmatriculare
"VF1234567890", ; && VIN
150000, ; && Km final
0, ; && Km initial
"Test", ; && Observatii
"", ; && Imagine base64
'[{"codPrestatie":"OE-1"}]', ; && Prestatii JSON
"COM001") && Nr comanda pentru logging
? "Eroare trimitere prezentare: " + loRar.ErrorMsg
Endif
Endproc && Test2
* Clasa pentru integrarea cu RAR AutoPass
#DEFINE C_API_TIMEOUT 30
#DEFINE C_TEST_URL "https://apps.rarom.ro/test-rar-autopass"
#DEFINE C_PROD_URL "https://apps.rarom.ro/rar-autopass"
* Clasa pentru integrarea cu RAR AutoPass
DEFINE CLASS RarAutoPass AS Custom
* Proprietati private
lcUrl = ""
lcEmail = ""
lcPassword = ""
lcToken = ""
lcError = ""
llTestMode = .T.
loXMLHTTP = null
* Proprietati publice
ErrorMsg = ""
LastResponse = ""
* Constructor
FUNCTION Init
THIS.lcUrl = ""
THIS.lcEmail = ""
THIS.lcPassword = ""
THIS.lcToken = ""
THIS.lcError = ""
THIS.llTestMode = .T.
THIS.loXMLHTTP = CREATEOBJECT("MSXML2.ServerXMLHTTP.6.0")
THIS.SetHttpTimeout()
* Cream tabelele necesare daca nu exista
THIS.InitializeStructure()
RETURN .T.
ENDFUNC
* Setare timeout pentru requesturi HTTP
FUNCTION SetHttpTimeout
LOCAL llSuccess
llSuccess = .F.
TRY
THIS.loXMLHTTP.setTimeouts(C_API_TIMEOUT*1000, ; && ResolveTimeout
C_API_TIMEOUT*1000, ; && ConnectTimeout
C_API_TIMEOUT*1000, ; && SendTimeout
C_API_TIMEOUT*1000) && ReceiveTimeout
llSuccess = .T.
CATCH TO loError
THIS.ErrorMsg = "Eroare setare timeout: " + loError.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Setare credentiale
FUNCTION SetCredentials
PARAMETERS tlTestMode
LOCAL llSuccess
llSuccess = .F.
TRY
* Setam modul de lucru (test/productie)
THIS.llTestMode = tlTestMode
* Setam URL-ul corespunzator
THIS.lcUrl = IIF(THIS.llTestMode, C_TEST_URL, C_PROD_URL)
* Citim credentialele din fisierul de setari
llSuccess = THIS.ReadSettings(tlTestMode)
CATCH TO loEx
THIS.ErrorMsg = "Eroare setare credentiale: " + loEx.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Initializare structura tabele
FUNCTION InitializeStructure
LOCAL llSuccess
llSuccess = .T.
TRY
IF !FILE("prestatii_rar.dbf")
CREATE TABLE prestatii_rar FREE (;
cod_prest C(10), ; && cod_prestatie
nume_prest C(250), ; && nume_prestatie
data_act D) && data_actualizare
INDEX ON cod_prest TAG cod_prest
USE IN SELECT('prestatii_rar')
ENDIF
IF !FILE("mapare_prestatii.dbf")
CREATE TABLE mapare_prestatii FREE (;
cod_op C(20), ; && cod_op_service
descr_op M, ; && descr_op_service
cod_rar C(10), ; && cod_prestatie_rar
auto_send L, ; && auto_send
data_act D) && data_actualizare
INDEX ON cod_op TAG cod_op
USE IN SELECT('mapare_prestatii')
ENDIF
IF !FILE("rar_log.dbf")
CREATE TABLE rar_log FREE (;
id I AUTOINC, ;
data_prez D, ; && data_prezentare
nr_comanda C(20), ;
vin C(20), ;
nr_inm C(10), ;
km_final N(10), ;
km_init N(10), ; && km_initial
prestatii M, ;
status C(20), ;
error_msg M, ;
data_trim T) && data_trimitere
USE IN SELECT('rar_log')
ENDIF
CATCH TO loEx
THIS.ErrorMsg = "Eroare initializare structura: " + loEx.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Login si obtinere token
FUNCTION Login
LOCAL lcJsonLogin, llSuccess
llSuccess = .F.
lcJsonLogin = '{"email":"' + THIS.lcEmail + '","password":"' + THIS.lcPassword + '"}'
TRY
THIS.loXMLHTTP.Open("POST", THIS.lcUrl + "/public/login", .F.)
THIS.loXMLHTTP.setRequestHeader("Content-Type", "application/json")
THIS.loXMLHTTP.Send(lcJsonLogin)
IF THIS.loXMLHTTP.Status != 200
THIS.ErrorMsg = "Eroare login: " + THIS.loXMLHTTP.responseText
llSuccess = .F.
RETURN llSuccess
ENDIF
* Folosim nfjsonread pentru a parsa raspunsul
loResponse = nfjsonread(THIS.loXMLHTTP.responseText)
IF TYPE('loResponse') == 'O' AND !ISNULL(loResponse)
THIS.lcToken = loResponse.token
IF EMPTY(THIS.lcToken)
THIS.ErrorMsg = "Nu s-a putut obtine token-ul"
llSuccess = .F.
ELSE
llSuccess = .T.
ENDIF
ELSE
THIS.ErrorMsg = "Eroare parsare raspuns JSON"
llSuccess = .F.
ENDIF
CATCH TO loEx
THIS.ErrorMsg = "Eroare login: " + loEx.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Actualizare nomenclator presta?ii
FUNCTION UpdateNomenclator
LPARAMETERS tlForceRefresh
LOCAL llSuccess
llSuccess = .F.
IF !tlForceRefresh AND FILE("prestatii_rar.dbf")
llSuccess = .T.
RETURN llSuccess
ENDIF
IF !THIS.Login()
RETURN .F.
ENDIF
TRY
THIS.loXMLHTTP.Open("GET", THIS.lcUrl + "/nomenclator/getNomenclatorPrestatii", .F.)
THIS.loXMLHTTP.setRequestHeader("Authorization", "Bearer " + THIS.lcToken)
THIS.loXMLHTTP.Send()
IF THIS.loXMLHTTP.Status != 200
THIS.ErrorMsg = "Eroare obtinere nomenclator: " + THIS.loXMLHTTP.responseText
llSuccess = .F.
RETURN llSuccess
ENDIF
* Folosim nfjsonread pentru a parsa raspunsul
loJson = nfjsonread(THIS.loXMLHTTP.responseText)
IF TYPE('loJson') == 'O' AND !ISNULL(loJson) AND TYPE('loJson.data') == 'O'
* Deschidem tabelul prestatii_rar
IF !USED("prestatii_rar")
USE prestatii_rar IN 0
ENDIF
SELECT prestatii_rar
* Procesam fiecare prestatie
FOR EACH loItem IN loJson.data
* Cautam prestatia dupa cod
LOCATE FOR cod_prest = loItem.codPrestatie
IF FOUND()
* Update daca exista ?i s-a modificat numele
IF nume_prest != loItem.numePrestatie
REPLACE ;
nume_prest WITH loItem.numePrestatie, ;
data_act WITH DATE()
ENDIF
ELSE
* Insert daca nu exista
INSERT INTO prestatii_rar (;
cod_prest, ;
nume_prest, ;
data_act) ;
VALUES (;
loItem.codPrestatie, ;
loItem.numePrestatie, ;
DATE())
ENDIF
ENDFOR
llSuccess = .T.
ELSE
THIS.ErrorMsg = "Eroare parsare raspuns JSON pentru nomenclator"
llSuccess = .F.
ENDIF
CATCH TO loEx
THIS.ErrorMsg = "Eroare actualizare nomenclator: " + loEx.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Trimitere prezentare individuala
FUNCTION SendPrezentare
LPARAMETERS tcDataPrest, tcNrInm, tcVin, tnKmFinal, tnKmInitial, ;
tcObs, tcImagineB64, tcPrestatii, tcNrComanda
LOCAL llSuccess, lcJson
llSuccess = .F.
IF !THIS.Login()
RETURN .F.
ENDIF
* Construim JSON-ul pentru prezentare
TEXT TO lcJson NOSHOW TEXTMERGE
{
"dataPrestatie": "<>",
"nrInmatriculare": "<>",
"vin": "<>",
"odometruFinal": <>,
"odometruInitial": <>,
"obs": "<>",
"b64Image": "<>",
"status": "FINALIZATA",
"prestatii": <>
}
ENDTEXT
TRY
THIS.loXMLHTTP.Open("POST", THIS.lcUrl + "/prezentari/postPrezentare", .F.)
THIS.loXMLHTTP.setRequestHeader("Content-Type", "application/json")
THIS.loXMLHTTP.setRequestHeader("Authorization", "Bearer " + THIS.lcToken)
THIS.loXMLHTTP.Send(lcJson)
THIS.LastResponse = THIS.loXMLHTTP.responseText
IF THIS.loXMLHTTP.Status != 200
THIS.ErrorMsg = "Eroare trimitere prezentare: " + THIS.LastResponse
THIS.LogPrezentare(tcDataPrest, tcNrComanda, tcVin, tcNrInm, ;
tnKmFinal, tnKmInitial, tcPrestatii, "ERROR", THIS.ErrorMsg)
llSuccess = .F.
ELSE
THIS.LogPrezentare(tcDataPrest, tcNrComanda, tcVin, tcNrInm, ;
tnKmFinal, tnKmInitial, tcPrestatii, "SUCCESS")
llSuccess = .T.
ENDIF
CATCH TO loEx
THIS.ErrorMsg = "Eroare trimitere prezentare: " + loEx.Message
THIS.LogPrezentare(tcDataPrest, tcNrComanda, tcVin, tcNrInm, ;
tnKmFinal, tnKmInitial, tcPrestatii, "ERROR", THIS.ErrorMsg)
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Logging prezentari
FUNCTION LogPrezentare
LPARAMETERS tcDataPrest, tcNrComanda, tcVin, tcNrInm, tnKmFinal, ;
tnKmInitial, tcPrestatii, tcStatus, tcErrorMsg
LOCAL llSuccess
llSuccess = .F.
TRY
IF !USED("rar_log")
USE rar_log IN 0
ENDIF
INSERT INTO rar_log (;
data_prez, ;
nr_comanda, ;
vin, ;
nr_inm, ;
km_final, ;
km_init, ;
prestatii, ;
status, ;
error_msg, ;
data_trim) ;
VALUES (;
CTOD(tcDataPrest), ;
tcNrComanda, ;
tcVin, ;
tcNrInm, ;
tnKmFinal, ;
tnKmInitial, ;
tcPrestatii, ;
tcStatus, ;
tcErrorMsg, ;
DATETIME())
llSuccess = .T.
CATCH TO loEx
THIS.ErrorMsg = "Eroare logging: " + loEx.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Procesare comenzi din XML
FUNCTION ProcessXMLComenzi
LPARAMETERS tcXMLFile
LOCAL loXML AS MSXML2.DOMDocument.6.0
LOCAL loNodes AS MSXML2.IXMLDOMNodeList
LOCAL loNode AS MSXML2.IXMLDOMNode
LOCAL lcPrestatii, llSuccess
llSuccess = .F.
TRY
loXML = CREATEOBJECT("MSXML2.DOMDocument.6.0")
loXML.async = .F.
IF !loXML.load(tcXMLFile)
THIS.ErrorMsg = "Eroare incarcare XML: " + loXML.parseError.reason
llSuccess = .F.
RETURN llSuccess
ENDIF
* Obtinem toate nodurile de comenzi
loNodes = loXML.selectNodes("/comenzi/comanda")
FOR EACH loNode IN loNodes
* Extragem datele din XML
lcNrComanda = loNode.selectSingleNode("nr_comanda").text
lcDataPrest = loNode.selectSingleNode("data").text
lcVin = loNode.selectSingleNode("vin").text
lcNrInm = loNode.selectSingleNode("nr_inmatriculare").text
lnKmFinal = VAL(loNode.selectSingleNode("km_final").text)
lnKmInitial = VAL(loNode.selectSingleNode("km_initial").text)
lcObs = NVL(loNode.selectSingleNode("observatii").text, "")
* Generam JSON cu prestatii din operatiile comenzii
lcPrestatii = THIS.GetPrestatiiFromXMLNode(loNode.selectNodes("operatii/operatie"))
* Trimitem prezentarea
IF !THIS.SendPrezentare(lcDataPrest, lcNrInm, lcVin, ;
lnKmFinal, lnKmInitial, lcObs, ;
"", lcPrestatii, lcNrComanda)
* Continuam cu urmatoarea comanda chiar daca una esueaza
* dar am logat deja eroarea in SendPrezentare
LOOP
ENDIF
ENDFOR
llSuccess = .T.
CATCH TO loEx
THIS.ErrorMsg = "Eroare procesare XML: " + loEx.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
* Generare JSON prestatii din noduri XML
FUNCTION GetPrestatiiFromXMLNode
LPARAMETERS loOperatiiNodes
LOCAL lcPrestatiiJson, lcCodRar
LOCAL loNode AS MSXML2.IXMLDOMNode
TEXT TO lcPrestatiiJson NOSHOW
[
ENDTEXT
lnCount = 0
FOR EACH loNode IN loOperatiiNodes
lcCodOperatie = loNode.selectSingleNode("cod_operatie").text
lcCodRar = THIS.GetCodRarPentruOperatie(lcCodOperatie)
IF !EMPTY(lcCodRar)
lcPrestatiiJson = lcPrestatiiJson + ;
IIF(lnCount > 0, ",", "") + ;
'{"codPrestatie":"' + lcCodRar + '","idPrezentare":null}'
lnCount = lnCount + 1
ENDIF
ENDFOR
lcPrestatiiJson = lcPrestatiiJson + "]"
RETURN lcPrestatiiJson
ENDFUNC
* Obtinere cod RAR pentru operatie service
FUNCTION GetCodRarPentruOperatie
LPARAMETERS tcCodOperatie
LOCAL lcCodRar
IF !USED("mapare_prestatii")
USE mapare_prestatii IN 0
ENDIF
SELECT mapare_prestatii
LOCATE FOR cod_op = tcCodOperatie
IF FOUND() AND auto_send
lcCodRar = cod_rar
ELSE
lcCodRar = ""
ENDIF
RETURN lcCodRar
ENDFUNC
* Functie pentru citirea credentialelor din settings.xml
FUNCTION ReadSettings
PARAMETERS tlTestMode
LOCAL loXML AS MSXML2.DOMDocument.6.0
LOCAL lcSettingsPath, lcEnvironment, loCredentials
LOCAL lcEmail, lcPassword, llSuccess
llSuccess = .F.
TRY
* Cream obiectul XML
loXML = CREATEOBJECT("MSXML2.DOMDocument.6.0")
loXML.async = .F.
* Determinam calea catre settings.xml
lcSettingsPath = ADDBS(JUSTPATH(SYS(16,0))) + "settings.xml"
* Verificam daca exista fisierul
IF !FILE(lcSettingsPath)
THIS.ErrorMsg = "Fisierul settings.xml nu exista in: " + lcSettingsPath
llSuccess = .F.
RETURN llSuccess
ENDIF
* Incarcam XML-ul
IF !loXML.load(lcSettingsPath)
THIS.ErrorMsg = "Eroare incarcare settings.xml: " + loXML.parseError.reason
llSuccess = .F.
RETURN llSuccess
ENDIF
* Determinam mediul (test/productie)
lcEnvironment = IIF(tlTestMode, "test", "production")
* Selectam credentialele pentru mediul dorit
loCredentials = loXML.selectSingleNode("/settings/" + lcEnvironment + "/credentials")
IF !ISNULL(loCredentials)
lcEmail = loCredentials.selectSingleNode("email").text
lcPassword = loCredentials.selectSingleNode("password").text
* Setam credentialele
THIS.lcEmail = lcEmail
THIS.lcPassword = lcPassword
llSuccess = .T.
ELSE
THIS.ErrorMsg = "Nu s-au gasit credentiale pentru mediul: " + lcEnvironment
llSuccess = .F.
ENDIF
CATCH TO loEx
THIS.ErrorMsg = "Eroare citire setari: " + loEx.Message
llSuccess = .F.
ENDTRY
RETURN llSuccess
ENDFUNC
ENDDEFINE