Marketplaces / Storesome / Storesome Order Download Obsolete / Storesome Order Download

Storesome Order Download

Version Created / Updated Notes
1.0 Bogomil Pavlov
1.1 Danail Deltchev Change uniqueness of items on the Get order to be tracked by the provided ID, not by the SKU (See Additional Information below the order mapping)

The purpose of this document is to give good understanding how order management will work for Storesome integration. Swagger link - https://storesome-test-seller-api.azurewebsites.net/index.html

1. Get Orders and Refunds

Get Orders

URL -GET /api​/orders Gets orders for the current seller.

For the initial run of the cron we get all orders of the seller for the last 2 years. After successful run of the cron we store a new record in order_read table. Every next run of the cron will get the last date from order_read and deduct 15mins.

As a parameter we will be filtering the orders by modifiedDate. Once an order is placed the modifiedDate will be the same as date created and if any changes occur on the order the modifiedDate will be updated.

Thus we will be using one cron for Get Orders and Update Orders filtered by modifiedDate. If the order exist in the system we will update the status if the order does not exist we will store the new order.

Status Mapping:

It is important to know that there are statuses on order level and on order item level. For specific “order” statuses for us to know how to handle the situation the right way we will have to look at the orderItem status as well. This will be commented in the status mapping table below

Note: in the payload the “orderItem” status is provided as orderItemLine status, meaning there will be a status for each quantity. This FOR THE TIME BEING is not the actual case though as any operation that can happen with an order is AT MOST on orderItem level. This means that each quantity WILL have the same status, effectively making the status an orderItem level

Storesome Order Status Hemi Status Comment
1 Not Paid Pending
2 Pending Ready For Shipping
3 Shipped Shipped
4 Canceled Cancelled
5 Voided Cancelled
6 Payment Declined Incomplete
7 Payment Error Incomplete
8 Refunded Cancelled
9 Refund Requested Shipped / Ready For Shipping / Incomplete NEW! IF INSERT: If we have at least one orderItemLines > status on “pending” we want to set the order as “Ready for Shipping”.

