/
Product Sync : Woo-commerce

Product Sync : Woo-commerce

Step 1: Enable Auto-Import in Eshopbox

When a seller toggle on the auto-import of products , and configure the below settings-

  • Map the tax classes of Woocommerce with those of Eshopbox. You can also select the default tax code for your products. If the tax code is not the same for all products, then leave it blank.

    • image-20240301-054609.png

      The mapped tax classes will be saved in DB.

  • The HSN code is not a default field saved with the WooCommerce product catalog. If seller has selected the HSN code attribute while creating a product then will mention the same here. If there are no attributes, can select the default HSN code of the products. If the HSN code is not the same for all products, then leave it blank


    image-20240301-054740.png

Once the configurations are saved will register webhook for products.

Create Webhook URL:

POST https://woo-casually-quality-runaway.wpcomstaging.com/wp-json/wc/v3/webhooks

Request Body:

{   "name": "Product created/Product updated/Product deleted",   "topic": "product.created/product.updated/product.deleted",   "delivery_url": "https://default-dot-esb-integration-engine-staging.appspot.com/_ah/api/esb/v3/woocommerce-productwebhook/{connectionId}" }

 

Whenever event will be triggered on the delivery URL:

  • The Woocommerce catalog comprises four types of products, out of which simple, variable and bundle products are synced in the Eshopbox catalog. The products in Woocommerce have three publishing status, namely Draft, Pending Review, and Published. All products, regardless of their status, will be pulled into the catalog.

     

{ "id": 66, "name": "New-ArrivalBag", "slug": "new-arrivalbag", "permalink": "https://woo-casually-quality-runaway.wpcomstaging.com/product/new-arrivalbag/", "date_created": "2023-12-06T20:02:30", "date_created_gmt": "2023-12-06T14:32:30", "date_modified": "2023-12-06T20:02:30", "date_modified_gmt": "2023-12-06T14:32:30", "type": "simple", "status": "publish", "featured": false, "catalog_visibility": "visible", "description": "\u003cp\u003e\u003cimg class\u003d\"alignnone size-medium wp-image-67\" src\u003d\"https://woo-casually-quality-runaway.wpcomstaging.com/wp-content/uploads/2023/12/fashionbag-300x300.jpg\" alt\u003d\"\" width\u003d\"300\" height\u003d\"300\" /\u003e\u003c/p\u003e\n", "short_description": "\u003cp\u003eNew fashionable bags in store\u003cbr /\u003e\n[contact-form]\u003c/p\u003e\n", "sku": "Newbag", "price": "1800", "regular_price": "1800", "sale_price": "", "on_sale": false, "purchasable": true, "total_sales": 0, "virtual": false, "downloadable": false, "downloads": [], "download_limit": -1, "download_expiry": -1, "external_url": "", "button_text": "", "tax_status": "taxable", "tax_class": "", "manage_stock": false, "backorders": "no", "backorders_allowed": false, "backordered": false, "sold_individually": false, "weight": "0.5", "dimensions": { "length": "12", "width": "13", "height": "14" }, "shipping_required": true, "shipping_taxable": true, "shipping_class": "", "shipping_class_id": 0, "reviews_allowed": true, "average_rating": "0.00", "rating_count": 0, "upsell_ids": [], "cross_sell_ids": [], "parent_id": 0, "purchase_note": "", "categories": [ { "id": 1375, "name": "Women", "slug": "women" } ], "tags": [], "images": [ { "id": 67, "date_created": "2023-12-07T01:30:00", "date_created_gmt": "2023-12-06T14:30:00", "date_modified": "2023-12-07T01:30:00", "date_modified_gmt": "2023-12-06T14:30:00", "src": "https://woo-casually-quality-runaway.wpcomstaging.com/wp-content/uploads/2023/12/fashionbag.jpg", "name": "fashionbag", "alt": "" } ], "attributes": [], "default_attributes": [], "variations": [], "grouped_products": [], "menu_order": 0, "price_html": "\u003cspan class\u003d\"woocommerce-Price-amount amount\"\u003e\u003cbdi\u003e\u003cspan class\u003d\"woocommerce-Price-currencySymbol\"\u003e\u0026#36;\u003c/span\u003e1,800.00\u003c/bdi\u003e\u003c/span\u003e", "related_ids": [ 27, 25, 26, 24 ], "meta_data": [ { "id": 346, "key": "_wpcom_is_markdown", "value": "1" }, { "id": 347, "key": "_last_editor_used_jetpack", "value": "classic-editor" }, { "id": 355, "key": "_product_addons", "value": [] }, { "id": 356, "key": "_product_addons_exclude_global", "value": "0" }, { "id": 372, "key": "group_of_quantity", "value": "" }, { "id": 373, "key": "minimum_allowed_quantity", "value": "" }, { "id": 374, "key": "maximum_allowed_quantity", "value": "" }, { "id": 375, "key": "minmax_do_not_count", "value": "no" }, { "id": 376, "key": "minmax_cart_exclude", "value": "no" }, { "id": 377, "key": "minmax_category_group_of_exclude", "value": "no" }, { "id": 385, "key": "_wpas_done_all", "value": "1" } ], "stock_status": "instock", "has_options": false, "post_password": "", "bundled_by": [], "bundle_stock_status": "instock", "bundle_virtual": false, "bundle_layout": "", "bundle_add_to_cart_form_location": "", "bundle_editable_in_cart": false, "bundle_sold_individually_context": "", "bundle_item_grouping": "", "bundle_min_size": "", "bundle_max_size": "", "bundle_price": [], "bundled_items": [], "bundle_sell_ids": [], "jetpack_publicize_connections": [], "jetpack_sharing_enabled": true, "jetpack_likes_enabled": true, "brands": [], "_links": { "self": [ { "href": "https://woo-casually-quality-runaway.wpcomstaging.com/wp-json/wc/v3/products/66" } ], "collection": [ { "href": "https://woo-casually-quality-runaway.wpcomstaging.com/wp-json/wc/v3/products" } ] } }

 

  • We will log the response received and push it in taskqueue, their will be a taskqueue listener in default service which will process and pass it to pubsub topic.

    • listener/woocommerceproducts

