Cart recalculation extension points
Available from B2Bsellers Suite 4.1.5.
Several B2Bsellers features price a cart outside the customer's own session: order approvals, offers, and sales representative fast orders all build a virtual cart and recalculate it. Order approvals go one step further and store a snapshot of the cart, then rebuild it from that snapshot whenever the approval is refreshed.
If your plugin keeps its own data on cart line items, or relies on entity extensions on the customer address, that data does not automatically survive the round trip. The snapshot stores a fixed set of fields, and a rebuilt address is a plain entity without your extensions. Anything your cart collectors or processors depend on has to be put back before recalculation runs.
These events are where you put it back.
Quick overview
OrderApprovalLineItemStructBuildEvent
Once per line item while the snapshot is created
Copy your payload data into the stored snapshot
OrderApprovalCartLineItemBuildEvent
Once per line item while the cart is rebuilt
Put your payload data back on the line item
OrderApprovalCartRebuiltEvent
Once after the cart has been rebuilt
Do one lookup for the whole cart instead of one per item
OrderApprovalAddressMappedEvent
When a customer address is stored in the approval snapshot
Carry address data that is not in the columns into the snapshot
VirtualCartContextBuiltEvent
After the virtual context is built, before recalculation
Re-attach entity extensions the recalculation needs
The first four live in B2bOrderApproval\Components\OrderApproval\Event. VirtualCartContextBuiltEvent lives in B2bSellersCore\Components\Checkout\Cart\Event and applies to every virtual cart, not only order approvals.
All five extend Symfony\Contracts\EventDispatcher\Event and expose their data through getters.
Preserving a value on the line item payload
The common case: your plugin writes a key to the line item payload, and your cart processor needs it to calculate a price. Use the two per-item events as a pair — one copies the value out, the other puts it back.
public function onStructBuild(OrderApprovalLineItemStructBuildEvent $event): void
{
$customFields = $event->getStructItem()->customFields ?? [];
$customFields[self::PAYLOAD_KEY] = $event->getCartLineItem()->getPayloadValue(self::PAYLOAD_KEY);
$event->getStructItem()->customFields = $customFields;
}
public function onCartLineItemBuild(OrderApprovalCartLineItemBuildEvent $event): void
{
$customFields = $event->getStructItem()->customFields ?? [];
if (isset($customFields[self::PAYLOAD_KEY])) {
$event->getLineItem()->setPayloadValue(self::PAYLOAD_KEY, $customFields[self::PAYLOAD_KEY]);
}
}The struct item is handed to you as a live object, so writing to its properties changes what is persisted into the order_approval.line_items column. The same is true of the line item: it is the exact instance that is added to the cart.
OrderApprovalCartLineItemBuildEvent is dispatched after every payload value the suite writes itself — position, originalUnitPrice, originalQuantity, customFields, comment, options — and after the B2bLineItemInformation and LineItemBudget extensions have been attached. Your subscriber always writes last and can override any of them.
Doing one lookup for the whole cart
OrderApprovalCartRebuiltEvent is dispatched once, after the cart has been rebuilt and every per-item event has run. It fires even when the snapshot contained nothing to rebuild.
Preserving data on the address
An order approval stores its own copy of the billing and shipping address, with a newly generated id. Entity extensions on the customer address are not part of that copy, and the originating customer_address.id cannot be recovered afterwards — so anything you need later has to be stored at the moment the snapshot is written.
OrderApprovalAddressMappedEvent gives you the source address and the payload that is about to be written. Both the billing and the shipping path go through it, so one subscriber covers every way an approval is created, including creation by a sales representative and conversion from an offer.
Custom fields and extensions stored on the snapshot are carried back onto the CustomerAddressEntity when the cart is rebuilt, so you can also register an entity extension on order_approval_address and read it directly instead of going through custom fields.
Adjusting the context before recalculation
VirtualCartContextBuiltEvent is the last point at which the sales channel context can be changed so that cart collectors and processors see it. It applies to every virtual cart — order approvals, offers, and sales representative fast orders.
Last updated
Was this helpful?