/
Perform SideLined Activities on Shipments

Perform SideLined Activities on Shipments

What is the purpose of this article?

This document explains the steps and flow that are performed after inventory is assigned to the orders along with their function's name.

DETAILS :- Project - Inventory Engine Client Portal Service - backend Endpoint - InventoryAllocationEndPoint API path - /_ah/api/esb/v2/shipmentAdditionalInfoData (POST Api)

Tasks to be perfomed in short - In this taskqueue listener API, we will perform the below these tasks on the shipment wise request body : assigning an expected ship date to each shipment, calculating dimension of the shipment and assigning a courier partner to the shipment after checking pincode serviceability. After performing these 3 tasks, we will again pass the request body in the taskqueue to create its shipment.

Technical steps to achieve the task

  1. After inventory is assigned and the data is pushed in task queue, we will make a listener API shipmentAdditionalInfoDataEndPoint(). All the shipment Level tasks will be performed here.This is because, from its parent API we have got shipment-wise response. This taskqueue listener API will receive the request body only if the inventory is assigned to the all the order items and none of them are unfulfillable. This task queue listener Api will have one service Layer function This service layer function will have 3 divisions (functions). These function will be made in helper layer.

    Sample Request Body for this API :- { "Tab_Demo234": { "orderId": 44176871, "externalChannelID": "CH5927", "expectedShipDate": "2023-04-01 22:04:48", "externalShipmentId": "5328212132135-5927-4903", "customerOrderNumber": "5328212132135", "isCOD": "0", "warehouseId": 846, "accountSlug": "tab", "orderItemIds": [ 23924357 ], "shippingAddress": { "city": "Guwahati", "countryCode": "IN", "postalCode": "999999", "addressLine1": "Tarun Nagar", "addressLine2": "house no 23", "countryName": "INDIA", "state": "Assam", "contactPhone": "917896543214", "customerName": "Nitish Kumar", "email": "nitish@eshopbox.com" }, "items": [ { "itemID": "46797275660583", "sku": "XFS1G3FNPWU", "isPrePackaged": "No", "externalWarehouseID": "Tab_Demo234", "quantity": 1, "outOfStock": "false" } ], "channelId": 5927, "externalWmsChannelId": 2078, "pickupPincode": "803101" } }
  2. The request body will contains a list with different shipments to be created for order items. Iterate over the requestList and call a function performSideLinedActivitiesOnShipments() with each shipment as a parameter in service layer. In this function, we will perform the below 3 tasks : assigning an expected ship date to each shipment, calculating dimension of the shipment and assigning a courier partner to the shipment after checking pincode serviceability.

  3. assignmentOfCpt() - CPT stands for expectedShipdate. This function will be responsible for finding the expected ship date of shipments. How many shipments are to be made will be known from the above API. Each shipment will have their own expectedShipDate (It means that expectedshipdate will be calculated at shipment Level and not at order Level).

    1. Pass the shipment as a parameter within this function

    2. Get the present time in this format yyyy-MM-dd HH:mm:ss

    3. Find present hour.

    4. Logic used :-
      if present hour (time) < 12 pm -> expectedShipDate will be 4pm same day
      if present hour > 12 pm -> expectedShipDate will be 4pm next day

      • Note - present hour is the current time i.e, the time when the API runs.

    5. Add the key “expectedShipDate “ in the response body

  4. Calculate Dimension For shipment - In this function, we will calculate the dimensions - length, breadth, height, weight of items within each shipment.

    curl --location --request GET 'https://esb-product-engine-prod.appspot.com/_ah/api/esb/v1/products?fields=unitPrice,groupCode,components,status,accountSlug,mrp,hsnCode,combo,channelCode,brand,type,sku,weight,dimensionHeight,dimensionLength,dimensionWidth,weightUnit,dimensionUnit&ids=020S43GRQ2V,9059F3GPQLV' --header 'Authorization: Bearer' --header 'ProxyHost: vitaminplanet' Request body {     "externalChannelID": "CH1299",     "items": [ { "sku": "24QGK3H1ZV5", "quantity": 1 }, { "sku": "24QGK3H1ZV5", "quantity": 1 } ] }
    1. Create a separete function fetchProductDimensionsFromPE()

    2. Fetch the skus from the items from the above request body (each shipment from request body) and call the get product API

    3. (non-virtual kit case) From the get product API, we will get the dimensions of skus only

    4. For virtual kit case, call the get product api from requested SKUs and this will return the components of the base skus

      1. Collect all the components and its quantity and call the get product apis with the component SKUs which will return the dimension of component SKUs.

    5. Now calculate the final dimensions with below mentioned logic :-

