Enhance logging system with detailed product tracking and console cleanup
- Added comprehensive product logging to match order detail level - Moved all debug console messages to proper log files - Added JSON structure analysis logging for both products and orders - Enhanced per-page progress tracking with counts and warnings - Unified logging format with [PRODUCTS] and [ORDERS] prefixes - Removed SET STEP ON debug statement - All debug information now properly logged instead of console output 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,7 +3,8 @@
|
|||||||
*.bak
|
*.bak
|
||||||
*.BAK
|
*.BAK
|
||||||
*.csv
|
*.csv
|
||||||
*.json
|
/log.*
|
||||||
|
/output/*.json
|
||||||
*.err
|
*.err
|
||||||
*.ERR
|
*.ERR
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
121
CLAUDE.md
121
CLAUDE.md
@@ -4,28 +4,40 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
This is a Visual FoxPro 9 project that interfaces with the GoMag e-commerce API. The main component is a script for retrieving product data from GoMag's REST API endpoints.
|
This is a Visual FoxPro 9 project that interfaces with the GoMag e-commerce API. The application retrieves both product and order data from GoMag's REST API endpoints with full pagination support and comprehensive error handling.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
- **Single File Application**: `gomag-vending.prg` - Main Visual FoxPro script
|
- **Main Application**: `gomag-vending.prg` - Primary Visual FoxPro script with pagination support
|
||||||
|
- **Utility Module**: `utils.prg` - INI file handling, logging, and helper functions
|
||||||
|
- **JSON Library**: `nfjson/` - Third-party JSON parsing library for VFP
|
||||||
- **Technology**: Visual FoxPro 9 with WinHttp.WinHttpRequest.5.1 for HTTP requests
|
- **Technology**: Visual FoxPro 9 with WinHttp.WinHttpRequest.5.1 for HTTP requests
|
||||||
- **API Integration**: GoMag REST API v1 for product management
|
- **API Integration**: GoMag REST API v1 for products and orders management
|
||||||
|
|
||||||
## Core Components
|
## Core Components
|
||||||
|
|
||||||
### gomag-vending.prg
|
### gomag-vending.prg
|
||||||
Main script that handles:
|
Main application script with:
|
||||||
- GoMag API authentication using Apikey and ApiShop headers
|
- Complete pagination support for products and orders
|
||||||
- HTTP GET requests to retrieve product data
|
- Configurable API settings via INI file
|
||||||
- JSON response parsing and analysis
|
- Comprehensive error handling and logging
|
||||||
- File output for API responses (timestamped .json files)
|
- Rate limiting compliance (1-second delays between requests)
|
||||||
- Error handling and connectivity testing
|
- JSON array output generation for both products and orders
|
||||||
|
|
||||||
### Key Configuration Variables
|
### utils.prg
|
||||||
- `lcApiUrl`: GoMag API endpoint (defaults to product read endpoint)
|
Utility functions module containing:
|
||||||
- `lcApiKey`: GoMag API key (must be configured)
|
- INI file operations (`ReadPini`, `WritePini`, `LoadSettings`)
|
||||||
- `lcApiShop`: Shop URL (must be configured)
|
- Logging system (`InitLog`, `LogMessage`, `CloseLog`)
|
||||||
|
- Connectivity testing (`TestConnectivity`)
|
||||||
|
- URL encoding utilities (`UrlEncode`)
|
||||||
|
- Default configuration creation (`CreateDefaultIni`)
|
||||||
|
|
||||||
|
### settings.ini
|
||||||
|
Configuration file with sections:
|
||||||
|
- `[API]` - API endpoints, credentials, and headers
|
||||||
|
- `[PAGINATION]` - Page size limits
|
||||||
|
- `[OPTIONS]` - Feature toggles for products/orders retrieval
|
||||||
|
- `[FILTERS]` - Date range filters for orders
|
||||||
|
|
||||||
## Development Commands
|
## Development Commands
|
||||||
|
|
||||||
@@ -35,51 +47,84 @@ DO gomag-vending.prg
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Running from Windows Command Line
|
### Running from Windows Command Line
|
||||||
Use the provided batch file for easy execution:
|
Use the provided batch file:
|
||||||
```cmd
|
```cmd
|
||||||
run-gomag.bat
|
run-gomag.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
Or directly with Visual FoxPro executable:
|
Direct execution with Visual FoxPro:
|
||||||
```cmd
|
```cmd
|
||||||
"C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -T "path\to\gomag-vending-test.prg"
|
"C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -T "gomag-vending.prg"
|
||||||
```
|
```
|
||||||
|
|
||||||
The batch file uses `%~dp0` to automatically detect the current directory, making it portable across different locations.
|
## Configuration Management
|
||||||
|
|
||||||
### Testing Connectivity
|
The application uses `settings.ini` for all configuration. Key settings:
|
||||||
The script includes a `TestConnectivity()` function for internet connectivity testing.
|
|
||||||
|
### Required Configuration
|
||||||
|
- `ApiKey` - Your GoMag API key
|
||||||
|
- `ApiShop` - Your shop URL (e.g., "https://yourstore.gomag.ro")
|
||||||
|
|
||||||
|
### Feature Control
|
||||||
|
- `GetProducts` - Set to "1" to retrieve products, "0" to skip
|
||||||
|
- `GetOrders` - Set to "1" to retrieve orders, "0" to skip
|
||||||
|
- `OrderDaysBack` - Number of days back to retrieve orders (default: 7)
|
||||||
|
|
||||||
|
### Pagination
|
||||||
|
- `Limit` - Records per page (default: 100, max recommended for GoMag API)
|
||||||
|
|
||||||
## API Integration Details
|
## API Integration Details
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
- Uses header-based authentication with `Apikey` and `ApiShop` headers
|
- Header-based authentication using `Apikey` and `ApiShop` headers
|
||||||
- Requires User-Agent to be different from "PostmanRuntime"
|
- User-Agent must differ from "PostmanRuntime"
|
||||||
|
|
||||||
### Endpoints Used
|
### Endpoints
|
||||||
- Primary: `https://api.gomag.ro/api/v1/product/read/json?enabled=1`
|
- Products: `https://api.gomag.ro/api/v1/product/read/json?enabled=1`
|
||||||
- Supports pagination, filtering by category/brand, and sorting parameters
|
- Orders: `https://api.gomag.ro/api/v1/order/read/json`
|
||||||
|
|
||||||
### Rate Limiting
|
### Rate Limiting
|
||||||
- No specific limitations for READ requests
|
- 1-second pause between paginated requests
|
||||||
- POST requests limited to ~1 request per second (Leaky Bucket algorithm)
|
- No specific READ request limitations
|
||||||
|
- POST requests limited to ~1 request per second (Leaky Bucket)
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
## File Structure
|
|
||||||
```
|
```
|
||||||
/
|
/
|
||||||
├── gomag-vending-test.prg # Main application script
|
├── gomag-vending.prg # Main application
|
||||||
├── run-gomag.bat # Windows batch file for easy execution
|
├── utils.prg # Utility functions
|
||||||
└── gomag_products_*.json # Generated API response files (timestamped)
|
├── settings.ini # Configuration file
|
||||||
|
├── run-gomag.bat # Windows launcher
|
||||||
|
├── nfjson/ # JSON parsing library
|
||||||
|
│ ├── nfjsoncreate.prg
|
||||||
|
│ └── nfjsonread.prg
|
||||||
|
├── log/ # Generated log files
|
||||||
|
├── output/ # Generated JSON files
|
||||||
|
└── products-example.json # Sample API response
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration Requirements
|
## Output Files
|
||||||
|
|
||||||
Before running, update these variables in `gomag-vending.prg:10-15`:
|
### Generated Files
|
||||||
1. `lcApiKey` - Your GoMag API key
|
- `log/gomag_sync_YYYYMMDD_HHMMSS.log` - Detailed execution logs
|
||||||
2. `lcApiShop` - Your shop URL (e.g., "https://yourstore.gomag.ro")
|
- `output/gomag_all_products_YYYYMMDD_HHMMSS.json` - Complete product array
|
||||||
|
- `output/gomag_orders_last7days_YYYYMMDD_HHMMSS.json` - Orders array
|
||||||
|
|
||||||
## Helper Functions
|
### Error Files
|
||||||
|
- `gomag_error_pageN_*.json` - Raw API responses for failed parsing
|
||||||
|
- `gomag_error_pageN_*.log` - HTTP error details with status codes
|
||||||
|
|
||||||
- `ParseJsonResponse()` - Basic JSON structure analysis
|
## Key Functions
|
||||||
- `TestConnectivity()` - Internet connectivity testing
|
|
||||||
- `UrlEncode()` - URL parameter encoding utility
|
### Main Application (gomag-vending.prg)
|
||||||
|
- `SaveProductsArray` - Converts paginated product data to JSON array
|
||||||
|
- `SaveOrdersArray` - Converts paginated order data to JSON array
|
||||||
|
- `MergeProducts` - Combines products from multiple pages
|
||||||
|
- `MergeOrdersArray` - Combines orders from multiple pages
|
||||||
|
|
||||||
|
### Utilities (utils.prg)
|
||||||
|
- `LoadSettings` - Loads complete INI configuration into object
|
||||||
|
- `InitLog`/`LogMessage`/`CloseLog` - Comprehensive logging system
|
||||||
|
- `TestConnectivity` - Internet connection verification
|
||||||
|
- `CreateDefaultIni` - Generates template configuration file
|
||||||
@@ -2,6 +2,13 @@
|
|||||||
*-- Autor: Claude AI
|
*-- Autor: Claude AI
|
||||||
*-- Data: 26.08.2025
|
*-- Data: 26.08.2025
|
||||||
|
|
||||||
|
SET SAFETY OFF
|
||||||
|
SET CENTURY ON
|
||||||
|
SET DATE DMY
|
||||||
|
SET EXACT ON
|
||||||
|
SET ANSI ON
|
||||||
|
SET DELETED ON
|
||||||
|
|
||||||
*-- Setari principale
|
*-- Setari principale
|
||||||
LOCAL lcApiBaseUrl, lcApiUrl, lcApiKey, lcUserAgent, lcContentType
|
LOCAL lcApiBaseUrl, lcApiUrl, lcApiKey, lcUserAgent, lcContentType
|
||||||
LOCAL loHttp, lcResponse, lcJsonResponse
|
LOCAL loHttp, lcResponse, lcJsonResponse
|
||||||
@@ -147,6 +154,15 @@ IF llGetProducts
|
|||||||
IF !ISNULL(loJsonData)
|
IF !ISNULL(loJsonData)
|
||||||
*-- Prima pagina - setam informatiile generale
|
*-- Prima pagina - setam informatiile generale
|
||||||
IF lnCurrentPage = 1
|
IF lnCurrentPage = 1
|
||||||
|
LogMessage("[PRODUCTS] Analyzing JSON structure...", "INFO", gcLogFile)
|
||||||
|
LOCAL ARRAY laJsonProps[1]
|
||||||
|
lnPropCount = AMEMBERS(laJsonProps, loJsonData, 0)
|
||||||
|
FOR lnDebugIndex = 1 TO MIN(lnPropCount, 10) && Primele 10 proprietati
|
||||||
|
lcPropName = laJsonProps(lnDebugIndex)
|
||||||
|
lcPropType = TYPE('loJsonData.' + lcPropName)
|
||||||
|
LogMessage("[PRODUCTS] Property: " + lcPropName + " (Type: " + lcPropType + ")", "DEBUG", gcLogFile)
|
||||||
|
ENDFOR
|
||||||
|
|
||||||
IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N'
|
IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N'
|
||||||
loAllJsonData.total = VAL(TRANSFORM(loJsonData.total))
|
loAllJsonData.total = VAL(TRANSFORM(loJsonData.total))
|
||||||
ENDIF
|
ENDIF
|
||||||
@@ -157,8 +173,23 @@ IF llGetProducts
|
|||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Adaugare produse din pagina curenta
|
*-- Adaugare produse din pagina curenta
|
||||||
|
LOCAL llHasProducts, lnProductsFound
|
||||||
|
llHasProducts = .F.
|
||||||
|
lnProductsFound = 0
|
||||||
|
|
||||||
IF TYPE('loJsonData.products') = 'O'
|
IF TYPE('loJsonData.products') = 'O'
|
||||||
|
*-- Numaram produsele din obiectul products
|
||||||
|
lnProductsFound = AMEMBERS(laProductsPage, loJsonData.products, 0)
|
||||||
|
IF lnProductsFound > 0
|
||||||
DO MergeProducts WITH loAllJsonData, loJsonData
|
DO MergeProducts WITH loAllJsonData, loJsonData
|
||||||
|
llHasProducts = .T.
|
||||||
|
LogMessage("[PRODUCTS] Found: " + TRANSFORM(lnProductsFound) + " products in page " + TRANSFORM(lnCurrentPage), "INFO", gcLogFile)
|
||||||
|
gnProductsProcessed = gnProductsProcessed + lnProductsFound
|
||||||
|
ENDIF
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
IF !llHasProducts
|
||||||
|
LogMessage("[PRODUCTS] WARNING: No products found in JSON response for page " + TRANSFORM(lnCurrentPage), "WARN", gcLogFile)
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Verificare daca mai sunt pagini
|
*-- Verificare daca mai sunt pagini
|
||||||
@@ -234,16 +265,15 @@ ENDDO
|
|||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
? "SARIT PESTE PRELUAREA PRODUSELOR (llGetProducts = .F.)"
|
LogMessage("[PRODUCTS] Skipped product retrieval (llGetProducts = .F.)", "INFO", gcLogFile)
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- SECTIUNEA COMENZI - se executa doar daca llGetOrders = .T.
|
*-- SECTIUNEA COMENZI - se executa doar daca llGetOrders = .T.
|
||||||
IF llGetOrders
|
IF llGetOrders
|
||||||
? ""
|
LogMessage("[ORDERS] =======================================", "INFO", gcLogFile)
|
||||||
? "======================================="
|
LogMessage("[ORDERS] RETRIEVING ORDERS FROM LAST " + TRANSFORM(loSettings.OrderDaysBack) + " DAYS", "INFO", gcLogFile)
|
||||||
? "PRELUARE COMENZI DIN ULTIMELE " + TRANSFORM(loSettings.OrderDaysBack) + " ZILE"
|
LogMessage("[ORDERS] Start date: " + lcStartDateStr, "INFO", gcLogFile)
|
||||||
? "Data de start: " + lcStartDateStr
|
LogMessage("[ORDERS] =======================================", "INFO", gcLogFile)
|
||||||
? "======================================="
|
|
||||||
|
|
||||||
*-- Reinitializare pentru comenzi
|
*-- Reinitializare pentru comenzi
|
||||||
lnCurrentPage = 1
|
lnCurrentPage = 1
|
||||||
@@ -258,7 +288,7 @@ DO WHILE llHasMorePages
|
|||||||
*-- Construire URL cu paginare si filtrare pe data (folosind startDate conform documentatiei GoMag)
|
*-- Construire URL cu paginare si filtrare pe data (folosind startDate conform documentatiei GoMag)
|
||||||
lcApiUrl = lcOrderApiUrl + "?startDate=" + lcStartDateStr + "&page=" + TRANSFORM(lnCurrentPage) + "&limit=" + TRANSFORM(lnLimit)
|
lcApiUrl = lcOrderApiUrl + "?startDate=" + lcStartDateStr + "&page=" + TRANSFORM(lnCurrentPage) + "&limit=" + TRANSFORM(lnLimit)
|
||||||
|
|
||||||
? "Preluare comenzi pagina " + TRANSFORM(lnCurrentPage) + "..."
|
LogMessage("[ORDERS] Page " + TRANSFORM(lnCurrentPage) + " fetching...", "INFO", gcLogFile)
|
||||||
|
|
||||||
*-- Configurare request
|
*-- Configurare request
|
||||||
TRY
|
TRY
|
||||||
@@ -293,16 +323,17 @@ DO WHILE llHasMorePages
|
|||||||
IF !ISNULL(loJsonData)
|
IF !ISNULL(loJsonData)
|
||||||
*-- Debug: Afisam structura JSON pentru prima pagina
|
*-- Debug: Afisam structura JSON pentru prima pagina
|
||||||
IF lnCurrentPage = 1
|
IF lnCurrentPage = 1
|
||||||
? "DEBUG: Analiza structura JSON comenzi..."
|
LogMessage("[ORDERS] Analyzing JSON structure...", "INFO", gcLogFile)
|
||||||
|
LOCAL ARRAY laJsonProps[1]
|
||||||
lnPropCount = AMEMBERS(laJsonProps, loJsonData, 0)
|
lnPropCount = AMEMBERS(laJsonProps, loJsonData, 0)
|
||||||
FOR lnDebugIndex = 1 TO MIN(lnPropCount, 10) && Primele 10 proprietati
|
FOR lnDebugIndex = 1 TO MIN(lnPropCount, 10) && Primele 10 proprietati
|
||||||
lcPropName = laJsonProps(lnDebugIndex)
|
lcPropName = laJsonProps(lnDebugIndex)
|
||||||
lcPropType = TYPE('loJsonData.' + lcPropName)
|
lcPropType = TYPE('loJsonData.' + lcPropName)
|
||||||
? " Proprietate: " + lcPropName + " (Tip: " + lcPropType + ")"
|
LogMessage("[ORDERS] Property: " + lcPropName + " (Type: " + lcPropType + ")", "DEBUG", gcLogFile)
|
||||||
ENDFOR
|
ENDFOR
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Prima pagina - setam informatiile generale
|
*-- Prima pagina - setam informatiile generale din metadata
|
||||||
IF lnCurrentPage = 1
|
IF lnCurrentPage = 1
|
||||||
IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N'
|
IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N'
|
||||||
loAllOrderData.total = VAL(TRANSFORM(loJsonData.total))
|
loAllOrderData.total = VAL(TRANSFORM(loJsonData.total))
|
||||||
@@ -310,42 +341,42 @@ DO WHILE llHasMorePages
|
|||||||
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
|
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
|
||||||
loAllOrderData.pages = VAL(TRANSFORM(loJsonData.pages))
|
loAllOrderData.pages = VAL(TRANSFORM(loJsonData.pages))
|
||||||
ENDIF
|
ENDIF
|
||||||
? "Total comenzi: " + TRANSFORM(loAllOrderData.total)
|
LogMessage("[ORDERS] Total orders: " + TRANSFORM(loAllOrderData.total), "INFO", gcLogFile)
|
||||||
? "Total pagini: " + TRANSFORM(loAllOrderData.pages)
|
LogMessage("[ORDERS] Total pages: " + TRANSFORM(loAllOrderData.pages), "INFO", gcLogFile)
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Adaugare comenzi din pagina curenta
|
*-- Adaugare comenzi din pagina curenta
|
||||||
*-- API-ul GoMag returneaza un array direct de comenzi
|
*-- API-ul GoMag returneaza obiect cu metadata si orders
|
||||||
LOCAL llHasOrders, lnOrdersFound
|
LOCAL llHasOrders, lnOrdersFound
|
||||||
llHasOrders = .F.
|
llHasOrders = .F.
|
||||||
lnOrdersFound = 0
|
lnOrdersFound = 0
|
||||||
|
|
||||||
*-- JSON-ul este direct un array de comenzi
|
*-- Verificam daca avem obiectul orders
|
||||||
lnDirectProps = AMEMBERS(laDirectProps, loJsonData, 0)
|
IF TYPE('loJsonData.orders') = 'O'
|
||||||
IF lnDirectProps > 0
|
*-- Numaram comenzile din obiectul orders
|
||||||
*-- Cream un obiect temporar cu structura asteptata
|
lnOrdersFound = AMEMBERS(laOrdersPage, loJsonData.orders, 0)
|
||||||
LOCAL loTempData
|
IF lnOrdersFound > 0
|
||||||
loTempData = CREATEOBJECT("Empty")
|
*-- Mergem comenzile din pagina curenta
|
||||||
ADDPROPERTY(loTempData, "orders", loJsonData)
|
DO MergeOrdersArray WITH loAllOrderData, loJsonData
|
||||||
DO MergeOrdersArray WITH loAllOrderData, loTempData
|
|
||||||
llHasOrders = .T.
|
llHasOrders = .T.
|
||||||
lnOrdersFound = lnDirectProps
|
LogMessage("[ORDERS] Found: " + TRANSFORM(lnOrdersFound) + " orders in page " + TRANSFORM(lnCurrentPage), "INFO", gcLogFile)
|
||||||
? " Gasit: " + TRANSFORM(lnDirectProps) + " comenzi in pagina " + TRANSFORM(lnCurrentPage)
|
gnOrdersProcessed = gnOrdersProcessed + lnOrdersFound
|
||||||
|
ENDIF
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
IF !llHasOrders
|
IF !llHasOrders
|
||||||
? " ATENTIE: Nu s-au gasit comenzi in raspunsul JSON pentru pagina " + TRANSFORM(lnCurrentPage)
|
LogMessage("[ORDERS] WARNING: No orders found in JSON response for page " + TRANSFORM(lnCurrentPage), "WARN", gcLogFile)
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Verificare daca mai sunt pagini
|
*-- Verificare daca mai sunt pagini folosind metadata
|
||||||
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
|
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
|
||||||
lnTotalPages = VAL(TRANSFORM(loJsonData.pages))
|
lnTotalPages = VAL(TRANSFORM(loJsonData.pages))
|
||||||
IF lnCurrentPage >= lnTotalPages
|
IF lnCurrentPage >= lnTotalPages
|
||||||
llHasMorePages = .F.
|
llHasMorePages = .F.
|
||||||
ENDIF
|
ENDIF
|
||||||
ELSE
|
ELSE
|
||||||
*-- Daca nu avem info despre pagini, verificam daca sunt comenzi
|
*-- Fallback: verifica daca am primit mai putin decat limita
|
||||||
IF !llHasOrders
|
IF !llHasOrders OR lnOrdersFound < lnLimit
|
||||||
llHasMorePages = .F.
|
llHasMorePages = .F.
|
||||||
ENDIF
|
ENDIF
|
||||||
ENDIF
|
ENDIF
|
||||||
@@ -398,13 +429,13 @@ ENDDO
|
|||||||
|
|
||||||
*-- Salvare array JSON cu toate comenzile
|
*-- Salvare array JSON cu toate comenzile
|
||||||
IF !ISNULL(loAllOrderData) AND TYPE('loAllOrderData.orders') = 'O'
|
IF !ISNULL(loAllOrderData) AND TYPE('loAllOrderData.orders') = 'O'
|
||||||
lcOrderJsonFileName = "gomag_orders_last7days_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json"
|
lcOrderJsonFileName = lcOutputDir + "\gomag_orders_last7days_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json"
|
||||||
DO SaveOrdersArray WITH loAllOrderData, lcOrderJsonFileName
|
DO SaveOrdersArray WITH loAllOrderData, lcOrderJsonFileName
|
||||||
? "Fisier JSON cu comenzi creat: " + lcOrderJsonFileName
|
LogMessage("[ORDERS] JSON file created: " + lcOrderJsonFileName, "INFO", gcLogFile)
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
? "SARIT PESTE PRELUAREA COMENZILOR (llGetOrders = .F.)"
|
LogMessage("[ORDERS] Skipped order retrieval (llGetOrders = .F.)", "INFO", gcLogFile)
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Curatare
|
*-- Curatare
|
||||||
@@ -438,7 +469,6 @@ IF TYPE('tloAllData.products') = 'O'
|
|||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Serializeaza produsul cu nfjsoncreate
|
*-- Serializeaza produsul cu nfjsoncreate
|
||||||
SET PROCEDURE TO nfjsoncreate.prg ADDITIVE
|
|
||||||
lcProductJson = nfJsonCreate(loProduct, .F.)
|
lcProductJson = nfJsonCreate(loProduct, .F.)
|
||||||
lcJsonContent = lcJsonContent + " " + lcProductJson
|
lcJsonContent = lcJsonContent + " " + lcProductJson
|
||||||
ENDIF
|
ENDIF
|
||||||
@@ -477,7 +507,6 @@ IF TYPE('tloAllData.orders') = 'O'
|
|||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
*-- Serializeaza comanda cu nfjsoncreate
|
*-- Serializeaza comanda cu nfjsoncreate
|
||||||
SET PROCEDURE TO nfjsoncreate.prg ADDITIVE
|
|
||||||
lcOrderJson = nfJsonCreate(loOrder, .F.)
|
lcOrderJson = nfJsonCreate(loOrder, .F.)
|
||||||
lcJsonContent = lcJsonContent + " " + lcOrderJson
|
lcJsonContent = lcJsonContent + " " + lcOrderJson
|
||||||
ENDIF
|
ENDIF
|
||||||
208
orders-example.json
Normal file
208
orders-example.json
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
{
|
||||||
|
"total": "399",
|
||||||
|
"page": "1",
|
||||||
|
"pages": 4,
|
||||||
|
"orders": {
|
||||||
|
"60644": {
|
||||||
|
"id": "60644",
|
||||||
|
"number": "436232189",
|
||||||
|
"date": "2025-08-27 16:32:43",
|
||||||
|
"invoice": {
|
||||||
|
"series": "",
|
||||||
|
"number": "0",
|
||||||
|
"date": "0000-00-00 00:00:00"
|
||||||
|
},
|
||||||
|
"total": "1026.24",
|
||||||
|
"status": "Comanda noua",
|
||||||
|
"statusId": "1",
|
||||||
|
"source": "internal",
|
||||||
|
"sales_channel": "Website",
|
||||||
|
"sales_channel_marketplace": "",
|
||||||
|
"sales_agent": "",
|
||||||
|
"currency": "RON",
|
||||||
|
"observation": "",
|
||||||
|
"payment": {
|
||||||
|
"name": "Numerar/Ramburs sau Card la easybox",
|
||||||
|
"online": "0",
|
||||||
|
"completed": "0"
|
||||||
|
},
|
||||||
|
"delivery": {
|
||||||
|
"name": "Transport gratuit",
|
||||||
|
"total": 0,
|
||||||
|
"date": "0000-00-00 00:00:00",
|
||||||
|
"lockerId": 0
|
||||||
|
},
|
||||||
|
"shipping": {
|
||||||
|
"company": "",
|
||||||
|
"firstname": "Liviu",
|
||||||
|
"lastname": "Stefan",
|
||||||
|
"phone": "0751013764",
|
||||||
|
"email": "liviustefan2001@gmail.com",
|
||||||
|
"address": "aleea Soarelui nr 2, casa nr 4, cartier Brates Lake",
|
||||||
|
"city": "Galați",
|
||||||
|
"region": "Galati",
|
||||||
|
"country": "Romania",
|
||||||
|
"zipcode": null
|
||||||
|
},
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "582",
|
||||||
|
"type": "product",
|
||||||
|
"sku": "8000070028685",
|
||||||
|
"ean": "8000070028685",
|
||||||
|
"name": "Lavazza Gusto Forte Vending Cafea Boabe 1kg",
|
||||||
|
"price": "69.79",
|
||||||
|
"baseprice": "78",
|
||||||
|
"vat": "11",
|
||||||
|
"quantity": "10.00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "589",
|
||||||
|
"type": "product",
|
||||||
|
"sku": "5941623010333",
|
||||||
|
"ean": "5941623010333",
|
||||||
|
"name": "Doncafe Espresso Intense Cafea Boabe 1 kg",
|
||||||
|
"price": "56.49",
|
||||||
|
"baseprice": "62",
|
||||||
|
"vat": "11",
|
||||||
|
"quantity": "2.00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "512",
|
||||||
|
"type": "product",
|
||||||
|
"sku": "82",
|
||||||
|
"ean": "",
|
||||||
|
"name": "Zahar Plic Lavazza 200buc",
|
||||||
|
"price": "10.99",
|
||||||
|
"baseprice": "14",
|
||||||
|
"vat": "21",
|
||||||
|
"quantity": "5.00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "671",
|
||||||
|
"type": "product",
|
||||||
|
"sku": "312349",
|
||||||
|
"ean": "",
|
||||||
|
"name": "Palete manuale din lemn 110mm 1000buc",
|
||||||
|
"price": "7.99",
|
||||||
|
"baseprice": "10.5",
|
||||||
|
"vat": "21",
|
||||||
|
"quantity": "2.00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "554",
|
||||||
|
"type": "product",
|
||||||
|
"sku": "8004990127091",
|
||||||
|
"ean": "8004990127091",
|
||||||
|
"name": "Ristora Ciocolată Instant 1kg",
|
||||||
|
"price": "25.99",
|
||||||
|
"baseprice": "28",
|
||||||
|
"vat": "21",
|
||||||
|
"quantity": "2.00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "567",
|
||||||
|
"type": "product",
|
||||||
|
"sku": "8004990125530",
|
||||||
|
"ean": "8004990125530",
|
||||||
|
"name": "Prolait Topping Blue Lapte Granulat 500g",
|
||||||
|
"price": "18.49",
|
||||||
|
"baseprice": "23",
|
||||||
|
"vat": "21",
|
||||||
|
"quantity": "5.00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"billing": {
|
||||||
|
"firstname": "Liviu",
|
||||||
|
"lastname": "Stefan",
|
||||||
|
"phone": "0751013764",
|
||||||
|
"email": "liviustefan2001@gmail.com",
|
||||||
|
"address": "aleea Soarelui nr 2, casa nr 4, cartier Brates Lake",
|
||||||
|
"city": "Galați",
|
||||||
|
"region": "Galati",
|
||||||
|
"country": "Romania",
|
||||||
|
"customerId": "5997"
|
||||||
|
},
|
||||||
|
"discounts": [
|
||||||
|
],
|
||||||
|
"updated": "2025-08-27 16:32:43"
|
||||||
|
},
|
||||||
|
"60643": {
|
||||||
|
"id": "60643",
|
||||||
|
"number": "436232175",
|
||||||
|
"date": "2025-08-27 16:19:29",
|
||||||
|
"invoice": {
|
||||||
|
"series": "",
|
||||||
|
"number": "0",
|
||||||
|
"date": "0000-00-00 00:00:00"
|
||||||
|
},
|
||||||
|
"total": "359.4",
|
||||||
|
"status": "Comanda noua",
|
||||||
|
"statusId": "1",
|
||||||
|
"source": "internal",
|
||||||
|
"sales_channel": "Website",
|
||||||
|
"sales_channel_marketplace": "",
|
||||||
|
"sales_agent": "",
|
||||||
|
"currency": "RON",
|
||||||
|
"observation": "",
|
||||||
|
"payment": {
|
||||||
|
"name": "Numerar/Ramburs sau Card la easybox",
|
||||||
|
"online": "0",
|
||||||
|
"completed": "0"
|
||||||
|
},
|
||||||
|
"delivery": {
|
||||||
|
"name": "Transport National",
|
||||||
|
"total": 30,
|
||||||
|
"date": "0000-00-00 00:00:00",
|
||||||
|
"lockerId": 0
|
||||||
|
},
|
||||||
|
"shipping": {
|
||||||
|
"company": "",
|
||||||
|
"firstname": "Alexandra",
|
||||||
|
"lastname": "TONE",
|
||||||
|
"phone": "0763571486",
|
||||||
|
"email": "aristocratgaminggr@gmail.com",
|
||||||
|
"address": "Str. Garii, Nr. 102",
|
||||||
|
"city": "Giurgiu",
|
||||||
|
"region": "Giurgiu",
|
||||||
|
"country": "Romania",
|
||||||
|
"zipcode": null
|
||||||
|
},
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "279",
|
||||||
|
"type": "product",
|
||||||
|
"sku": "30006ozLavazza",
|
||||||
|
"ean": "",
|
||||||
|
"name": "Pahar carton 6oz Lavazza RLP bax 3000buc",
|
||||||
|
"price": "329.4",
|
||||||
|
"baseprice": "360",
|
||||||
|
"vat": "21",
|
||||||
|
"quantity": "1.00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"billing": {
|
||||||
|
"company": {
|
||||||
|
"name": "ARISTOCRAT GAMING SRL",
|
||||||
|
"code": "32128076",
|
||||||
|
"registrationNo": "J27/487/2013",
|
||||||
|
"bank": "",
|
||||||
|
"iban": ""
|
||||||
|
},
|
||||||
|
"firstname": "Alexandra",
|
||||||
|
"lastname": "TONE",
|
||||||
|
"phone": "0763571486",
|
||||||
|
"email": "aristocratgaminggr@gmail.com",
|
||||||
|
"address": "Aleea Revolutiei, Spatiul Comercial Nr.32",
|
||||||
|
"city": "Roman",
|
||||||
|
"region": "Neamt",
|
||||||
|
"country": "Romania",
|
||||||
|
"customerId": "12283"
|
||||||
|
},
|
||||||
|
"discounts": [
|
||||||
|
],
|
||||||
|
"updated": "2025-08-27 16:19:29"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shippingAsProduct": false
|
||||||
|
}
|
||||||
137
products-example.json
Normal file
137
products-example.json
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
{
|
||||||
|
"total": "Numar total de rezultate",
|
||||||
|
"page": "Pagina curenta",
|
||||||
|
"pages": "Numar total de pagini",
|
||||||
|
"products": {
|
||||||
|
"id": "ID intern al produsului",
|
||||||
|
"sku": "SKU",
|
||||||
|
"name": "Denumire",
|
||||||
|
"description": "Descriere",
|
||||||
|
"short_description": "Descriere scurta",
|
||||||
|
"url": "URL",
|
||||||
|
"canonical_url": "URL canonic",
|
||||||
|
"brand": "Marca produs",
|
||||||
|
"categories": {
|
||||||
|
"Branch 1": [
|
||||||
|
{
|
||||||
|
"id": "ID-ul categoriei",
|
||||||
|
"name": "Denumirea categoriei"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ID-ul categoriei",
|
||||||
|
"name": "Denumirea categoriei"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Branch 2": [
|
||||||
|
{
|
||||||
|
"id": "ID-ul categoriei",
|
||||||
|
"name": "Denumirea categoriei"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ID-ul categoriei",
|
||||||
|
"name": "Denumirea categoriei"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"...": [
|
||||||
|
"..."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"weight": "Greutatea produsului (kg)",
|
||||||
|
"enabled": "Activ (0/1)",
|
||||||
|
"parent": "ID produs parinte",
|
||||||
|
"parent_sku": "SKU produs parinte",
|
||||||
|
"group_key": "Codul de grupare al variantelor de produs",
|
||||||
|
"stockManagement": "Gestioneaza automat stocul produsului",
|
||||||
|
"stock": "Stoc cantitativ",
|
||||||
|
"stockStatus": "Status stoc",
|
||||||
|
"base_price": "Pret de baza al produsului",
|
||||||
|
"price": "Pret de vanzare al produsului (dupa aplicarea adaosurilor si reducerilor)",
|
||||||
|
"vat_included": "Pret include TVA (0/1)",
|
||||||
|
"vat": "Valoare TVA",
|
||||||
|
"currency": "Moneda",
|
||||||
|
"ecotax": "Valoare taxa verde",
|
||||||
|
"um": "Unitate de masura",
|
||||||
|
"html_title": "Titlu html",
|
||||||
|
"html_description": "Descrierere html",
|
||||||
|
"customSearchKeys": "Cuvinte cheie folosite la cautarea SEO",
|
||||||
|
"feedDescription": "Descriere pentru feed-uri",
|
||||||
|
"allowOrdersWhenOutOfStock": "Produsul se aduce la comanda",
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"id": "ID atribut",
|
||||||
|
"type": "Tip atribut: dropdown, textinput, textarea",
|
||||||
|
"name": "Denumire atribut",
|
||||||
|
"value": "Optiune"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ID atribut",
|
||||||
|
"type": "Tip atribut multipleselect (accepta valori multiple)",
|
||||||
|
"name": "Denumire atribut",
|
||||||
|
"value": [
|
||||||
|
"Optiune1",
|
||||||
|
"Optiune2",
|
||||||
|
"..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images": [
|
||||||
|
"Imagine 1 (principala)",
|
||||||
|
"Imagine 2",
|
||||||
|
"..."
|
||||||
|
],
|
||||||
|
"variations": [
|
||||||
|
{
|
||||||
|
"id": "ID intern al produsului",
|
||||||
|
"sku": "SKU",
|
||||||
|
"base_price": "Pret de baza al produsului",
|
||||||
|
"price": "Pret de vanzare al produsului (dupa aplicarea adaosurilor si reducerilor)",
|
||||||
|
"stock": "Stoc cantitativ",
|
||||||
|
"stockStatus": "Status stoc",
|
||||||
|
"stockManagement": "Gestioneaza automat stocul produsului",
|
||||||
|
"versionAttributes": {
|
||||||
|
"id Attribut": {
|
||||||
|
"name": "Denumire atribut",
|
||||||
|
"value": "Valoare atribut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ID intern al produsului",
|
||||||
|
"sku": "SKU",
|
||||||
|
"base_price": "Pret de baza al produsului",
|
||||||
|
"price": "Pret de vanzare al produsului (dupa aplicarea adaosurilor si reducerilor)",
|
||||||
|
"stock": "Stoc cantitativ",
|
||||||
|
"stockStatus": "Status stoc",
|
||||||
|
"stockManagement": "Gestioneaza automat stocul produsului",
|
||||||
|
"versionAttributes": {
|
||||||
|
"id Attribut": {
|
||||||
|
"id": "ID atribut",
|
||||||
|
"name": "Denumire atribut",
|
||||||
|
"value": "Valoare atribut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ean": "EAN",
|
||||||
|
"videos": [
|
||||||
|
"URL video"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"URL fisiere"
|
||||||
|
],
|
||||||
|
"updated": "Ultima modificare",
|
||||||
|
"created": "Data crearii",
|
||||||
|
"delivery_time": "Timp de livrare",
|
||||||
|
"delivery_time_type": "Tip timp de livrare",
|
||||||
|
"bundleItems": [
|
||||||
|
{
|
||||||
|
"sku": "SKU componenta",
|
||||||
|
"quantity": "Cantitate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sku": "SKU componenta",
|
||||||
|
"quantity": "Cantitate"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@echo off
|
@echo off
|
||||||
cd /d "%~dp0"
|
cd /d "%~dp0"
|
||||||
"C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -T "%~dp0gomag-vending-test.prg"
|
"C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -T "%~dp0gomag-vending.prg"
|
||||||
pause
|
pause
|
||||||
Reference in New Issue
Block a user