If we don’t but have at least one orderItemLines > status on “shipped” we want to set the order as “Shipped” In any other situation (meaning we either have only orderItemLines > status as “refund requested“ or we have a mix of item statuses “refund requested” + “refunded” / “cancelled” / “voided” / etc we want to inspect the active refund section: • If we have orderItems >activeRefundRequest > typeId = 1 we mark the order as Ready For Shipping • If we have orderItems >activeRefundRequest > typeId = 3 we mark the order as Shipped • If we don’t have any of the above typeIds (which also includes receiving a “null” for the actual “activeRefundRequest”) we want to set the Order status in Hemisphere as “Incomplete” with an error “Not enough information to determine the Order Status” IF UPDATE: Do not change the Orders status and update only the Order Item > Status | | 10 Refunded Partially | Shipped / Ready For Shipping / Incomplete | NEW! IF INSERT: If we have at least one orderItemLines > status on “pending” we want to set the order as “Ready for Shipping”. If we don’t but have at least one orderItemLines > status on “shipped” we want to set the order as “Shipped” If we don’t have either “pending” nor “shipped” but we have at least one orderItemLines > status as “refund requested” we want to inspect the active refund section: • If we have orderItems >activeRefundRequest > typeId = 1 we mark the order as Ready For Shipping • If we have orderItems >activeRefundRequest > typeId = 3 we mark the order as Shipped • If we don’t have any of the above typeIds (which also includes receiving a “null” for the actual “activeRefundRequest”) OR we don’t have any of the mentioned orderItemLines > status values we want to set the Order status in Hemisphere as “Incomplete” with an error “Not enough information to determine the Order Status” IF UPDATE: Do not change the Orders status and update only the Order Item > Status | | 11 Delivered | Shipped | |

Additional Statuses information - As of the scoping of this document we can only ship the whole order (we can’t ship items or lines) and Refunds/Claims can happen only on item level.

Sample Payload:

{
  "pageSize": 0,
  "pageIndex": 0,
  "totalItems": 0,
  "items": [
    {
      "id": 0,
      "trackingId": "string",
      "carrierName": "string",
      "orderDate": "2021-09-01T09:59:41.412Z",
      "modifiedDate": "2021-09-01T09:59:41.412Z",
      "totalPrice": 0,
      "totalShippingPrice": 0,
      "orderItems": [
        {
          "id": 0,
          "title": "string",
          "quantity": 0,
          "totalPrice": 0,
          "totalShippingPrice": 0,
          "shippingTitle": "string",
          "shippingPrice": "string",
          "productSKU": "string",
          "activeRefundRequest": {
            "id": 0,
            "typeId": 0,
            "isActioned": true,
            "refundDate": "2021-09-01T09:59:41.412Z"
          },
          "orderItemLines": [
            {
              "lineId": 0,
              "status": "string"
            }
          ]
        }
      ],
      "shippingAddress": {
        "addressLine": "string",
        "recipientFirstName": "string",
        "recipientLastName": "string",
        "phone": "string",
        "city": "string",
        "country": "string",
        "postcode": "string"
      },
      "billingAddress": {
        "addressLine": "string",
        "recipientFirstName": "string",
        "recipientLastName": "string",
        "phone": "string",
        "city": "string",
        "country": "string",
        "postcode": "string"
      },
      "status": "string",
      "paymentType": "string",
      "currency": "string",
      "transactionId": "string",
      "buyerName": "string",
      "buyerEmail": "string",
      "postcode": "string"
    }
  ]
}

Field Mapping

Storesome Field Hemi Field Comment
id orders > Marketplace Order ID
trackingId orders > Tracking Number
carrierName orders > Carrier
orderDate orders > Order Created Time
modifiedDate N/A Used for filtering when downloading orders > Dev team to decide if it is worth saving this in the DB as well
totalPrice orders > Order Total Amount
totalShippingPrice orders > Shipping Service Cost
orderItems >id order_item > Item Order Line ID
orderItems >title order_item > Title
orderItems >quantity order_item > Quantity
orderItems >totalPrice order_item > Item Trans Price New: Store directly in the field!
orderItems >totalShippingPrice order_item > Item Shipping Cost
orderItems >shippingTitle orders > Shipping Service

AND Order Item Storesome > Shipping Service | In the odd case where we have different shipping methods for items in a combined order we want to store each service per the item but want to extrapolate 1 leading Service for the whole order. We should do that via the ACTUAL Storesome shipping services. We are creating them separately for the listing of the items so we can update them accordingly, meaning we already have them in Hemisphere. The priority of the services (always 3) should be “Expedited” > “Standard” > “Economy”. Whatever the 3 names of the services we should create additional field in the Storesome services table to be able to mark the different services with a unique value and create the dependency. This in a real situation would look like this:

  1. We receive an order with 2 items, one with shippingTitle “Easy ship - Free”, one with shippingTitle “Pew Pew shipping - 6.99”
  2. We load the services and map those two against their relevant “Shipping Type” and see that one is “Economy” where the other is “Expedited”
  3. Each OrderItemStoresome gets its own Service and for the Order we store “Expedited” | | orderItems >shippingPrice | N/A | | | orderItems >productSKU | order_item > SKU | | | orderItems > activeRefundRequest | | If no refunds “null“ value will be received | | orderItems >activeRefundRequest > id | order_payment >Transaction ID | This will be the transaction id of the refund row | | orderItems >activeRefundRequest > typeId | | TypeID indicates if it is a return, cancel etc. the IDs are 1 -Cancel 2 - Not Recieved 3 - Returned | | orderItems >activeRefundRequest > isActioned | | If isActioned = true this means the refund in completed otherwise we do not store it | | orderItems >activeRefundRequest > refundDate | order_payment - Payment Date | | | orderItems >orderItemLines> lineId | order_item_line > Marketplace ID | | | orderItems >orderItemLines> status | order_item_line > Status | | | shippingAddress > addressLine | orders > Shipping Street 1 | | | shippingAddress >recipientFirstName | orders > Shipping Buyer Name | | | shippingAddress >recipientLastName | orders > Shipping Buyer Name | | | shippingAddress >phone | orders > Shipping Phone | | | shippingAddress >city | orders > Shipping City | | | shippingAddress > country | orders > Shipping Country | | | shippingAddress >postcode | orders > Shipping Postcode | | | billingAddress > addressLine | orders > Billing Street 1 | | | billingAddress >recipientFirstName | orders > Billing Name | | | billingAddress >recipientLastName | orders > Billing Name | | | billingAddress >phone | orders > Billing Phone | | | billingAddress >city | orders > Billing City Name | | | billingAddress > country | orders > Billing Country Name | | | billingAddress >postcode | orders > Billing Postal Code | | | status | orders > Marketplace Status | | | paymentType | orders > Order Payment Method | | | currency | orders > Currency | | | transactionId | orders > External Trans ID order_payment > TransactionID | | | buyerName | orders > BuyerID | | | buyerEmail | orders > Buyer Email | | | postcode | N/A | | | N/A | orders > Order Subtotal Amount | totalPrice - totalShippingPrice | | N/A | orders > Billing Country Code | Using Allegro Country Code List LookUp Group to map the country name and add the country code | | N/A | orders > Shipping Country Code | Using Allegro Country Code List LookUp Group to map the country name and add the country code |

Additional Information

  • Recently (May 2022) it was find out that there is a situation in which a SKU can change on an order. Storesome work on a SKU uniqueness throughout their whole system. The way they track information is with least data duplication possible. This means that when they store an order there is a connection by ID to the product that was ordered and SKU and some other information is not directly stored in the order record itself. If a Storesome client decides they want to change their product completely this will affect the order information that is shown on the order itself (it will look like a different product has been purchased). To move away from that if the SKU needs to be used for a new product Storesome change the previous SKU to include a timestamp of a deletion operation. In result IF for some reason we get this order again it will have a different SKU than what we have in Hemi. Because of this difference and our uniqueness by SKU that we are looking for we identify a completely new item and try to store it. For any such checks we need to move to a uniqueness by id ("orderItems" > "id") We are still expecting that we can’t receive two items with the same SKU but because of this difference in Storesome we need to map their items via the ID to Hemi instead of the SKU. This way we will identify this product as already existing and even if its SKU is different we will skip it as something that needs changes

Get Refunds

Because we are not receiving all the details about a refund in the get orders response we will need to use a separate set of calls to properly get all the refund details. To do so we will have to do 2 separate operations.

  1. Get all the refunds API Call: GET /api/refund/get-completed-refunds Through this call we want to get all completed refunds that have changed in the time since its last run. Best way to do so is by utilising the “sortBy” and “sortDirection” options to chose “ModifiedDate” and “desc”. This way we will be able to read refunds from the top to the moment we hit the latest dates (overlap including) we’ve already read and stop there. The issue with the returned payload is we actually don't know if the refund has been accepted or rejected at this point… we just know it has been completed and that’s it… Through this call though we can get all refund IDs that we can then use in step 2
  2. Get specific refund’s details API Call: GET /api/refund/{refundRequestId} Through this call we can get proper details of the already completed refunds. First we want to make sure that the “isActioned” field is set to true - this indicates to us that the refund is “completed” one way or another (it can be rejected or accepted) Then to know that a refund is Accepted (we want to store and work ONLY with accepted refunds) we have to check fields refundAmountTypeId and amount - if they are empty or “NULL” this means the refund has been rejected. If those fields have a numeric value < or = 0 we should store an error. Everything else (positive value) means we have an accepted refund. Based on the ID and value supplied we have the following options that we can encounter
refundAmountTypeId Storesome Meaning WAP Notes
1 Item Cost If we have value 1 this means that the refund is only for the item cost. In the Amount we are expecting to see the refunded value for all quantity of this product. Meaning from the fields in the payload if we multiply itemPrice with itemQuantitywe should get the “amount”. In this case we are expecting to store a refund that will have only a refund row of type “item”
2 Shipping Cost If we have value 2 this means that the refund is only for the shipping cost. In the Amount we are expecting to see the refunded value for the shippingCost of this item. In this case we are expecting to store a refund that will have only a refund row of type “shipping”
3 Item Shipping Cost If we have value 3 this means that the refund is for all the cost of this item. The above mentioned options should combine to provide us with the end value that we have as a total refunded cost in the “amount”. In this case we are expecting to store a refund with a refund row of each type (“item” and “shipping”) so e can capture the differences properly
4 Other If we have value 4 this means that the refund is a specific custom value that can be a part of a product, part of multiple quantities or even fully refunded product and partially refunded shipping (full refund is also optional). Literally any option can happen as it is just an open custom value. What we want to do is start assigning the value first from the available total of the products and then if needed move to the shipping as well. The “amount” can never be more than the total available payment for the specific product (itemPrice * itemQuantity + ShippingCost). Depending on our value assignments we are to store a refund with either only item type refund row or both item and shipping type refund rows

IMPORTANT: Even if one refund gets processed for a product successfully we are not expecting a second refund to be possible to be triggered from Storesome. It is pushing the products to a final state, meaning a new refund can not be requested by the buyer. I’d prefer if we still make the option to prepare for multiple refunds on the same product with the check of the available sum in our own system and in case more than the available is refunded then to store a refund with the correct error.

Sample Response:

{
  "id": 0,
  "orderId": 0,
  "productSKU": "string",
  "description": "string",
  "itemPrice": 0,
  "shippingCost": 0,
  "itemQuantity": 0,
  "returnReason": "string",
  "orderStastusId": 0,
  "orderStastusCode": "string",
  "orderStastusDisplay": "string",
  "orderItemStastusId": 0,
  "orderItemStastusCode": "string",
  "orderItemStastusDisplay": "string",
  "buyerEmail": "string",
  "sellerName": "string",
  "modifiedDate": "2021-08-31T21:13:45.794Z",
  "refundAmountTypeId": 0,
  "amount": 0,
  "isActioned": true,
  "refundMessages": [
    {
      "id": 0,
      "message": "string",
      "senderName": "string",
      "isRead": true,
      "createDate": "2021-08-31T21:13:45.794Z"
    }
  ]
}

Each refund we are getting should be for a specific SKU and will hold all its quantity with its relevant price and shipping price. This means that if we decide a refund has been successfully processed we need to ensure we are tracking both the ‘itemPrice’ and ‘shippingCost’ so we can differentiate the types of refund rows we want to store (item vs shipping in Hemisphere)

Field Mapping

Storesome Field Hemi Field Comment
productSKU Order Refund Row > SKU
itemPrice N/A
shippingCost N/A
returnReason Order Payment > Reason
amount Order Payment > Total Amount

AND Refund Row > Amount | Direct match and map for the Order Payment > Total Amount Based on the above description might need to be split for multiple refund rows based on their type (item and shipping) | | modifiedDate | Order Payment > Payment Date | |

Please run all other needed fields as per our standard requirements (transaction ID needs to be populated, changing payment statuses on the order and items, etc.)

2. Ship Orders

URL - PATCH /api​/orders​/{id}​/shipping

Using the marketplace order id as a parameter we indicate which order we would like to ship. Sample payload:

{
  "sellerId": 0,
  "orderId": 0,
  "carrierName": "string",
  "trackingNumber": "string"
}

Field Mapping

Storesome field Hemi field Hemi Notes
sellerId N/A Not mandatory, we don’t map anything
orderId Orders > Marketplace Order ID
carrierName Orders > Shipment > Courier
trackingNumber Orders > Shipment > Tracking Number

We are to use the new Shipment model with its Shipping abstraction part. The standard communication goes with the Status field (pending means to be sent, etc. more on the abstraction can be read here: https://wearepentagon.atlassian.net/wiki/spaces/HEMI/pages/2075820405/Order+management+general+requirements#Ship )

Storesome/Autofixa don’t allow for partial shipments at the moment so there is no need to worry for that. We are expecting we are sending Shipment information for the whole order every time. Still all standard validations should apply - meaning if we don’t have at least one line in the shipment that is applicable for shipment we are to block the whole Shipment with the corresponding error. Besides the standard validations in the Shipment processor we don’t want to add anything more. Everything within the abstraction should work as a standard for the Hemi input information (if we are trying to ship 2 lines and one is not eligible the Shipment goes to a Warning state even if we are sending a full shipment update every time, etc.)

Is this article helpful?
0 0 0