Onlinestoresync Documentation

Online Store Sync Controller Documentation

File: /controllers/onlinestoresync.php

Purpose: Real-time data synchronization between ERP and online store with automatic inventory management

Last Updated: December 20, 2024

Total Functions: 25+

Lines of Code: ~1,136

---

๐Ÿ“‹ Overview

The Online Store Sync Controller provides real-time, bidirectional data synchronization between the ERP system and external online stores. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Synchronization Tables

Table NamePurposeKey Columns
**onlinetempcategory**Modified categories queueid, productCatId, changes pending sync
**onlinetempproduct**Modified products queueid, productId, changes pending sync
**onlinetempstoredetail**Inventory change queueid, productid, storeid, quantity changes
**onlinetempstorereport**Store report queueid, storereportid, operation details
### Order Processing Tables

Table NamePurposeKey Columns
**onlinetemporder**Order stagingid, onlineorderid, customerid, ordertotal, orderstatus
**onlinetemporderclient**Customer stagingid, erpid, customer_id, clientname, clientmobile, clientareaid
**onlinetemporderproduct**Order items stagingid, orderid, productid, quantity, price, total
### Core Data Tables

Table NamePurposeKey Columns
**productcat**Categories masterproductCatId, productCatName, productCatParent, conditions
**product**Products masterproductId, productName, productCatId, conditions, pricing
**storedetail**Inventory quantitiesstoredetailid, productid, storeid, productquantity
**storereport**Inventory movementsstorereportid, productid, storeid, operation details
**storemovement**Store transfersid, productid, storeidfrom, storeidto, transferproductamount
**client**Customer masterclientid, clientname, clientdebt, clientareaid
**clientdebtchange**Debt change logclientdebtchangeid, clientid, amount, type, date
### Configuration Tables

Table NamePurposeKey Columns
**onlinestoresetting**Sync configurationurl, availableStores, timing settings
**programsettings**System settingsusedParcode, parcodeDigits, inventory settings
**availableparcode**Barcode poolvalue, available barcodes
---

๐Ÿ”‘ Key Functions

1. syncCatAndProducts - Real-time Change Sync

Location: Line 232

Purpose: Synchronize only categories and products that have changed

Process Flow:

