Tutorial

This tutorial explains how commercetools supports the ability to edit an already placed order.

Order Edits vs. Direct Order Updates

The first aspect to be aware of when it comes to order editing is the difference between an OrderEdit and a direct order update. The basic principle of an OrderEdit is that it implies financial changes to the purchase agreement. When, e.g., line items are to be removed, added or have their quantity changed, the agreement of the order is changed in a manner that the order total is impacted. Update actions like these have to be captured and processed under an OrderEdit. Direct order updates, on the other hand, do not impact the order total. When ,e.g., the status of the order or a line item is updated, or delivery details are added to the order, these update actions can be performed directly on the order and do not have to be performed through an OrderEdit.

Here is an overview of the order properties that can be updated directly and the properties that have to be updated through an OrderEdit:

Properties that can be updated directly:

  • Order Number
  • States
  • Locale
  • Customer Email Address
  • Billing Address
  • Shipping Address *
  • Payment Info
  • Return Info
  • Deliveries
  • Sync Info

Properties that have to be updated through an OrderEdit:

  • Line Items
  • Custom Line Items
  • Shipping Address *
  • Shipping Rate Input
  • Discounts

Please note that it is possible to update all the properties from the first list under an OrderEdit as well. When an OrderEdit is created because financial aspects of the agreement are to be changed, non-financial properties, such as e.g., email address change, can be updated alongside the financial ones.

(*) You may notice that Shipping Address is listed twice. State and country of a shipping address are used to identify shipping method and rate for an order. This evaluation will, however, only be triggered when the changes to state and country occur within an OrderEdit. If change to state and country is performed via a direct order update, no evaluation of the shipping method and rate will occur.

Example Order Used In This tutorial

Throughout this tutorial, order editing will be illustrated using the order seen below. It is an order with ID "b56f60e5-e93f-4d20-beea-8a4c30050453" and contains line items of product 1, product 2 and product 3 with a cart discount of 10% on all line items.

{
  "id": "b56f60e5-e93f-4d20-beea-8a4c30050453",
  "version": 1,
  "totalPrice": {
    "centAmount": 126000
  },
  "lineItems": [
    {
      "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
      "quantity": 10,
      "productId": "72db8767-446e-499f-8e95-1417aa83f07a",
      "name": {
        "en": "product 1"
      },
      "price": {
        "value": {
          "centAmount": 1000
        }
      },
      "discountedPricePerQuantity": {
        "discountedPrice": {
          "includedDiscounts": [
            {
              "discount": {
                "typeId": "cart-discount",
                "id": "fe8357af-1fbe-456d-b775-57951d397e75"
              },
              "discountedAmount": {
                "centAmount": 100
              }
            }
          ]
        }
      },
      "totalPrice": {
        "centAmount": 9000
      }
    },
    {
      "id": "3ad040f4-bebf-4d7c-ba21-ff2b10bf7555",
      "quantity": 20,
      "productId": "800be733-4707-4019-803c-216d92bba1b0",
      "name": {
        "en": "product 2"
      },
      "price": {
        "value": {
          "centAmount": 2000
        }
      },
      "discountedPricePerQuantity": {
        "discountedPrice": {
          "includedDiscounts": [
            {
              "discount": {
                "typeId": "cart-discount",
                "id": "fe8357af-1fbe-456d-b775-57951d397e75"
              },
              "discountedAmount": {
                "centAmount": 200
              }
            }
          ]
        }
      },
      "totalPrice": {
        "centAmount": 36000
      }
    },
    {
      "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
      "quantity": 30,
      "productId": "34f5df52-5f44-4b3b-85ed-658a86757795",
      "name": {
        "en": "product 3"
      },
      "price": {
        "value": {
          "centAmount": 3000
        }
      },
      "discountedPricePerQuantity": {
        "discountedPrice": {
          "includedDiscounts": [
            {
              "discount": {
                "typeId": "cart-discount",
                "id": "fe8357af-1fbe-456d-b775-57951d397e75"
              },
              "discountedAmount": {
                "centAmount": 300
              }
            }
          ]
        }
      },
      "totalPrice": {
        "centAmount": 81000
      }
    }
  ],
  "inventoryMode": "None",
  "shippingAddress": {
    "country": "DE"
  }
}

Anatomy of an Order Edit

Before illustrating how the above order can be edited, let us first give an overview of the anatomy of an OrderEdit. It is important to think of an OrderEdit as an entity in its own right and not just an action applied to an order. Thus, an OrderEdit consists mainly of the fields id, version, resource, comment, stagedActions, result.

Resource

The resource refers to the order that is to be edited. It can be used with reference expansion with the query parameter expand=resource to get the current data of the Order into the obj field.

{
  "resource": {
    "id": "b56f60e5-e93f-4d20-beea-8a4c30050453",
    "typeId": "order",
    "obj": {
      "totalPrice": {
        "centAmount": 126000
      },
      "lineItems": [
        {
          "quantity": 10,
          "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "totalPrice": {
            "centAmount": 9000
          }
        },
        {
          "quantity": 20,
          "id": "3ad040f4-bebf-4d7c-ba21-ff2b10bf7555",
          "totalPrice": {
            "centAmount": 36000
          }
        },
        {
          "quantity": 30,
          "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
          "totalPrice": {
            "centAmount": 81000
          }
        }
      ]
    }
  }
}

Comment

The comment allows you to document the reason for creating the OrderEdit.

{
  "comment": "The customer called immediately after creating the order to correct the quantities."
}

StagedActions

The stagedActions array contains the update actions which are intended to be applied to the order. The OrderEdit can be thought of as an umbrella entity that encapsulates a series of updates. Once an OrderEdit has been applied, it is no longer possible to update the stagedActions or to apply them again.

{
  "stagedActions": [
    {
      "action": "changeLineItemQuantity",
      "lineItemId": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
      "quantity": 23
    }
  ]
}

Result

The polymorphic result fields holds the state of the OrderEdit.

NotProcessed

Unapplied OrderEdits appear in the OrderEdit query endpoint as NotProcessed.

{
  "result": {
    "type": "NotProcessed"
  }
}

PreviewSuccess

Unapplied valid OrderEdits which are fetched or updated via key or ID contain a preview of the updated order as well as the messages that would be emitted if applied.

{
  "result": {
    "type": "PreviewSuccess",
    "preview": {
      "totalPrice": {
        "centAmount": 137700
      },
      "lineItems": [
        {
          "quantity": 23,
          "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "discountedPricePerQuantity": {
            "discountedPrice": {
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 100
                  }
                }
              ]
            }
          },
          "totalPrice": {
            "centAmount": 20700
          }
        },
        {
          "quantity": 20,
          "id": "3ad040f4-bebf-4d7c-ba21-ff2b10bf7555",
          "discountedPricePerQuantity": {
            "discountedPrice": {
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 200
                  }
                }
              ]
            }
          },
          "totalPrice": {
            "centAmount": 36000
          }
        },
        {
          "quantity": 30,
          "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
          "discountedPricePerQuantity": {
            "discountedPrice": {
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 300
                  }
                }
              ]
            }
          },
          "totalPrice": {
            "centAmount": 81000
          }
        }
      ]
    },
    "messagePayloads": [
      {
        "lineItem": {
          "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "quantity": 23,
          "discountedPrice": {
            "value": {
              "centAmount": 900
            },
            "includedDiscounts": [
              {
                "discount": {
                  "typeId": "cart-discount",
                  "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                },
                "discountedAmount": {
                  "centAmount": 100
                }
              }
            ]
          },
          "discountedPricePerQuantity": [
            {
              "quantity": 10,
              "discountedPrice": {
                "value": {
                  "centAmount": 900
                },
                "includedDiscounts": [
                  {
                    "discount": {
                      "typeId": "cart-discount",
                      "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                    },
                    "discountedAmount": {
                      "centAmount": 100
                    }
                  }
                ]
              }
            }
          ],
          "totalPrice": {
            "centAmount": 9000
          }
        },
        "addedQuantity": 13,
        "type": "OrderLineItemAdded"
      },
      {
        "lineItemId": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
        "discountedPricePerQuantity": [
          {
            "quantity": 23,
            "discountedPrice": {
              "value": {
                "centAmount": 900
              },
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 100
                  }
                }
              ]
            }
          }
        ],
        "totalPrice": {
          "centAmount": 20700
        },
        "taxedPrice": {
          "totalNet": {
            "centAmount": 17395
          },
          "totalGross": {
            "centAmount": 20700
          }
        },
        "type": "OrderLineItemDiscountSet"
      },
      {
        "price": {
          "total": {
            "type": "centPrecision",
            "centAmount": 137700
          },
          "taxed": {
            "totalNet": {
              "centAmount": 115714
            },
            "totalGross": {
              "centAmount": 137700
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 21986
                },
                "name": "de"
              }
            ]
          }
        },
        "oldPrice": {
          "total": {
            "type": "centPrecision",
            "centAmount": 126000
          },
          "taxed": {
            "totalNet": {
              "centAmount": 105882
            },
            "totalGross": {
              "centAmount": 126000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 20118
                },
                "name": "de"
              }
            ]
          }
        },
        "type": "OrderPriceChanged"
      },
      {
        "edit": {
          "typeId": "order-edit",
          "id": "ad268127-4da3-44cc-987f-61862e618a61"
        },
        "result": {
          "type": "Applied",
          "appliedAt": "2018-08-08T12:01:42.382Z",
          "excerptBeforeEdit": {
            "totalPrice": {
              "centAmount": 126000
            },
            "taxedPrice": {
              "totalNet": {
                "centAmount": 105882
              },
              "totalGross": {
                "centAmount": 126000
              },
              "taxPortions": [
                {
                  "rate": 0.19,
                  "amount": {
                    "centAmount": 20118
                  },
                  "name": "de"
                }
              ]
            },
            "version": 1
          },
          "excerptAfterEdit": {
            "totalPrice": {
              "centAmount": 137700
            },
            "taxedPrice": {
              "totalNet": {
                "centAmount": 115714
              },
              "totalGross": {
                "centAmount": 137700
              },
              "taxPortions": [
                {
                  "rate": 0.19,
                  "amount": {
                    "centAmount": 21986
                  },
                  "name": "de"
                }
              ]
            },
            "version": 5
          }
        },
        "type": "OrderEditApplied"
      }
    ]
  }
}

PreviewFailure

Unapplied invalid OrderEdits which are fetched or updated via key or ID contain a preview of the updated order as well as messages that would be emitted if applied.

{
  "result": {
    "errors": [
      {
        "code": "InvalidField",
        "message": "The value '-1' is not valid for field 'quantity'. Negative quantity is not allowed.",
        "action": {
          "action": "changeLineItemQuantity",
          "lineItemId": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "quantity": -1
        },
        "actionIndex": 1,
        "invalidValue": -1,
        "field": "quantity"
      }
    ],
    "type": "PreviewFailure"
  }
}

Applied

The state when an edit has taken effect on the order.

  1. the order version that the OrderEdit resulted in, as well as the order version the OrderEdit was applied to
  2. a timestamp capturing when the OrderEdit was applied
  3. the totalPrice and the taxedPrice before and after the OrderEdit was applied
{
  "result": {
    "type": "Applied",
    "appliedAt": "2018-08-08T12:01:46.641Z",
    "excerptBeforeEdit": {
      "totalPrice": {
        "centAmount": 126000
      },
      "taxedPrice": {
        "totalNet": {
          "centAmount": 105882
        },
        "totalGross": {
          "centAmount": 126000
        },
        "taxPortions": [
          {
            "rate": 0.19,
            "amount": {
              "centAmount": 20118
            },
            "name": "de"
          }
        ]
      },
      "version": 1
    },
    "excerptAfterEdit": {
      "totalPrice": {
        "centAmount": 109800
      },
      "taxedPrice": {
        "totalNet": {
          "centAmount": 92269
        },
        "totalGross": {
          "centAmount": 109800
        },
        "taxPortions": [
          {
            "rate": 0.19,
            "amount": {
              "centAmount": 17531
            },
            "name": "de"
          }
        ]
      },
      "version": 12
    }
  }
}

Order Edit Flow

The basic flow for an OrderEdit is to:

  1. Create an order edit
  2. Configure intended changes
  3. Review the preview
  4. Apply the order edit

In the following, each step will be explained with examples.

1. Create an Order Edit

To create an OrderEdit, the endpoint POST /{projectKey}/orders/edits is called.

When you create an OrderEdit, there is no pointer to a specific order version and no properties from the order are copied and persisted into the OrderEdit. The OrderEdit is merely a staging area that captures the intended changes that are to be performed on the order.

It is possible to create several OrderEdits in parallel for the same order. As mentioned above, an OrderEdit can be given a comment which allows you to e.g., document the reason for creating the OrderEdit.

In the following example, you can see that the OrderEdit intends to change the quantity of a line item of the order "b56f60e5-e93f-4d20-beea-8a4c30050453":

{
  "resource": {
    "id": "b56f60e5-e93f-4d20-beea-8a4c30050453",
    "typeId": "order"
  },
  "stagedActions": [
    {
      "action": "changeLineItemQuantity",
      "lineItemId": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
      "quantity": 23
    }
  ],
  "comment": "The customer called immediately after creating the order to correct the quantities."
}

Once an OrderEdit has been created, it is possible to query it to retrieve the current set of updates it encapsulates. This is done by performing the following query: GET /{projectKey}/orders/edits.

Please note that the OrderEdit feature in its initial release does not support the tracking or reserving of inventory. An OrderEdit can therefore only be created if the InventoryMode of the order is "None".

2. Configure Intended Changes

To capture the intended changes an OrderEdit should encapsulate, you post update actions to /{projectKey}/orders/edits/{editId}. If e.g., you wish to remove one line item and change the quantity to 33 for another line item, you post the following:

{
  "version": 1,
  "actions": [
    {
      "action": "addStagedAction",
      "stagedAction": {
        "action": "removeLineItem",
        "lineItemId": "3ad040f4-bebf-4d7c-ba21-ff2b10bf7555"
      }
    },
    {
      "action": "addStagedAction",
      "stagedAction": {
        "action": "changeLineItemQuantity",
        "lineItemId": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
        "quantity": 33
      }
    }
  ]
}

and get the edit with the updated stagedActions:

{
  "id": "ad268127-4da3-44cc-987f-61862e618a61",
  "version": 3,
  "resource": {
    "id": "b56f60e5-e93f-4d20-beea-8a4c30050453",
    "typeId": "order"
  },
  "comment": "The customer called immediately after creating the order to correct the quantities.",
  "stagedActions": [
    {
      "action": "changeLineItemQuantity",
      "lineItemId": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
      "quantity": 23
    },
    {
      "action": "removeLineItem",
      "lineItemId": "3ad040f4-bebf-4d7c-ba21-ff2b10bf7555"
    },
    {
      "action": "changeLineItemQuantity",
      "lineItemId": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
      "quantity": 33
    }
  ],
  "result": {
    "type": "PreviewSuccess",
    "preview": {
      "totalPrice": {
        "centAmount": 109800
      },
      "lineItems": [
        {
          "quantity": 23,
          "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "discountedPricePerQuantity": {
            "discountedPrice": {
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 100
                  }
                }
              ]
            }
          },
          "totalPrice": {
            "centAmount": 20700
          }
        },
        {
          "quantity": 33,
          "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
          "discountedPricePerQuantity": {
            "discountedPrice": {
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 300
                  }
                }
              ]
            }
          },
          "totalPrice": {
            "centAmount": 89100
          }
        }
      ]
    },
    "messagePayloads": [
      {
        "lineItem": {
          "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "quantity": 23,
          "discountedPrice": {
            "value": {
              "centAmount": 900
            },
            "includedDiscounts": [
              {
                "discount": {
                  "typeId": "cart-discount",
                  "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                },
                "discountedAmount": {
                  "centAmount": 100
                }
              }
            ]
          },
          "discountedPricePerQuantity": [
            {
              "quantity": 10,
              "discountedPrice": {
                "value": {
                  "centAmount": 900
                },
                "includedDiscounts": [
                  {
                    "discount": {
                      "typeId": "cart-discount",
                      "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                    },
                    "discountedAmount": {
                      "centAmount": 100
                    }
                  }
                ]
              }
            }
          ],
          "totalPrice": {
            "centAmount": 9000
          }
        },
        "addedQuantity": 13,
        "type": "OrderLineItemAdded"
      },
      {
        "lineItemId": "3ad040f4-bebf-4d7c-ba21-ff2b10bf7555",
        "removedQuantity": 20,
        "newQuantity": 0,
        "type": "OrderLineItemRemoved"
      },
      {
        "price": {
          "total": {
            "type": "centPrecision",
            "centAmount": 90000
          },
          "taxed": {
            "totalNet": {
              "centAmount": 75630
            },
            "totalGross": {
              "centAmount": 90000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 14370
                },
                "name": "de"
              }
            ]
          }
        },
        "oldPrice": {
          "total": {
            "type": "centPrecision",
            "centAmount": 126000
          },
          "taxed": {
            "totalNet": {
              "centAmount": 105882
            },
            "totalGross": {
              "centAmount": 126000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 20118
                },
                "name": "de"
              }
            ]
          }
        },
        "type": "OrderPriceChanged"
      },
      {
        "lineItem": {
          "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
          "quantity": 33,
          "discountedPrice": {
            "value": {
              "centAmount": 2700
            },
            "includedDiscounts": [
              {
                "discount": {
                  "typeId": "cart-discount",
                  "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                },
                "discountedAmount": {
                  "centAmount": 300
                }
              }
            ]
          },
          "discountedPricePerQuantity": [
            {
              "quantity": 30,
              "discountedPrice": {
                "value": {
                  "centAmount": 2700
                },
                "includedDiscounts": [
                  {
                    "discount": {
                      "typeId": "cart-discount",
                      "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                    },
                    "discountedAmount": {
                      "centAmount": 300
                    }
                  }
                ]
              }
            }
          ],
          "totalPrice": {
            "centAmount": 81000
          }
        },
        "addedQuantity": 3,
        "type": "OrderLineItemAdded"
      },
      {
        "lineItemId": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
        "discountedPricePerQuantity": [
          {
            "quantity": 23,
            "discountedPrice": {
              "value": {
                "centAmount": 900
              },
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 100
                  }
                }
              ]
            }
          }
        ],
        "totalPrice": {
          "centAmount": 20700
        },
        "taxedPrice": {
          "totalNet": {
            "centAmount": 17395
          },
          "totalGross": {
            "centAmount": 20700
          }
        },
        "type": "OrderLineItemDiscountSet"
      },
      {
        "price": {
          "total": {
            "type": "centPrecision",
            "centAmount": 101700
          },
          "taxed": {
            "totalNet": {
              "centAmount": 85462
            },
            "totalGross": {
              "centAmount": 101700
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 16238
                },
                "name": "de"
              }
            ]
          }
        },
        "oldPrice": {
          "total": {
            "type": "centPrecision",
            "centAmount": 90000
          },
          "taxed": {
            "totalNet": {
              "centAmount": 75630
            },
            "totalGross": {
              "centAmount": 90000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 14370
                },
                "name": "de"
              }
            ]
          }
        },
        "type": "OrderPriceChanged"
      },
      {
        "lineItemId": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
        "discountedPricePerQuantity": [
          {
            "quantity": 33,
            "discountedPrice": {
              "value": {
                "centAmount": 2700
              },
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                  },
                  "discountedAmount": {
                    "centAmount": 300
                  }
                }
              ]
            }
          }
        ],
        "totalPrice": {
          "centAmount": 89100
        },
        "taxedPrice": {
          "totalNet": {
            "centAmount": 74874
          },
          "totalGross": {
            "centAmount": 89100
          }
        },
        "type": "OrderLineItemDiscountSet"
      },
      {
        "price": {
          "total": {
            "type": "centPrecision",
            "centAmount": 109800
          },
          "taxed": {
            "totalNet": {
              "centAmount": 92269
            },
            "totalGross": {
              "centAmount": 109800
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 17531
                },
                "name": "de"
              }
            ]
          }
        },
        "oldPrice": {
          "total": {
            "type": "centPrecision",
            "centAmount": 101700
          },
          "taxed": {
            "totalNet": {
              "centAmount": 85462
            },
            "totalGross": {
              "centAmount": 101700
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 16238
                },
                "name": "de"
              }
            ]
          }
        },
        "type": "OrderPriceChanged"
      },
      {
        "edit": {
          "typeId": "order-edit",
          "id": "ad268127-4da3-44cc-987f-61862e618a61"
        },
        "result": {
          "type": "Applied",
          "appliedAt": "2018-08-08T12:01:43.441Z",
          "excerptBeforeEdit": {
            "totalPrice": {
              "centAmount": 126000
            },
            "taxedPrice": {
              "totalNet": {
                "centAmount": 105882
              },
              "totalGross": {
                "centAmount": 126000
              },
              "taxPortions": [
                {
                  "rate": 0.19,
                  "amount": {
                    "centAmount": 20118
                  },
                  "name": "de"
                }
              ]
            },
            "version": 1
          },
          "excerptAfterEdit": {
            "totalPrice": {
              "centAmount": 109800
            },
            "taxedPrice": {
              "totalNet": {
                "centAmount": 92269
              },
              "totalGross": {
                "centAmount": 109800
              },
              "taxPortions": [
                {
                  "rate": 0.19,
                  "amount": {
                    "centAmount": 17531
                  },
                  "name": "de"
                }
              ]
            },
            "version": 10
          }
        },
        "type": "OrderEditApplied"
      }
    ]
  }
}

As soon as you post update actions to an OrderEdit, the entire set of actions captured under stagedActions will be run against the order. As a response, you get the order back as if the update actions had been applied. The dry run is always performed against the latest version of the order. Should the order endpoint have any API extensions, these will always be called as part of the dry run.

In addition to the preview order, the response will also include messages. The messages are capturing the semantic change you applied to an order. E.g., there will be a OrderLineItemAdded message telling you that a line item was added. Another example could be that with the addition of a specific line item, the order is now eligible for a certain discount, in which case there will be a message OrderDiscountAdded. This makes it easy to see the changes of the OrderEdit and understand the impact on the total order price.

Apart from the update action addStagedAction, which appends a staged action at the end of the stagedActions array of an edit, the action setStagedActions can be used to replace all stagedActions.

3. Review the preview

A careful review is needed due to the order always respecting the current product catalog with the current price configuration and the current promotions.

The previous example is an OrderEdit that occurred close to the time of the original order placement. A customer calling customer service an hour after the order was placed asking for a line item to be removed. In this case, no additional impact of editing the order is likely to occur. Therefore, the staged resulting order and the accompanying messages will reflect only the changes that have been actively posted to the OrderEdit.

Now let us assume that more time has passed between order placement and the creation of an OrderEdit. In this time span, one of the products referred by a line item now has a different price, and the cart discount that applied to the original order was time bound and no longer valid at the time of the OrderEdit. In this case, the actively posted update action is still to remove a line item, but the consequence of the edit is much broader. The staged resulting order does not only have a line item removed; another line item has a new price and the cart discount is no longer applied.

Depending on your business protocol, the OrderEdit can now be updated to account for these derived consequences of opening the order up for editing. In the following example, we assume that business protocol states that the new price will be applied, but that the cart discount should still apply. For such a case, the customer service department have a dedicated discount code, named “10% Cart Discount” that can be applied to achieve the wanted cart discount. Therefore, the “10% Cart Discount” is added to the stagedAction set.

{
  "version": 3,
  "actions": [
    {
      "action": "addStagedAction",
      "stagedAction": {
        "action": "addDiscountCode",
        "code": "code-7835005b-f251-4133-918e-3ac847dcdd97"
      }
    }
  ]
}

You now see in the result that the loss of the cart discount has been circumvented.

For review purposes, it is also important to be aware that the messages that are returned in the OrderEdit response include a OrderEditApplied message. This message captures the “before” and “after” value of the Net Total, Gross Total and Tax Portion. By having such a summary message, it can easily be presented and recognized if the overall impact of the OrderEdit is acceptable and whether the OrderEdit is okay to be applied to the order.

{
  "result": {
    "type": "PreviewSuccess",
    "preview": {
      "totalPrice": {
        "centAmount": 109800
      },
      "lineItems": [
        {
          "quantity": 23,
          "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "discountedPricePerQuantity": {
            "discountedPrice": {
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "7835005b-f251-4133-918e-3ac847dcdd97"
                  },
                  "discountedAmount": {
                    "centAmount": 100
                  }
                }
              ]
            }
          },
          "totalPrice": {
            "centAmount": 20700
          }
        },
        {
          "quantity": 33,
          "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
          "discountedPricePerQuantity": {
            "discountedPrice": {
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "7835005b-f251-4133-918e-3ac847dcdd97"
                  },
                  "discountedAmount": {
                    "centAmount": 300
                  }
                }
              ]
            }
          },
          "totalPrice": {
            "centAmount": 89100
          }
        }
      ]
    },
    "messagePayloads": [
      {
        "lineItem": {
          "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
          "quantity": 23,
          "discountedPrice": {
            "value": {
              "centAmount": 900
            },
            "includedDiscounts": [
              {
                "discount": {
                  "typeId": "cart-discount",
                  "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                },
                "discountedAmount": {
                  "centAmount": 100
                }
              }
            ]
          },
          "discountedPricePerQuantity": [
            {
              "quantity": 10,
              "discountedPrice": {
                "value": {
                  "centAmount": 900
                },
                "includedDiscounts": [
                  {
                    "discount": {
                      "typeId": "cart-discount",
                      "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                    },
                    "discountedAmount": {
                      "centAmount": 100
                    }
                  }
                ]
              }
            }
          ],
          "totalPrice": {
            "centAmount": 9000
          }
        },
        "addedQuantity": 13,
        "type": "OrderLineItemAdded"
      },
      {
        "lineItemId": "3ad040f4-bebf-4d7c-ba21-ff2b10bf7555",
        "removedQuantity": 20,
        "newQuantity": 0,
        "type": "OrderLineItemRemoved"
      },
      {
        "price": {
          "total": {
            "type": "centPrecision",
            "centAmount": 90000
          },
          "taxed": {
            "totalNet": {
              "centAmount": 75630
            },
            "totalGross": {
              "centAmount": 90000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 14370
                },
                "name": "de"
              }
            ]
          }
        },
        "oldPrice": {
          "total": {
            "type": "centPrecision",
            "centAmount": 126000
          },
          "taxed": {
            "totalNet": {
              "centAmount": 105882
            },
            "totalGross": {
              "centAmount": 126000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 20118
                },
                "name": "de"
              }
            ]
          }
        },
        "type": "OrderPriceChanged"
      },
      {
        "lineItem": {
          "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
          "quantity": 33,
          "discountedPrice": {
            "value": {
              "centAmount": 2700
            },
            "includedDiscounts": [
              {
                "discount": {
                  "typeId": "cart-discount",
                  "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                },
                "discountedAmount": {
                  "centAmount": 300
                }
              }
            ]
          },
          "discountedPricePerQuantity": [
            {
              "quantity": 30,
              "discountedPrice": {
                "value": {
                  "centAmount": 2700
                },
                "includedDiscounts": [
                  {
                    "discount": {
                      "typeId": "cart-discount",
                      "id": "fe8357af-1fbe-456d-b775-57951d397e75"
                    },
                    "discountedAmount": {
                      "centAmount": 300
                    }
                  }
                ]
              }
            }
          ],
          "totalPrice": {
            "centAmount": 81000
          }
        },
        "addedQuantity": 3,
        "type": "OrderLineItemAdded"
      },
      {
        "discountCode": {
          "typeId": "discount-code",
          "id": "bf3f7b14-e83e-49fb-9085-000b6cbea04a"
        },
        "type": "OrderDiscountCodeAdded"
      },
      {
        "lineItemId": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
        "discountedPricePerQuantity": [
          {
            "quantity": 23,
            "discountedPrice": {
              "value": {
                "centAmount": 900
              },
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "7835005b-f251-4133-918e-3ac847dcdd97"
                  },
                  "discountedAmount": {
                    "centAmount": 100
                  }
                }
              ]
            }
          }
        ],
        "totalPrice": {
          "centAmount": 20700
        },
        "taxedPrice": {
          "totalNet": {
            "centAmount": 17395
          },
          "totalGross": {
            "centAmount": 20700
          }
        },
        "type": "OrderLineItemDiscountSet"
      },
      {
        "price": {
          "total": {
            "type": "centPrecision",
            "centAmount": 101700
          },
          "taxed": {
            "totalNet": {
              "centAmount": 85462
            },
            "totalGross": {
              "centAmount": 101700
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 16238
                },
                "name": "de"
              }
            ]
          }
        },
        "oldPrice": {
          "total": {
            "type": "centPrecision",
            "centAmount": 90000
          },
          "taxed": {
            "totalNet": {
              "centAmount": 75630
            },
            "totalGross": {
              "centAmount": 90000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 14370
                },
                "name": "de"
              }
            ]
          }
        },
        "type": "OrderPriceChanged"
      },
      {
        "lineItemId": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
        "discountedPricePerQuantity": [
          {
            "quantity": 33,
            "discountedPrice": {
              "value": {
                "centAmount": 2700
              },
              "includedDiscounts": [
                {
                  "discount": {
                    "typeId": "cart-discount",
                    "id": "7835005b-f251-4133-918e-3ac847dcdd97"
                  },
                  "discountedAmount": {
                    "centAmount": 300
                  }
                }
              ]
            }
          }
        ],
        "totalPrice": {
          "centAmount": 89100
        },
        "taxedPrice": {
          "totalNet": {
            "centAmount": 74874
          },
          "totalGross": {
            "centAmount": 89100
          }
        },
        "type": "OrderLineItemDiscountSet"
      },
      {
        "price": {
          "total": {
            "type": "centPrecision",
            "centAmount": 109800
          },
          "taxed": {
            "totalNet": {
              "centAmount": 92269
            },
            "totalGross": {
              "centAmount": 109800
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 17531
                },
                "name": "de"
              }
            ]
          }
        },
        "oldPrice": {
          "total": {
            "type": "centPrecision",
            "centAmount": 101700
          },
          "taxed": {
            "totalNet": {
              "centAmount": 85462
            },
            "totalGross": {
              "centAmount": 101700
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 16238
                },
                "name": "de"
              }
            ]
          }
        },
        "type": "OrderPriceChanged"
      },
      {
        "discountCode": {
          "typeId": "discount-code",
          "id": "bf3f7b14-e83e-49fb-9085-000b6cbea04a"
        },
        "state": "MatchesCart",
        "type": "OrderDiscountCodeStateSet"
      },
      {
        "edit": {
          "typeId": "order-edit",
          "id": "ad268127-4da3-44cc-987f-61862e618a61"
        },
        "result": {
          "type": "Applied",
          "appliedAt": "2018-08-08T12:01:46.073Z",
          "excerptBeforeEdit": {
            "totalPrice": {
              "centAmount": 126000
            },
            "taxedPrice": {
              "totalNet": {
                "centAmount": 105882
              },
              "totalGross": {
                "centAmount": 126000
              },
              "taxPortions": [
                {
                  "rate": 0.19,
                  "amount": {
                    "centAmount": 20118
                  },
                  "name": "de"
                }
              ]
            },
            "version": 1
          },
          "excerptAfterEdit": {
            "totalPrice": {
              "centAmount": 109800
            },
            "taxedPrice": {
              "totalNet": {
                "centAmount": 92269
              },
              "totalGross": {
                "centAmount": 109800
              },
              "taxPortions": [
                {
                  "rate": 0.19,
                  "amount": {
                    "centAmount": 17531
                  },
                  "name": "de"
                }
              ]
            },
            "version": 12
          }
        },
        "type": "OrderEditApplied"
      }
    ]
  }
}

4. Applying an Order Edit

Once you are ready to apply the OrderEdit to the order, you do so by using the apply update action on POST /orders/edits/:id/apply with the version of the order and the version of the edit as parameters:

{
  "resourceVersion": 1,
  "editVersion": 4
}

Taking the second example from above, when the OrderEdit is applied, the resulting order version looks like this:

{
  "id": "b56f60e5-e93f-4d20-beea-8a4c30050453",
  "version": 12,
  "totalPrice": {
    "centAmount": 109800
  },
  "lineItems": [
    {
      "id": "90a0b9e2-5ab7-437e-bb63-38820f6e211e",
      "quantity": 23,
      "productId": "72db8767-446e-499f-8e95-1417aa83f07a",
      "name": {
        "en": "product 1"
      },
      "price": {
        "value": {
          "centAmount": 1000
        }
      },
      "discountedPricePerQuantity": {
        "discountedPrice": {
          "includedDiscounts": [
            {
              "discount": {
                "typeId": "cart-discount",
                "id": "7835005b-f251-4133-918e-3ac847dcdd97"
              },
              "discountedAmount": {
                "centAmount": 100
              }
            }
          ]
        }
      },
      "totalPrice": {
        "centAmount": 20700
      }
    },
    {
      "id": "f3051e28-bd43-4024-ab52-ffaba6323ad2",
      "quantity": 33,
      "productId": "34f5df52-5f44-4b3b-85ed-658a86757795",
      "name": {
        "en": "product 3"
      },
      "price": {
        "value": {
          "centAmount": 3000
        }
      },
      "discountedPricePerQuantity": {
        "discountedPrice": {
          "includedDiscounts": [
            {
              "discount": {
                "typeId": "cart-discount",
                "id": "7835005b-f251-4133-918e-3ac847dcdd97"
              },
              "discountedAmount": {
                "centAmount": 300
              }
            }
          ]
        }
      },
      "totalPrice": {
        "centAmount": 89100
      }
    }
  ],
  "inventoryMode": "None",
  "shippingAddress": {
    "country": "DE"
  }
}

Order Messages for Applied Edits

When an OrderEdit is applied, the order itself, i.e., NOT the OrderEdit, will trigger a notification with the message OrderEditAppliedMessage.

As with any other message type, the message endpoint can be used to query this message. This will provide you with information about the edit that has been applied to ther order:

GET /messages?where=resource(id = "${order.id}") and resourceVersion > ${edit.result.excerptBeforeEdit.version} and resourceVersion <= ${edit.result.excerptBeforeEdit.version}&sort=sequenceNumber asc

{
  "count": 11,
  "total": 11,
  "results": [
    {
      "id": "c68a6af1-24a2-4cc4-a721-5a9fc383f3c3",
      "type": "OrderLineItemAdded",
      "resourceVersion": 2,
      "sequenceNumber": 2
    },
    {
      "id": "9c56480b-fef6-4ca1-9f46-ed9f8134fc1f",
      "type": "OrderLineItemRemoved",
      "resourceVersion": 3,
      "sequenceNumber": 3
    },
    {
      "id": "e9e97b06-9aa1-4cdf-a9d2-9ccfe1eb7f45",
      "type": "OrderPriceChanged",
      "resourceVersion": 4,
      "sequenceNumber": 4
    },
    {
      "id": "f526c8c9-375f-45c6-aef1-f48d1bba4aac",
      "type": "OrderLineItemAdded",
      "resourceVersion": 5,
      "sequenceNumber": 5
    },
    {
      "id": "6352b22d-7ff5-431c-9897-43562d25978d",
      "type": "OrderDiscountCodeAdded",
      "resourceVersion": 6,
      "sequenceNumber": 6
    },
    {
      "id": "3d18ee04-3438-407a-87ca-6a728049ae5a",
      "type": "OrderLineItemDiscountSet",
      "resourceVersion": 7,
      "sequenceNumber": 7
    },
    {
      "id": "e1aeacaa-c63e-4946-bc4c-ea565ce849d9",
      "type": "OrderPriceChanged",
      "resourceVersion": 8,
      "sequenceNumber": 8
    },
    {
      "id": "ed36566a-1226-4a19-b026-31da586d981b",
      "type": "OrderLineItemDiscountSet",
      "resourceVersion": 9,
      "sequenceNumber": 9
    },
    {
      "id": "905cc22b-8f47-402b-9f32-9b0e2528048e",
      "type": "OrderPriceChanged",
      "resourceVersion": 10,
      "sequenceNumber": 10
    },
    {
      "id": "c7723b17-84a2-4d0c-845a-0f87278c96de",
      "type": "OrderDiscountCodeStateSet",
      "resourceVersion": 11,
      "sequenceNumber": 11
    },
    {
      "id": "82382cc4-0151-4060-80c0-7818e6e8bada",
      "type": "OrderEditApplied",
      "resourceVersion": 12,
      "sequenceNumber": 12,
      "result": {
        "type": "Applied",
        "appliedAt": "2018-08-08T12:01:46.641Z",
        "excerptBeforeEdit": {
          "totalPrice": {
            "centAmount": 126000
          },
          "taxedPrice": {
            "totalNet": {
              "centAmount": 105882
            },
            "totalGross": {
              "centAmount": 126000
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 20118
                },
                "name": "de"
              }
            ]
          },
          "version": 1
        },
        "excerptAfterEdit": {
          "totalPrice": {
            "centAmount": 109800
          },
          "taxedPrice": {
            "totalNet": {
              "centAmount": 92269
            },
            "totalGross": {
              "centAmount": 109800
            },
            "taxPortions": [
              {
                "rate": 0.19,
                "amount": {
                  "centAmount": 17531
                },
                "name": "de"
              }
            ]
          },
          "version": 12
        }
      }
    }
  ]
}