Order
Changed on:
17 Oct 2023
Overview
The Order module is responsible for exporting orders to Fluent and receiving order updates.
Key Features:
- Triggers customer export when an order is placed.
- Exports new orders to Fluent.
- Opens a webhook to receive Fluent order-related updates. Other extensions like fulfillment and consignment will leverage this webhook.
- Updates order status based on Fluent updates.
- Creates shipments for all order items based on an incoming order status update. Note that this will blindly mark all items as shipped regardless of how they have been consigned at Fluent.
- This is disabled by default in favour of the consignment module that creates shipments based on how items are actually consigned and shipped at Fluent.
Limitations:
- Does not sync old orders created before the extension is installed.
- If the order sync is temporarily disabled, it will not sync orders placed while it has been disabled once it is re-enabled.
Detailed Technical Description
Order Export
Adobe’s Commerce native message queue was used to export orders. Once an order is saved the system triggers the
`sales_order_save_after event`
`FluentConnector\Order\Observer\PublishOrderToExportQueue`
`FluentConnector\Order\Model\ConfigProvider`
If there is a need to customize when an order is considered ready to be sent to Fluent - ConfigProvider class should be rewritten in DI configuration. To validate order has not been published before the extension tracks when orders are exported through extension attributes: order.extension_attributes.fluent.publish_status should be empty or equal to 0. When an order is ready to be exported then it is added to the message queue with the topic name of fluentcommerce.order.publisher.
Adding order to the export queue contains a few steps:
- Observing order after saving event.
- Running order validation - determining if the order can be exported to Fluent.
- Pushing order data to Adobe’s Message Queue.
- Updating order.extension_attributes.fluent.publish_status to 1(PUBLISHED)
The order exporting process flow :
Exporting logic:
- Read a message from the queue
- Retrieve order entity by order_id(stored in the message)
- Update order.extension_attributes.fluent.publish_status = 2(PROCESSING)
- Create customer
- Check if the customer exists
- Create customer if not present in relevant fluent retailer
- Build create order API request payload
- Send API request
- Authentication
- Sending POST API request itself
- Update order.extension_attributes.fluent.publish_status = 4(COMPLETE)
- Save received fluent_order_id into Adobe order using extension attributes.
Order Status Update
Webhook processing happens in 2 stages.
The first stage does the validation of the signature and checks the content has the required parameters. If all goes well, the request is added to the message queue to be processed asynchronously otherwise Adobe will return an error to Fluent to signal that it was unable to accept the request.
The second stage is the actual processing of the webhook message. The message name is key to drive, how the message is going to be processed as these are mapped to internal handlers in Adobe.
`1 <type name="FluentConnector\General\Api\WebHook\HandlerFactoryInterface"> 2 <arguments> 3 <argument name="handlers" xsi:type="array"> 4 <item name="OrderStatusChanged" xsi:type="string">FluentConnector\Order\Handler\OrderStatusUpdateHandler</item> 5 </argument> 6 </arguments> 7 </type>`
Other modules utilize the same approach by adding their own handlers and enabling the processing of different messages that are specific to their modules.
All webhook carry minimal information and required Adobe to fetch extra details from Fluent in order to complete processing the message received. The diagram below represents the flow executed for an order status update message. It is possible to override certain parts of the code and extend its functionality. For example, fetching more details from Fluent and either saving it in Adobe or using it to drive extra logic. There are some events that can be leveraged to achieve this but if the events aren’t enough Adobe’s Commerce dependency injection is the recommended way.
Order Events
Name | Description | Parameters |
fluent_order_push_before | Event before the order is pushed to Fluent | order of type OrderInterface |
fluent_order_push_after | Event after the order is successfully pushed to Fluent | order of type OrderInterface |
fluent_order_push_prepare_simple_payload_after | Allows customisation of an order line containing a simple product | payload of type array |
fluent_order_push_prepare_configurable_payload_after | Allows customisation of an order line containing a configurable product | payload of type array order_item of type OrderItemInterface |
fluent_order_push_prepare_fulfilment_choice_payload_after | Allows customisation of the fulfilment choice properties | fulfilment of type array request_data of type PushOrderDataRequestInterface |
fluent_order_push_prepare_order_payload_after | Allows customisation of order level properties | order of type OrderInterface payload of type PushOrderDataRequestInterface |
fluent_order_push_query_build_after | Allows customisation of order mutation query | query of type string |