The delivery URL : https://default-dot-esb-integration-engine-staging.appspot.com/_ah/api/esb/v3/woocommerce-productwebhook/connectionId
has parameter connectionId actual identifier of the connection for which you want to receive product import data.

  • We will get the connectionId from the endpoint to fetch the authentication token details and also against which account, we have to create a product.

Will execute the below query to fetch the connections details againts which we have received an event

SELECT ie_appinstall_connection.id AS connectionId, ie_appinstall_connection.inputFields, ie_app_automation_steps.id AS appAutomationStepId, ie_app_automation_steps.appId, ie_app_automation_steps_config.isActive, ie_app_automation_steps_config.latestSyncTimeStamp AS latestSyncTimeStamp, ie_appinstall_connection.isActive AS appIsActive, ie_app_automation_steps.otherDetails FROM ie_appinstall_connection LEFT JOIN ie_app_installation ON ie_app_installation.appInstallationId = ie_appinstall_connection.appInstallationId LEFT JOIN ie_app ON ie_app.appId = ie_app_installation.appId LEFT JOIN ie_app_automation_steps ON ie_app_automation_steps.appId = ie_app.appId LEFT JOIN ie_app_automation_steps_config ON ie_app_automation_steps_config.connectionId = ie_appinstall_connection.id AND ie_app_automation_steps_config.appAutomationStepId = ie_app_automation_steps.id WHERE ie_appinstall_connection.id IN (:connectionId) AND ie_app_automation_steps_config.isActive = '1';

 

for that connection run the below query to fetch the channel Data

  • Fetches channel data from cache, if not in cache it fetches data from Database.

  • .String cacheKey = connection_channeldata + connectionId;

SELECT accounts.account_slug AS accountSlug, channels.connectionId AS connectionId, channels.externalChannelId AS externalChannelId, external_wms_channels.locationId AS locationId, warehouses.externalWarehouseId AS externalWareHouseId FROM channels LEFT JOIN external_wms_channels ON channels.id = external_wms_channels.channel_id LEFT JOIN warehouses ON warehouses.id = external_wms_channels.warehouse_id LEFT JOIN accounts ON channels.account_id = accounts.id LEFT JOIN channel_account_mapping ON channel_account_mapping.external_wms_channel_id = external_wms_channels.id WHERE channels.connectionId = :connectionId AND channel_account_mapping.enrollmentStatus = 'ACTIVE';

Channel connection map object:

{ "channelData": { "integrationType": "", "externalChannelId": " ", "accountSlug": " ", "connectionId": " ", "isActive": "active", "inputFields": { "consumer_key": "harshitaeshop", "consumer_secret": "harshita@123" } "otherDetails": { "taxCode" : { "WOO_CLASS1":"ESBHH1", "WOO_CLASS2":"ESBHH1", "WOO_CLASS3":"ESBHH2" }, } } } }

 

We will push the channel connection data in the middlelayer along with product details received from webhook event and create products in WMS.

Before creating product in Eshopbox we have to check that if attributes.variation= true and variation list is not empty then call the API for each variations.

Variant cases:

If in products response we get key type=”variable” and also “attributes.variations” is “true” then, iterate through each variations and fetch the product details for each

"variations": [ 64, 63, 62 ]

 

Iterate through each variationId and call API for each variantId

variations API for each variationId

