BLogic Systems

Menu Sync Implementation

Last updated on 

Menu sync Implementation

1. Preface

  • Before implementing this approach, it is important to follow certain rules.
  • To ensure data correctness, we need to use transactions when updating the database.
  • Because Record ID might match went we storage it in Central Database. So the primary key will be the pair key (RecordID, StoreID)
  • This implementation uses the merging data approach, where we combine the data from the local and server sources based on the Record ID and Record UpdatedAt criteria.
  • On Cloud we will remove all foreign keys for tables (because we using pair primary key [ID, StoreID] so using foreign key constrant might strict some correct record inserted)

2. Data Center Endpoints

  • Supported tables:
        "autoSendMesssage"
        "bulkDetails"
        "bulks"
        "buttonInfo"
        "forceModifierTemplates"
        "initParams"
        "itemDepartmentModifiers"
        "itemGroups"
        "itemCategories"
        "items"
        "itemKitchenDetails"
        "itemLocations"
        "itemPriceLevels"
        "itemStoreDetails"
        "itemTimePrices"
        "itemTypes"
        "itemVendorDetails"
        "modifiers"
        "modifierGroups"
        "purchaseOrderDetails"
        "purchaseOrders"
        "saleTypes"
        "specialItems"
        "stores"
        "taxAuthorities"
        "taxCodeDetails"
        "taxCodes"
        "timePriceDetails"
        "timePrices"
        "vendors"
        "auditImages"
        "GlobalPriceLevels"
        "ItemKDSDetails"
        "KDSPrinter"
        "Kitchens"
        "LabelPrinter"
        "ServiceCharge"

Sync Menu Endpoint Usages

  • URL: {{host}}/api/menus/sync
  • HEADER: Method: POST, Content-Type: multipart/form-data
    • lastSyncDate: Last time the POS server synced
    • storeID: ID of the store
    • other properties: The key represents the table name, and the value is an array of all changed data since the lastSyncDate.
    • imageFiles: List of files
  • Response:

Body Contents:

// Request
{
      "lastSyncDate": "2023-06-21T16:52:42.8865722+07:00",
      "storeID": "11111",
      "autoSendMesssage": [],
      "bulkDetails": null,
      "bulks": null,
      "buttonInfo": null,
      "forceModifierTemplates": null,
      "initParams": null,
      "itemDepartmentModifiers": null,
      "itemGroups": null,
      "itemCategories": null,
      "items": null,
      "itemKitchenDetails": null,
      "itemLocations": null,
      "itemPriceLevels": null,
      "itemStoreDetails": null,
      "itemTimePrices": null,
      "itemTypes": null,
      "itemVendorDetails": null,
      "modifiers": null,
      "modifierGroups": null,
      "purchaseOrderDetails": null,
      "purchaseOrders": null,
      "saleTypes": null,
      "specialItems": null,
      "stores": null,
      "taxAuthorities": null,
      "taxCodeDetails": null,
      "taxCodes": null,
      "timePriceDetails": null,
      "timePrices": null,
      "vendors": null,
          "auditImages": null,
          "imageFiles": null
  }
  // Response
{
      "lastSyncDate": "2023-06-21T16:52:42.8865722+07:00",
      "storeID": "11111",
      "autoSendMesssage": [],
      "bulkDetails": null,
      "bulks": null,
      "buttonInfo": null,
      "forceModifierTemplates": null,
      "initParams": null,
      "itemDepartmentModifiers": null,
      "itemGroups": null,
      "itemCategories": null,
      "items": null,
      "itemKitchenDetails": null,
      "itemLocations": null,
      "itemPriceLevels": null,
      "itemStoreDetails": null,
      "itemTimePrices": null,
      "itemTypes": null,
      "itemVendorDetails": null,
      "modifiers": null,
      "modifierGroups": null,
      "purchaseOrderDetails": null,
      "purchaseOrders": null,
      "saleTypes": null,
      "specialItems": null,
      "stores": null,
      "taxAuthorities": null,
      "taxCodeDetails": null,
      "taxCodes": null,
      "timePriceDetails": null,
      "timePrices": null,
      "vendors": null,
      "auditImages" : null
  }
  • lastSyncDate: Time Server finish sync
  • storeID: ID of the store
  • other properties: The key represents the table name, and the value is an array of the merged list.

3. Workflow

Overview of the workflow - The POS server must persistently save the LastSyncDate field, which represents the last time we synced. - The POS server sends the records that have been updated/created since the last sync. - The Data Center compares the received list with its local database to determine which records are newly created and which ones are updated. - The Data Center queries the records that have been updated/created since the last sync. - Finally, the Data Center merges the two lists (the list changed from the POS and the list changed from the Data Center) into one, considering only the latest changes. - The merged list will be filter to get update records List from server - The update records List from server is then sent back to the POS server. - The POS server takes the update records and updates its database accordingly. - The POS server update LastSyncDate

sync_implement.drawio.png

## 4. Scalability This scalability is applicable to the Data Center Sync endpoint. - Adding new tables to sync is straightforward if you follow a few steps: - Add a new table to the database, (Note add StoreID as Primary key). - Create an entity class. Example C# [Table("[pos].[ItemTypes]")] [PrimaryKeyAttribute(Key = "ItemTypeCode")] public class ItemTypeEntity : IMenuComponent { [ExplicitKey] public string ItemTypeCode { get; set; } [ExplicitKey] public string StoreID { get; set; } public string ItemTypeName { get; set; } public string Description { get; set; } public DateTime UpdatedAt { get; set; } public bool IsDeleted { get; set; } } - Add the new table and entity class to the syncOrder Collection in the SyncService class. Note that the new table should follow the sync order since a relational database is used. - Add the table property in Menu_Sync_Request. Follow the convention of making the property’s key the same as the table name. - Run and test the result.

5. Testing

This section describes the ways to test the Sync endpoint: - Postman is used to test this endpoint. You can check out some predefined cases in this file (please import it into your postman) - Some seeder endpoints have also been created to assist in testing. - After importing, your Postman should appear as shown in the following screenshot:

postman-test-sync.png
postman-test-sync.png

Cases I’ve tested:

Case: Sync 35 tables (Full table)

Descriptions: - Sync up means pushing the changes to the server. - Sync down means pulling the changes from the server. 1. Sync up Create Full table - Call 5/ Sync Up All Created 2. Sync up Update Full table - Call 6/ Sync Up All Updated 3. Sync down Create Full table - Call Seeder/5_Create ALL Entities - Call 3/ Sync Down All Created 4. Sync down Update Full table - Call Seeder/6_Update ALL Entities - Call 4/ Sync Down All Updated 5. Sync up + down Create - Call Seeder/5_Create ALL Entities - Call 6/ Sync Up + Down All Created 6. Sync up + down Update - Call Seeder/6_Update ALL Entities - Call 6/ Sync Up + Down All Updated