Major architectural changes: - Convert Oracle IMPORT_PARTENERI.cauta_sau_creeaza_partener from FUNCTION to PROCEDURE with OUT parameter for VFP compatibility - Add IS_PERSOANA_JURIDICA parameter to support individual vs company detection - Implement sync-comenzi-web.prg orchestrator for generic web order processing with 5-minute timer automation - Create ApplicationSetup class for proper object-oriented configuration management - Add comprehensive Oracle connection and sync settings via settings.ini configuration system - Implement generic web order processing functions (ProcessWebOrder, ValidateWebOrder, CleanWebText, ConvertWebDate) - Add proper VFP-Oracle integration with correct procedure call syntax using OUT parameters - Rename gomag-vending.prg to gomag-adapter.prg for clarity and platform-specific functionality - Move CheckIniFile function to utils.prg for better code organization - Add settings.ini.example template and update .gitignore to exclude actual settings files - Implement comprehensive logging system with rotation and error handling - Add connection validation and retry logic for robust Oracle integration Technical improvements: - Proper JSON processing integration with existing nfjson library - Comprehensive error handling with categorized logging (INFO, ERROR, WARN) - Timer-based automation with configurable intervals - Settings validation and default value creation - Generic function naming for multi-platform support - Class-based setup system replacing procedural approach 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
203 lines
4.7 KiB
Plaintext
203 lines
4.7 KiB
Plaintext
*-- utils.prg - Functii utilitare generale
|
|
*-- Contine doar functii utilitare reutilizabile (INI, HTTP, logging, encoding)
|
|
*-- Autor: Claude AI
|
|
*-- Data: 10 septembrie 2025
|
|
|
|
*-- Functie pentru citirea fisierelor INI private
|
|
*-- Returneaza valoarea din sectiunea si intrarea specificata sau blank daca nu e gasita
|
|
FUNCTION ReadPini
|
|
PARAMETERS cSection, cEntry, cINIFile
|
|
LOCAL cDefault, cRetVal, nRetLen
|
|
|
|
cDefault = ""
|
|
cRetVal = SPACE(255)
|
|
nRetLen = LEN(cRetVal)
|
|
|
|
DECLARE INTEGER GetPrivateProfileString IN WIN32API ;
|
|
STRING cSection, ;
|
|
STRING cEntry, ;
|
|
STRING cDefault, ;
|
|
STRING @cRetVal, ;
|
|
INTEGER nRetLen, ;
|
|
STRING cINIFile
|
|
|
|
nRetLen = GetPrivateProfileString(cSection, ;
|
|
cEntry, ;
|
|
cDefault, ;
|
|
@cRetVal, ;
|
|
nRetLen, ;
|
|
cINIFile)
|
|
|
|
RETURN LEFT(cRetVal, nRetLen)
|
|
ENDFUNC
|
|
|
|
*-- Functie pentru scrierea in fisierele INI private
|
|
*-- Returneaza .T. daca e successful, .F. daca nu
|
|
FUNCTION WritePini
|
|
PARAMETERS cSection, cEntry, cValue, cINIFile
|
|
LOCAL nRetVal
|
|
|
|
DECLARE INTEGER WritePrivateProfileString IN WIN32API ;
|
|
STRING cSection, ;
|
|
STRING cEntry, ;
|
|
STRING cValue, ;
|
|
STRING cINIFile
|
|
|
|
nRetVal = WritePrivateProfileString(cSection, ;
|
|
cEntry, ;
|
|
cValue, ;
|
|
cINIFile)
|
|
|
|
RETURN nRetVal = 1
|
|
ENDFUNC
|
|
|
|
|
|
*-- Test conectivitate internet
|
|
FUNCTION TestConnectivity
|
|
LOCAL loHttp, llResult
|
|
|
|
llResult = .T.
|
|
|
|
TRY
|
|
loHttp = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
|
|
loHttp.Open("GET", "https://www.google.com", .F.)
|
|
loHttp.SetTimeouts(5000, 5000, 5000, 5000)
|
|
loHttp.Send()
|
|
|
|
IF loHttp.Status != 200
|
|
llResult = .F.
|
|
ENDIF
|
|
|
|
CATCH
|
|
llResult = .F.
|
|
ENDTRY
|
|
|
|
loHttp = NULL
|
|
RETURN llResult
|
|
ENDFUNC
|
|
|
|
*-- Functie pentru codificare URL
|
|
FUNCTION UrlEncode
|
|
PARAMETERS tcString
|
|
|
|
LOCAL lcResult, lcChar, lnI
|
|
|
|
lcResult = ""
|
|
|
|
FOR lnI = 1 TO LEN(tcString)
|
|
lcChar = SUBSTR(tcString, lnI, 1)
|
|
|
|
DO CASE
|
|
CASE ISALPHA(lcChar) OR ISDIGIT(lcChar) OR INLIST(lcChar, "-", "_", ".", "~")
|
|
lcResult = lcResult + lcChar
|
|
OTHERWISE
|
|
lcResult = lcResult + "%" + RIGHT("0" + TRANSFORM(ASC(lcChar), "@0"), 2)
|
|
ENDCASE
|
|
ENDFOR
|
|
|
|
RETURN lcResult
|
|
ENDFUNC
|
|
|
|
*-- Functie pentru verificarea existentei fisierului INI
|
|
FUNCTION CheckIniFile
|
|
PARAMETERS cINIFile
|
|
LOCAL llExists
|
|
|
|
TRY
|
|
llExists = FILE(cINIFile)
|
|
CATCH
|
|
llExists = .F.
|
|
ENDTRY
|
|
|
|
RETURN llExists
|
|
ENDFUNC
|
|
|
|
*-- Functie pentru initializarea logging-ului
|
|
FUNCTION InitLog
|
|
PARAMETERS cBaseName
|
|
LOCAL lcLogFile, lcStartTime, lcLogHeader, lcLogDir
|
|
|
|
*-- Cream directorul log daca nu existe
|
|
lcLogDir = gcAppPath + "log"
|
|
IF !DIRECTORY(lcLogDir)
|
|
MKDIR (lcLogDir)
|
|
ENDIF
|
|
|
|
*-- Generam numele fisierului log cu timestamp in directorul log
|
|
lcStartTime = DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "")
|
|
lcLogFile = lcLogDir + "\" + cBaseName + "_" + lcStartTime + ".log"
|
|
|
|
*-- Header pentru log
|
|
lcLogHeader = "[" + TIME() + "] [START] === GoMag Sync Started ===" + CHR(13) + CHR(10)
|
|
lcLogHeader = lcLogHeader + "[" + TIME() + "] [INFO ] Date: " + DTOC(DATE()) + " | VFP: " + VERSION() + CHR(13) + CHR(10)
|
|
|
|
*-- Cream fisierul log
|
|
STRTOFILE(lcLogHeader, lcLogFile)
|
|
|
|
RETURN lcLogFile
|
|
ENDFUNC
|
|
|
|
*-- Functie pentru logging cu nivel si timestamp
|
|
FUNCTION LogMessage
|
|
PARAMETERS cMessage, cLevel, cLogFile
|
|
LOCAL lcTimeStamp, lcLogEntry, lcExistingContent
|
|
|
|
*-- Setam nivel implicit daca nu e specificat
|
|
IF EMPTY(cLevel)
|
|
cLevel = "INFO "
|
|
ELSE
|
|
*-- Formatam nivelul pentru a avea 5 caractere
|
|
cLevel = LEFT(cLevel + " ", 5)
|
|
ENDIF
|
|
|
|
*-- Cream timestamp-ul
|
|
lcTimeStamp = TIME()
|
|
|
|
*-- Formatam mesajul pentru log
|
|
lcLogEntry = "[" + lcTimeStamp + "] [" + cLevel + "] " + cMessage + CHR(13) + CHR(10)
|
|
|
|
*-- Adaugam la fisierul existent
|
|
lcExistingContent = ""
|
|
IF FILE(cLogFile)
|
|
lcExistingContent = FILETOSTR(cLogFile)
|
|
ENDIF
|
|
|
|
STRTOFILE(lcExistingContent + lcLogEntry, cLogFile)
|
|
|
|
RETURN .T.
|
|
ENDFUNC
|
|
|
|
*-- Functie pentru inchiderea logging-ului cu statistici
|
|
FUNCTION CloseLog
|
|
PARAMETERS nStartTime, nProductsCount, nOrdersCount, cLogFile
|
|
LOCAL lcEndTime, lcDuration, lcStatsEntry
|
|
|
|
lcEndTime = TIME()
|
|
*-- Calculam durata in secunde
|
|
nDuration = SECONDS() - nStartTime
|
|
|
|
*-- Formatam statisticile finale
|
|
lcStatsEntry = "[" + lcEndTime + "] [END ] === GoMag Sync Completed ===" + CHR(13) + CHR(10)
|
|
lcStatsEntry = lcStatsEntry + "[" + lcEndTime + "] [STATS] Duration: " + TRANSFORM(INT(nDuration)) + "s"
|
|
|
|
IF nProductsCount > 0
|
|
lcStatsEntry = lcStatsEntry + " | Products: " + TRANSFORM(nProductsCount)
|
|
ENDIF
|
|
|
|
IF nOrdersCount > 0
|
|
lcStatsEntry = lcStatsEntry + " | Orders: " + TRANSFORM(nOrdersCount)
|
|
ENDIF
|
|
|
|
lcStatsEntry = lcStatsEntry + CHR(13) + CHR(10)
|
|
|
|
*-- Adaugam la log
|
|
LOCAL lcExistingContent
|
|
lcExistingContent = ""
|
|
IF FILE(cLogFile)
|
|
lcExistingContent = FILETOSTR(cLogFile)
|
|
ENDIF
|
|
|
|
STRTOFILE(lcExistingContent + lcStatsEntry, cLogFile)
|
|
|
|
RETURN .T.
|
|
ENDFUNC |