Column1

Length

Breadth

Height

Weight

Column1

Length

Breadth

Height

Weight

Item1

21

15

18

0.5

item2

13

8

12

0.5

conclusion:

21 (choosing the greatest length)

15 (choosing the greatest length)

30 (will get added)

1

  • NOTE - For virtual kit case, when we call the get product API from requested SKUs and this will return the components of the base SKUs, this can happen that the same base SKU can be returned multiple times. In that case, This also needs to be kept in mind and achieved. We also have to check the quantity of base SKU and calculate their dimension accordingly. For eg. see the example below

Column1

Length

Breadth

Height

Weight

Column1

Length

Breadth

Height

Weight

Item1, quantity = 1

21

15

18

0.5

item2,

quantity = 1

13

8

12

0.5

item2 ,

quantity = 2

13

8

12 * 2

0.5 * 2

conclusion:

21 (choosing the greatest length)

15 (choosing the greatest length)

54 (All heights will get added)

2 (add all the weight)

  • We also need to check the quantity of parent sku in sent the request and calculate the correct dimension.Let’s understand with an example

suppose this is a non virtual kit sku ==> "9059F3GPQLV", quantity = 1
its dimensions => length = 6, breadth = 1, height = 1, weight = 1.2
And this a virtual kit sku ==> zxcv , quantity = 3
Its child skus are =>  
  a) zxcv1 , quantity = 1  
  b.) zxcv2, quantity = 2
dimension for zxcv1 ==> length = 1, breadth = 1, height = 0.5, weight = 1.5
dimension for zxcv2 ==> length = 1, breadth = 1, height = 0.7, weight = 1

Final dimension :-
length = 6,
breadth = 1,
height = 1+(0.5 + 0.7 *2) *3  // here multiplying with 3 beacause its parent skus quantitity is 3 weight = 1.2 + (1.5+1*2)*3 // same here

  • Logic that I have implemented to calculate the dimension

    1. Collected the skus from the items from the above request and call the get product API

    2. In a Map<String, object> skuAndQuantityMap , SKUs and their quantity was stored (for both virtual kit skus and non virtual kit skus )

    3. Again all the skus were collected (both virtual and non virtual kit skus ) and called the get product API and store the result in a Map

    4. Iterated the result map and matched the skus contained in skuAndQuantityMap. Multiply height and weight with the quantity to get the correct height and weight.

    5. For Length, Breadth, choose the greatest.

  • Sample response for the above API:-

  • Response body {     "externalChannelID": "CH1299", “dimensionLength":, “dimensionWidth":, “dimensionHeight":, “dimensionUnit":, "weightUnit":,     "items": [ { "sku": "24QGK3H1ZV5", "quantity": 1 }, { "sku": "24QGK3H1ZV5", "quantity": 1 } ] }