https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/<product_id>/variations/<id>

Response

{ "id": 78, "date_created": "2023-12-21T11:03:24", "date_created_gmt": "2023-12-21T05:33:24", "date_modified": "2023-12-21T11:09:51", "date_modified_gmt": "2023-12-21T05:39:51", "description": "", "permalink": "https://woo-briskly-different-dinosaur.wpcomstaging.com/product/jacket-new/?attribute_size=M", "sku": "jacketcheckM", "price": "230", "regular_price": "234", "sale_price": "230", "date_on_sale_from": null, "date_on_sale_from_gmt": null, "date_on_sale_to": null, "date_on_sale_to_gmt": null, "on_sale": true, "status": "publish", "purchasable": true, "virtual": false, "downloadable": false, "downloads": [], "download_limit": -1, "download_expiry": -1, "tax_status": "taxable", "tax_class": "", "manage_stock": true, "stock_quantity": 20, "stock_status": "instock", "backorders": "no", "backorders_allowed": false, "backordered": false, "low_stock_amount": null, "weight": "1", "dimensions": { "length": "12", "width": "13", "height": "14" }, "shipping_class": "", "shipping_class_id": 0, "image": null, "attributes": [ { "id": 0, "name": "size", "slug": "size", "option": "M" } ], "menu_order": 1, "meta_data": [ { "id": 734, "key": "_gift_card_template_default_use_image", "value": "product" }, { "id": 740, "key": "min_max_rules", "value": "no" }, { "id": 741, "key": "variation_group_of_quantity", "value": "" }, { "id": 742, "key": "variation_minimum_allowed_quantity", "value": "" }, { "id": 743, "key": "variation_maximum_allowed_quantity", "value": "" }, { "id": 744, "key": "variation_minmax_do_not_count", "value": "no" }, { "id": 745, "key": "variation_minmax_cart_exclude", "value": "no" }, { "id": 746, "key": "variation_minmax_category_group_of_exclude", "value": "no" } ], "name": "M", "parent_id": 77, "_links": { "self": [ { "href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/77/variations/78" } ], "collection": [ { "href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/77/variations" } ], "up": [ { "href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/77" } ] } }

In this case for every variant will get unique SKU accordingly will create the product in Eshopbox.

If the SKU is blank, Eshopbox will use the Woocommerce unique ID of the product with the prefix "woo-" as the SKU.

To Create or Update Product -

Step 1 : Check if product exist or not in Eshopbox based on “active” inventoryItem Id from listing table and if it exist then update the Product else Create new Product in Eshopbox.

We will pass the list of itemId to check the status of itemId which we receive

SELECT * FROM listings WHERE itemID = 'SDL490996946' AND channel_id = 2710 AND STATUS = "ACTIVE"

Case 1 : If record exist from the above query, then update the Product in Eshopbox.

Update Product API:

PUT : https://{workspace}.myeshopbox.com/product-engine/api/v1/products/{sku}

Request Body:

{ "imageUrl": "https://cdn.filestackcontent.com/hdYluVCqSADCASjjjcuaeC", "mrp": 1499.0, "unitPrice": 799.0, "hsnCode": "6101112", "weight": 167.0, "dimensionLength": 5.0, "dimensionWidth": 5.0, "dimensionHeight": 5.0, "dimensionUnit": "cm" }'
  • In case dimensions are updated in Woocommerce, the corresponding dimensions will be updated in Eshopbox, if Weight and dimensions are not verified.

  • According to Product and Inventory Team,Dimension and product Images are not update when ProductWeightVerification status is in inverification status other then this user is allowed to change the Dimension of the product

  • Case 2 i) : Else, check product exist in Eshopbox or not,

    • https://{workspace}.myeshopbox.com/product-engine/api/v1/products

If product exist will get Esin in response and mark the product available in Eshopbox.

{ "87162143127": { "esin": "0SGAT12SG25F", "brand": "Kapas Kraft" }, "623731HSHS": { "esin": "7HASI6ASDJ8S", "brand": "Kapas Kraft" } }

 

Mark Product Availability:

POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk

Request Body

{ "channelCode": "CH1234", "availability": true, "productMap": [ { "ESIN": { "sellersku": "sku", "productId_variantId/productId": "key" }, "ESIN1" :{ "sellersku": "sku", "productId_variantId/productId": "key" } } ] }

We will save the mark available response body and when will create the products will together mark it as avaialble.

ii) : If product does not exist in Eshopbox create product.

Check the configuration of product sync for that connection saved in otherDetails which are fetched already and saved in channel Object.

"otherDetails": { "taxCode" : { "WOO_CLASS1":"ESBHH1", "WOO_CLASS2":"ESBHH1", "WOO_CLASS3":"ESBHH2" }, }

 

 

