Decathlon Order management
The purpose of this document is to give good understanding how we will incorporate the order management within our Decathlon integration.
Summary of Changes: (The purpose of this table is to keep traceability and Product team to highlight the things that were changed into the scope, based on comments or discussions)
Version | Date | Created / Updated | Notes |
---|---|---|---|
v1.0 | 31.03.2022 | Bogomil Pavlov | First publish |
v1.1 | 29.06.2022 | Bogomil Pavlov | Refund Reasons added and confirmed |
v1.2 | 15.08.2022 | Bogomil Pavlov | Customer ID mapping change |
v1.3 | 22.08.2022 | Bogomil Pavlov | Incident Open Order Status details added |
v1.4 | 23.08.2022 | Bogomil Pavlov | Add logic for Quantity in refunds |
v1.5 | 24.08.2022 | Bogomil Pavlov | Rework of the Refunds |
v1.6 | 13.09.2022 | Bogomil Pavlov | Refunded status update |
v1.7 | 10.10.2022 | Bogomil Pavlov | Item Price need to be divided by quantity |
v1.8 | 22.11.2022 | Bogomil Pavlov | REFUNDED status in the list when accepting order items |
v1.9 | 09.12.2022 | Bogomil Pavlov | Logic for downloading shipped orders added |
v2.0 | 07.02.2023 | Bogomil Pavlov | Updated mapping for order item status |
v2.1 | 13.02.2024 | Bogomil Pavlov | Incorporate Cancellation on not debited orders. |
The order management will be downloading new orders, downloading modified orders, accept orders, ship orders, refund orders.
Note: Download order, Accept Order, Get modified (update statuses until we get RFS status)
Get New Orders
In order to get orders, we will use GET OR11 - List orders. The first run will check for new orders in the last 90 days and afterwards we will get the date from last_date_run table and filter orders using parameter: start_date - {last_date_run - 1 hours} date format - 2022-03-25T11:02:04Z
For each Decathlon channel we will have separate account in Hemi. Please make sure having the same Account API key and End Point for each Decathlon account wont be a problem? One way to distinguish the order is to use the channel from the Get Orders payload and map it with Account Decathlon > Channel, this way we will know for which account is the order and will be storing only these orders for which we have active account with the same Account Decathlon > Channel
Sales Tax Group | Marketplace VAT Group | Internal VAT Group |
---|---|---|
Orders >Total Sales Tax | Orders > Total Marketplace VAT | Orders > Total VAT |
Orders >Total Shipping Sales Tax | Orders > Total Shipping Marketplace VAT | Orders > Total Shipping VAT |
Product In Order > Item Sales Tax Price | Product in Order > Marketplace VAT Item Price | Product In Order > Vat Item Price |
Product In Order > Sales Tax Percent | Product in Order > Marketplace VAT Percent | Product In Order > Vat Percent |
Product In Order > Item Shipping Cost Sales Tax | Product in Order > Marketplace VAT Item Shipping Cost | Product In Order > Vat Item Shipping Cost |
Mirakl do no support bundles so we take care of them internally and use our standard logic for debundling.
API Call: /api/orders
Parameter | Value | Required | Comment |
---|---|---|---|
start_date | last_date_run > date created - 1 hours | Ye |
API Docs: https://decathlonbelgium-preprod.mirakl.net/help/api-doc/seller/mmp.html#OR11
Example Response:
{
"orders": [
{
"acceptance_decision_date": "2019-04-02T14:56:01Z",
"can_cancel": false,
"can_shop_ship": false,
"channel": {
"code": "US",
"label": "Website US"
},
"commercial_id": "Order_00010",
"created_date": "2019-04-02T14:18:43Z",
"currency_iso_code": "USD",
"customer": {
"accounting_contact": {
"customer_id": "Customer_id_003",
"firstname": "Thomas",
"lastname": "Anderson",
"locale": "en_US"
},
"billing_address": {
"city": "New York City",
"civility": "M",
"country": "USA",
"country_iso_code": "USA",
"firstname": "smith",
"lastname": "Taylor",
"company": "LIMARK Company",
"state": "Manhattan",
"street_1": "113 MacDougal Street",
"street_2": "1st floor",
"zip_code": "NY 10012"
},
"civility": "M",
"customer_id": "Customer_id_001",
"delivery_contact": {
"customer_id": "Customer_id_002",
"firstname": "Stella",
"lastname": "Lettiere",
"locale": "en_US"
},
"firstname": "Smith",
"lastname": "Taylor",
"locale": "en_US",
"organization": {
"address": {
"city": "New York",
"country_iso_code": "USA",
"state": "Manhattan",
"street_1": "113 MacDougal Street",
"street_2": "1st floor",
"zip_code": "NY 10012"
},
"identification_number": "982837446",
"name": "Limark Company Inc.",
"organization_id": "organization_id_001",
"tax_identification_number": "96-25472919"
},
"shipping_address": {
"additional_info": "One article per box",
"city": "New York",
"civility": "M",
"company": "LIMARK Company",
"country": "USA",
"country_iso_code": "USA",
"firstname": "Smith",
"lastname": "Taylor",
"state": "Manhattan",
"street_1": "113 MacDougal Street",
"street_2": "1st floor",
"zip_code": "NY 10012"
}
},
"customer_debited_date": "2019-04-02T14:58:22.460Z",
"customer_notification_email": "notification+ec1riop21ju4rfynl0helvzou.e0z0r7cj2@notification.mirakl.net",
"delivery_date": {
"earliest": "2019-09-02T08:07:22.326Z",
"latest": "2019-09-03T08:07:22.326Z"
},
"has_customer_message": false,
"has_incident": false,
"has_invoice": false,
"invoice_details": {
"document_details": [
{
"format": "PDF"
},
{
"format": "cXML"
}
],
"payment_terms": {
"days": 10,
"type": "NET"
}
},
"last_updated_date": "2019-04-02T14:59:58Z",
"leadtime_to_ship": 5,
"order_additional_fields": [],
"order_id": "Order_00010-A",
"order_lines": [
{
"can_refund": true,
"cancelations": [],
"category_code": "5110114",
"category_label": "Coffee Machines",
"commission_fee": 21.3,
"commission_taxes": [
{
"amount": 0,
"code": "TAXZERO",
"rate": 0
}
],
"created_date": "2019-04-02T14:18:43Z",
"debited_date": "2019-04-02T14:58:22Z",
"description": null,
"last_updated_date": "2019-04-02T14:59:58Z",
"offer_id": 2130,
"offer_sku": "S2000",
"offer_state_code": "11",
"order_line_additional_fields": [
{
"code": "delivery-countries",
"type": "MULTIPLE_VALUES_LIST",
"value": [
"USA"
]
}
],
"order_line_id": "Order_00010-A-1",
"order_line_index": 1,
"order_line_state": "RECEIVED",
"order_line_state_reason_code": null,
"order_line_state_reason_label": null,
"price": 165,
"price_additional_info": null,
"price_unit": 55,
"product_medias": [
{
"media_url": "/media/product/image/57b58b2e-8849-4d8d-9072-0aa33d314e5c",
"mime_type": "JPEG",
"type": "MEDIUM"
},
{
"media_url": "/media/product/image/8bc8241d-0747-4891-bb2e-881202f5465a",
"mime_type": "JPEG",
"type": "LARGE"
},
{
"media_url": "/media/product/image/d3fd1d4e-a943-4df0-8878-3343ba139dd9",
"mime_type": "JPEG",
"type": "SMALL"
}
],
"product_sku": "MKP100000000037254",
"product_title": "Breville Cafe Roma Stainless Espresso/Cappuccino Machine - ESP8C",
"promotions": [],
"quantity": 3,
"received_date": "2019-04-02T14:59:58Z",
"refunds": [
{
"amount": 2,
"commission_amount": 1.2,
"commission_taxes": [
{
"amount": 0,
"code": "TAXZERO"
}
],
"commission_total_amount": 1.2,
"created_date": "2019-04-02T14:59:14Z",
"id": "1129",
"quantity": 0,
"reason_code": "15",
"shipping_amount": 2,
"shipping_taxes": [
{
"amount": 2,
"code": "tax1",
"rate": 17.5000
},
{
"amount": 2,
"code": "tax2"
}
],
"state": "WAITING_REFUND",
"taxes": [
{
"amount": 2,
"code": "tax1",
"rate": 17.5000
},
{
"amount": 2,
"code": "tax2"
}
]
}
],
"shipped_date": "2019-04-02T14:58:39Z",
"shipping_from": {
"address": {
"city": "New York City",
"country_iso_code": "USA",
"state": "New York",
"street_1": "10E 40th Street",
"street_2": "14th floor",
"zip_code": "10016"
}
},
"shipping_price": 8,
"shipping_taxes": [
{
"amount": 10,
"code": "tax1",
"rate": 17.5000
},
{
"amount": 10,
"code": "tax2"
"tax_calculation_rule": "PROPORTIONAL_TO_AMOUNT"
}
],
"taxes": [
{
"amount": 10,
"code": "tax1",
"rate": 17.5000
"tax_calculation_rule": "NONE"
},
{
"amount": 10,
"code": "tax2"
}
],
"total_commission": 21.3,
"total_price": 173
}
],
"order_state": "RECEIVED",
"order_state_reason_code": null,
"order_state_reason_label": null,
"payment_type": "Visa",
"payment_workflow": "PAY_ON_ACCEPTANCE",
"price": 165,
"promotions": {
"applied_promotions": [],
"total_deduced_amount": 0
},
"quote_id": null,
"references": {
"order_reference_for_customer": "ref_customer",
"order_reference_for_seller": "ref_seller"
}
"shipping_carrier_code": "UPS",
"shipping_company": "UPS",
"shipping_deadline": "2019-09-01T08:07:22.326Z",
"shipping_price": 8,
"shipping_pudo_id": "C1039",
"shipping_tracking": "2344",
"shipping_tracking_url": "https://wwwapps.ups.com/WebTracking/track?track=yes&trackNums=2344",
"shipping_type_code": "STD",
"shipping_type_label": "Standard",
"shipping_zone_code": "INT1",
"shipping_zone_label": "International 1",
"total_commission": 21.3,
"total_price": 173,
"transaction_date": "2019-06-25T07:42:21.215Z",
"transaction_number": "TR_MIR-PHHV83UB",
"fulfillment": {
"center": {
"code": "FULFILLMENT_CENTER_CODE"
}
},
"customer_directly_pays_seller": false
}
],
"total_count": 1
}
Response Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes | ||||
---|---|---|---|---|---|---|---|---|
orders |
List of orders | |||||||
acceptance_decision_date |
The date where the shop decided to accept or refuse the order. Null when the order was automatically refused or accepted. | |||||||
date-time | N/A | |||||||
can_cancel |
Indicate if the order can be cancelled. | |||||||
boolean | N/A | We will use this field to check before each refund/cancellation which request to make OR28 or OR30 | ||||||
can_shop_ship |
Indicates if shops can or cannot ship orders | |||||||
boolean | N/A | |||||||
channel |
The channel of the commercial's order | |||||||
code |
Channel code | N/A | Used to map to the correct account. | |||||
Channel > Code = Account Decathlon > Channel | ||||||||
label |
Channel label | N/A | ||||||
commercial_id |
Commercial order's identifier | N/A | ||||||
created_date |
Order's creation date | |||||||
2019-04-02T14:18:43Z | Order > Order Created Time | |||||||
currency_iso_code |
Shop's currency (ISO format) | |||||||
One of: AED, ARS, AUD, BGN, BHD, BRL, CAD, CHF, CLP, CNY, COP, CZK, DKK, EGP, EUR, GBP, HKD, HRK, HUF, ILS, INR, JOD, JPY, KES, KRW, KWD, LKR, MXN, MYR, NGN, NOK, NZD, OMR, PEN, PHP, PKR, PLN, RON, RSD, RUB, SAR, SEK, SGD, TND, TRY, THB, TWD, UAH, USD, UYU, VND, ZAR | Order > Order Currency | |||||||
customer |
Information of the customer who ordered | You can see below the mapping for Billing/Shipping | ||||||
accounting_contact |
Data related to the accounting contact in the organization | |||||||
civility |
Customer contact's civility | N/A | ||||||
customer_id |
Customer contact's identifier | N/A | ||||||
firstname |
Customer contact's firstname | N/A | ||||||
lastname |
Customer contact's lastname | N/A | ||||||
locale |
Customer contact's locale | N/A | ||||||
billing_address |
Customer's billing address | |||||||
city |
Address city | Orders > Billing City Name | ||||||
civility |
Civility of the person associated with the address | N/A | ||||||
company |
Company of the person associated with the address | Orders > Company Name | ||||||
country |
Address country | Orders > Billing Country Name | ||||||
country_iso_code |
Orders > Billing Country Code | As we store in Hemi 2 letter code, we should convert the value from MIRAKL (3letted code) into 2 letter code and store it in Hemi. | ||||||
firstname |
First name of the person associated with the address | Orders > Billing Name | Concatenate with “lastname” with a single space between them | |||||
lastname |
Last name of the person associated with the address | Orders > Billing Name | Concatenate with “firstname” with a single space between them | |||||
phone |
Phone | Orders > Billing Phone | ||||||
phone_secondary |
Phone secondary | N/A | ||||||
state |
Address state | Orders > Billing State Province | ||||||
street_1 |
First information line of the address street | Orders > Billing Street 1 | ||||||
street_2 |
Second information line of the address street | Orders > Billing Street 2 | ||||||
zip_code |
Address zip code | Orders > Billing Postal Code | ||||||
civility |
Customer's civility | N/A | ||||||
customer_id |
Customer's identifier | Order > Buyer User ID | ||||||
delivery_contact |
Data related to the delivery contact in the organization | |||||||
civility |
Customer contact's civility | N/A | ||||||
customer_id |
Customer contact's identifier | N/A | ||||||
firstname |
Customer contact's firstname | N/A | ||||||
lastname |
Customer contact's lastname | N/A | ||||||
locale |
Customer contact's locale | N/A | ||||||
firstname |
Customer's first name | N/A | ||||||
lastname |
Customer's last name | N/A | ||||||
locale |
Customer's locale | N/A | ||||||
organization |
Data related to the organization that created the order (B2B transactions) | N/A | ||||||
address |
Address of the organization. Required for new organizations. | N/A | ||||||
city |
Address city | N/A | ||||||
country_iso_code |
Country ISO 3166-1 code of the address, used by Mirakl to format the address (back office, delivery bill, invoices...) and to adapt the address validation to the country (see zip_code field) | N/A | As we store in Hemi 2 letter code, we should convert the value from MIRAKL (3letted code) into 2 letter code and store it in Hemi. | |||||
state |
Address state | N/A | ||||||
street_1 |
First information line of the address street | N/A | ||||||
street_2 |
Second information line of the address street | N/A | ||||||
zip_code |
Address zip code, mandatory (unless the country_iso_code corresponds to Chile or Peru) | N/A | ||||||
identification_number |
Number used to identify the customer organization as an established business in a country. E.g: SIRET number in France, NIF in Spain. Required for new organizations. | N/A | ||||||
name |
Name of the organization. Required for new organizations. | N/A | ||||||
organization_id |
Customer's organization id (from the operator's system) | N/A | ||||||
tax_identification_number |
Tax identification number of the organization. | N/A | ||||||
shipping_address |
Customer's Shipping address | see below fields | ||||||
additional_info |
Additional information for the shipping address | N/A | ||||||
city |
Address city | Orders > Shipping City | ||||||
civility |
Civility of the person associated with the address | N/A | ||||||
company |
Company of the person associated with the address | N/A | ||||||
country |
Address country | Orders > Shipping Country Name | ||||||
country_iso_code |
Orders > Shipping Country Code | |||||||
firstname |
First name of the person associated with the address | Orders > Shipping Buyer Name | Concatenate with “lastname” with a single space between them | |||||
lastname |
Last name of the person associated with the address | Orders > Shipping Buyer Name | Concatenate with “firstname” with a single space between them | |||||
state |
Orders > Shipping State Province | |||||||
street_1 |
First information line of the address street | Orders > Shipping Street 1 | ||||||
street_2 |
Second information line of the address street | Orders > Shipping Street 2 | ||||||
zip_code |
Address zip code | Orders > Shipping Postal Code | ||||||
customer_debited_date |
The payment's date of the order by the customer | Orders > Order Paid Time | We will store UNIX format in Hemi but we need to display Human readable format into the UI | |||||
customer_notification_email |
Anonymized customer email usable for notifications that do not expect an answer | Order > Buyer mail | ||||||
delivery_date |
Expected order delivery date | N/A | ||||||
earliest |
Earliest order delivery date | N/A | ||||||
latest |
Latest order delivery date | Order > Delivery By Date | ||||||
has_customer_message |
Indicate if the customer has sent a message related to this order | N/A | ||||||
has_incident |
Indicate if order has incident on at least one order line | N/A | ||||||
has_invoice |
Is an invoice available for this order | N/A | ||||||
invoice_details |
Invoice information linked to the order | N/A | ||||||
document_details |
Invoice document information | |||||||
format |
Accounting document format | N/A | ||||||
payment_terms |
Payment terms | |||||||
days |
Number of days | N/A | ||||||
type |
Payment terms type | N/A | ||||||
last_updated_date |
Order's last updated date | N/A | ||||||
leadtime_to_ship |
Order's lead time to ship, in calendar days. | |||||||
Deprecated | N/A | |||||||
order_additional_fields |
Order's additional fields | N/A | ||||||
order_id |
Order's identifier | Order >Marketplace Order ID | ||||||
order_lines |
Order lines | |||||||
can_refund |
Indicate whether the order line full amount can be refunded | N/A | We will use this field to check before each refund/cancellation which request to make OR28 or OR30 | |||||
cancelations |
List of the cancellations | N/A | *Note:** Please note here we will receive the same information as we receive into the refund node (under row 94) | |||||
category_code |
Category code of the product associated with the order line | N/A | ||||||
category_label |
Category label of the product associated with the order line | N/A | ||||||
commission_fee |
Order line's commission fee | Orders > Marketplace Fee | We need to sum all order line commissions and store them on order level | |||||
commission_taxes |
Commission taxes | N/A | ||||||
amount |
N/A | |||||||
code |
N/A | |||||||
rate |
N/A | |||||||
created_date |
Order line's creation date | N/A | ||||||
debited_date |
Order line's debited date | N/A | ||||||
description |
Order line's description | N/A | ||||||
last_updated_date |
Order line's last updated date | N/A | ||||||
offer_id |
Associated offer's id | Product in Order > Channel Item ID | ||||||
offer_sku |
Associated offer sku (this is the sku of the offer defined by the shop) | Product in Order > SKU | ||||||
offer_state_code |
State of the offer associated with the order line | N/A | ||||||
order_line_additional_fields |
List of additional fields | |||||||
code |
N/A | |||||||
type |
N/A | |||||||
value |
N/A | |||||||
order_line_id |
Order line's identifier | Product in Order > Item Order Line ID | ||||||
order_line_index |
Order line's index in the order | N/A | As discussed , we do not store order_line_index | |||||
order_line_state |
Order line's state | |||||||
STAGING, WAITING_ACCEPTANCE, WAITING_DEBIT, WAITING_DEBIT_PAYMENT, SHIPPING, SHIPPED, TO_COLLECT, RECEIVED, CLOSED, REFUSED, CANCELED, INCIDENT_OPEN, REFUNDED, | Product in Order > Status | |||||||
order_line_state_reason_code |
Reason's code of the order line's state | N/A | ||||||
order_line_state_reason_label |
Reason's label of the order line's state | N/A | ||||||
price |
Order line's price without shipping price | Product in Order > Item Price / Product In Order > Quantity | ||||||
price_additional_info |
Price's additional information of the offer | N/A | ||||||
price_unit |
Unit price for the offer associated with the order line | N/A | ||||||
product_medias |
List of all product's media associated to the order line | |||||||
media_url |
Media URL | N/A | ||||||
mime_type |
Media MIME Type (.jpg, .png ...) | N/A | ||||||
type |
Media TYPE (small, large...) | N/A | ||||||
product_sku |
Sku of the product associated with the order line | N/A | ||||||
product_title |
Title of the product associated with the order line | Product in Order > Item Title | ||||||
promotions |
List of promotions | N/A | ||||||
quantity |
Product's quantity for the order line | Product in Order > Quantity | ||||||
received_date |
Product's date of receipt | N/A | ||||||
refunds |
List of the refunds | Order Payment with type 'Refund” if there are details in the refund node we will need to create a new refund row. | ||||||
amount |
Refund's amount | Order Refund row > Amount | ||||||
commission_amount |
Refund's commission amount | N/A | ||||||
commission_taxes |
Refund's commission taxes | |||||||
amount |
N/A | |||||||
code |
N/A | |||||||
commission_total_amount |
The total commission amount of the refund (commission amount + commission taxes) | N/A | ||||||
created_date |
Refund's creation date | Order Refund row > Initially Created Date | ||||||
id |
Refund's id | Order Payment > Transaction ID | If we have same Transaction IDs in the response we will need to group them in one single payment row with type=refund |
We need to have the same logic also when we are downloading refund from MIRAKL and compare it to the transaction id.
e.g: Transaction id = 2346-3563-1563
This means there are 3 refunds on the order and we store then in one payment row with 3 refund rows however the transaction id is constructed with all MIRAKL refund ids for the order “2346“, “3563“, “1563“ so when we are downloading the order we need to compare all refund ids. |
| | | | quantity
| | The quantity of products canceled (This quantity is informative only) | | N/A | Based on the details added in the refund row. |
| | | | reason_code
| | Reason's code of the refund | | Order Payment > Reason | Based on the ID we need to store the relevant reason
"code": "15" = "Out of stock"
"code": "16"= "Cancelled by the client prior to shipping"
"code": "17" = "Item returned"
"code": "18"= "Item not received"
"code": "19" = "Agreement found with the vendor" |
| | | | shipping_amount
| | Refund's shipping amount | | Order Refund Row > Amount | This applies for the row with type “shipping“ |
| | | | shipping_taxes
| | The taxes on the shipping price | | | |
| | | | | amount
| Tax amount | | Order Refund Row > Refund VAT | This applies for the row with type “shipping“ |
| | | | | code
| Tax code | | N/A | |
| | | | | rate
| Tax rate | | N/A | |
| | | | state
| | Refund's state
WAITING_REFUND, WAITING_REFUND_PAYMENT, REFUNDED | | N/A | |
| | | | taxes
| | The taxes on the price | | N/A | |
| | | | | amount
| Tax amount | | Order Refund Row > Refund VAT | This applies for the row with type “item“ |
| | | | | code
| Tax code | | N/A | |
| | | | | rate
| Tax rate | | N/A | |
| | | shipped_date
| | | Order line's shipped date | | Orders > Shipping Shipped Date | |
| | | shipping_from
| | | From where (country or full address) the order line is shipped | | N/A | |
| | | | address
| | Describe the address from where the offer is shipped | | | |
| | | | | city
| Address City | | N/A | |
| | | | | country_iso_code
| Address Country ISO 3166-1 alpha-3 code (3 letters country code) | | N/A | |
| | | | | state
| Address State | | N/A | |
| | | | | street_1
| First information line of the address street | | N/A | |
| | | | | street_2
| Second information line of the address street | | N/A | |
| | | | | zip_code
| Address zip code | | N/A | |
| | | shipping_price
| | | Total price of the order line's shipping price | | Product in Order > Item Shipping Cost | |
| | | shipping_taxes
| | | List of taxes applied on shipping charges | | | |
| | | | amount
| | | | Product in Order >Item shipping tax cost | |
| | | | code
| | | | N/A | |
| | | | rate
| | | | N/A | |
| | | taxes
| | | List of taxes applied on product price | | | |
| | | | amount
| | | | Product in Order > Item tax price | |
| | | | code
| | | | N/A | |
| | | | rate
| | | | N/A | |
| | | | tax_calculation_rule
| | The type of automated calculation done during a partial refund or cancellation.
Possible values:
• none: No calculation will be done in case of partial refund or cancellation. You must provide the amount of tax you want to refund or cancel when you request a refund or cancellation. Otherwise, the tax will not get refunded/cancelled.
• proportional_to_amount: Mirakl will automatically calculate the proportional tax amount when a refund or cancellation is requested. You do not need to provide the amount of this tax when you request a refund or cancellation. | | TBD | |
| | | total_commission
| | | Order line's total commission (sum of the commission fee and the commission vat) | | N/A | |
| | | total_price
| | | Order line's price with shipping price | | N/A | |
| | order_state
| | | | Order's state
STAGING, WAITING_ACCEPTANCE, WAITING_DEBIT, WAITING_DEBIT_PAYMENT, SHIPPING, SHIPPED, TO_COLLECT, RECEIVED, CLOSED, REFUSED, CANCELED, INCIDENT_OPEN, REFUNDED, | | Order > Order Status | Note: You can find more detailed explanations & mapped MP statuses to Hemi statuses under “mapping” table. |
| | order_state_reason_code
| | | | Reason's code of the order state | | N/A | |
| | order_state_reason_label
| | | | Reason's label of the order state | | N/A | |
| | payment_type
| | | | The payment's type used by the customer to pay this order | | Order > Order Payment Method | |
| | payment_workflow | | | | The payment workflow followed by the order
PAY_ON_ACCEPTANCE, PAY_ON_DELIVERY, PAY_ON_DUE_DATE, PAY_ON_SHIPMENT, NO_CUSTOMER_PAYMENT_CONFIRMATION | | | PAY_ON_ACCEPTANCE
PAY_ON_DELIVERY
PAY_ON_DUE_DATE
PAY_ON_SHIPMENT
NO_CUSTOMER_PAYMENT_CONFIRMATION |
| | price
| | | | Order's price (sum of order line's price) | | Order > Оrder Subtotal Аmount | without shipping cost |
| | promotions
| | | | Promotions' summary applied to the order | | N/A | |
| | | applied_promotions
| | | The promotions applied on this order | | Order > Discount Type | |
| | | total_deduced_amount
| | | The total amount deduced on this order thanks to the promotions | | Order > Discount | |
| | quote_id
| | | | Quote's id from which the order has been placed, or null if it was not from a quote | | N/A | |
| | references
| | | | Order references | | N/A | |
| | | order_reference_for_customer
| | | Order reference for customer | | N/A | |
| | | order_reference_for_seller
| | | Order reference for seller | | N/A | |
| | shipping_carrier_code
| | | | Shipping carrier code (associated with the Shipping company label) | | N/A | |
| | shipping_company
| | | | Shipping company | | Order Shipment > Carrier
OR
Orders > Carrier | |
| | shipping_deadline
| | | | Order's shipping deadline | | N/A | |
| | shipping_price
| | | | Order's shipping price (sum of order line's shipping price) | | Order > Shipping Service Cost | |
| | shipping_pudo_id
| | | | PickUp DropOff (PUDO) point identifier | | N/A | |
| | shipping_tracking
| | | | Shipping tracking | | Order Shipment > Tracking Number | |
| | shipping_tracking_url
| | | | Shipping tracking url | | Order Shipment > Tracking URL | |
| | shipping_type_code
| | | | Code of shipping's type | | N/A | |
| | shipping_type_label
| | | | Label of shipping's type | | Order > Shipping Service| | | |
shipping_zone_code| | | | Code of shipping's zone | | N/A | | | |
shipping_zone_label| | | | Label of shipping's zone | | N/A | | | |
total_commission| | | | Order's total commission (sum of the order line's total commission) | | Order> Total Fee | | | |
total_price| | | | Total order's price (sum of the order's price and the order's shipping price). | | Order > Оrder Тotal Аmount | | | |
transaction_date| | | | Payment's transaction date | | Order Payment Details > Payment Date | With type “payment“ | | |
transaction_number| | | | Payment's transaction number | | Order Payment Details > Transaction ID | With type “payment“ | | |
fulfillment| | | | Fulfillment information | | N/A | | | | |
center| | | Fulfillment center code | | | | | | | |
code| | Center code | | N/A | | | |
customer_directly_pays_seller| | | | True if order is paid directly to seller. False otherwise | | N/A | | |
total_count` | | | | | Total count of orders | | N/A | |
Get Orders cron should download orders according to their marketplace status:
MP Status | Hemi Status | |
---|---|---|
1 | STAGING | Test Orders |
2 | WAITING_ACCEPTANCE | Pending |
3 | WAITING_DEBIT | Pending |
4 | WAITING_DEBIT_PAYMENT | Pending |
5 | SHIPPING | Ready for Shipping |
6 | SHIPPED | Shipped |
7 | TO_COLLECT | Ready for Shipping |
8 | RECEIVED | Shipped |
9 | CLOSED | Cancelled |
10 | REFUSED | Cancelled |
11 | CANCELED | Cancelled |
12 | INCIDENT_OPEN | Operators and customers can open an incident on an order whenever the order status allows an incident to be opened: |
• Shipping in Progress, • Shipped, • Received. So we will need to make sure we update the Order Item Marketplace Status because the incidents are per order line. If the order is not yet paid if the buyer opens an incident then the seller wont get paid. | | 13 | REFUNDED | Cancelled |
Depend on which status we will receive the order we will need to follow different steps below is described the success flow however we might have cases where we are receiving order directly on Shipping status or even Shipped, thus we need to make sure depends on the status we are receiving the correct actions are performed. For example we are now incorporating the Order Acknowledge flag for MIRAKLs and if we download an order which is already accepted we need to update it as “Completed” otherwise by default each new order is downloaded with “Pending” statuses
If we have a new order which is already shipped we need to store all the relevant details like the order shipments, shipping info and the right statuses. If we have an order which is already stored in Hemi but is not shipped yet and we receive order updated we are updating the order with status shipped we still need to check if the order shipment is created, the shipping information is populated and the statuses are updated. If we have an order which is already stored in Hemi but is not shipped yet however we have added the order shipment and the shipping information and we receive order updated we are updating the order with status shipped without updating any other information in the shipping details
Success Flow:
- MP status = WAITING_ACCEPTANCE; Tool status = Pending and there wont be payment row yet;
- MP status = WAITING_DEBIT; Tool status = Pending and we create a payment row with status Pending;
- MP status = WAITING_DEBIT_PAYMENT; Tool status = Pending and we create a payment row with status Pending;
- MP status = SHIPPING; Tool status = Ready For Shipping and the payment row status is Completed;
- MP status = SHIPPED; Tool status = Shipped and the payment row status is Completed;
- MP status = RECEIVED; Tool status = Shipped and the payment row status is Completed;
Get Modified Orders
In order to get modified orders, we will use GET OR11 - List orders. API Call: GET /api/orders
Parameter | Value | Required | Comment |
---|---|---|---|
order_id | Order identifier | Ye | A comma-separated list of order's identifiers+ |
API Docs: https://decathlonbelgium-preprod.mirakl.net/help/api-doc/seller/mmp.html#OR11
We need to be able to update the orders according to their status on the Marketplace. We have to call each order in the last 30 days which are with statuses different from Closed , Canceled and Shipped. Pease note Get Modified orders will ONLY update existing orders in Hemi but not create new orders. This means depends on the status of the order we will have to create the payment row, update the statuses, delivery details etc. The successful case will be get orders will get all new orders from the last 60 min and they will be with Waiting Acceptance status. Then we will accept the order and Get Modified Orders will update the status of the order as WAITING_DEBIT_PAYMENT Then Get Modified will update to the following status which is Shipping and will have to download the delivery and payment data.
Payload and mapping is the same as Get New Orders.
Hemi Status | Transition | Comment |
---|---|---|
Pending | From “Pending“ we can move to any other Hemi Status | Pending status is indicating that something need to happen on the order like clear debit, waiting acceptance etc. |
Incomplete | From “Incomplete” we can move to | |
”Ready For Shipping”, “Shipped“, “Cancelled“ | Incomplete status is used when we have something missing on the order, like address, items etc. | |
Ready For Shipping | From ”Ready For Shipping” we can move to “Shipped“ or “Cancelled“ only | Ready For Shipping indicates the order can be shipped successfully have all required information stored and payment cleared |
Shipped | From “Shipped“ we can move to “Cancelled“ | Shipped indicating that the order has been dispatched. |
Cancelled | “Cancelled“ is our final status. | Cancelled is the Hemi final status and we cannot revert back or move forward. |
Accept / Reject Orders
By default we do accept all orders in Hemi however we have different cases which we need to cover.
We accept all order items with Product In Order > Status ="WAITING_ACCEPTANCE"
and Order > Marketplace Status = “WAITING_ACCEPTANCE“ we also need to tack the Orders > Acknowledge status.
If we want to pick an order for acceptance we need to have:
Order > Status = “Pending“
Order > Marketplace Status = “WAITING_ACCEPTANCE“
Order > Is Acknowledge = “Pending”
Product In Order > Status ="WAITING_ACCEPTANCE"
Once we push the acceptance successfully we update :
Orders > Marketplace Status = “Acceptance Sent“
Product In Order > Status ="WAITING_ACCEPTANCE"
Order > Is Acknowledge = “Sent”
Order > Status = “Pending“
this way we know the acceptance was sent and waiting for modified order to update the order details and to avoid sending another acceptance for this order.
If we receive an error during the acceptance we update:
Orders > Marketplace Status = “WAITING_ACCEPTANCE
Product In Order > Status ="WAITING_ACCEPTANCE"
Order > Is Acknowledge = “Error”
Order > Status = “Pending“
and we store the relevant error message in Order Error table
If we successfully accept an order we update:
Orders > Marketplace Status = “Shipping”
Product In Order > Status = "Shipping"
Order > Is Acknowledge = “Completed”
Order > Status = “Ready for Shipping“
API Call: PUT /api/orders/{order_id}/accept
API Docs: https://decathlonbelgium-preprod.mirakl.net/help/api-doc/seller/mmp.html#OR21
Example Call:
{
"order_lines": [
{
"accepted": true,
"id": "Order_00012-B-1"
}
]
}
Query parameters:
Parameter | Integration Notes / Value | Required | Notes | |
---|---|---|---|---|
order_lines |
List of representations of order line for acceptance | Yes | ||
accepted |
Boolean indicating if the order line is accepted or refused | |||
‘TRUE' or 'FALSE’ | Yes | In our case if we want to accept we will sent “TRUE“ otherwise “FALSE“ | ||
id |
string | Yes | The value stored in Product In Order > Order Item Line |
Please note we DO accept only order items which are with Order Item > Rejected Order Item = 0 or the status of the order item is NOT “CANCELED“ or “REFUNDED”. This way we have both cases cover we download an order on status “Awaiting Acceptance“ with cancelled order item and if we try to accept it we will receive an error so we need to make sure that only order items with the correct status are accepted. Then if we have order which we do not want to accept all order item our internal teams can set Order Item > Rejected Order Item = 1 and we need to reject the item.
Ship Orders
To ship an order, the order must be accepted & tool status “Ready for shipping“.
Once we have Orders > Update Shipping Pending = Yes, first we need to update the shipping details (Courier, Tracking, Tracking URL) using OR23 then we just mark the order as shipped in Mirakl with OR24 but before all this happen we need to validate the shipping details. In order to do so we check if the Orders > Courier is part from the Mirakl shipping list (SH21).
At the moment when sending shipping updates to Decathlon we are using the courier from Order Shipments > Carrier We want to introduce Courier mapping. Thus we need to create a slave table under Courier called “Decathlon Courier Mapping”. In this table we need to have a dropdown field with all the carriers.
field name | notes |
---|---|
Decathlon Courier | This should be a drop-down menu with the carriers which we get with the GET SH21 - List all carriers. We need to send the carrier_code related to the carrier as well. |
Have all this structure the mapping will works based on: If Order Shipment > Carrier match Courier > Name we send the selected courier from Decathlon Courier Mapping > Decathlon Courier
We also would like to introduce a default case in Account Decathlon called “Default Carrier” where again the same list with carriers (GET SH21 - List all carriers.) to be displayed and to be able to select on specific carrier.
This way the logic will be first we are checking if there is any mapping set in Decathlon Courier Mapping and if we match any of the couriers. If not We are checking if there is default carrier set in Account Decathlon. If not we are should return an error.
We want to be doing this mapping when sending the actual shipping update to the marketplace, so there will be no changes in the record created in Orders > Order Shipments table and we will create the record as we do with our current functionality.
This will be our pilot mapping for a Mirakl integration and ideally we would want to implement it across all Mirakl integrations at some point.
Please note it would be good if we can have button to update the carriers in Decathlon Courier Mapping table.
- GET SH21 - List all carriers
With this call we get all carriers that we could ship with. Please, bear in mind, If we do not match any courier we are shipping with “other“ carrier we have to push carrier code as “Other“ with carrier name (Order Shipment > Carrier) and tracking num (Order Shipment> Tracking Number)
API Call: /api/shipping/carriers
API Docs: https://Decathlon.mirakl.net/help/api-doc/seller/mmp.html#SH21
{
"carriers": [
{
"code": "20-FED",
"label": "Fed Ex",
"tracking_url": "http://www.fedex.com/Tracking?action=track&tracknumbers={trackingId}&zipcode={zipCode}"
},
{
"code": "45-UPS",
"label": "UPS",
"tracking_url": "https://wwwapps.ups.com/WebTracking/track?track=yes&trackNums={trackingId}"
},
{
"code": "23-EVRI",
"label": "EVRI",
"tracking_url": "https://www.evri.com/track/receipt/{trackingId}/list"
}
]
}
- PUT OR23 - Update carrier tracking information for a specific order.
Via this call, we should push to order the reuired information as stated into the below example.
API Call: /api/orders/{order_id}/tracking
API Docs: https://Decathlon.mirakl.net/help/api-doc/seller/mmp.html#OR23
Parameters:
Parameter | Value | Required |
---|---|---|
order_id | String | |
Order identifier | Yes |
Example Call:
{
"carrier_code": "UPS",
"carrier_name": "UPS",
"carrier_url": "https://ups.com",
"tracking_number": 5555
}
Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Note |
---|---|---|---|---|
carrier_code |
String | |||
The code of a carrier. This information is mandatory for a registered carrier. | N | N/A | We Get this from the Shipping List if we match our Order Shipment > Courier with the label | |
carrier_name |
String | |||
The name of a carrier. This information is mandatory for an unregistered carrier. | Y | N/A | We Get this from the Shipping List if we match our Order Shipment > Courier with the label | |
carrier_url |
String | |||
The tracking url of a carrier. This information is unused for registered carriers (because computed automatically). This information is optional for unregistered carriers. | Y | N/A | We Get this from the Shipping List if we match our Order Shipment> Courier with the label | |
tracking_number |
String | |||
The carrier tracking number. This information is mandatory for a registered carrier with a URL requiring a tracking number. | Y | Order Shipment > Tracking Number |
Example Call with “Other“:
{
"carrier_code": "Other",
"carrier_name": "UPS",
"carrier_url": "https://ups.com",
"tracking_number": 5555
}
Mapping with Other:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Note |
---|---|---|---|---|
carrier_code |
String | |||
The code of a carrier. This information is mandatory for a registered carrier. | N | Hardcoded as “Other“ | ||
(If there is no match with the Decathlon carrier list) | ||||
carrier_name |
String | |||
The name of a carrier. This information is mandatory for an unregistered carrier. | Y | Order Shipment > Courier | ||
carrier_url |
String | |||
The tracking url of a carrier. This information is unused for registered carriers (because computed automatically). This information is optional for unregistered carriers. | Y | Order Shipment >Tracking URL | ||
tracking_number |
String | |||
The carrier tracking number. This information is mandatory for a registered carrier with a URL requiring a tracking number. | Y | Order Shipment > Tracking Number |
- PUT OR24 - Validate the shipment of an order
Using this call we simply make a validation of the shipment, after success, the status of the order in Hemi will be “Shipped“
API Call: /api/orders/{order_id}/ship
API Docs: https://Decathlon.mirakl.net/help/api-doc/seller/mmp.html#OR24
Parameters:
Parameter | Value | Required |
---|---|---|
order_id | String | |
Order identifier | Yes |
*Note:** OR23 & OR24 API calls should be incorporated into 1 cron! First we update shipping information (OR23) and then we should validate the shipment (OR24).
Because Mirakl do no support partial shipping we still need to add the shipments in the order but will always ship the full order. However we might have the case where the order will be shipped on Mirakl so we will have to add additional case where if we receive error:
{ "message": "Cannot mark the order with id 'DUX004667443-A' to the new status. Current status is 'SHIPPED', expected is one of '[SHIPPING]'.", "status": 400 }
Again to update our orders > tool status as “Shipped”.
Create Refund/Cancellation
-
The refund/cancellation request on MIRAKL is per item line id and we can include each separate item as additional “refund“ or “cancellation“ node. To process the refund/cancellation , we have to specify a reason which need to be added in the Refund UI for Decathlon Marketplace. In order to obtain the reasons, we should use GET RE01 - List reasons call and then, to make a refund/cancellation , we should use PUT OR28 - Request a refund and OR30 - Request cancelations on order lines
- GET RE01 - List reasons
API Call:
/api/reasons
https://Decathlon.mirakl.net/help/api-doc/seller/mmp.html#RE01
Please note we need to store only the reasons which are with type = “REFUND“ and type = “CANCELATION“
Example response:
{ "reasons": [ { "code": "1", "is_shop_right": false, "label": "Item not received", "type": "INCIDENT_OPEN" }, { "code": "2", "is_shop_right": false, "label": "Item not as ordered", "type": "INCIDENT_OPEN" }, { "code": "3", "is_shop_right": false, "label": "Defective item", "type": "INCIDENT_OPEN" }, { "code": "4", "is_shop_right": false, "label": "Right to retract order", "type": "INCIDENT_OPEN" }, { "code": "5", "is_shop_right": false, "label": "Counterfeit item", "type": "INCIDENT_OPEN" }, { "code": "6", "is_shop_right": false, "label": "Delivery took longer than expected", "type": "INCIDENT_OPEN" }, { "code": "7", "is_shop_right": false, "label": "Client did not respond", "type": "INCIDENT_CLOSE" }, { "code": "8", "is_shop_right": true, "label": "I finally received my order", "type": "INCIDENT_CLOSE" }, { "code": "9", "is_shop_right": false, "label": "Item fit the description after all", "type": "INCIDENT_CLOSE" }, { "code": "10", "is_shop_right": true, "label": "Replacement item received", "type": "INCIDENT_CLOSE" }, { "code": "11", "is_shop_right": false, "label": "Agreement made with the vendor", "type": "INCIDENT_CLOSE" }, { "code": "12", "is_shop_right": false, "label": "Solution found by the operator", "type": "INCIDENT_CLOSE" }, { "code": "13", "is_shop_right": true, "label": "Customer Service handled by the vendor", "type": "INCIDENT_CLOSE" }, { "code": "14", "is_shop_right": false, "label": "No response from the shop", "type": "REFUND" }, { "code": "15", "is_shop_right": true, "label": "Out of stock", "type": "REFUND" }, { "code": "16", "is_shop_right": true, "label": "Cancelled by the client prior to shipping", "type": "REFUND" }, { "code": "17", "is_shop_right": true, "label": "Item returned", "type": "REFUND" }, { "code": "18", "is_shop_right": true, "label": "Item not received", "type": "REFUND" }, { "code": "19", "is_shop_right": true, "label": "Agreement found with the vendor", "type": "REFUND" }, { "code": "20", "is_shop_right": true, "label": "Question about delivery", "type": "MESSAGING" }, { "code": "21", "is_shop_right": true, "label": "Cancel the order", "type": "MESSAGING" }, { "code": "22", "is_shop_right": true, "label": "Issue with item received", "type": "MESSAGING" }, { "code": "23", "is_shop_right": true, "label": "Item not received", "type": "MESSAGING" }, { "code": "24", "is_shop_right": true, "label": "Request an invoice", "type": "MESSAGING" }, { "code": "25", "is_shop_right": true, "label": "Information on the product", "type": "MESSAGING" }, { "code": "26", "is_shop_right": true, "label": "Other question", "type": "MESSAGING" }, { "code": "27", "is_shop_right": true, "label": "Information about the product", "type": "MESSAGING" }, { "code": "28", "is_shop_right": true, "label": "Delivery conditions", "type": "MESSAGING" }, { "code": "29", "is_shop_right": true, "label": "Cancelation, return and refund conditions", "type": "MESSAGING" }, { "code": "30", "is_shop_right": true, "label": "Pricing", "type": "MESSAGING" }, { "code": "31", "is_shop_right": true, "label": "Other", "type": "MESSAGING" }, { "code": "20", "is_shop_right": true, "label": "Question about delivery", "type": "ORDER_MESSAGING" }, { "code": "21", "is_shop_right": true, "label": "Cancel the order", "type": "ORDER_MESSAGING" }, { "code": "22", "is_shop_right": true, "label": "Issue with item received", "type": "ORDER_MESSAGING" }, { "code": "23", "is_shop_right": true, "label": "Item not received", "type": "ORDER_MESSAGING" }, { "code": "24", "is_shop_right": true, "label": "Request an invoice", "type": "ORDER_MESSAGING" }, { "code": "25", "is_shop_right": true, "label": "Information on the product", "type": "ORDER_MESSAGING" }, { "code": "26", "is_shop_right": true, "label": "Other question", "type": "ORDER_MESSAGING" }, { "code": "27", "is_shop_right": true, "label": "Information about the product", "type": "OFFER_MESSAGING" }, { "code": "28", "is_shop_right": true, "label": "Delivery conditions", "type": "OFFER_MESSAGING" }, { "code": "29", "is_shop_right": true, "label": "Cancelation, return and refund conditions", "type": "OFFER_MESSAGING" }, { "code": "30", "is_shop_right": true, "label": "Pricing", "type": "OFFER_MESSAGING" }, { "code": "31", "is_shop_right": true, "label": "Other", "type": "OFFER_MESSAGING" }, { "code": "34", "is_shop_right": true, "label": "Cancelled by the client prior to shipping", "type": "CANCELATION" }, { "code": "CANCELATION_UTS", "is_shop_right": true, "label": "Unable to Ship - Out of stock", "type": "CANCELATION" }, { "code": "SYSTEM_LATE_SHIPMENT_CANCELATION", "is_shop_right": false, "label": "Canceled due to late shipment", "type": "CANCELATION" }, { "code": "CANCELATION_SELLERCUSTOMER", "is_shop_right": true, "label": "Customer Cancelled Via Seller", "type": "CANCELATION" } ], "total_count": 47 }
Bear in mind we need to display the
label
into the UI but to send thecode
. Because in our UI we cannot distinguish the refund from the cancellation we need to add in the label what type is the reason is for the refund or for cancellation. E.G. Refund - {label} or Cancelation - {label}- PUT OR28 - Request a refund
API Call:
/api/orders/refund
API Docs: https://decathlon.mirakl.net/help/api-doc/seller/mmp.html#OR28
*Note:** Each payment row (type=refund) will need to be send as a separate request.
Example call: (one item in order)
{ "refunds": [ { "amount": 10.00, "currency_iso_code": "GBP", "order_line_id": "Order_25082022-6-A-1", "quantity": 1, "reason_code": "15", "excluded_from_shipment": false, "shipping_amount": 2.00 } ] }
Example call: (two items in order)
{ "refunds": [ { "amount": 10.00, "currency_iso_code": "GBP", "order_line_id": "Order_25082022-6-A-1", "quantity": 1, "reason_code": "15", "excluded_from_shipment": false, "shipping_amount": 0 }, { "amount": 10.00, "currency_iso_code": "GBP", "order_line_id": "Order_25082022-6-A-2", "quantity": 1, "reason_code": "15", "excluded_from_shipment": false, "shipping_amount": 0 } ] }
MIRAKL allows us to refund:
- Partially items;
- Shipping
- Orders
So the only validation we will need is to make sure we are not refunding more than we can for particular order item line!
Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes | |
---|---|---|---|---|---|
refunds |
|||||
amount |
Refund Row > Amount | Refund rows with type “item“ | |||
currency_iso_code |
Order > Order currency | ||||
order_line_id |
Product In Order >Item Order Line ID | ||||
quantity |
Product In Order > Quantity | Based on the Refund Row > Amount we need to calculate the quantity! |
• If we are doing partial line refund we specify the quantity as 0.
• If we are doing full line refund (the full quantity)
we specify the actual quantity we have for the item e.g. 1, 2, 3 etc. |
| | reason_code
| | | Order Payment > Reason | We need to use the reason code. |
| | excluded_from_shipment
| | | N/A | |
| | shipping_amount
| | | Refund Row > Amount | Refund rows with type “shipping “ |
Example Response: (one item in order)
{
"order_tax_mode": "TAX_INCLUDED",
"refunds": [
{
"amount": 10.00,
"amount_breakdown": {
"parts": [
{
"amount": 10.00,
"commissionable": true,
"debitable_from_customer": true,
"payable_to_shop": true
}
]
},
"currency_iso_code": "GBP",
"excluded_from_shipment": false,
"order_line_id": "Order_25082022-6-A-1",
"quantity": 1,
"reason_code": "15",
"refund_id": "1109",
"shipping_amount": 2.00,
"shipping_amount_breakdown": {
"parts": [
{
"amount": 2.00,
"commissionable": true,
"debitable_from_customer": true,
"payable_to_shop": true
}
]
},
"shipping_taxes": [],
"taxes": []
}
]
}
Response Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes | ||
---|---|---|---|---|---|---|
order_tax_mode |
||||||
refunds |
||||||
amount |
N/A | |||||
amount_breakdown |
N/A | |||||
currency_iso_code |
N/A | |||||
excluded_from_shipment |
N/A | |||||
order_line_id |
N/A | This will be used for the mapping | ||||
quantity |
N/A | |||||
reason_code |
N/A | |||||
refund_id |
Order Payment Details > Transaction ID | Because each order item is pushed in a separate transaction we will receive more than one refund_id thus we will have to concatenate them with “-“ | ||||
shipping_amount |
||||||
shipping_amount_breakdown |
||||||
shipping_taxes |
||||||
taxes |
- PUT OR30 - Request cancelations on order lines
API Call: /api/orders/cancel
API Docs: https://decathlon.mirakl.net/help/api-doc/seller/mmp.html#OR28
*Note:** Each payment row (type=refund) will need to be send as a separate request.
Example call: (one item in order)
{
"cancelations": [
{
"amount": 1996,
"currency_iso_code": "GBP",
"order_line_id": "419244321-PUM-A-1",
"quantity": 0,
"reason_code": 34,
"shipping_amount": 0
}
]
}
Example call: (two items in order)
{
"cancelations": [
{
"amount": 1996,
"currency_iso_code": "GBP",
"order_line_id": "419244321-PUM-A-1",
"quantity": 0,
"reason_code": 34,
"shipping_amount": 0
},
{
"amount": 1996,
"currency_iso_code": "GBP",
"order_line_id": "419244321-PUM-A-2",
"quantity": 0,
"reason_code": 34,
"shipping_amount": 0
}
]
}
MIRAKL allows us to refund:
- Partially items;
- Shipping
- Orders
So the only validation we will need is to make sure we are not refunding more than we can for particular order item line!
Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes | |
---|---|---|---|---|---|
cancellations |
|||||
amount |
Refund Row > Amount | Refund rows with type “item“ | |||
currency_iso_code |
Order > Order currency | ||||
order_line_id |
Product In Order >Item Order Line ID | ||||
quantity |
Product In Order > Quantity | Based on the Refund Row > Amount we need to calculate the quantity! |
• If we are doing partial line refund we specify the quantity as 0.
• If we are doing full line refund (the full quantity)
we specify the actual quantity we have for the item e.g. 1, 2, 3 etc. |
| | reason_code
| | | Order Payment > Reason | We need to use the reason code. |
| | shipping_amount
| | | Refund Row > Amount | Refund rows with type “shipping “ |
Example Response: (one item in order)
{
"cancelations": [
{
"amount": 2.00,
"amount_breakdown": {
"parts": [
{
"amount": 2.00,
"commissionable": true,
"debitable_from_customer": true,
"payable_to_shop": true
}
]
},
"cancelation_id": "1146",
"currency_iso_code": "GBP",
"order_line_id": "419244321-PUM-A-2",
"quantity": 0,
"reason_code": "34",
"shipping_amount": 0.00,
"shipping_amount_breakdown": {
"parts": [
{
"amount": 0.00,
"commissionable": true,
"debitable_from_customer": true,
"payable_to_shop": true
}
]
},
"shipping_taxes": [
],
"taxes": [
]
}
],
"order_tax_mode": "TAX_INCLUDED"
}
Response Mapping:
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes |
---|
Integration Field | Integration Notes | Integration required | Hemi Mapping | Hemi Notes | |||
---|---|---|---|---|---|---|---|
cancelations |
|||||||
amount |
N/A | ||||||
amount_breakdown |
N/A | ||||||
parts |
|||||||
amount |
N/A | ||||||
commissionable |
N/A | ||||||
debitable_from_customer |
N/A | ||||||
payable_to_shop |
N/A | ||||||
cancellation_id |
Order Payment Details > Transaction ID | Because each order item is pushed in a separate transaction we will receive more than one refund_id thus we will have to concatenate them with “-“ | |||||
currency_iso_code |
N/A | ||||||
excluded_from_shipment |
N/A | ||||||
order_line_id |
N/A | This will be used for the mapping | |||||
quantity |
N/A | ||||||
reason_code |
N/A | ||||||
shipping_amount |
N/A | ||||||
shipping_amount_breakdown |
N/A | ||||||
parts |
|||||||
amount |
N/A | ||||||
commissionable |
N/A | ||||||
debitable_from_customer |
N/A | ||||||
payable_to_shop |
N/A | ||||||
shipping_taxes |
N/A | ||||||
taxes |
N/A | ||||||
order_tax_mode |
N/A |
<v2.1>
PUT OR29 - Cancel an order not yet debited from the customer
API Call: /api/orders/{order_id}/cancel
API Docs: https://help.mirakl.net/help/api-doc/seller/mmp.html#OR29
We have to specify in the URL our Orders
> Marketplace Order Id
Cancel an order not yet debited from the customer. All accepted but NOT shipped orders are treated as “Not Yet Debited” which means that if a cancellation has to happen, we need to use the OR29 call instead of OR30. Please note only full order cancellations for non debited orders are allowed and we would like to add internal validation and return internal error if not full cancellation is done.
Example call:
PUT https://mirakl.marketplace.laredoute.com/api/orders/12341231-A/cancel
Example Response: 204: No Content
Please note since there is no content in the response we wont have a transaction id for the refund so we need to make a OR11 - List Orders call for the specific order that we have cancelled and store the transaction ID.
This needs to be done after each 204: No Content response for the specific order that we are cancelling.
We have developed all possible scenarios:
- If we have
can_cancel
=true
andcustomer_debited_date
=null
andcan_refund
=false
We need to use the OR29 to cancel the order - If we have
can_cancel
=true
andcustomer_debited_date
=date
(in a2023-12-04T12:26:07.043Z
format) andcan_refund
=false
we need to use the OR30 to cancel - If we have for some reason
can_refund
=true
andcan_cancel
=true
we need to use the OR30 to cancel (this is not an expected behavior anyways, if for some reason it happens for whatever reason we want to have it covered) - If we have
can_cancel
=false
andcustomer_debited_date
=null
andcan_refund
=true
We need to use the OR28 to refund the order (this is not an expected behavior anyways, if for some reason it happens for whatever reason we want to have it covered) -
If we have
can_cancel
=false
andcustomer_debited_date
=date
(in a2023-12-04T12:26:07.043Z
format) andcan_refund
=true
We need to use the OR28 to refund the order</v2.1>
Specifics:
We will have couple of cases here because we will have one Order Payment row with type = refund but in MIRAKL there might be couple of transaction:
- If all transaction are successfully and we receive the
refund_id
or thecancellation_id
,we need to mark the Order Payment > Status = "Completed" and Refund Row > Status = "Completed" - If not all transactions are completed but we have one or more completed we mark the Order Payment > Status = “Partially Completed“, Refund Row > Status = “Completed“ for the successful line and Refund Row > Status = “Error“.
Note: The error message stating which Order Item Line failed is stored in Order Error table.
- If all transactions failed we mark Order Payment > Status = “Error“, Refund Row > Status = “Error“ and store the error in Order Error table.
How to decide when to make a cancellation or refund is stated on the order. There are two flags which we can rely on in the order payload called "can_cancel" and “can_refund“ based on them we will know which is the correct request.