Skip to content

Commit 02a02dc

Browse files
jarndt-ltmGitHub Enterprise
authored andcommitted
Merge pull request #45 from dzak/main
W-9302034 and W-10275269: Adds cart to order sample apex back in.
2 parents 5704f65 + efce93d commit 02a02dc

File tree

6 files changed

+331
-21
lines changed

6 files changed

+331
-21
lines changed

examples/checkout-main/flows/Checkout_Subflow_Calculate_Promotions.flow

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@
221221
<locationX>1177</locationX>
222222
<locationY>855</locationY>
223223
<flowName>Checkout_Subflow_Error</flowName>
224+
<inputAssignments>
225+
<name>cartId</name>
226+
<value>
227+
<elementReference>cartId</elementReference>
228+
</value>
229+
</inputAssignments>
224230
<inputAssignments>
225231
<name>ErrorMessage</name>
226232
<value>

examples/checkout-main/flows/Checkout_Subflow_Confirm_Price.flow

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@
221221
<locationX>1177</locationX>
222222
<locationY>855</locationY>
223223
<flowName>Checkout_Subflow_Error</flowName>
224+
<inputAssignments>
225+
<name>cartId</name>
226+
<value>
227+
<elementReference>cartId</elementReference>
228+
</value>
229+
</inputAssignments>
224230
<inputAssignments>
225231
<name>ErrorMessage</name>
226232
<value>
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
/**
2+
* This is designed as a handy starting point for writing code to convert a cart to an order. The built in CartToOrder invocable
3+
* action is maintained and has additions and fixes not found in this class. Whenever possible, it is suggested to use that invocable
4+
* action rather than relying on this invocable action that has limited support and is not tested each release.
5+
*
6+
* Multi-currency has not been tested, though you'll see a couple uses of currency codes (CurrencyIsoCode) commented out in this class.
7+
* If you are using multi-currency in your org, I would uncomment those lines out.
8+
*/
9+
public class B2BCartToOrderDraft {
10+
11+
public class B2BCartToOrderDraftRequest {
12+
13+
@InvocableVariable(required=true)
14+
public ID checkoutSessionId;
15+
16+
@InvocableVariable(required=true)
17+
public ID cartId;
18+
}
19+
20+
/**
21+
* @description Maps a cart to an order. Activates it, and closes the cart. Returns the resulting order summary id.
22+
* @param request The checkout session and cart id.
23+
* @return The OrderId that resulted from this class.
24+
*/
25+
@InvocableMethod(label='Map Cart to Order Draft' description='Maps the cart and related data to an order' category='B2B Commerce')
26+
public static List<ID> cartToOrder(List<B2BCartToOrderDraftRequest> request) {
27+
28+
// screen flows do not run in bulk
29+
Id cartId = request[0].cartId;
30+
Id checkoutSessionId = request[0].checkoutSessionId;
31+
32+
// load the primary delivery group (only one supported at this time)
33+
Id cartDeliveryGroupId = [SELECT Id FROM CartDeliveryGroup WHERE CartId = :cartId][0].Id;
34+
35+
Id orderId = mapAndInsertCartToOrder(cartId);
36+
updateCheckoutSession(checkoutSessionId, orderId);
37+
38+
Id orderDeliveryGroupId = mapAndInsertCartDeliveryGroupToOrderDeliveryGroup(cartDeliveryGroupId, orderId);
39+
mapAndInsertCartItems(cartDeliveryGroupId, orderId, orderDeliveryGroupId);
40+
41+
List<ID> orderIds = new List<ID>();
42+
orderIds.add(orderId);
43+
return orderIds;
44+
}
45+
46+
/**
47+
* @description Satisfy the preconditions required to use the following call to Activate the Order
48+
*/
49+
private static void updateCheckoutSession(Id checkoutSessionId, Id orderId) {
50+
try {
51+
CartCheckoutSession checkoutSession = [SELECT OrderId, NextState FROM CartCheckoutSession WHERE Id = :checkoutSessionId LIMIT 1];
52+
checkoutSession.OrderId = orderId;
53+
checkoutSession.NextState = 'Complete';
54+
update checkoutSession;
55+
} catch (Exception e) {
56+
System.debug('An error occurred updating checkout session with the draft order Id');
57+
}
58+
}
59+
60+
/**
61+
* @description Maps the cart entity to an order entity and returns the id of the order entity that was created.
62+
* @param cartId The cart id to map to an order.
63+
* @return The id of the order that was created.
64+
*/
65+
private static Id mapAndInsertCartToOrder(Id cartId) {
66+
// Get the cart data needed to populate the order
67+
List<WebCart> carts = [SELECT Id,
68+
AccountId,
69+
OwnerId,
70+
WebStoreId,
71+
PoNumber,
72+
BillingStreet,
73+
BillingCity,
74+
BillingState,
75+
BillingPostalCode,
76+
BillingCountry,
77+
// CurrencyIsoCode -- multi-currency only
78+
BillingLatitude,
79+
BillingLongitude
80+
FROM WebCart WHERE Id = :cartId];
81+
WebCart cart = carts[0];
82+
83+
84+
// Create the order
85+
Date now = Date.today();
86+
Order order = new Order(
87+
AccountId = cart.AccountId,
88+
OwnerId = cart.OwnerId,
89+
SalesStoreId = cart.WebStoreId,
90+
PoNumber = cart.PoNumber,
91+
BillingStreet = cart.BillingStreet,
92+
BillingCity = cart.BillingCity,
93+
BillingState = cart.BillingState,
94+
BillingPostalCode = cart.BillingPostalCode,
95+
BillingCountry = cart.BillingCountry,
96+
BillingLatitude = cart.BillingLatitude,
97+
BillingLongitude = cart.BillingLongitude,
98+
// CurrencyIsoCode = cart.CurrencyIsoCode, -- multi-currency only
99+
EffectiveDate = now,
100+
OrderedDate = now,
101+
Status = 'Draft'
102+
);
103+
104+
insert(order);
105+
return order.Id;
106+
}
107+
108+
/**
109+
* @description Maps the cart delivery group entity to an order delivery group entity and returns the id of the
110+
* order delivery group entity that was created.
111+
* @param cartDeliveryGroupId The cartDeliveryGroup id to map.
112+
* @param orderId The orderDeliveryGroup is linked to the original order.
113+
* @return The id of the order delivery group that was created.
114+
*/
115+
private static Id mapAndInsertCartDeliveryGroupToOrderDeliveryGroup(Id cartDeliveryGroupId, Id orderId) {
116+
// Get the cart delivery group data needed to populate the order delivery group
117+
List<CartDeliveryGroup> cartDeliveryGroups = [SELECT
118+
DesiredDeliveryDate,
119+
DeliverToName,
120+
ShippingInstructions,
121+
DeliverToStreet,
122+
DeliverToCity,
123+
DeliverToState,
124+
DeliverToPostalCode,
125+
DeliverToCountry,
126+
DeliverToLatitude,
127+
DeliverToLongitude,
128+
DeliveryMethodId
129+
FROM CartDeliveryGroup WHERE Id = :cartDeliveryGroupId];
130+
CartDeliveryGroup cartDeliveryGroup = cartDeliveryGroups[0];
131+
132+
// Create the order delivery group
133+
Date desiredDeliveryDate = toDate(cartDeliveryGroup.DesiredDeliveryDate);
134+
OrderDeliveryGroup orderDeliveryGroup = new OrderDeliveryGroup(
135+
DesiredDeliveryDate = desiredDeliveryDate,
136+
DeliverToName = cartDeliveryGroup.DeliverToName,
137+
DeliveryInstructions = cartDeliveryGroup.ShippingInstructions,
138+
DeliverToStreet = cartDeliveryGroup.DeliverToStreet,
139+
DeliverToCity = cartDeliveryGroup.DeliverToCity,
140+
DeliverToState = cartDeliveryGroup.DeliverToState,
141+
DeliverToPostalCode = cartDeliveryGroup.DeliverToPostalCode,
142+
DeliverToCountry = cartDeliveryGroup.DeliverToCountry,
143+
DeliverToLatitude = cartDeliveryGroup.DeliverToLatitude,
144+
DeliverToLongitude = cartDeliveryGroup.DeliverToLongitude,
145+
OrderDeliveryMethodId = cartDeliveryGroup.DeliveryMethodId,
146+
OrderId = orderId
147+
);
148+
149+
insert(orderDeliveryGroup);
150+
return orderDeliveryGroup.Id;
151+
}
152+
153+
/**
154+
* @description Maps the cart items to a set of order items. This also creates order item adjustments.
155+
* Tax adjustments could probably also be done here, but are not part of the example.
156+
* @param cartDeliveryGroupId the cartDeliveryGroup id for this set of cart items.
157+
* @param orderId The items are linked to the original order.
158+
* @param orderDeliveryGroupId The items are linked to the order delivery group.
159+
*/
160+
private static void mapAndInsertCartItems(Id cartDeliveryGroupId, Id orderId, Id orderDeliveryGroupId) {
161+
// Get the cart items needed to populate the order items and adjustments
162+
List<CartItem> cartItems = [SELECT
163+
AdjustmentAmount,
164+
Product2Id,
165+
Type,
166+
Quantity,
167+
ListPrice,
168+
SalesPrice,
169+
TotalLineAmount
170+
FROM CartItem WHERE CartDeliveryGroupId = :cartDeliveryGroupId];
171+
172+
List<OrderItem> orderItems = new List<OrderItem>();
173+
// For each item, map it to an order, then add adjustments
174+
for (CartItem cartItem : cartItems) {
175+
orderItems.add(mapCartItemToOrderItem(cartItem, orderId, orderDeliveryGroupId));
176+
}
177+
178+
// If there are no items to insert, we can't do anything
179+
if (orderItems.size() == 0 || cartItems.size() != orderItems.size()) {
180+
return;
181+
}
182+
183+
insert(orderItems);
184+
185+
List<OrderItemAdjustmentLineItem> lineItemAdjustments = new List<OrderItemAdjustmentLineItem>();
186+
for (Integer index = 0; index < cartItems.size(); index++) {
187+
OrderItemAdjustmentLineItem lineItemAdjustment = mapOrderItemAdjustmentLineItemTo(cartItems.get(index), orderItems.get(index).Id);
188+
if (lineItemAdjustment != null) {
189+
lineItemAdjustments.add(lineItemAdjustment);
190+
}
191+
}
192+
if (lineItemAdjustments.size() > 0) {
193+
insert(lineItemAdjustments);
194+
}
195+
}
196+
197+
/**
198+
* @description Maps the cart item to an order item.
199+
* @param cartItem The cartItem to map to an order item.
200+
* @param orderId The item is linked to the original order.
201+
* @param orderDeliveryGroupId The item is linked to the order delivery group.
202+
* @return The order item to be inserted.
203+
*/
204+
private static OrderItem mapCartItemToOrderItem(CartItem cartItem, Id orderId, Id orderDeliveryGroupId) {
205+
String orderItemType = getOrderItemType(cartItem.Type);
206+
Decimal unitPrice = getUnitPrice(cartItem);
207+
208+
OrderItem orderItem = new OrderItem(
209+
Product2Id = cartItem.Product2Id,
210+
Type = orderItemType,
211+
Quantity = cartItem.Quantity,
212+
ListPrice = cartItem.ListPrice,
213+
UnitPrice = unitPrice,
214+
OrderId = orderId,
215+
OrderDeliveryGroupId = orderDeliveryGroupId,
216+
TotalLineAmount = cartItem.TotalLineAmount
217+
);
218+
219+
return orderItem;
220+
}
221+
222+
223+
224+
/**
225+
* @description Maps the cart item to create an adjustment line item. If the item would normally cost
226+
* $100, but costs $80, this is where that adjustment is recorded.
227+
* @param cartItem The cartItem to map to an order adjustment line item.
228+
* @param orderItemId The adjustment is mapped to an order item.
229+
* @return The order item adjustment to be inserted.
230+
*/
231+
private static OrderItemAdjustmentLineItem mapOrderItemAdjustmentLineItemTo(CartItem cartItem, Id orderItemId) {
232+
Decimal adjustmentAmount = getAdjustmentAmount(cartItem);
233+
if (adjustmentAmount == null || adjustmentAmount == 0.0) {
234+
return null;
235+
}
236+
237+
OrderItemAdjustmentLineItem orderItemAdjustmentLineItem = new OrderItemAdjustmentLineItem(
238+
Amount = adjustmentAmount,
239+
OrderItemId = orderItemId,
240+
Name = 'Price Adjustment'
241+
);
242+
243+
return orderItemAdjustmentLineItem;
244+
}
245+
246+
247+
/**
248+
* @description Gets the adjustment amount from the cart item. If none exists, returns zero.
249+
* @param cartItem Where to get the adjustment amount from.
250+
* @return The adjustment amount (0, if there is no adjustment).
251+
*/
252+
private static Decimal getAdjustmentAmount(CartItem cartItem) {
253+
if (cartItem.AdjustmentAmount == null) {
254+
return 0;
255+
}
256+
257+
return cartItem.AdjustmentAmount;
258+
}
259+
260+
/**
261+
* @description Gets the order item type from the sales item type. This maps the cart item type to the order item type.
262+
* @param salesItemType The cart item's type.
263+
* @return The order Item Type or null if the type doesn't map.
264+
*/
265+
private static String getOrderItemType(String cartItemType) {
266+
if (cartItemType == 'Product') {
267+
return 'Order Product';
268+
}
269+
if (cartItemType == 'Charge') {
270+
return 'Delivery Charge';
271+
}
272+
273+
return null;
274+
}
275+
276+
/**
277+
* @description Gets the unit price from the cart item. This tries to use the sales price but will default to the list price
278+
* if there is no sales price.
279+
* @param cartItem The item that has the prices.
280+
* @return The unit price.
281+
*/
282+
private static Decimal getUnitPrice(CartItem cartItem) {
283+
if (cartItem.SalesPrice != null) {
284+
return cartItem.SalesPrice;
285+
}
286+
287+
return cartItem.ListPrice;
288+
}
289+
290+
/**
291+
* @description Converts a DateTime object to a Date object.
292+
* @param dt The datetime to convert.
293+
* @return The new Date.
294+
*/
295+
private static Date toDate(DateTime dt) {
296+
if (dt != null) {
297+
return Date.newinstance(dt.year(), dt.month(), dt.day());
298+
}
299+
300+
return null;
301+
}
302+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3+
<apiVersion>54.0</apiVersion>
4+
<status>Active</status>
5+
</ApexClass>

examples/lwc/force-app/main/default/lwc/navigationButtons/navigationButtons.html

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@
22
<div class="slds-card__footer slds-p-vertical_x-small">
33

44
<!-- Previous Button -->
5-
<div if:true={canGoPrevious} class="slds-button slds-button_brand">
6-
<a href="javascript:void(0)" onclick={handlePreviousButton}
7-
>{previousButtonLabel}</a
8-
>
9-
</div>
5+
<button if:true={canGoPrevious} class="slds-button slds-button_outline-brand" onclick={handlePreviousButton}
6+
>{previousButtonLabel}</button
7+
>
108

119
<!-- Next Button -->
12-
<div class="slds-button slds-button_brand">
13-
<a href="javascript:void(0)" onclick={handleNextButton}
14-
>{nextButtonLabel}</a
15-
>
16-
</div>
10+
<button class="slds-button slds-button_brand" onclick={handleNextButton}
11+
>{nextButtonLabel}</button
12+
>
1713
</div>
1814
</template>

examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.html

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,11 @@
108108

109109
<!-- Navigation buttons -->
110110
<div class="slds-card__footer slds-p-vertical_x-small">
111-
112-
<div if:true={canGoPrevious} class="slds-button slds-button_brand">
113-
<a href="javascript:void(0)" onclick={handlePreviousButton}
114-
>{previousButtonLabel}</a
115-
>
116-
</div>
117-
<div class="slds-button slds-button_brand">
118-
<a href="javascript:void(0)" onclick={handlePaymentButton}
119-
>{nextButtonLabel}</a
120-
>
121-
</div>
111+
<button if:true={canGoPrevious} class="slds-button slds-button_outline-brand" onclick={handlePreviousButton}
112+
>{previousButtonLabel}</button
113+
>
114+
<button class="slds-button slds-button_brand" onclick={handlePaymentButton}
115+
>{nextButtonLabel}</button
116+
>
122117
</div>
123118
</template>

0 commit comments

Comments
 (0)