Files
gomag-vending/gomag-vending-test.prg
Marius Mutu 6f362f41e7 Backup: JSON optimization attempt with direct string merge
This version attempted to optimize JSON processing by:
- Direct string concatenation without deserialization
- MergeProductsJsonDirect and MergeOrdersJsonDirect functions
- Direct STRTOFILE instead of nfJsonCreate

Issues found:
- Only 100 products saved instead of 812 (merge failed)
- Invalid JSON syntax in orders: 'discounts':[,
- Pattern matching errors for GoMag API structure

Reverting to stable version 8324a26 next.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-27 17:22:05 +03:00

656 lines
24 KiB
Plaintext

*-- Script Visual FoxPro 9 pentru accesul la GoMag API cu paginare completa
*-- Autor: Claude AI
*-- Data: 26.08.2025
SET SAFETY OFF
SET EXACT ON
SET CENTURY ON
SET DELETED ON
SET DATE DMY
*-- Setari principale
LOCAL lcApiBaseUrl, lcApiUrl, lcApiKey, lcUserAgent, lcContentType
LOCAL loHttp, lcResponse, lcJsonResponse
LOCAL laHeaders[10], lnHeaderCount
Local lcApiShop, lcCsvFileName, lcErrorResponse, lcFileName, lcLogContent, lcLogFileName, lcPath
Local lcStatusText, lnStatusCode, loError
Local lnLimit, lnCurrentPage, llHasMorePages, loAllJsonData, lnTotalPages, lnTotalProducts
Local lcOrderApiUrl, loAllOrderData, lcOrderCsvFileName, lcOrderJsonFileName
Local ldStartDate, lcStartDateStr
Local lcIniFile, loSettings
LOCAL llGetProducts, llGetOrders
PRIVATE gcAppPath, loJsonData, gcLogFile, gnStartTime, gnProductsProcessed, gnOrdersProcessed
gcAppPath = ADDBS(JUSTPATH(SYS(16,0)))
SET DEFAULT TO (m.gcAppPath)
lcPath = gcAppPath + 'nfjson;'
SET PATH TO (m.lcPath) ADDITIVE
SET PROCEDURE TO utils.prg ADDITIVE
SET PROCEDURE TO nfjsonread.prg ADDITIVE
SET PROCEDURE TO nfjsoncreate.prg ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
*-- Initializare logging si statistici
gnStartTime = SECONDS()
gnProductsProcessed = 0
gnOrdersProcessed = 0
gcLogFile = InitLog("gomag_sync")
*-- Cream directorul output daca nu existe
LOCAL lcOutputDir
lcOutputDir = gcAppPath + "output"
IF !DIRECTORY(lcOutputDir)
MKDIR (lcOutputDir)
ENDIF
*-- Incarcarea setarilor din fisierul INI
lcIniFile = gcAppPath + "settings.ini"
*-- Verificare existenta fisier INI
IF !CheckIniFile(lcIniFile)
LogMessage("ATENTIE: Fisierul settings.ini nu a fost gasit!", "WARN", gcLogFile)
LogMessage("Cream un fisier settings.ini implicit...", "INFO", gcLogFile)
IF CreateDefaultIni(lcIniFile)
LogMessage("Fisier settings.ini creat cu succes.", "INFO", gcLogFile)
LogMessage("IMPORTANT: Modifica setarile din settings.ini (ApiKey, ApiShop) inainte de a rula scriptul din nou!", "INFO", gcLogFile)
RETURN .F.
ELSE
LogMessage("EROARE: Nu s-a putut crea fisierul settings.ini!", "ERROR", gcLogFile)
RETURN .F.
ENDIF
ENDIF
*-- Incarcarea setarilor
loSettings = LoadSettings(lcIniFile)
*-- Verificare setari obligatorii
IF EMPTY(loSettings.ApiKey) OR loSettings.ApiKey = "YOUR_API_KEY_HERE"
LogMessage("EROARE: ApiKey nu este setat in settings.ini!", "ERROR", gcLogFile)
RETURN .F.
ENDIF
IF EMPTY(loSettings.ApiShop) OR "yourstore.gomag.ro" $ loSettings.ApiShop
LogMessage("EROARE: ApiShop nu este setat corect in settings.ini!", "ERROR", gcLogFile)
RETURN .F.
ENDIF
*-- Configurare API din settings.ini
lcApiBaseUrl = loSettings.ApiBaseUrl
lcOrderApiUrl = loSettings.OrderApiUrl
lcApiKey = loSettings.ApiKey
lcApiShop = loSettings.ApiShop
lcUserAgent = loSettings.UserAgent
lcContentType = loSettings.ContentType
lnLimit = loSettings.Limit
llGetProducts = loSettings.GetProducts
llGetOrders = loSettings.GetOrders
lnCurrentPage = 1 && Pagina de start
llHasMorePages = .T. && Flag pentru paginare
loAllJsonData = NULL && Obiect pentru toate datele
*-- Calculare data pentru ultimele X zile (din settings.ini)
ldStartDate = DATE() - loSettings.OrderDaysBack
lcStartDateStr = TRANSFORM(YEAR(ldStartDate)) + "-" + ;
RIGHT("0" + TRANSFORM(MONTH(ldStartDate)), 2) + "-" + ;
RIGHT("0" + TRANSFORM(DAY(ldStartDate)), 2)
*-- Verificare daca avem WinHttp disponibil
TRY
loHttp = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
CATCH TO loError
LogMessage("Eroare la crearea obiectului WinHttp: " + loError.Message, "ERROR", gcLogFile)
RETURN .F.
ENDTRY
*-- Removed SET STEP ON for silent operation
*-- SECTIUNEA PRODUSE - se executa doar daca llGetProducts = .T.
IF llGetProducts
LogMessage("[PRODUCTS] Starting product retrieval", "INFO", gcLogFile)
*-- Bucla pentru preluarea tuturor produselor (paginare) - optimizare JSON direct
LOCAL lcAllProductsJson
lcAllProductsJson = ""
lnTotalProducts = 0
DO WHILE llHasMorePages
*-- Construire URL cu paginare
lcApiUrl = lcApiBaseUrl + "&page=" + TRANSFORM(lnCurrentPage) + "&limit=" + TRANSFORM(lnLimit)
LogMessage("[PRODUCTS] Page " + TRANSFORM(lnCurrentPage) + " fetching...", "INFO", gcLogFile)
*-- Configurare request
TRY
*-- Initializare request GET
loHttp.Open("GET", lcApiUrl, .F.)
*-- Setare headers conform documentatiei GoMag
loHttp.SetRequestHeader("User-Agent", lcUserAgent)
loHttp.SetRequestHeader("Content-Type", lcContentType)
loHttp.SetRequestHeader("Accept", "application/json")
loHttp.SetRequestHeader("Apikey", lcApiKey) && Header pentru API Key
loHttp.SetRequestHeader("ApiShop", lcApiShop) && Header pentru shop URL
*-- Setari timeout
loHttp.SetTimeouts(30000, 30000, 30000, 30000) && 30 secunde pentru fiecare
*-- Trimitere request
loHttp.Send()
*-- Verificare status code
lnStatusCode = loHttp.Status
lcStatusText = loHttp.StatusText
IF lnStatusCode = 200
*-- Success - preluare raspuns
lcResponse = loHttp.ResponseText
*-- Optimizare: folosim JSON direct fara parsare completa
IF lnCurrentPage = 1
*-- Prima pagina - parsam doar pentru metadata
SET PATH TO nfjson ADDITIVE
loJsonData = nfJsonRead(lcResponse)
IF !ISNULL(loJsonData)
IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N'
lnTotalProducts = VAL(TRANSFORM(loJsonData.total))
ENDIF
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
lnTotalPages = VAL(TRANSFORM(loJsonData.pages))
ENDIF
LogMessage("[PRODUCTS] Total items: " + TRANSFORM(lnTotalProducts) + " | Pages: " + TRANSFORM(lnTotalPages), "INFO", gcLogFile)
ENDIF
*-- Salvam JSON-ul complet pentru prima pagina
lcAllProductsJson = lcResponse
ELSE
*-- Paginile urmatoare - merge direct JSON
lcAllProductsJson = MergeProductsJsonDirect(lcAllProductsJson, lcResponse)
ENDIF
*-- Verificare daca mai sunt pagini
IF lnCurrentPage = 1 AND !ISNULL(loJsonData)
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
lnTotalPages = VAL(TRANSFORM(loJsonData.pages))
IF lnCurrentPage >= lnTotalPages
llHasMorePages = .F.
ENDIF
ELSE
*-- Daca nu avem info despre pagini, verificam daca sunt produse
IF TYPE('loJsonData.products') != 'O'
llHasMorePages = .F.
ENDIF
ENDIF
ELSE
*-- Pentru paginile urmatoare, verificam daca am ajuns la limita
IF lnTotalPages > 0 AND lnCurrentPage >= lnTotalPages
llHasMorePages = .F.
ENDIF
ENDIF
lnCurrentPage = lnCurrentPage + 1
ELSE
*-- Eroare HTTP
LogMessage("[PRODUCTS] HTTP Error " + TRANSFORM(lnStatusCode) + ": " + lcStatusText + " on page " + TRANSFORM(lnCurrentPage), "ERROR", gcLogFile)
*-- Detalii despre eroare daca sunt disponibile
TRY
lcErrorResponse = loHttp.ResponseText
IF !EMPTY(lcErrorResponse)
LogMessage("[PRODUCTS] Error details: " + LEFT(lcErrorResponse, 200), "ERROR", gcLogFile)
ENDIF
CATCH
LogMessage("[PRODUCTS] Could not read error details", "WARN", gcLogFile)
ENDTRY
llHasMorePages = .F.
ENDIF
CATCH TO loError
*-- Script error in products section
LogMessage("[PRODUCTS] Script Error #" + TRANSFORM(loError.ErrorNo) + ": " + loError.Message + " (Line: " + TRANSFORM(loError.LineNo) + ")", "ERROR", gcLogFile)
llHasMorePages = .F.
ENDTRY
*-- Pauza scurta intre cereri pentru a evita rate limiting
IF llHasMorePages
INKEY(1) && Pauza de 1 secunda
ENDIF
ENDDO
*-- Salvare JSON direct (optimizat)
IF !EMPTY(lcAllProductsJson)
lcJsonFileName = lcOutputDir + "\gomag_all_products_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json"
STRTOFILE(lcAllProductsJson, lcJsonFileName)
LogMessage("[PRODUCTS] JSON saved: " + lcJsonFileName, "INFO", gcLogFile)
gnProductsProcessed = lnTotalProducts
ENDIF
ELSE
LogMessage("[PRODUCTS] Skipped (disabled in settings)", "INFO", gcLogFile)
ENDIF
*-- SECTIUNEA COMENZI - se executa doar daca llGetOrders = .T.
IF llGetOrders
LogMessage("[ORDERS] Starting orders retrieval (last " + TRANSFORM(loSettings.OrderDaysBack) + " days from " + lcStartDateStr + ")", "INFO", gcLogFile)
*-- Reinitializare pentru comenzi - optimizare JSON direct
lnCurrentPage = 1
llHasMorePages = .T.
LOCAL lcAllOrdersJson
lcAllOrdersJson = ""
*-- Bucla pentru preluarea comenzilor
DO WHILE llHasMorePages
*-- Construire URL cu paginare si filtrare pe data (folosind startDate conform documentatiei GoMag)
lcApiUrl = lcOrderApiUrl + "?startDate=" + lcStartDateStr + "&page=" + TRANSFORM(lnCurrentPage) + "&limit=" + TRANSFORM(lnLimit)
LogMessage("[ORDERS] Page " + TRANSFORM(lnCurrentPage) + " fetching...", "INFO", gcLogFile)
*-- Configurare request
TRY
*-- Initializare request GET
loHttp.Open("GET", lcApiUrl, .F.)
*-- Setare headers conform documentatiei GoMag
loHttp.SetRequestHeader("User-Agent", lcUserAgent)
loHttp.SetRequestHeader("Content-Type", lcContentType)
loHttp.SetRequestHeader("Accept", "application/json")
loHttp.SetRequestHeader("Apikey", lcApiKey) && Header pentru API Key
loHttp.SetRequestHeader("ApiShop", lcApiShop) && Header pentru shop URL
*-- Setari timeout
loHttp.SetTimeouts(30000, 30000, 30000, 30000) && 30 secunde pentru fiecare
*-- Trimitere request
loHttp.Send()
*-- Verificare status code
lnStatusCode = loHttp.Status
lcStatusText = loHttp.StatusText
IF lnStatusCode = 200
*-- Success - preluare raspuns
lcResponse = loHttp.ResponseText
*-- Optimizare: folosim JSON direct pentru comenzi
IF lnCurrentPage = 1
*-- Prima pagina - parsam doar pentru metadata si salvam JSON-ul complet
loJsonData = nfJsonRead(lcResponse)
IF !ISNULL(loJsonData)
LogMessage("[ORDERS] DEBUG: Analyzing JSON structure...", "DEBUG", gcLogFile)
lnPropCount = AMEMBERS(laJsonProps, loJsonData, 0)
FOR lnDebugIndex = 1 TO MIN(lnPropCount, 10)
lcPropName = laJsonProps(lnDebugIndex)
lcPropType = TYPE('loJsonData.' + lcPropName)
LogMessage("[ORDERS] Property: " + lcPropName + " (Type: " + lcPropType + ")", "DEBUG", gcLogFile)
ENDFOR
LOCAL lnTotalOrders
IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N'
lnTotalOrders = VAL(TRANSFORM(loJsonData.total))
ENDIF
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
lnTotalPages = VAL(TRANSFORM(loJsonData.pages))
ENDIF
LogMessage("[ORDERS] Total items: " + TRANSFORM(lnTotalOrders) + " | Pages: " + TRANSFORM(lnTotalPages), "INFO", gcLogFile)
*-- Calculam comenzile din prima pagina
LOCAL lnFirstPageOrders
lnFirstPageOrders = 0
IF TYPE('loJsonData.orders') = 'O'
lnFirstPageOrders = AMEMBERS(laTemp, loJsonData.orders, 0)
ENDIF
gnOrdersProcessed = gnOrdersProcessed + lnFirstPageOrders
ENDIF
*-- Salvam JSON-ul complet pentru prima pagina
lcAllOrdersJson = lcResponse
ELSE
*-- Paginile urmatoare - merge direct JSON
lcAllOrdersJson = MergeOrdersJsonDirect(lcAllOrdersJson, lcResponse)
*-- Estimare comenzi procesate din dimensiunea JSON-ului
gnOrdersProcessed = gnOrdersProcessed + INT(LEN(lcResponse) / 500)
ENDIF
*-- Verificare daca mai sunt pagini
IF lnCurrentPage = 1 AND !ISNULL(loJsonData)
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
lnTotalPages = VAL(TRANSFORM(loJsonData.pages))
IF lnCurrentPage >= lnTotalPages
llHasMorePages = .F.
ENDIF
ENDIF
ELSE
*-- Pentru paginile urmatoare, verificam daca am ajuns la limita
IF lnTotalPages > 0 AND lnCurrentPage >= lnTotalPages
llHasMorePages = .F.
ENDIF
ENDIF
lnCurrentPage = lnCurrentPage + 1
ELSE
*-- Eroare HTTP pentru comenzi
LogMessage("[ORDERS] HTTP Error " + TRANSFORM(lnStatusCode) + ": " + lcStatusText + " on page " + TRANSFORM(lnCurrentPage), "ERROR", gcLogFile)
*-- Detalii despre eroare daca sunt disponibile
TRY
lcErrorResponse = loHttp.ResponseText
IF !EMPTY(lcErrorResponse)
LogMessage("[ORDERS] Error details: " + LEFT(lcErrorResponse, 200), "ERROR", gcLogFile)
ENDIF
CATCH
LogMessage("[ORDERS] Could not read error details", "WARN", gcLogFile)
ENDTRY
llHasMorePages = .F.
ENDIF
CATCH TO loError
*-- Script error in orders section
LogMessage("[ORDERS] Script Error #" + TRANSFORM(loError.ErrorNo) + ": " + loError.Message + " (Line: " + TRANSFORM(loError.LineNo) + ")", "ERROR", gcLogFile)
llHasMorePages = .F.
ENDTRY
*-- Pauza scurta intre cereri pentru a evita rate limiting
IF llHasMorePages
INKEY(1) && Pauza de 1 secunda
ENDIF
ENDDO
*-- Salvare JSON direct (optimizat)
IF !EMPTY(lcAllOrdersJson)
lcOrderJsonFileName = lcOutputDir + "\gomag_orders_last7days_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json"
STRTOFILE(lcAllOrdersJson, lcOrderJsonFileName)
LogMessage("[ORDERS] JSON saved: " + lcOrderJsonFileName, "INFO", gcLogFile)
ENDIF
ELSE
LogMessage("[ORDERS] Skipped (disabled in settings)", "INFO", gcLogFile)
ENDIF
*-- Curatare
loHttp = NULL
*-- Inchidere logging cu statistici finale
CloseLog(gnStartTime, gnProductsProcessed, gnOrdersProcessed, gcLogFile)
*-- Functie pentru salvarea array-ului de produse in format JSON
PROCEDURE SaveProductsArray
PARAMETERS tloAllData, tcFileName
LOCAL lcJsonContent, lnPropCount, lnIndex, lcPropName, loProduct
*-- Incepe array-ul JSON
lcJsonContent = "[" + CHR(13) + CHR(10)
*-- Verifica daca avem produse
IF TYPE('tloAllData.products') = 'O'
lnPropCount = AMEMBERS(laProducts, tloAllData.products, 0)
FOR lnIndex = 1 TO lnPropCount
lcPropName = laProducts(lnIndex)
loProduct = EVALUATE('tloAllData.products.' + lcPropName)
IF TYPE('loProduct') = 'O'
*-- Adauga virgula pentru elementele anterioare
IF lnIndex > 1
lcJsonContent = lcJsonContent + "," + CHR(13) + CHR(10)
ENDIF
*-- Serializeaza produsul cu nfjsoncreate
lcProductJson = nfJsonCreate(loProduct, .F.)
lcJsonContent = lcJsonContent + " " + lcProductJson
ENDIF
ENDFOR
ENDIF
*-- Inchide array-ul JSON
lcJsonContent = lcJsonContent + CHR(13) + CHR(10) + "]"
*-- Salveaza fisierul
STRTOFILE(lcJsonContent, tcFileName)
ENDPROC
*-- Functie pentru salvarea array-ului de comenzi in format JSON
PROCEDURE SaveOrdersArray
PARAMETERS tloAllData, tcFileName
LOCAL lcJsonContent, lnPropCount, lnIndex, lcPropName, loOrder
*-- Incepe array-ul JSON
lcJsonContent = "[" + CHR(13) + CHR(10)
*-- Verifica daca avem comenzi
IF TYPE('tloAllData.orders') = 'O'
lnPropCount = AMEMBERS(laOrders, tloAllData.orders, 0)
FOR lnIndex = 1 TO lnPropCount
lcPropName = laOrders(lnIndex)
loOrder = EVALUATE('tloAllData.orders.' + lcPropName)
IF TYPE('loOrder') = 'O'
*-- Adauga virgula pentru elementele anterioare
IF lnIndex > 1
lcJsonContent = lcJsonContent + "," + CHR(13) + CHR(10)
ENDIF
*-- Serializeaza comanda cu nfjsoncreate
lcOrderJson = nfJsonCreate(loOrder, .F.)
lcJsonContent = lcJsonContent + " " + lcOrderJson
ENDIF
ENDFOR
ENDIF
*-- Inchide array-ul JSON
lcJsonContent = lcJsonContent + CHR(13) + CHR(10) + "]"
*-- Salveaza fisierul
STRTOFILE(lcJsonContent, tcFileName)
ENDPROC
*-- Functie pentru unirea produselor din toate paginile (versiune simpla)
PROCEDURE MergeProducts
PARAMETERS tloAllData, tloPageData
LOCAL lnPropCount, lnIndex, lcPropName, loProduct
*-- Verifica daca avem produse in pagina curenta
IF TYPE('tloPageData.products') = 'O'
*-- Itereaza prin toate produsele din pagina
lnPropCount = AMEMBERS(laPageProducts, tloPageData.products, 0)
FOR lnIndex = 1 TO lnPropCount
lcPropName = laPageProducts(lnIndex)
loProduct = EVALUATE('tloPageData.products.' + lcPropName)
IF TYPE('loProduct') = 'O'
*-- Adauga produsul la colectia principala
ADDPROPERTY(tloAllData.products, lcPropName, loProduct)
ENDIF
ENDFOR
ENDIF
ENDPROC
*-- Functie pentru unirea comenzilor din array direct (structura GoMag)
PROCEDURE MergeOrdersArray
PARAMETERS tloAllData, tloPageData
LOCAL lnPropCount, lnIndex, lcPropName, loOrder
*-- Verifica daca avem comenzi in pagina curenta
IF TYPE('tloPageData.orders') = 'O'
*-- Itereaza prin toate comenzile din pagina (array direct)
lnPropCount = AMEMBERS(laPageOrders, tloPageData.orders, 0)
FOR lnIndex = 1 TO lnPropCount
lcPropName = laPageOrders(lnIndex)
loOrder = EVALUATE('tloPageData.orders.' + lcPropName)
IF TYPE('loOrder') = 'O'
*-- Folosim ID-ul comenzii ca nume proprietate, sau un index secvential
LOCAL lcOrderId
lcOrderId = ""
IF TYPE('loOrder.id') = 'C'
lcOrderId = "order_" + loOrder.id
ELSE
lcOrderId = "order_" + TRANSFORM(lnIndex)
ENDIF
*-- Adauga comanda la colectia principala
ADDPROPERTY(tloAllData.orders, lcOrderId, loOrder)
ENDIF
ENDFOR
ENDIF
ENDPROC
*-- Functie optimizata pentru merge direct JSON produse (fara deserializare)
PROCEDURE MergeProductsJsonDirect
PARAMETERS tcFirstPageJson, tcNextPageJson
LOCAL lcEndPos, lcStart, lcEnd, lcNewProperties, lcResult
*-- Gaseste sfârșitul secțiunii products din prima pagina - cautam pozitia } inainte de "total"
lcEndPos = AT('},\"total\"', tcFirstPageJson)
IF lcEndPos = 0
*-- Fallback: gaseste ultimul } inainte de total
lcEndPos = AT('\"total\"', tcFirstPageJson)
IF lcEndPos > 0
lcEndPos = RAT('}', LEFT(tcFirstPageJson, lcEndPos - 1))
ENDIF
ENDIF
IF lcEndPos = 0
*-- Nu putem face merge, returnam prima pagina
RETURN tcFirstPageJson
ENDIF
*-- Debug logging pentru debugging
LogMessage("[PRODUCTS] DEBUG: Starting merge - Page 1 size: " + TRANSFORM(LEN(tcFirstPageJson)) + " | Next page size: " + TRANSFORM(LEN(tcNextPageJson)), "DEBUG", gcLogFile)
LogMessage("[PRODUCTS] DEBUG: Products end position found at: " + TRANSFORM(lcEndPos), "DEBUG", gcLogFile)
*-- Daca nu putem extrage cu regex, incercam metoda manuala
lcStart = AT('\"products\":{', tcNextPageJson)
IF lcStart > 0
lcStart = lcStart + 11 && dupa {"products":{
lcEnd = AT('},\"total\"', tcNextPageJson)
IF lcEnd = 0
lcEnd = AT('\"total\"', tcNextPageJson)
IF lcEnd > 0
lcEnd = RAT('}', LEFT(tcNextPageJson, lcEnd - 1))
ENDIF
ENDIF
IF lcEnd > lcStart
lcNewProperties = SUBSTR(tcNextPageJson, lcStart, lcEnd - lcStart)
LogMessage("[PRODUCTS] DEBUG: Extracted " + TRANSFORM(LEN(lcNewProperties)) + " chars from next page", "DEBUG", gcLogFile)
*-- Insereaza proprietatile cu virgula separator
lcResult = STUFF(tcFirstPageJson, lcEndPos, 0, ',' + lcNewProperties)
LogMessage("[PRODUCTS] DEBUG: Merge successful, result size: " + TRANSFORM(LEN(lcResult)), "DEBUG", gcLogFile)
RETURN lcResult
ELSE
LogMessage("[PRODUCTS] ERROR: Invalid extraction positions - Start: " + TRANSFORM(lcStart) + ", End: " + TRANSFORM(lcEnd), "ERROR", gcLogFile)
ENDIF
ENDIF
*-- Daca nu putem extrage, returnam prima pagina
RETURN tcFirstPageJson
ENDPROC
*-- Functie optimizata pentru merge direct JSON comenzi (fara deserializare)
PROCEDURE MergeOrdersJsonDirect
PARAMETERS tcFirstPageJson, tcNextPageJson
LOCAL lcEndPos, lcStart, lcEnd, lcNewOrders, lcResult
LOCAL lcTotalPos
*-- Debug logging pentru debugging
LogMessage("[ORDERS] DEBUG: Starting merge - Page 1 size: " + TRANSFORM(LEN(tcFirstPageJson)) + " | Next page size: " + TRANSFORM(LEN(tcNextPageJson)), "DEBUG", gcLogFile)
*-- Cautam pozitia pentru inserare inainte de "total", "page" sau "pages"
lcEndPos = AT('},\"total\"', tcFirstPageJson)
IF lcEndPos = 0
lcEndPos = AT('},\"page\"', tcFirstPageJson)
ENDIF
IF lcEndPos = 0
lcEndPos = AT('},\"pages\"', tcFirstPageJson)
ENDIF
IF lcEndPos = 0
LogMessage("[ORDERS] ERROR: Cannot find orders end position in first page", "ERROR", gcLogFile)
RETURN tcFirstPageJson
ENDIF
LogMessage("[ORDERS] DEBUG: Orders end position found at: " + TRANSFORM(lcEndPos), "DEBUG", gcLogFile)
*-- Extrage doar continutul din "orders":{...} din pagina urmatoare
lcStart = AT('\"orders\":{', tcNextPageJson)
IF lcStart > 0
lcStart = lcStart + 10 && dupa {"orders":{
*-- Gaseste sfarsitul obiectului orders din pagina urmatoare
lcEnd = AT('},\"total\"', tcNextPageJson)
IF lcEnd = 0
lcEnd = AT('},\"page\"', tcNextPageJson)
ENDIF
IF lcEnd = 0
lcEnd = AT('},\"pages\"', tcNextPageJson)
ENDIF
IF lcEnd > lcStart
lcNewOrders = SUBSTR(tcNextPageJson, lcStart, lcEnd - lcStart)
LogMessage("[ORDERS] DEBUG: Extracted " + TRANSFORM(LEN(lcNewOrders)) + " chars from next page", "DEBUG", gcLogFile)
*-- Curatam orice } de la final daca exista
lcNewOrders = RTRIM(lcNewOrders, ' }')
*-- Insereaza noile comenzi cu virgula
lcResult = STUFF(tcFirstPageJson, lcEndPos, 0, ',' + lcNewOrders)
LogMessage("[ORDERS] DEBUG: Merge successful, result size: " + TRANSFORM(LEN(lcResult)), "DEBUG", gcLogFile)
RETURN lcResult
ELSE
LogMessage("[ORDERS] ERROR: Invalid extraction positions - Start: " + TRANSFORM(lcStart) + ", End: " + TRANSFORM(lcEnd), "ERROR", gcLogFile)
ENDIF
ENDIF
*-- Daca nu putem extrage, returnam prima pagina
RETURN tcFirstPageJson
ENDPROC
*-- Functiile utilitare au fost mutate in utils.prg
*-- Scriptul cu paginare completa pentru preluarea tuturor produselor si comenzilor
*-- Caracteristici principale:
*-- - Paginare automata pentru toate produsele si comenzile
*-- - Pauze intre cereri pentru respectarea rate limiting
*-- - Salvare JSON array-uri pure (fara metadata de paginare)
*-- - Utilizare nfjsoncreate pentru generare JSON corecta
*-- - Logging separat pentru fiecare pagina in caz de eroare
*-- - Afisare progres in timpul executiei
*-- INSTRUCTIUNI DE UTILIZARE:
*-- 1. Modifica settings.ini cu setarile tale:
*-- - ApiKey: cheia ta API de la GoMag
*-- - ApiShop: URL-ul magazinului tau
*-- - GetProducts: 1 pentru a prelua produse, 0 pentru a sari peste
*-- - GetOrders: 1 pentru a prelua comenzi, 0 pentru a sari peste
*-- - OrderDaysBack: numarul de zile pentru preluarea comenzilor
*-- 2. Ruleaza scriptul - va prelua doar ce ai selectat
*-- 3. Verifica fisierele JSON generate cu array-uri pure
*-- Script optimizat cu salvare JSON array-uri - verificati fisierele generate