Create a Product:

POST https://{workspace}.myeshopbox.com/product-engine/api/v1/products

 

Mapping for creating product in WMS

Eshopbox Keys

Woocommerce Identifier

Eshopbox Keys

Woocommerce Identifier

sku

sku -in case of simple product
variations.sku in case of variable product

imageurl

images[0].src in case of simple product

In case of variable product, usevariations.images[0].src if it is not blank else use images[0].src

description

description

mrp

regular_price

dimensionwidth

dimensions.width(cm) retrieve units from setting API and convert to cm. For variable product, if not available use parents product

dimensionheight

dimensions.height(cm) retrieve units from setting API and convert to cm. For variable product, if not available use parents product

dimensionlenght

dimensions.length(cm)retrieve units from setting API and convert to cm. For variable product, if not available use parents product

weight

"weight"(kg) retrieve units from setting API. For variable product, if not available use parents products

hsnc

Attribute as selected in app settings

taxcode

"tax class" and check the value saved in otherdetails with respect to eshopbox

properties.{Woo}_slug

slug

properties.{Woo}_sku

sku in case of simple product
variations.sku in case of variable product

dimensionUnit

cm

brand

tag.name

type

base

 

Mark Product Availability:

POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk

Request Body

{ "channelCode": "CH1234", "availability": true, "productMap": [ { "ESIN": { "sellersku": "sku", "productId_variantId/productId": "key" }, "ESIN1" :{ "sellersku": "sku", "productId_variantId/productId": "key" } } ] }

 

Similarly if there are updates in fields in Eshopbox workspace, corresponding product should be updated in Woocommerce catalog then will update it in Woocommerce whenever will receieve event from of update product from WMS by the productId will update it in woocommerce also.

Update Product API in woocommerce

In request body will mention the fields which need to be updated in woocommerce

PUT https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/<product_id> -u consumer_key:consumer_secret -H "Content-Type: application/json" -d ' { "sku": "trouser", "regular_price": "180" }

Response

{ "id": 84, "name": "Trouser", "slug": "trouser", "permalink": "https://woo-briskly-different-dinosaur.wpcomstaging.com/product/trouser/", "date_created": "2023-12-21T18:40:19", "date_created_gmt": "2023-12-21T13:10:19", "date_modified": "2023-12-27T15:39:29", "date_modified_gmt": "2023-12-27T10:09:29", "type": "simple", "status": "publish", "featured": false, "catalog_visibility": "visible", "description": "Trouser", "short_description": "", "sku": "trouser", "price": "99", "regular_price": "180", "sale_price": "99", "date_on_sale_from": null, "date_on_sale_from_gmt": null, "date_on_sale_to": null, "date_on_sale_to_gmt": null, "on_sale": true, "purchasable": true, "total_sales": 1, "virtual": false, "downloadable": false, "downloads": [], "download_limit": -1, "download_expiry": -1, "external_url": "", "button_text": "", "tax_status": "taxable", "tax_class": "", "manage_stock": true, "stock_quantity": 26, "backorders": "no", "backorders_allowed": false, "backordered": false, "low_stock_amount": null, "sold_individually": false, "weight": "", "dimensions": { "length": "", "width": "", "height": "" }, "shipping_required": true, "shipping_taxable": true, "shipping_class": "", "shipping_class_id": 0, "reviews_allowed": true, "average_rating": "0", "rating_count": 0, "upsell_ids": [], "cross_sell_ids": [], "parent_id": 0, "purchase_note": "", "categories": [ { "id": 1374, "name": "Men", "slug": "men" } ], "tags": [], "images": [], "attributes": [], "default_attributes": [], "variations": [], "grouped_products": [], "menu_order": 0, "price_html": "<del aria-hidden=\"true\"><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#8377;</span>180.00</bdi></span></del> <ins><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#8377;</span>99.00</bdi></span></ins>", "related_ids": [ 77, 24, 60, 27, 70 ], "meta_data": [ { "id": 754, "key": "_last_editor_used_jetpack", "value": "classic-editor" }, { "id": 758, "key": "_product_addons", "value": [] }, { "id": 759, "key": "_product_addons_exclude_global", "value": "0" }, { "id": 775, "key": "group_of_quantity", "value": "" }, { "id": 776, "key": "minimum_allowed_quantity", "value": "" }, { "id": 777, "key": "maximum_allowed_quantity", "value": "" }, { "id": 778, "key": "minmax_do_not_count", "value": "no" }, { "id": 779, "key": "minmax_cart_exclude", "value": "no" }, { "id": 780, "key": "minmax_category_group_of_exclude", "value": "no" }, { "id": 785, "key": "_wpas_done_all", "value": "1" }, { "id": 800, "key": "_wpcom_is_markdown", "value": "1" } ], "stock_status": "instock", "has_options": false, "post_password": "", "permalink_template": "https://woo-briskly-different-dinosaur.wpcomstaging.com/product/%pagename%/", "generated_slug": "trouser", "bundled_by": [], "bundle_stock_status": "instock", "bundle_stock_quantity": 26, "bundle_virtual": false, "bundle_layout": "", "bundle_add_to_cart_form_location": "", "bundle_editable_in_cart": false, "bundle_sold_individually_context": "", "bundle_item_grouping": "", "bundle_min_size": "", "bundle_max_size": "", "bundled_items": [], "bundle_sell_ids": [], "jetpack_publicize_connections": [], "jetpack_sharing_enabled": true, "jetpack_likes_enabled": true, "brands": [ { "id": 1377, "name": "ray", "slug": "ray" } ], "_links": { "self": [ { "href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/84" } ], "collection": [ { "href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products" } ] } }

 