1. Process Modified Categories:

   $onlineTempCategory = $productCatExt->queryAllForCURLSyncAndLock();
   if (count($onlineTempCategory) > 0) {
       // Encode category images
       foreach ($onlineTempCategory as $value) {
           $path = str_replace('\\', '/', getcwd()) . '/../views/default/images/cat_image/' . $value->logo;
           $value->logo_base64 = base64_encode(file_get_contents($path));
       }
       
       // Send to online store
       $response = CURL_IT2($onlineTempCategory, $onlineStoreSetting->url . '/api_erp/syncEditedCatsFromERPCURL');
       
       // Clear queue if successful
       if ((int) $response == 1) {
           $onlineTempCategoryEX->TRUNCATE();
       } else {
           // Log error for retry
           $myfile = fopen("backup/" . date("Y-m-d") . ".txt", "a+");
           $txt = "syncEditedCatsFromERPCURL ERROR " . date("Y-m-d H:i:s") . " ;\r\n";
           fwrite($myfile, $txt);
       }
   }
   ```

2. **Process Modified Products**:
   ```php
   $onlineTempProduct = $productExt->queryAllSimpleForCurlNormalSyncAndLock('', $joinConditionWithStore);
   if (count($onlineTempProduct) > 0) {
       // Process product images (up to 8 per product)
       foreach ($onlineTempProduct as $value) {
           $path = str_replace('\\', '/', getcwd()) . '/../views/default/images/product_image/';
           $value->logo_base64 = base64_encode(file_get_contents($path . $value->logo));
           $value->logo1_base64 = base64_encode(file_get_contents($path . $value->logo1));
           // ... through logo7_base64
       }
       
       $response = CURL_IT2($onlineTempProduct, $onlineStoreSetting->url . '/api_erp/syncEditedProductsFromERPCURL');
       if ((int) $response == 1) {
           $onlineTempProductEX->TRUNCATE();
       }
   }
   ```

---

### 2. **syncProductQuantityAndStoreReport - Inventory Sync**
**Location**: Line 283  
**Purpose**: Sync inventory quantities and store movement reports

**Process Flow**:
1. **Quantity Synchronization**:
   ```php
   $onlineTempStoreDetail = $productExt->queryAllOrderedLimitedSimpleForCurlNormal2('', $joinConditionWithStore);
   
   foreach ($onlineTempStoreDetail as $value) {
       // Calculate quantity based on store selection
       if (empty($onlineStoreSetting->availableStores)) {
           $value->quantity = 0;
       } else {
           $value->quantity = $value->sumProductQuantity;
       }
       
       // Encode images for quantity update
       $path = str_replace('\\', '/', getcwd()) . '/../views/default/images/product_image/';
       $value->logo_base64 = base64_encode(file_get_contents($path . $value->logo));
       // ... additional image encoding
   }
   
   $response = CURL_IT2($onlineTempStoreDetail, $onlineStoreSetting->url . '/api_erp/syncProductQuantityFromERPCURL');
   ```

2. **Store Report Synchronization**:
   ```php
   $onlineTempStoreReport = $onlineTempStoreReportEX->queryAllSimpleAndLockForCurl();
   if (count($onlineTempStoreReport) > 0) {
       $response = CURL_IT2($onlineTempStoreReport, $onlineStoreSetting->url . '/api_erp/insertNewStoreReportFromERPCURL');
       if ((int) $response == 1) {
           $onlineTempStoreReportEX->TRUNCATE();
       }
   }
   ```

---

### 3. **syncClientsDeptOnline - Customer Debt Sync**
**Location**: Line 335  
**Purpose**: Synchronize customer debt changes to online store

**Process Flow**:
1. Get last synchronized debt change ID
2. Query all debt changes after that ID
3. Send in batches to online store
4. Update synchronization pointer

**Implementation**:
php

if ($onlineStoreSetting->clientdebtchangeStartId >= 0) {

$last = $onlineStoreSetting->clientdebtchangeStartId;

} else {

// Get last ID from online store

$last = CURL_IT2($clientsDebtHistory, $onlineStoreSetting->url . '/api_erp/getLastClientDebtChangeIdInOnlineShop');

}

$clientsDebtHistory = $clientDeptChangeEX->getAllClientDeptChangeAfterId($id, ' and client.clientid != 1 ');

foreach ($clientsDebtHistory as $value) {

array_push($partOfClientsDebtHistory, $value);

CURL_IT($partOfClientsDebtHistory, $onlineStoreSetting->url . '/api_erp/updateClientsDebtFromERPCURL');

$partOfClientsDebtHistory = array();

}

---

### 4. **saveOnlineOrders - Order Processing**
**Location**: Line 365  
**Purpose**: Retrieve and process orders from online store

**Process Flow**:
1. **Retrieve Orders from Online Store**:
   ```php
   $allOrders = CURL_IT2(array(), $onlineStoreSetting->url . '/api_erp/ERPSendOrders');
   $allOrders = json_decode($allOrders);
   ```

2. **Process Each Order**:
   ```php
   foreach ($allOrders as $data_arr) {
       $the_order = $data_arr->order;
       $order_products = $data_arr->order_products;
       
       // Save/update order header
       $onlineTempOrder = $onlineTempOrderDAO->queryByOnlineorderid($the_order->id);
       $onlineTempOrder->customerid = getclientId($the_order->client, $onlineStoreSetting, $the_order->id, $the_order->customer_id);
       $onlineTempOrder->ordertotal = $the_order->order_total;
       $onlineTempOrder->shippingcost = $the_order->shipping_cost;
       // ... additional order fields
       
       if (isset($onlineTempOrder->id) && $onlineTempOrder->id > 0) {
           $onlineTempOrderDAO->update($onlineTempOrder);
       } else {
           $onlineTempOrderDAO->insert($onlineTempOrder);
       }
   }
   ```

3. **Process Order Products with Inventory Movement**:
   ```php
   $operationnum = getNextIdStoreMovement();
   foreach ($order_products as $value) {
       $onlineTempOrderProduct->productid = getProductId($value->product_data, $onlineStoreSetting);
       $onlineTempOrderProduct->quantity = $value->quantity;
       // ... save order product
       
       // Move inventory: main store โ†’ online store  
       moveProductFromStoreToAnother($onlineTempOrderProduct->productid, 
                                    $onlineTempOrderProduct->quantity, 
                                    $mainStoreId, $onlineStoreId, $operationnum);
   }
   ```

---

### 5. **getclientId() - Customer Management**
**Location**: Line 579  
**Purpose**: Get or create customer from online order data

**Function Signature**:
php

function getclientId($client_data, $onlineStoreSetting, $orderid, $customer_id)

**Process Flow**:
1. Check if customer has ERP ID (existing customer)
2. If not, create temporary customer record
3. Use default client area for new customers
4. Store customer data for later processing

---

### 6. **getProductId() - Product Management**
**Location**: Line 615  
**Purpose**: Get or create product from online order data

**Function Signature**:
php

function getProductId($product_data, $onlineStoreSetting)

**Process Flow**:
1. **Check Existing Product**:
   ```php
   $productId = (int) $product_data->erpid;
   if ($productId < 1) {
       // Product doesn't exist in ERP, create new
   }
   ```

2. **Create New Product**:
   ```php
   $product = $productDAO->queryByProductName($product_data->name);
   $parcode = generateParcode();
   removeParcodeFromTable($parcode);
   
   // Set product properties
   $product->productName = $product_data->name;
   $product->productCatId = getCatId($product_data->cat, $onlineStoreSetting);
   $product->productBuyPrice = $product_data->productBuyPrice;
   $product->parcode = $parcode;
   // ... additional properties
   
   $productId = $productDAO->insert($product);
   ```

3. **Handle Product Images**:
   ```php
   $success = file_put_contents('../views/default/images/product_image/' . $product_data->logo, 
                                base64_decode($product_data->logo_base64));
   // ... save additional images
   ```

4. **Create Supporting Records**:
   ```php
   // Product unit
   $productUnit->productid = $productId;
   $productUnit->unitid = 1;
   $productUnitDAO->insert($productUnit);
   
   // Store detail  
   $storeDetail->productid = $productId;
   $storeDetail->productquantity = 0;
   $storeDetailDAO->insert($storeDetail);
   
   // Store report
   $storeReport->processname = "ุฅุถุงูุฉ ู…ู†ุชุฌ";
   $storeReportDAO->insert($storeReport);
   ```

---

### 7. **getCatId() - Category Management**
**Location**: Line 744  
**Purpose**: Get or create category from online data

**Function Signature**:
php

function getCatId($cat_data, $onlineStoreSetting)

**Similar to getProductId() but for categories**:
- Check existing category by ERP ID
- Create new category if needed
- Handle category images
- Set up category relationships
- Sync back to online store

---

### 8. **Inventory Management Functions**

#### **moveProductFromStoreToAnother()**
**Location**: Line 1002  
**Purpose**: Transfer inventory between stores with full tracking

php

function moveProductFromStoreToAnother($productId, $transferproductAmount, $storeidfrom, $storeidto, $operationnum)

{

// Record the movement

$myStoremovement->productid = $productId;

$myStoremovement->transferproductamount = $transferproductAmount;

$myStoremovement->storeidfrom = $storeidfrom;

$myStoremovement->storeidto = $storeidto;

$myStoremovement->operationnum = $operationnum;

$transferproductId = $myStoremovementRecord->insert($myStoremovement);

// Decrease quantity in source store

$storedetailFromData = getStoredetailData($storeidfrom, $productId);

$productquantityFromAfter = decreaseProductQuantity($storedetailFromId,

$productquantityFromBefore,

$transferproductAmount);

// Increase quantity in destination store

$storedetailToData = getStoredetailData($storeidto, $productId);

$productquantityToAfter = increaseProductQuantity($storedetailToId,

$productquantityToBefore,

$transferproductAmount);

// Record both movements in store report

insertStorereport($productId, $storeidfrom, $transferproductAmount,

$productquantityFromBefore, $productquantityFromAfter,

1, $transferproductId, "ุชุญูˆูŠู„ ู…ู†ุชุฌุงุช ู…ู† ุงู„ู…ุฎุฒู†", "storemovementController.php");

insertStorereport($productId, $storeidto, $transferproductAmount,

$productquantityToBefore, $productquantityToAfter,

0, $transferproductId, "ุชุญูˆูŠู„ ู…ู†ุชุฌุงุช ุฅู„ู‰ ุงู„ู…ุฎุฒู†", "storemovementController.php");

}

#### **increaseProductQuantity() / decreaseProductQuantity()**
**Location**: Lines 919, 942  
**Purpose**: Modify store quantities with sync notification

php

function increaseProductQuantity($storedetailId, $productquantityBefore, $productChangeAmount)

{

$productquantityAfter = $productquantityBefore + $productChangeAmount;

// Update database

$myStoredetail = $myStoredetailRecord->load($storedetailId);

$myStoredetail->productquantity = $productquantityAfter;

$myStoredetailEx->updateProductquantity($myStoredetail);

// Trigger sync notification

onlineTempStoreDetailFunc($myStoredetail->storeid, $myStoredetail->productid,

0, 0, abs($productChangeAmount), 1);

return $productquantityAfter;

}

---

### 9. **Barcode Generation System**

#### **generateParcode()**
**Location**: Line 865  
**Purpose**: Generate unique product barcode

php

function generateParcode()

{

global $availableParcodeEX;

$parcode = $availableParcodeEX->getAvailableParcodeValue();

// Recursively check uniqueness

$data = checkbarcode($parcode);

if ($data != 2) {

$parcode = generateParcode(); // Recursive call

}

return $parcode;

}

#### **checkbarcode()**
**Location**: Line 814  
**Purpose**: Validate barcode uniqueness and format

php

function checkbarcode($parcode, $productId = 0)

{

if ($Programsettingdata->usedParcode == 0) {

// Check available barcode pool

$parcodeResult = $availableParcodeDAO->queryByValue($parcode);

if (isset($parcodeResult) && count($parcodeResult) > 0) {

return 2; // Available

}

}

// Check for duplicates in products

$data = $productExt->isParcodeRepated($parcode, $query);

return count($data) > 0 ? 1 : 2; // 1=duplicate, 2=unique

}

#### **removeParcodeFromTable()**
**Location**: Line 877  
**Purpose**: Remove used barcode from available pool

---

### 10. **Sync Helper Functions**

#### **CURL_IT() / CURL_IT2()**
**Location**: Lines 1081, 1109  
**Purpose**: Send data to online store with response handling

php

function CURL_IT2($data_arr, $url)

{

$post = ['data_arr' => json_encode($data_arr)];

$ch = curl_init($url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

$response = curl_exec($ch);

curl_close($ch);

return $response; // CURL_IT2 returns response, CURL_IT doesn't

}

---

## ๐Ÿ”„ Workflows

### Workflow 1: Real-time Change Synchronization

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ START: Real-time Sync Process โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 1. Check Change Queues โ”‚

โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚

โ”‚ โ”‚ Category Changes: โ”‚ โ”‚

โ”‚ โ”‚ - Query onlinetempcategory table โ”‚ โ”‚

โ”‚ โ”‚ - Lock records for processing โ”‚ โ”‚

โ”‚ โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ Product Changes: โ”‚ โ”‚

โ”‚ โ”‚ - Query onlinetempproduct table โ”‚ โ”‚

โ”‚ โ”‚ - Include store filter conditions โ”‚ โ”‚

โ”‚ โ”‚ - Lock records for processing โ”‚ โ”‚

โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 2. Process Category Changes โ”‚

โ”‚ IF categories have changes: โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Load category data with images โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Encode images to Base64 โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Send via CURL to online store โ”‚

โ”‚ โ”‚ โ””โ”€ POST to /api_erp/syncEditedCatsFromERPCURL โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Check response status โ”‚

โ”‚ โ”‚ โ”œโ”€ Success: Clear change queue โ”‚

โ”‚ โ”‚ โ””โ”€ Failure: Log error for retry โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ””โ”€โ†’ Continue to product processing โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 3. Process Product Changes โ”‚

โ”‚ IF products have changes: โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Load product data with store quantities โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Calculate quantities from selected stores โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Process multiple product images โ”‚

โ”‚ โ”‚ โ”œโ”€ Main product image (logo) โ”‚

โ”‚ โ”‚ โ””โ”€ Additional images (logo1-7) โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Encode all images to Base64 โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Send via CURL to online store โ”‚

โ”‚ โ”‚ โ””โ”€ POST to /api_erp/syncEditedProductsFromERPCURLโ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ””โ”€โ†’ Clear change queue if successful โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 4. Error Handling and Logging โ”‚

โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚

โ”‚ โ”‚ Success Path: โ”‚ โ”‚

โ”‚ โ”‚ - Clear processed change queues โ”‚ โ”‚

โ”‚ โ”‚ - Return "Done" status โ”‚ โ”‚

โ”‚ โ”‚ - Update last sync timestamp โ”‚ โ”‚

โ”‚ โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ Error Path: โ”‚ โ”‚

โ”‚ โ”‚ - Write to backup/[date].txt file โ”‚ โ”‚

โ”‚ โ”‚ - Preserve changes for retry โ”‚ โ”‚

โ”‚ โ”‚ - Log specific error details โ”‚ โ”‚

โ”‚ โ”‚ - Return error status โ”‚ โ”‚

โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

### Workflow 2: Online Order Processing and Fulfillment

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ START: Process Online Orders โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 1. Retrieve Orders from Online Store โ”‚

โ”‚ - Call online store API: /api_erp/ERPSendOrders โ”‚

โ”‚ - Parse JSON response โ”‚

โ”‚ - Extract order headers and line items โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 2. Process Each Order โ”‚

โ”‚ FOR EACH order in response: โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Extract order header data โ”‚

โ”‚ โ”‚ โ”œโ”€ Order ID, customer info โ”‚

โ”‚ โ”‚ โ”œโ”€ Totals, shipping, status โ”‚

โ”‚ โ”‚ โ””โ”€ Payment information โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Process customer information โ”‚

โ”‚ โ”‚ โ”œโ”€ Check if customer exists in ERP โ”‚

โ”‚ โ”‚ โ”œโ”€ Create/update customer record โ”‚

โ”‚ โ”‚ โ””โ”€ Handle customer area assignment โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ””โ”€โ†’ Save/update order header โ”‚

โ”‚ โ”œโ”€ Insert new orders โ”‚

โ”‚ โ””โ”€ Update existing orders โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 3. Process Order Line Items โ”‚

โ”‚ FOR EACH product in order: โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Validate/Create Product โ”‚

โ”‚ โ”‚ โ”œโ”€ Check if product exists in ERP โ”‚

โ”‚ โ”‚ โ”œโ”€ Create new product if needed โ”‚

โ”‚ โ”‚ โ”‚ โ”œโ”€ Generate barcode โ”‚

โ”‚ โ”‚ โ”‚ โ”œโ”€ Create category if needed โ”‚

โ”‚ โ”‚ โ”‚ โ”œโ”€ Save product images โ”‚

โ”‚ โ”‚ โ”‚ โ”œโ”€ Create store records โ”‚

โ”‚ โ”‚ โ”‚ โ””โ”€ Initialize inventory โ”‚

โ”‚ โ”‚ โ””โ”€ Get/assign ERP product ID โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ”œโ”€โ†’ Save order line item โ”‚

โ”‚ โ”‚ โ”œโ”€ Product ID, quantity, price โ”‚

โ”‚ โ”‚ โ”œโ”€ Shipping cost allocation โ”‚

โ”‚ โ”‚ โ””โ”€ Discount information โ”‚

โ”‚ โ”‚ โ”‚

โ”‚ โ””โ”€โ†’ Handle Inventory Movement โ”‚

โ”‚ โ”œโ”€ Get next operation number โ”‚

โ”‚ โ”œโ”€ Move inventory: main store โ†’ online store โ”‚

โ”‚ โ”œโ”€ Update store quantities โ”‚

โ”‚ โ”œโ”€ Record store movements โ”‚

โ”‚ โ””โ”€ Generate store reports โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 4. Inventory Allocation Process โ”‚

โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚

โ”‚ โ”‚ For Each Order Product: โ”‚ โ”‚

โ”‚ โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ Step 1: Get Inventory Data โ”‚ โ”‚

โ”‚ โ”‚ - Load current quantities from main store โ”‚ โ”‚

โ”‚ โ”‚ - Validate sufficient inventory โ”‚ โ”‚

โ”‚ โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ Step 2: Record Movement โ”‚ โ”‚

โ”‚ โ”‚ - Insert storemovement record โ”‚ โ”‚

โ”‚ โ”‚ - Set operation number for grouping โ”‚ โ”‚

โ”‚ โ”‚ - Link to order for tracking โ”‚ โ”‚

โ”‚ โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ Step 3: Update Source Store (Main) โ”‚ โ”‚

โ”‚ โ”‚ - Decrease quantity in main store โ”‚ โ”‚

โ”‚ โ”‚ - Record "outbound" store report โ”‚ โ”‚

โ”‚ โ”‚ - Update last process date โ”‚ โ”‚

โ”‚ โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ Step 4: Update Destination Store (Online) โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ - Increase quantity in online store โ”‚ โ”‚

โ”‚ โ”‚ - Record "inbound" store report โ”‚ โ”‚

โ”‚ โ”‚ - Trigger sync notification โ”‚ โ”‚

โ”‚ โ”‚ โ”‚ โ”‚

โ”‚ โ”‚ Step 5: Handle Store Creation โ”‚ โ”‚

โ”‚ โ”‚ - Create store record if doesn't exist โ”‚ โ”‚

โ”‚ โ”‚ - Initialize with transferred quantity โ”‚ โ”‚

โ”‚ โ”‚ - Record creation in store report โ”‚ โ”‚

โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ”‚

โ–ผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”

โ”‚ 5. Completion and Status Update โ”‚

โ”‚ - Update order processing status โ”‚

โ”‚ - Clear temporary order data โ”‚

โ”‚ - Return success confirmation โ”‚

โ”‚ - Trigger inventory sync if needed โ”‚

โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

## ๐ŸŒ URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|----------------|-------------|
| `do=syncCatAndProducts` | Real-time sync | Sync changed categories and products |
| `do=syncProductQuantityAndStoreReport` | Inventory sync | Sync quantities and store reports |
| `do=syncClientsDeptOnline` | Debt sync | Sync customer debt changes |
| `do=saveOnlineOrders` | Order processing | Process orders from online store |
| `do=autoSyncWithOnline` | Auto sync UI | Display auto-sync interface |
| `do=autoSyncWithOnlinCatAndProduct` | Category/Product UI | Auto-sync for categories/products |
| `do=autoSyncWithOnlinProductQuantity` | Quantity UI | Auto-sync for quantities |
| `do=updateonlineproductsFromTo` | Range sync | Sync products by ID range |
| `do=updateonlineclientsFromTo` | Range sync | Sync clients by ID range |
| `do=syncClientsDeptOnlineFromTo` | Range sync | Sync debt changes by ID range |

### Range Synchronization Parameters

**Product Range Sync** (`do=updateonlineproductsFromTo`):
- `from` - Starting product ID
- `afterFromId` - Whether to start after the from ID (0/1)
- `to` - Ending product ID  
- `tillEnd` - Sync to end of table (0/1)

**Client Range Sync** (`do=updateonlineclientsFromTo`):
- `from` - Starting client ID
- `afterFromId` - Whether to start after the from ID (0/1)
- `to` - Ending client ID
- `tillEnd` - Sync to end of table (0/1)

**Debt Range Sync** (`do=syncClientsDeptOnlineFromTo`):
- `from` - Starting debt change ID
- `afterFromId` - Whether to start after the from ID (0/1) 
- `to` - Ending debt change ID
- `tillEnd` - Sync to end of table (0/1)

---

## ๐Ÿงฎ Synchronization Logic

### Change Detection System
The system uses temporary tables to track changes:

php

// Categories: onlinetempcategory

// Products: onlinetempproduct

// Store quantities: onlinetempstoredetail

// Store reports: onlinetempstorereport

// Changes are queued when:

// 1. Category is modified

// 2. Product is modified

// 3. Inventory quantity changes

// 4. Store movements occur

### Store Inventory Calculation
php

if (empty($onlineStoreSetting->availableStores)) {

$value->quantity = 0; // No stores selected

} else {

$value->quantity = $value->sumProductQuantity; // Sum from selected stores

}

### Inventory Movement Logic
php

// Order fulfillment flow:

// 1. Customer places order online

// 2. System reserves inventory in main store

// 3. Transfers inventory to online store

// 4. Updates both store quantities

// 5. Records movements for audit

$mainStoreId = explode(',', $onlineStoreSetting->availableStores)[0];

$onlineStoreId = $onlineStoreSetting->onlinestoreid;

moveProductFromStoreToAnother($productId, $quantity, $mainStoreId, $onlineStoreId, $operationnum);

---

## ๐Ÿ”’ Security & Permissions

### Change Queue Security
- Queue tables prevent concurrent access issues
- Locking mechanisms during processing
- Transaction rollback on errors

### Data Validation
php

// Product creation validation

if (isset($product->productName) && $product->productName != "") {

// Only process if valid product name

}

// Barcode uniqueness validation

$data = checkbarcode($parcode);

if ($data != 2) {

$parcode = generateParcode(); // Generate new if not unique

}

### Access Control
- Session-based authentication required
- Admin permissions for sync operations
- Store access restrictions apply

---

## ๐Ÿ“Š Performance Considerations

### Batch Processing Optimization
1. **Real-time Processing**: Only process changed records
2. **Queue Management**: Clear queues after successful sync
3. **Error Recovery**: Preserve failed records for retry
4. **Image Processing**: Batch encode multiple images efficiently

### Memory Management
php

// Process images in batches to prevent memory exhaustion

foreach ($onlineTempProduct as $value) {

// Process 8 images per product

// Clear variables after each batch

}

### Database Performance
1. **Indexes Required**:
   - `onlinetempcategory(productCatId)`
   - `onlinetempproduct(productId)`
   - `onlinetempstoredetail(productid, storeid)`

2. **Queue Optimization**:
   - Regular queue cleanup
   - Efficient TRUNCATE operations
   - Proper locking mechanisms

---

## ๐Ÿ› Common Issues & Troubleshooting

### 1. **Sync Queue Buildup**
**Issue**: Change queues grow but don't process  
**Cause**: Network issues or online store downtime

**Solutions**:
php

// Check queue sizes

SELECT COUNT(*) FROM onlinetempcategory;

SELECT COUNT(*) FROM onlinetempproduct;

// Manual queue cleanup (if needed)

TRUNCATE onlinetempcategory;

TRUNCATE onlinetempproduct;

### 2. **Image Processing Failures**
**Issue**: Products sync but images missing  
**Cause**: File path issues or corrupted images

**Debug**:
php

// Check image path resolution

$path = str_replace('\\', '/', getcwd()) . '/../views/default/images/product_image/';

echo "Image path: " . $path . "\n";

// Check file existence

if (!file_exists($path . $value->logo)) {

echo "Missing image: " . $value->logo . "\n";

}

### 3. **Inventory Discrepancies**
**Issue**: Online store quantities don't match ERP  
**Cause**: Failed inventory movements or store filter issues

**Debug Queries**:
sql

-- Check store detail quantities

SELECT sd.productid, sd.storeid, sd.productquantity

FROM storedetail sd

WHERE sd.productid = [PRODUCT_ID];

-- Check store movements

SELECT * FROM storemovement

WHERE productid = [PRODUCT_ID]

ORDER BY transferproductdate DESC;

-- Check online store settings

SELECT availableStores FROM onlinestoresetting WHERE id = 1;

### 4. **Order Processing Failures**
**Issue**: Orders not creating products/customers  
**Cause**: Missing category data or barcode generation issues

**Debug**:
php

// Check barcode generation

$parcode = generateParcode();

echo "Generated barcode: " . $parcode . "\n";

// Check category creation

echo "Category ID: " . getCatId($cat_data, $onlineStoreSetting) . "\n";

---

## ๐Ÿงช Testing Scenarios

### Test Case 1: Real-time Sync

1. Modify a category in ERP

2. Verify entry in onlinetempcategory table

3. Run syncCatAndProducts

4. Verify queue cleared and category updated online

5. Repeat for products

### Test Case 2: Order Processing

1. Create test order in online store

2. Run saveOnlineOrders

3. Verify order appears in onlinetemporder

4. Check customer creation/mapping

5. Verify inventory movements

6. Check store quantities updated

### Test Case 3: Inventory Sync

1. Change product quantity in ERP store

2. Verify entry in onlinetempstoredetail

3. Run syncProductQuantityAndStoreReport

4. Verify online store quantity updated

5. Check store reports generated

### Test Case 4: Range Synchronization

1. Use updateonlineproductsFromTo with specific range

2. Verify only products in range synchronized

3. Test afterFromId and tillEnd flags

4. Check performance with large ranges

```

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur