Salesforce Order Management: Create Order & Order Summary

Our Salesforce Order Management journey has started with an introduction post and then continued with the data model post. Now, it is time to initiate the order lifecycle in Salesforce Order Management.

What you’re seeing is the order management lifecycle. It may be different for each project but it shows each stage of the lifecycle in a single view. What I’d like to do is: review each stage of the order management lifecycle and as you can see, it starts with Order & Order Summary objects.

Before jumping into Salesforce Order Management, let’s review some of the channels that can be integrated with Salesforce Order Management.

Salesforce Order Management Sales Channels

Salesforce B2C, B2B & D2C (formerly known as B2B2C and probably in the future will be called B2C) channels represent Salesforce Commerce Cloud products and “Others” can be anything such as Amazon, Google, Facebook, SPS Commerce and so on.

You might wonder why Salesforce B2C is not included in the Salesforce Platform box but Salesforce B2C & D2C. The reason is: Salesforce B2C & D2C are built in Salesforce core. Salesforce B2B, D2C and OMS all are apps on the Salesforce platform but Salesforce B2C is not. It is hosted outside the Salesforce platform. It is formerly known as Demandware which was acquired by Salesforce and turned into a Salesforce product.

Salesforce B2B & D2C share the management app, components, commerce services and shared data model. Thus, orders are created directly in Salesforce. Since Salesforce B2C lives outside of the Salesforce platform, it is connected to Salesforce by an internal (out of the box) Heroku application. In case a custom integration is needed (other channels), Salesforce APIs can be used to create orders in Salesforce.

The Order Object

If you reviewed the previous post data model, you’ll notice that there is an object called Order. That is the object we start with our journey but in Salesforce Order Management, using Order object is not enough. The reason is; consider that this is the entry point of the order lifecycle and there are more stages which will create other records and those records will get some values from this moment.

The diagram above shows us Order & related objects. Blue ones required, green ones optional.

There is nothing preventing us from creating only the Order object but when it comes to creating Order Summary, things will fail due to lack of information. Therefore, there are some required objects that have to be created along with the order object.

  • Order Item: Represents an order product that your organization sells
  • Order Delivery Group: A group of order items that share a delivery method and address. The delivery method and address are used during the fulfillment process, such as shipping as a gift, downloading, picking up in store, or shipping to a standard address

Those are the objects we’ll create on the way along with the order object but an order needs more information. Information that is already defined and will be assigned to the order such as Account, Sales Channel, Order Delivery Method, Payment Gateway or Products. Order objects or the related objects will use relationships in order to bring more data to Order Summary (and related summary objects) therefore service agents can perform various service actions or see all the needed information in a single view.

Creating the Order

As I mentioned above, there are a lot of ways to create an Order in Salesforce Order Management. I’ll use Salesforce APIs to create the order & related records because I believe it is much easier to understand which fields we will populate.

This is the order payload we’ll use to start our journey.

If you check the payload, you will notice that this is a composite request and the payload actually contains multiple requests in it. It has the creation of Order, OrderDeliveryGroup, OrderItem(s) and also updating the order we just created.

Order

Required fields of the Order object are: EffectiveDate, AccountId & Status. The status of the order must be Draft until all the related items are inserted such as OrderItem records and the reason is once the order is activated, it is not editable and most of the projects have a record-triggered flow for status change when an order is activated, automatically, an OrderSummary gets created. So, be sure that you activate the order at the end.

OrderDeliveryGroup

Required fields of the OrderDeliveryGroup object are: OrderId & DeliverToName. Each composite request in the payload returns a response and for OrderId field, as you can see, we use the Id of the composite request’s response which is the Order. OrderDeliveryMethodId field is required for FulfillmentOrder but we’ll cover this one later.

OrderItem

Required fields of the OrderItem object are: OrderId, PricebookEntryId & Product2Id. If Enable Optional Price Books for Orders order setting is enabled in your org, then instead you can skip populating PricebookEntryId and set ListPrice for order items.

And in the last composite request, we update the order status as Activated. That means OrderSummary record can be created for this order.

{
    "allOrNone": true,
    "compositeRequest": [
        {
            "method": "POST",
            "url": "/services/data/v58.0/sobjects/Order",
            "referenceId": "refOrder",
            "body": {
                "Name": "Firat Esmer",
                "EffectiveDate": "2023-07-14",
                "OrderReferenceNumber": "{{orderNumber}}",
                "BillingStreet": "Street",
                "BillingCity": "NEW FAIRFIELD",
                "BillingPostalCode": "06812-2209",
                "BillingCountry": "United States",
                "BillingState": "California",
                "BillingPhoneNumber": "3333333333",
                "OrderedDate": "2023-07-14T00:00:00.000Z",
                "BillingEmailAddress": "firat@esmer.com",
                "AccountId": "0018F00000Bl5r0QAB",
                "Status": "Draft"
            }
        },
        {
            "method": "POST",
            "url": "/services/data/v58.0/composite/sobjects",
            "referenceId": "refGroup1",
            "body": {
                "records": [
                    {
                        "attributes": {
                            "type": "OrderDeliveryGroup"
                        },
                        "EmailAddress": "firat@esmer.com",
                        "DeliverToCity": "NEW YORK",
                        "DeliverToCountry": "United States",
                        "DeliverToName": "Firat Esmer",
                        "DeliverToPostalCode": "06812-2209",
                        "DeliverToStreet": "Street",
                        "DeliverToState": "New York",
                        "PhoneNumber": "3333333333",
                        "OrderDeliveryMethodId": "2Dm8F000000L11qSAC",
                        "OrderId": "@{refOrder.id}"
                    }
                ]
            }
        },
        {
            "method": "POST",
            "url": "/services/data/v58.0/composite/sobjects",
            "referenceId": "refGroup2",
            "body": {
                "allOrNone": true,
                "records": [
                    {
                        "attributes": {
                            "type": "OrderItem"
                        },
                        "Description": "AnteAGE Travel Kit Small",
                        "Type": "Order Product",
                        "Quantity": 5,
                        "TotalLineAmount": 50.00,
                        "LineNumber": 1,
                        "UnitPrice": 10.00,
                        "ListPrice": 10.00,
                        "OrderId": "@{refOrder.id}",
                        "OrderDeliveryGroupId": "@{refGroup1[0].id}",
                        "Product2Id": "01t8F000001fil4QAA"
                    },
                    {
                        "attributes": {
                            "type": "OrderItem"
                        },
                        "Description": "AnteAGE Travel Kit Medium",
                        "Type": "Order Product",
                        "Quantity": 4,
                        "TotalLineAmount": 40.00,
                        "LineNumber": 2,
                        "UnitPrice": 10.00,
                        "ListPrice": 10.00,
                        "OrderId": "@{refOrder.id}",
                        "OrderDeliveryGroupId": "@{refGroup1[0].id}",
                        "Product2Id": "01t8F000001figzQAA"
                    },
                    {
                        "attributes": {
                            "type": "OrderItem"
                        },
                        "Description": "Shipping",
                        "Product2Id": "01t8F000000mxv4QAA",
                        "Type": "Delivery Charge",
                        "Quantity": 1,
                        "TotalLineAmount": 10.00,
                        "LineNumber": 1000,
                        "UnitPrice": 10.00,
                        "ListPrice": 10.00,
                        "OrderId": "@{refOrder.id}",
                        "OrderDeliveryGroupId": "@{refGroup1[0].id}"
                    }
                ]
            }
        },
        {
            "method": "PATCH",
            "url": "/services/data/v58.0/sobjects/Order/@{refOrder.id}",
            "referenceId": "refUpdateOrder",
            "body": {
                "Status": "Activated"
            }
        }
    ]
}

Creating the Order Summary

Activating the Order is not enough to have an OrderSummary record and since the OrderSummary object is some kind of special object, that can’t be created by DML directly. If Apex is preferred, we have to execute a certain method. If flow is preferred, we have to execute a core action.

Salesforce Order Management comes with out-of-the-box flows that are ready to be used. One of them is called Create Order Summary Flow which creates the OrderSummary automatically for you whenever an Order record gets Activated.

In order to create OrderSummary with Apex, we’ll use the core action of Salesforce Order Management. Core actions of Salesforce Order Management are gathered under ConnectAPI namespace.

OrderSummaryCreation class is responsible for holding the method that creates the OrderSummary record.

ConnectApi.OrderSummaryInputRepresentation input = new ConnectApi.OrderSummaryInputRepresentation();
input.orderId = orderId; // required
input.orderLifeCycleType = 'MANAGED';
ConnectAPI.OrderSummaryCreation.createOrderSummary(input);

The only required field of the input is OrderId and OrderLifeCycleType field has the default value as Managed but I would like to talk about order life cycle type as well since it’s an important topic.

Other Ways to Create Order Summary

Creating Order Summary requires ConnectAPI but ConnectAPI doesn’t require Apex always. For example, you can use Flow Core Action for Create Order Summary or Order Summaries REST API.

Order Life Cycle Type

Salesforce Order Management has two types of order life cycle types: Managed & Unmanaged.

Managed means the order will be automatically processed by Order Management. Therefore, all the financial values will be calculated and related records will be created automatically.

Unmanaged means the order will exist as historical order (just for view) and won’t be processed by Order Management. Also, using Order Management core actions won’t be possible.

Order to OrderSummary

When you create the OrderSummary, you will notice that it comes along with related records. Those records are created by that ConnectAPI we just used. You can see how to convertion takes place.

Salesforce Order Management - Order to Order Summary

The original records (on the left side) have their own summary records except OrderPaymentSummary. It collects the information from multiple payment related records.

The core action has a feature that makes our life much easier which is: if you have a custom field on both objects with the same name and the same data type, the value will be copied over to summary object. Therefore additional assignment is not needed after the creation.

Finally, if you’d like to know when an Order Summary record has been created, you can subscribe to OrderSummaryCreatedEvent which is a standard platform event provided by Salesforce.

4 Comments

  1. If we use Apex and ConnectAPI.OrderSummaryCreation.createOrderSummary to create a OrderSummary, will the OrderSummaryCreatedEvent be published?

    1. Hey,
      Yes, the standard platform event OrderSummaryCreatedEvent will be published automatically. You can find more details at the end of the post where I shared a link as well.

  2. Is it possible to update the existing Order and the update that has been done should also update the order summary? For example I want add new Line Item on the existing Order and Order Summary should also updated.

    1. Hey,
      Once the Order Summary record (Managed) is created, you can’t directly modify its items or original Order’s items. You need to apply the changes to Order Summary record by using OMS core actions (ConnectAPIs) which will apply the changes to original Order too.
      For example, there is only one way to add a new Order Item (Summary) record which is using the Add Order Item Summary core action.
      https://help.salesforce.com/s/articleView?id=sf.flow_ref_elements_om_actions_add_ois.htm&type=5

Leave a Comment

Your email address will not be published. Required fields are marked *