Delete Product if it is deleted in Woocommerce Mark it unavailble in Eshopbox.

In case we recieved event for delete product through webhook on delete delivery url.

Response:

{ "id": 794, "name": "Premium Quality", "slug": "premium-quality-19", "permalink": "https://example.com/product/premium-quality-19/", "date_created": "2017-03-23T17:01:14", "date_created_gmt": "2017-03-23T20:01:14", "date_modified": "2017-03-23T17:01:14", "date_modified_gmt": "2017-03-23T20:01:14", "type": "simple", "status": "deleted", "featured": false, "catalog_visibility": "visible", "description": "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>\n", "short_description": "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>\n", "sku": "", "price": "24.54", "regular_price": "24.54", "sale_price": "", "date_on_sale_from": null, "date_on_sale_from_gmt": null, "date_on_sale_to": null, "date_on_sale_to_gmt": null, "price_html": "<span class=\"woocommerce-Price-amount amount\"><span class=\"woocommerce-Price-currencySymbol\">&#36;</span>24.54</span>", "on_sale": false, "purchasable": true, "total_sales": 0, "virtual": false, "downloadable": false, "downloads": [], "download_limit": -1, "download_expiry": -1, "external_url": "", "button_text": "", "tax_status": "taxable", "tax_class": "", "manage_stock": false, "stock_quantity": null, "stock_status": "instock", "backorders": "no", "backorders_allowed": false, "backordered": false, "sold_individually": false, "weight": "", "dimensions": { "length": "", "width": "", "height": "" }, "shipping_required": true, "shipping_taxable": true, "shipping_class": "", "shipping_class_id": 0, "reviews_allowed": true, "average_rating": "0.00", "rating_count": 0, "related_ids": [ 479, 387, 22, 463, 396 ], "upsell_ids": [], "cross_sell_ids": [], "parent_id": 0, "purchase_note": "", "categories": [ { "id": 9, "name": "Clothing", "slug": "clothing" }, { "id": 14, "name": "T-shirts", "slug": "t-shirts" } ], "tags": [], "images": [ { "id": 792, "date_created": "2017-03-23T14:01:13", "date_created_gmt": "2017-03-23T20:01:13", "date_modified": "2017-03-23T14:01:13", "date_modified_gmt": "2017-03-23T20:01:13", "src": "https://example.com/wp-content/uploads/2017/03/T_2_front-4.jpg", "name": "", "alt": "" }, { "id": 793, "date_created": "2017-03-23T14:01:14", "date_created_gmt": "2017-03-23T20:01:14", "date_modified": "2017-03-23T14:01:14", "date_modified_gmt": "2017-03-23T20:01:14", "src": "https://example.com/wp-content/uploads/2017/03/T_2_back-2.jpg", "name": "", "alt": "" } ], "attributes": [], "default_attributes": [], "variations": [], "grouped_products": [], "menu_order": 0, "meta_data": [], "_links": { "self": [ { "href": "https://example.com/wp-json/wc/v3/products/794" } ], "collection": [ { "href": "https://example.com/wp-json/wc/v3/products" } ] } }

We will pass the data to taskqueue and fetch all the connectionId with channeldata details and pass it in pubsub and delete/mark unavailable the product on Eshopbox.

In case of product is deleted ,mark it as unavailable by calling unavailability API.

Mark Product UnAvailability:

POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing

Request Body

{ "channelCode": "CH1234", "availability": false, "productMap": [ { "ESIN": { "sellersku": "sku", "productId_variantId/productId": "key" }, "ESIN1" :{ "sellersku": "sku", "productId_variantId/productId": "key" } } ] }

 

 

 

CRON to Create Product :

GET https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products?modified_after=2024-03-01T06:00:31

We pass modified_after date in parameter to sync the product if their is any update in that, which will be the latestsynctimestamp in Eshopbox.

 

Step 1: Cron Endpoint /_ah/api/esb/v1/woocommerce/productupdate/sync

Use-case: It fetches the active connectionIds:

SELECT channels.connectionId FROM channels WHERE integrationType= 18

Fetch the Connections data for all connectionId’s where stepId for product Update Sync is on.Push the data to taskqueue.

 

SELECT ie_appinstall_connection.id AS connectionId, ie_appinstall_connection.accessToken AS accessToken, ie_appinstall_connection.inputFields, ie_app_automation_steps.id AS appAutomationStepId, ie_app_automation_steps.appId, ie_app_automation_steps_config.isActive, ie_app_automation_steps_config.otherDetails AS otherDetails, ie_app_automation_steps_config.latestSyncTimeStamp AS latestSyncTimeStamp, ie_app.clientId AS appClientId, ie_app.userName AS appWmsUserName, ie_appinstall_connection.isActive AS appIsActive FROM ie_appinstall_connection LEFT JOIN ie_app_installation ON ie_app_installation.appInstallationId = ie_appinstall_connection.appInstallationId LEFT JOIN ie_app ON ie_app.appId = ie_app_installation.appId LEFT JOIN ie_app_automation_steps ON ie_app_automation_steps.appId = ie_app.appId LEFT JOIN ie_app_automation_steps_config ON ie_app_automation_steps_config.connectionId = ie_appinstall_connection.id AND ie_app_automation_steps_config.appAutomationStepId = ie_app_automation_steps.id WHERE ie_appinstall_connection.id IN (:connectionIds) AND ie_app_automation_steps.id = :stepId AND ie_app_automation_steps_config.isActive = 1;

Step 3:TaskQueue Listener: /_ah/api/esb/v1/productupdate/cron/listener

For Active connectionId it fetches their respective channel data

for that connection run the below query to fetch the channel Data

  • Fetches channel data from cache, if not in cache it fetches data from Database.

  • .String cacheKey = connection_channeldata + connectionId;

SELECT accounts.account_slug AS accountSlug, channels.connectionId AS connectionId, channels.externalChannelId AS externalChannelId, external_wms_channels.locationId AS locationId, warehouses.externalWarehouseId AS externalWareHouseId FROM channels LEFT JOIN external_wms_channels ON channels.id = external_wms_channels.channel_id LEFT JOIN warehouses ON warehouses.id = external_wms_channels.warehouse_id LEFT JOIN accounts ON channels.account_id = accounts.id LEFT JOIN channel_account_mapping ON channel_account_mapping.external_wms_channel_id = external_wms_channels.id WHERE channels.connectionId = :connectionId AND channel_account_mapping.enrollmentStatus = 'ACTIVE';

Push the connectionchannel data in the Taskqueue

Use-case: It listens and prepares woocommerce product update Sync url to fetch product update Details :

Woocommerce URL:

https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products?modified_after=2024-03-01T06:00:31

Response :

Pagination will be applied per page will fetch 10 response until we do not received empty response.

[ { "id": 18, "name": "trouser", "slug": "trouser", "permalink": "https://mayurkarwa123.wpcomstaging.com/product/trouser/", "date_created": "2024-01-02T15:44:22", "date_created_gmt": "2024-01-02T10:14:22", "date_modified": "2024-03-01T11:49:31", "date_modified_gmt": "2024-03-01T06:19:31", "type": "simple", "status": "publish", "featured": false, "catalog_visibility": "visible", "description": "", "short_description": "", "sku": "newtrouser", "price": "400", "regular_price": "500", "sale_price": "400", "date_on_sale_from": null, "date_on_sale_from_gmt": null, "date_on_sale_to": null, "date_on_sale_to_gmt": null, "on_sale": true, "purchasable": true, "total_sales": 6, "virtual": false, "downloadable": false, "downloads": [], "download_limit": -1, "download_expiry": -1, "external_url": "", "button_text": "", "tax_status": "taxable", "tax_class": "", "manage_stock": true, "stock_quantity": 72, "backorders": "no", "backorders_allowed": false, "backordered": false, "low_stock_amount": null, "sold_individually": false, "weight": "", "dimensions": { "length": "", "width": "", "height": "" }, "shipping_required": true, "shipping_taxable": true, "shipping_class": "", "shipping_class_id": 0, "reviews_allowed": true, "average_rating": "0.00", "rating_count": 0, "upsell_ids": [ 15 ], "cross_sell_ids": [], "parent_id": 0, "purchase_note": "", "categories": [], "tags": [], "images": [], "attributes": [ { "id": 0, "name": "HSN", "slug": "HSN", "position": 0, "visible": true, "variation": false, "options": [ "1224" ] } ], "default_attributes": [], "variations": [], "grouped_products": [], "menu_order": 0, "price_html": "<del aria-hidden=\"true\"><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#8377;</span>500.00</bdi></span></del> <ins><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#8377;</span>400.00</bdi></span></ins>", "related_ids": [], "meta_data": [ { "id": 42, "key": "_created_via", "value": "post-new" }, { "id": 43, "key": "_last_editor_used_jetpack", "value": "classic-editor" }, { "id": 66, "key": "_wpas_done_all", "value": "1" } ], "stock_status": "instock", "has_options": false, "post_password": "", "jetpack_publicize_connections": [], "jetpack_likes_enabled": true, "jetpack_sharing_enabled": true, "jetpack-related-posts": [], "_links": { "self": [ { "href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/18" } ], "collection": [ { "href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products" } ] } } ]

Before creating product in Eshopbox we have to check that if attributes.variation= true and variation list is not empty then call the API for each variations.

Variant cases:

If in products response we get key type=”variable” and also “attributes.variations” is “true” then, iterate through each variations and fetch the product details for each

"variations": [ 64, 63, 62 ]

 

Iterate through each variationId and call API for each variantId

variations API for each variationId

https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/<product_id>/

To Create or Update Product -

Step 1 : Check if product exist or not in Eshopbox based on “active” inventoryItem Id from listing table and if it exist then update the Product else Create new Product in Eshopbox.

We will pass the list of itemId to check the status of itemId which we receive

SELECT * FROM listings WHERE itemID = 'SDL490996946' AND channel_id = 2710 AND STATUS = "ACTIVE"

Case 1 : if record exist from the above query, then update the Product in Eshopbox.

Update Product API:

PUT : https://{workspace}.myeshopbox.com/product-engine/api/v1/products/{sku}

Request Body:

{ "imageUrl": "https://cdn.filestackcontent.com/hdYluVCqSADCASjjjcuaeC", "mrp": 1499.0, "unitPrice": 799.0, "hsnCode": "6101112", "weight": 167.0, "dimensionLength": 5.0, "dimensionWidth": 5.0, "dimensionHeight": 5.0, "dimensionUnit": "cm" }'

Case

  1. Will get sku from listing table for respective itemId which is ESIN in Workspace.

  2. Will call Get product API with esin.

https://{workspace}.auperator.co/product-engine/api/v1/products?fields=weight_dimension_status&ids=45HY03FRI2B

Response :

{ "45HY03FRI2B": { "weight_dimension_status": "unverified" } }


If weight_dimension_status = inverification/verified in two status we can not update the weight dimension in such cases will be notified of such a mismatch in the product availability section of dimension

Case 2 : Else,

  • Case 2 i) : Else, check product exist in Eshopbox or not,

    • https://{workspace}.myeshopbox.com/product-engine/api/v1/products

If product exist will get Esin in response and mark the product available in Eshopbox.

{ "87162143127": { "esin": "0SGAT12SG25F", "brand": "Kapas Kraft" }, "623731HSHS": { "esin": "7HASI6ASDJ8S", "brand": "Kapas Kraft" } }

 

Mark Product Availability:

POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk

Request Body

{ "channelCode": "CH1234", "availability": true, "productMap": [ { "ESIN": { "sellersku": "sku", "productId_variantId/productId": "key" }, "ESIN1" :{ "sellersku": "sku", "productId_variantId/productId": "key" } } ] }

We will save the mark available response body and when will create the products will together mark it as avaialble.

ii) : If product does not exist in Eshopbox create product.

Check the configuration of product sync for that connection saved in otherDetails which are fetched already and saved in channel Object.

"otherDetails": { "taxCode" : { "WOO_CLASS1":"ESBHH1", "WOO_CLASS2":"ESBHH1", "WOO_CLASS3":"ESBHH2" }, }

 

Create a Product:

POST https://{workspace}.myeshopbox.com/product-engine/api/v1/products

 

Mapping for creating product in WMS

Eshopbox Keys

Woocommerce Identifier

Eshopbox Keys

Woocommerce Identifier

sku

sku -in case of simple product
variations.sku in case of variable product

imageurl

images[0].src in case of simple product

In case of variable product, usevariations.images[0].src if it is not blank else use images[0].src

description

description

mrp

regular_price

dimensionwidth

dimensions.width(cm) retrieve units from setting API and convert to cm. For variable product, if not available use parents product

dimensionheight

dimensions.height(cm) retrieve units from setting API and convert to cm. For variable product, if not available use parents product

dimensionlenght

dimensions.length(cm)retrieve units from setting API and convert to cm. For variable product, if not available use parents product

weight

"weight"(kg) retrieve units from setting API. For variable product, if not available use parents products

hsnc

Attribute as selected in app settings

taxcode

"tax class" and check the value saved in otherdetails with respect to eshopbox

properties.{Woo}_slug

slug

properties.{Woo}_sku

sku in case of simple product
variations.sku in case of variable product

dimensionUnit

cm

brand

tag.name

type

base

 

Mark Product Availability:

POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk

Request Body

{ "channelCode": "CH1234", "availability": true, "productMap": [ { "ESIN": { "sellersku": "sku", "productId_variantId/productId": "key" }, "ESIN1" :{ "sellersku": "sku", "productId_variantId/productId": "key" } } ] }

 

In case of Delete Cron will mark the product Unavailable in Eshopbox by calling unavailable API.

If grouped products are to be fetched, in case of grouped product :

Grouped Product -

We have option of grouped Product in Woocommerce , In which seller can grouped 2-3 products together and create a product.

when we create order the behvaiour of grouped products -

"line_items": [ { "id": 12, "name": "Demo Product 1", "product_id": 74, "variation_id": 0, "quantity": 2, "tax_class": "", "subtotal": "800.00", "subtotal_tax": "0.00", "total": "800.00", "total_tax": "0.00", "taxes": [], "meta_data": [], "sku": "groupdemosku", "price": 400, "image": { "id": "75", "src": "https://i0.wp.com/mayurkarwa123.wpcomstaging.com/wp-content/uploads/2024/03/organicproducts1-1.jpg?fit=500%2C329&ssl=1" }, "parent_name": null }


We get line_items in response where we do not get the individual products details.
But if we will be fetching the Grouped Products in Eshopbox then,

API to fetch Grouped Product -

https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/

If type = grouped
Response :

{ "id": 74, "name": "Demo Product 1", "slug": "demo-product-1", "permalink": "https://mayurkarwa123.wpcomstaging.com/product/demo-product-1/", "date_created": "2024-03-04T14:31:42", "date_created_gmt": "2024-03-04T09:01:42", "date_modified": "2024-03-04T14:31:42", "date_modified_gmt": "2024-03-04T09:01:42", "type": "grouped", "status": "publish", "featured": false, "catalog_visibility": "visible", "description": "", "short_description": "", "sku": "groupdemosku", "price": "400", "regular_price": "", "sale_price": "", "date_on_sale_from": null, "date_on_sale_from_gmt": null, "date_on_sale_to": null, "date_on_sale_to_gmt": null, "on_sale": true, "purchasable": false, "total_sales": 0, "virtual": false, "downloadable": false, "downloads": [], "download_limit": -1, "download_expiry": -1, "external_url": "", "button_text": "", "tax_status": "taxable", "tax_class": "", "manage_stock": false, "stock_quantity": null, "backorders": "no", "backorders_allowed": false, "backordered": false, "low_stock_amount": null, "sold_individually": false, "weight": "", "dimensions": { "length": "", "width": "", "height": "" }, "shipping_required": true, "shipping_taxable": true, "shipping_class": "", "shipping_class_id": 0, "reviews_allowed": true, "average_rating": "0.00", "rating_count": 0, "upsell_ids": [], "cross_sell_ids": [], "parent_id": 0, "purchase_note": "", "categories": [], "tags": [], "images": [ { "id": 75, "date_created": "2024-03-04T20:01:31", "date_created_gmt": "2024-03-04T09:01:31", "date_modified": "2024-03-04T20:01:31", "date_modified_gmt": "2024-03-04T09:01:31", "src": "https://i0.wp.com/mayurkarwa123.wpcomstaging.com/wp-content/uploads/2024/03/organicproducts1-1.jpg?fit=500%2C329&ssl=1", "name": "organicproducts1-1", "alt": "" } ], "attributes": [], "default_attributes": [], "variations": [], "grouped_products": [ 18, 37 ], "menu_order": 0, "price_html": "<span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#8377;</span>400.00</bdi></span> &ndash; <span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#8377;</span>2,300.00</bdi></span>", "related_ids": [], "meta_data": [ { "id": 329, "key": "_created_via", "value": "post-new" }, { "id": 330, "key": "_last_editor_used_jetpack", "value": "classic-editor" }, { "id": 356, "key": "_wpas_done_all", "value": "1" } ], "stock_status": "instock", "has_options": false, "post_password": "", "jetpack_publicize_connections": [], "jetpack_likes_enabled": true, "jetpack_sharing_enabled": true, "jetpack-related-posts": [], "_links": { "self": [ { "href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/74" } ], "collection": [ { "href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products" } ] } }

If type = grouped , then will check for key “grouped_products“ where will get the products which are grouped.

 "grouped_products": [         18,         37     ]


Product API :

https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/37

Will call the product API of Woocommerce for each product_id listed in grouped_products ,fetch the product details and will check is it available in Eshopbox if not create the product in Eshopbox.

 

 

Related content