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