Files
gomag-vending/vfp/sync-comenzi-web.prg
Marius Mutu 5d43509987 Update VFP integration with improved error handling and settings management
- Add output/ directory to .gitignore to exclude generated JSON files
- Fix ApplicationSetup.prg parameter handling with LPARAMETERS and proper validation
- Update gomag-adapter.prg to use global settings object and clean old JSON files
- Enhance sync-comenzi-web.prg with Oracle integration improvements
- Add Visual FoxPro project files (roawebcomenzi.PJT/.pjx)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 17:01:00 +03:00

579 lines
19 KiB
Plaintext

*-- sync-comenzi-web.prg - Orchestrator pentru sincronizarea comenzilor web cu Oracle ROA
*-- Autor: Claude AI
*-- Data: 10 septembrie 2025
*-- Dependency: gomag-vending.prg trebuie rulat mai intai pentru generarea JSON-urilor
SET SAFETY OFF
SET CENTURY ON
SET DATE DMY
SET EXACT ON
SET ANSI ON
SET DELETED ON
*-- Variabile globale
PRIVATE gcAppPath, gcLogFile, gnStartTime, gnOrdersProcessed, gnOrdersSuccess, gnOrdersErrors
PRIVATE goConnectie, goSettings, goAppSetup
LOCAL lcJsonPattern, laJsonFiles[1], lnJsonFiles, lnIndex, lcJsonFile
LOCAL loJsonData, lcJsonContent, lnOrderCount, lnOrderIndex
LOCAL loOrder, lcResult, llProcessSuccess, lcPath
goConnectie = NULL
*-- Initializare
gcAppPath = ADDBS(JUSTPATH(SYS(16,0)))
SET DEFAULT TO (m.gcAppPath)
lcPath = gcAppPath + 'nfjson;'
SET PATH TO &lcPath ADDITIVE
SET PROCEDURE TO utils.prg ADDITIVE
SET PROCEDURE TO ApplicationSetup.prg ADDITIVE
SET PROCEDURE TO nfjsonread.prg ADDITIVE
SET PROCEDURE TO nfjsoncreate.prg ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
*-- Statistici
gnStartTime = SECONDS()
gnOrdersProcessed = 0
gnOrdersSuccess = 0
gnOrdersErrors = 0
*-- Initializare logging
gcLogFile = InitLog("sync_comenzi")
LogMessage("=== SYNC COMENZI WEB > ORACLE ROA ===", "INFO", gcLogFile)
*-- Creare si initializare clasa setup aplicatie
goAppSetup = CREATEOBJECT("ApplicationSetup", gcAppPath)
*-- Setup complet cu validare si afisare configuratie
IF !goAppSetup.Initialize()
LogMessage("EROARE: Setup-ul aplicatiei a esuat sau necesita configurare!", "ERROR", gcLogFile)
RETURN .F.
ENDIF
*-- Obtinere setari din clasa
goSettings = goAppSetup.GetSettings()
*-- Verificare directoare necesare
IF !DIRECTORY(gcAppPath + "output")
LogMessage("EROARE: Directorul output/ nu exista! Ruleaza mai intai adapter-ul web", "ERROR", gcLogFile)
RETURN .F.
ENDIF
*-- Rulare automata adapter pentru obtinere comenzi (daca este configurat)
IF goSettings.AutoRunAdapter
LogMessage("Rulez adapter pentru obtinere comenzi: " + goSettings.AdapterProgram, "INFO", gcLogFile)
IF !ExecuteAdapter()
LogMessage("EROARE la rularea adapter-ului, continuez cu fisierele JSON existente", "WARN", gcLogFile)
ENDIF
ELSE
LogMessage("AutoRunAdapter este dezactivat, folosesc doar fisierele JSON existente", "INFO", gcLogFile)
ENDIF
SET STEP ON
*-- Gasire fisiere JSON comenzi din pattern configurat
lcJsonPattern = gcAppPath + "output\" + goSettings.JsonFilePattern
lnJsonFiles = ADIR(laJsonFiles, lcJsonPattern)
IF lnJsonFiles = 0
LogMessage("AVERTISMENT: Nu au fost gasite fisiere JSON cu comenzi web", "WARN", gcLogFile)
LogMessage("Ruleaza mai intai adapter-ul web cu GetOrders=1 in settings.ini", "INFO", gcLogFile)
RETURN .T.
ENDIF
LogMessage("Gasite " + TRANSFORM(lnJsonFiles) + " fisiere JSON cu comenzi web", "INFO", gcLogFile)
*-- Incercare conectare Oracle (folosind conexiunea existenta din sistem)
IF !ConnectToOracle()
LogMessage("EROARE: Nu s-a putut conecta la Oracle ROA", "ERROR", gcLogFile)
RETURN .F.
ENDIF
*-- Procesare fiecare fisier JSON gasit
FOR lnIndex = 1 TO lnJsonFiles
lcJsonFile = gcAppPath + "output\" + laJsonFiles[lnIndex, 1]
LogMessage("Procesez fisierul: " + laJsonFiles[lnIndex, 1], "INFO", gcLogFile)
*-- Citire si parsare JSON
TRY
lcJsonContent = FILETOSTR(lcJsonFile)
IF EMPTY(lcJsonContent)
LogMessage("AVERTISMENT: Fisier JSON gol - " + laJsonFiles[lnIndex, 1], "WARN", gcLogFile)
LOOP
ENDIF
*-- Parsare JSON array cu comenzi
loJsonData = nfJsonRead(lcJsonContent)
IF ISNULL(loJsonData)
LogMessage("EROARE: Nu s-a putut parsa JSON-ul din " + laJsonFiles[lnIndex, 1], "ERROR", gcLogFile)
LOOP
ENDIF
*-- Verificare daca este array
IF TYPE('loJsonData') != 'O'
LogMessage("EROARE: JSON-ul nu este un array valid - " + laJsonFiles[lnIndex, 1], "ERROR", gcLogFile)
LOOP
ENDIF
SET STEP ON
*-- Obtinere numar comenzi din array
lnOrderCount = 0
IF TYPE('loJsonData.array') = 'U'
lnOrderCount = ALEN(loJsonData.array)
ENDIF
LogMessage("Gasite " + TRANSFORM(lnOrderCount) + " comenzi in " + laJsonFiles[lnIndex, 1], "INFO", gcLogFile)
*-- Procesare fiecare comanda din JSON
FOR EACH loOrder IN loJsonData.array
IF TYPE('loOrder') = 'O'
gnOrdersProcessed = gnOrdersProcessed + 1
llProcessSuccess = ProcessWebOrder(loOrder)
IF llProcessSuccess
gnOrdersSuccess = gnOrdersSuccess + 1
ELSE
gnOrdersErrors = gnOrdersErrors + 1
ENDIF
ENDIF
ENDFOR
CATCH TO loError
LogMessage("EROARE la procesarea fisierului " + laJsonFiles[lnIndex, 1] + ": " + loError.Message, "ERROR", gcLogFile)
gnOrdersErrors = gnOrdersErrors + 1
ENDTRY
ENDFOR
*-- Inchidere conexiune Oracle
DisconnectFromOracle()
*-- Logging final cu statistici
LogMessage("=== PROCESARE COMPLETA ===", "INFO", gcLogFile)
LogMessage("Total comenzi procesate: " + TRANSFORM(gnOrdersProcessed), "INFO", gcLogFile)
LogMessage("Comenzi importate cu succes: " + TRANSFORM(gnOrdersSuccess), "INFO", gcLogFile)
LogMessage("Comenzi cu erori: " + TRANSFORM(gnOrdersErrors), "INFO", gcLogFile)
CloseLog(gnStartTime, 0, gnOrdersProcessed, gcLogFile)
RETURN .T.
*-- ===================================================================
*-- HELPER FUNCTIONS
*-- ===================================================================
*-- Functie pentru conectarea la Oracle folosind setarile din settings.ini
FUNCTION ConnectToOracle
LOCAL llSuccess, lcConnectionString, lnHandle
llSuccess = .F.
TRY
*-- Conectare Oracle folosind datele din settings.ini
lnHandle = SQLCONNECT(goSettings.OracleDSN, goSettings.OracleUser, goSettings.OraclePassword)
IF lnHandle > 0
goConnectie = lnHandle
llSuccess = .T.
LogMessage("Conectare Oracle reusita - Handle: " + TRANSFORM(lnHandle), "INFO", gcLogFile)
LogMessage("DSN: " + goSettings.OracleDSN + " | User: " + goSettings.OracleUser, "DEBUG", gcLogFile)
ELSE
LogMessage("EROARE: Conectare Oracle esuata - Handle: " + TRANSFORM(lnHandle), "ERROR", gcLogFile)
LogMessage("DSN: " + goSettings.OracleDSN + " | User: " + goSettings.OracleUser, "ERROR", gcLogFile)
ENDIF
CATCH TO loError
LogMessage("EROARE la conectarea Oracle: " + loError.Message, "ERROR", gcLogFile)
ENDTRY
RETURN llSuccess
ENDFUNC
*-- Functie pentru deconectarea de la Oracle
FUNCTION DisconnectFromOracle
IF TYPE('goConnectie') = 'N' AND goConnectie > 0
SQLDISCONNECT(goConnectie)
LogMessage("Deconectare Oracle reusita", "INFO", gcLogFile)
ENDIF
RETURN .T.
ENDFUNC
*-- Functie principala de procesare comanda web
FUNCTION ProcessWebOrder
PARAMETERS loOrder
LOCAL llSuccess, lcOrderNumber, lcOrderDate, lnPartnerID, lcArticlesJSON
LOCAL lcObservatii, lcSQL, lnResult, lcErrorDetails
llSuccess = .F.
TRY
*-- Validare comanda
IF !ValidateWebOrder(loOrder)
LogMessage("EROARE: Comanda web invalida - lipsesc date obligatorii", "ERROR", gcLogFile)
RETURN .F.
ENDIF
*-- Extragere date comanda
lcOrderNumber = CleanWebText(TRANSFORM(loOrder.number))
lcOrderDate = ConvertWebDate(loOrder.date)
LogMessage("Procesez comanda: " + lcOrderNumber + " din " + lcOrderDate, "INFO", gcLogFile)
*-- Procesare partener (billing address)
lnPartnerID = ProcessPartnerFromBilling(loOrder.billing)
IF lnPartnerID <= 0
LogMessage("EROARE: Nu s-a putut procesa partenerul pentru comanda " + lcOrderNumber, "ERROR", gcLogFile)
RETURN .F.
ENDIF
LogMessage("Partener identificat/creat: ID=" + TRANSFORM(lnPartnerID), "INFO", gcLogFile)
*-- Construire JSON articole
lcArticlesJSON = BuildArticlesJSON(loOrder.items)
IF EMPTY(lcArticlesJSON)
LogMessage("EROARE: Nu s-au gasit articole valide in comanda " + lcOrderNumber, "ERROR", gcLogFile)
RETURN .F.
ENDIF
*-- Construire observatii cu detalii suplimentare
lcObservatii = BuildOrderObservations(loOrder)
*-- Apel package Oracle pentru import comanda
lcSQL = "SELECT PACK_IMPORT_COMENZI.importa_comanda_web(?, TO_DATE(?, 'YYYY-MM-DD'), ?, ?, NULL, ?) AS ID_COMANDA FROM dual"
lnResult = SQLEXEC(goConnectie, lcSQL, ;
lcOrderNumber, ; && p_nr_comanda_ext
lcOrderDate, ; && p_data_comanda
lnPartnerID, ; && p_id_partener
lcArticlesJSON, ; && p_json_articole
lcObservatii, ; && p_observatii
"cursor_comanda")
IF lnResult > 0 AND RECCOUNT("cursor_comanda") > 0 AND cursor_comanda.ID_COMANDA > 0
LogMessage("SUCCES: Comanda importata - ID Oracle: " + TRANSFORM(cursor_comanda.ID_COMANDA), "INFO", gcLogFile)
USE IN cursor_comanda
llSuccess = .T.
ELSE
*-- Obtinere detalii eroare Oracle
lcErrorDetails = GetOracleErrorDetails()
LogMessage("EROARE: Import comanda esuat pentru " + lcOrderNumber + " - " + lcErrorDetails, "ERROR", gcLogFile)
IF USED("cursor_comanda")
USE IN cursor_comanda
ENDIF
ENDIF
CATCH TO loError
LogMessage("EXCEPTIE la procesarea comenzii " + lcOrderNumber + ": " + loError.Message, "ERROR", gcLogFile)
ENDTRY
RETURN llSuccess
ENDFUNC
*-- Functie pentru validarea comenzii web
FUNCTION ValidateWebOrder
PARAMETERS loOrder
LOCAL llValid
llValid = .T.
*-- Verificari obligatorii
IF TYPE('loOrder.number') != 'C' OR EMPTY(loOrder.number)
llValid = .F.
ENDIF
IF TYPE('loOrder.date') != 'C' OR EMPTY(loOrder.date)
llValid = .F.
ENDIF
IF TYPE('loOrder.billing') != 'O'
llValid = .F.
ENDIF
IF TYPE('loOrder.items') != 'O'
llValid = .F.
ENDIF
RETURN llValid
ENDFUNC
*-- Functie pentru procesarea partenerului din billing GoMag
FUNCTION ProcessPartnerFromBilling
PARAMETERS loBilling
LOCAL lnPartnerID, lcDenumire, lcCodFiscal, lcAdresa, lcTelefon, lcEmail
LOCAL lcSQL, lnResult
lnPartnerID = 0
TRY
*-- Extragere date partener din datele billing
LOCAL lnIsPersoanaJuridica
IF TYPE('loBilling.company') = 'O' AND !EMPTY(loBilling.company.name)
*-- Companie - persoana juridica
lcDenumire = CleanWebText(loBilling.company.name)
lcCodFiscal = IIF(TYPE('loBilling.company.code') = 'C', loBilling.company.code, NULL)
lnIsPersoanaJuridica = 1 && Persoana juridica
ELSE
*-- Persoana fizica
lcDenumire = CleanWebText(ALLTRIM(loBilling.firstname) + " " + ALLTRIM(loBilling.lastname))
lcCodFiscal = NULL && Persoanele fizice nu au CUI in platformele web
lnIsPersoanaJuridica = 0 && Persoana fizica
ENDIF
*-- Formatare adresa pentru Oracle (format semicolon cu prefix JUD:)
lcAdresa = FormatAddressForOracle(loBilling)
*-- Date contact
lcTelefon = IIF(TYPE('loBilling.phone') = 'C', loBilling.phone, "")
lcEmail = IIF(TYPE('loBilling.email') = 'C', loBilling.email, "")
LogMessage("Partener: " + lcDenumire + " | CUI: " + IIF(ISNULL(lcCodFiscal), "NULL", lcCodFiscal) + " | Tip: " + IIF(lnIsPersoanaJuridica = 1, "JURIDICA", "FIZICA"), "DEBUG", gcLogFile)
*-- Apel package Oracle IMPORT_PARTENERI (PROCEDURA cu parametru OUT)
*-- Folosind sintaxa corecta pentru parametrii OUT in VFP
LOCAL lnPartnerResult
lnPartnerResult = 0
lcSQL = "BEGIN PACK_IMPORT_PARTENERI.cauta_sau_creeaza_partener(?lcCodFiscal, ?lcDenumire, ?lcAdresa, ?lcTelefon, ?lcEmail, ?lnIsPersoanaJuridica, ?@lnPartnerResult); END;"
lnResult = SQLEXEC(goConnectie, lcSQL)
IF lnResult > 0
lnPartnerID = lnPartnerResult
LogMessage("Partener procesat cu succes: ID=" + TRANSFORM(lnPartnerID), "DEBUG", gcLogFile)
ELSE
*-- Obtinere detalii eroare Oracle
lcErrorDetails = GetOracleErrorDetails()
LogMessage("EROARE la apelul procedurii PACK_IMPORT_PARTENERI pentru: " + lcDenumire + " - " + lcErrorDetails, "ERROR", gcLogFile)
lnPartnerID = 0
ENDIF
CATCH TO loError
LogMessage("EXCEPTIE la procesarea partenerului: " + loError.Message, "ERROR", gcLogFile)
ENDTRY
RETURN lnPartnerID
ENDFUNC
*-- Functie pentru construirea JSON-ului cu articole conform package Oracle
FUNCTION BuildArticlesJSON
PARAMETERS loItems
LOCAL lcJSON, lnItemCount, lnIndex, lcItemProp, loItem
LOCAL lcSku, lcQuantity, lcPrice
lcJSON = ""
TRY
IF TYPE('loItems') != 'O'
RETURN ""
ENDIF
lnItemCount = AMEMBERS(laItems, loItems, 0)
IF lnItemCount = 0
RETURN ""
ENDIF
lcJSON = "["
FOR lnIndex = 1 TO lnItemCount
lcItemProp = laItems[lnIndex]
loItem = EVALUATE('loItems.' + lcItemProp)
IF TYPE('loItem') = 'O'
*-- Extragere date articol
lcSku = IIF(TYPE('loItem.sku') = 'C', CleanWebText(loItem.sku), "")
lcQuantity = IIF(TYPE('loItem.quantity') = 'C' OR TYPE('loItem.quantity') = 'N', TRANSFORM(VAL(TRANSFORM(loItem.quantity))), "1")
lcPrice = IIF(TYPE('loItem.price') = 'C' OR TYPE('loItem.price') = 'N', TRANSFORM(VAL(TRANSFORM(loItem.price))), "0")
IF !EMPTY(lcSku)
*-- Adaugare virgula pentru elementele urmatoare
IF lnIndex > 1
lcJSON = lcJSON + ","
ENDIF
*-- Format JSON conform package Oracle: {"sku":"...", "cantitate":..., "pret":...}
lcJSON = lcJSON + '{"sku":"' + lcSku + '","cantitate":' + lcQuantity + ',"pret":' + lcPrice + '}'
ENDIF
ENDIF
ENDFOR
lcJSON = lcJSON + "]"
CATCH TO loError
LogMessage("EROARE la construirea JSON articole: " + loError.Message, "ERROR", gcLogFile)
lcJSON = ""
ENDTRY
RETURN lcJSON
ENDFUNC
*-- Functie pentru curatarea textului web (HTML entities → ASCII simplu)
FUNCTION CleanWebText
PARAMETERS tcText
LOCAL lcResult
IF EMPTY(tcText) OR TYPE('tcText') != 'C'
RETURN ""
ENDIF
lcResult = tcText
*-- Conversie HTML entities in caractere simple (fara diacritice)
lcResult = STRTRAN(lcResult, '&#259;', 'a') && ă → a
lcResult = STRTRAN(lcResult, '&#537;', 's') && ș → s
lcResult = STRTRAN(lcResult, '&#539;', 't') && ț → t
lcResult = STRTRAN(lcResult, '&#238;', 'i') && î → i
lcResult = STRTRAN(lcResult, '&#226;', 'a') && â → a
lcResult = STRTRAN(lcResult, '&amp;', '&')
lcResult = STRTRAN(lcResult, '&lt;', '<')
lcResult = STRTRAN(lcResult, '&gt;', '>')
lcResult = STRTRAN(lcResult, '&quot;', '"')
*-- Eliminare tag-uri HTML simple
lcResult = STRTRAN(lcResult, '<br>', ' ')
lcResult = STRTRAN(lcResult, '<br/>', ' ')
lcResult = STRTRAN(lcResult, '<br />', ' ')
RETURN ALLTRIM(lcResult)
ENDFUNC
*-- Functie pentru conversia datei web in format Oracle
FUNCTION ConvertWebDate
PARAMETERS tcWebDate
LOCAL lcResult
IF EMPTY(tcWebDate) OR TYPE('tcWebDate') != 'C'
RETURN DTOS(DATE())
ENDIF
*-- Web date format: "2025-08-27 16:32:43" → "2025-08-27"
lcResult = LEFT(tcWebDate, 10)
*-- Validare format YYYY-MM-DD
IF LEN(lcResult) = 10 AND SUBSTR(lcResult, 5, 1) = '-' AND SUBSTR(lcResult, 8, 1) = '-'
RETURN lcResult
ELSE
RETURN DTOS(DATE())
ENDIF
ENDFUNC
*-- Functie pentru formatarea adresei in format semicolon pentru Oracle
FUNCTION FormatAddressForOracle
PARAMETERS loBilling
LOCAL lcAdresa, lcJudet, lcOras, lcStrada
*-- Extragere componente adresa
lcJudet = IIF(TYPE('loBilling.region') = 'C', CleanWebText(loBilling.region), "Bucuresti")
lcOras = IIF(TYPE('loBilling.city') = 'C', CleanWebText(loBilling.city), "BUCURESTI")
lcStrada = IIF(TYPE('loBilling.address') = 'C', CleanWebText(loBilling.address), "Adresa necunoscuta")
*-- Format semicolon cu prefix JUD: conform specificatiilor Oracle
lcAdresa = "JUD:" + lcJudet + ";" + lcOras + ";" + lcStrada
RETURN lcAdresa
ENDFUNC
*-- Functie pentru construirea observatiilor comenzii
FUNCTION BuildOrderObservations
PARAMETERS loOrder
LOCAL lcObservatii
lcObservatii = ""
*-- Informatii plata si livrare
IF TYPE('loOrder.payment') = 'O' AND TYPE('loOrder.payment.name') = 'C'
lcObservatii = lcObservatii + "Payment: " + CleanWebText(loOrder.payment.name) + "; "
ENDIF
IF TYPE('loOrder.delivery') = 'O' AND TYPE('loOrder.delivery.name') = 'C'
lcObservatii = lcObservatii + "Delivery: " + CleanWebText(loOrder.delivery.name) + "; "
ENDIF
*-- Status si sursa
IF TYPE('loOrder.status') = 'C'
lcObservatii = lcObservatii + "Status: " + CleanWebText(loOrder.status) + "; "
ENDIF
IF TYPE('loOrder.source') = 'C'
lcObservatii = lcObservatii + "Source: " + CleanWebText(loOrder.source)
IF TYPE('loOrder.sales_channel') = 'C'
lcObservatii = lcObservatii + " " + CleanWebText(loOrder.sales_channel)
ENDIF
lcObservatii = lcObservatii + "; "
ENDIF
*-- Verificare adrese diferite shipping vs billing
IF TYPE('loOrder.shipping') = 'O' AND TYPE('loOrder.billing') = 'O'
IF TYPE('loOrder.shipping.address') = 'C' AND TYPE('loOrder.billing.address') = 'C'
IF !ALLTRIM(loOrder.shipping.address) == ALLTRIM(loOrder.billing.address)
lcObservatii = lcObservatii + "Shipping: " + CleanWebText(loOrder.shipping.address)
IF TYPE('loOrder.shipping.city') = 'C'
lcObservatii = lcObservatii + ", " + CleanWebText(loOrder.shipping.city)
ENDIF
lcObservatii = lcObservatii + "; "
ENDIF
ENDIF
ENDIF
*-- Limitare lungime observatii pentru Oracle
IF LEN(lcObservatii) > 500
lcObservatii = LEFT(lcObservatii, 497) + "..."
ENDIF
RETURN lcObservatii
ENDFUNC
*-- Functie pentru obtinerea detaliilor erorii Oracle
FUNCTION GetOracleErrorDetails
LOCAL lcError, laError[1], lnErrorLines, lnIndex
lcError = ""
*-- Obtinere eroare Oracle
lnErrorLines = AERROR(laError)
IF lnErrorLines > 0
FOR lnIndex = 1 TO lnErrorLines
IF lnIndex > 1
lcError = lcError + " | "
ENDIF
lcError = lcError + ALLTRIM(STR(laError[lnIndex, 1])) + ": " + laError[lnIndex, 2]
ENDFOR
ENDIF
IF EMPTY(lcError)
lcError = "Eroare Oracle nedefinita"
ENDIF
RETURN lcError
ENDFUNC
*-- Functie pentru executia adapter-ului configurat
FUNCTION ExecuteAdapter
LOCAL llSuccess, lcAdapterPath
llSuccess = .F.
TRY
lcAdapterPath = gcAppPath + goSettings.AdapterProgram
IF FILE(lcAdapterPath)
LogMessage("Executie adapter: " + lcAdapterPath, "INFO", gcLogFile)
DO (lcAdapterPath)
llSuccess = .T.
LogMessage("Adapter executat cu succes", "INFO", gcLogFile)
ELSE
LogMessage("EROARE: Adapter-ul nu a fost gasit la: " + lcAdapterPath, "ERROR", gcLogFile)
ENDIF
CATCH TO loError
LogMessage("EXCEPTIE la executia adapter-ului " + goSettings.AdapterProgram + ": " + loError.Message, "ERROR", gcLogFile)
ENDTRY
RETURN llSuccess
ENDFUNC
*-- Orchestrator complet pentru sincronizarea comenzilor web cu Oracle ROA
*-- Caracteristici:
*-- - Citeste JSON-urile generate de gomag-vending.prg
*-- - Proceseaza comenzile cu toate helper functions necesare
*-- - Integreaza cu package-urile Oracle validate in Phase 1
*-- - Logging complet cu statistici de procesare
*-- - Error handling pentru toate situatiile
*-- - Support pentru toate formatele GoMag (billing/shipping, companii/persoane fizice)