5. checkPincodeServiceabilityAndCourierPartner() - In this function, we will check if the delivery pincode is serviceable or not and assigning courier to the shipments. To achieve this task, This will be performed at shipment level because the warehouse address from where shipment is created will be our “source“ and delivery address will be “destination“ and pincodeServiceability happens from source to destination. For this reason pincodeServiceability will be checked separately for separate shipments.

  • To check for pincode servicibility and assiging courier to the shipment, call recommendation API.

  • This is the body to be passed in recommendation

  • API POST 'https://www.clickpost.in/api/v1/recommendation_api/?key=5b5c41f7-33a6-4d58-9a78-92703470f217 [     {         "pickup_pincode": "421302", => get from warehouse table. Already added in response of 1st API         "drop_pincode": "497339", => already given in request         "order_type": "PREPAID", => from orders table if isCOD = 0 then PREPAID else COD         "reference_number": "4571602911385-1299-0905", => externalShipmentID         "item": "vitaminplanet", => account Slug. Already added in response of 1st API         "invoice_value": 1999, => order items table, add every order associated, paas itemID         "delivery_type": "FORWARD" => to be hardcoded "additional": { "custom_fields": [{ "key": "orderTotal", => query from orders.orderTotal "value": "1299" }, { "key": "chargeableWeight", => shipment dead weight is to be passed "value": "140" }, { "key": "orderSiteId", => query from orders.orderTotal "value": "" }] } } ] NOTE - shipment dead weight is simply the total weight
  • Query to get the details for preparing recommendation API Body

    SELECT orders.isCOD, order_items.invoiceTotal,orders.orderTotal, orders.orderSiteID FROM orders LEFT JOIN order_items ON orders.id = order_items.order_id LEFT JOIN channels ON orders.channel_id = channels.id WHERE channels.externalChannelID = 'CH2064' AND orders.customerOrderNumber = "4357063344267" AND order_items.itemID IN ('42668361154699') GROUP BY order_items.id LIMIT 3;
  • Details to be passed in Query :-

    1. order_items.itemID = all itemIds in the shipment

    2. limit -> sum of all the quantities of the itemIDS in the shipment

  • From the response of this recommendation API, we will come top know whether the pincode is serviceable or not.

    Response body of recommendation API { "externalChannelID": "CH1299", “dimensionLength":, “dimensionWidth":, “dimensionHeight":, “dimensionUnit":, "weightUnit":, "isPincodeServiceable": true, "courierPartner":, "items": [ { "sku": "24QGK3H1ZV5", "quantity": 1 }, { "sku": "24QGK3H1ZV5", "quantity": 1 } ] }
  • For setting "courierPartner", we will choose that "courierPartner" whose priority is 1.

  • Add the below keys in the request body at shipment level

    • cp_id, cp_name

    • From the response of the recommendation API, check the preference array, if the preference array is blank then consider that the pincode serviceability is false else true,

    • If pin code pincode serviceability is false then only add the below two keys in item level :-

      • status = ONHOLD, onHold = 1

      • We are saving these two keys to create the shipment in onhold status because its pincode is not serviceable.

6. When the iteration ends, this function performSideLinedActivitiesOnShipments() returns the response body as below response :-

[ { "Tab_Demo234": { "orderId": 44176871, "externalChannelID": "CH5927", "expectedShipDate": "2023-04-01 22:04:48", "externalShipmentId": "5328212132135-5927-4903", "customerOrderNumber": "5328212132135", "isCOD": "0", "warehouseId": 846, "accountSlug": "tab", "orderItemIds": [ 23924357 ], "shippingAddress": { "city": "Guwahati", "countryCode": "IN", "postalCode": "999999", "addressLine1": "Tarun Nagar", "addressLine2": "house no 23", "countryName": "INDIA", "state": "Assam", "contactPhone": "917896543214", "customerName": "Nitish Kumar", "email": "nitish@eshopbox.com" }, "items": [ { "itemID": "46797275660583", "sku": "XFS1G3FNPWU", "isPrePackaged": "No", "externalWarehouseID": "Tab_Demo234", "quantity": 1, "outOfStock": "false" } ], "channelId": 5927, "externalWmsChannelId": 2078, "pickupPincode": "803101", "dimensionLength": 10, "dimensionWidth": 10, "dimensionHeight": 10, "weight": 20000, "dimensionUnit": "cm", "weightUnit": "kg", "cp_name": "Delhivery", "cp_id": 4, "isPincodeServiceable": true, "courierPartner": "Symphony_Delhivery_Heavy60" } } ]

7. After the response is prepared, we will check the riskScore of this order using the below logic.

a. fetch the riskScore by query from WMS DB

SELECT riskScore, isRiskScoreEnabled FROM orders LEFT JOIN channels ON orders.channel_id = channels.id LEFT JOIN account_additional_config ON channels.account_id = account_additional_config.account_id WHERE orders.id = :id

b. If query returns null value forriskScore then it means that riskScore has not been calculated yet and not been saved in DB. It must still be in process of calculating and saving it. So call the call orderVerification API to get the value of riskScore. (value of riskScore can be high/medium/low).

c. Add a key riskScore with its value.

8. Pass the above request body in a task queue again to create its shipment. Taskqueue lister API Details :-

DETAILS :- Project - Inventory Engine Client Portal Service - backend Endpoint - InventoryAllocationEndPoint API path - /_ah/api/esb/v2/shipment/create (POST Api)
Add label

Related content