Skip to content

Commit 8c3dcfe

Browse files
authored
feat: add support for line items on carts (#326)
1 parent be5a2b5 commit 8c3dcfe

File tree

6 files changed

+737
-7
lines changed

6 files changed

+737
-7
lines changed

.changeset/cold-buttons-attend.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@labdigital/commercetools-mock": minor
3+
---
4+
5+
Add support for custom line items on cart

src/repositories/cart/actions.ts

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@ import type {
1111
Address,
1212
AddressDraft,
1313
Cart,
14+
CartAddCustomLineItemAction,
1415
CartAddItemShippingAddressAction,
1516
CartAddLineItemAction,
17+
CartChangeCustomLineItemMoneyAction,
18+
CartChangeCustomLineItemQuantityAction,
1619
CartChangeLineItemQuantityAction,
1720
CartChangeTaxRoundingModeAction,
21+
CartRemoveCustomLineItemAction,
1822
CartRemoveDiscountCodeAction,
1923
CartRemoveLineItemAction,
2024
CartRemoveShippingMethodAction,
@@ -39,8 +43,10 @@ import type {
3943
Product,
4044
ProductPagedQueryResponse,
4145
ProductVariant,
46+
TaxCategoryReference,
4247
} from "@commercetools/platform-sdk";
4348
import type {
49+
CustomLineItem,
4450
DirectDiscount,
4551
TaxPortion,
4652
TaxedItemPrice,
@@ -58,11 +64,14 @@ import {
5864
createCentPrecisionMoney,
5965
createCustomFields,
6066
createTypedMoney,
67+
getReferenceFromResourceIdentifier,
6168
roundDecimal,
6269
} from "../helpers";
6370
import {
6471
calculateCartTotalPrice,
6572
calculateLineItemTotalPrice,
73+
calculateTaxedPrice,
74+
createCustomLineItemFromDraft,
6675
selectPrice,
6776
} from "./helpers";
6877

@@ -319,6 +328,175 @@ export class CartUpdateHandler
319328
resource.totalPrice.centAmount = calculateCartTotalPrice(resource);
320329
}
321330

331+
addCustomLineItem(
332+
context: RepositoryContext,
333+
resource: Writable<Cart>,
334+
{
335+
money,
336+
name,
337+
slug,
338+
quantity = 1,
339+
taxCategory,
340+
custom,
341+
priceMode = "Standard",
342+
key,
343+
}: CartAddCustomLineItemAction,
344+
) {
345+
const customLineItem = createCustomLineItemFromDraft(
346+
context.projectKey,
347+
{ money, name, slug, quantity, taxCategory, custom, priceMode, key },
348+
this._storage,
349+
resource.country,
350+
);
351+
352+
resource.customLineItems.push(customLineItem);
353+
resource.totalPrice.centAmount = calculateCartTotalPrice(resource);
354+
}
355+
356+
removeCustomLineItem(
357+
context: RepositoryContext,
358+
resource: Writable<Cart>,
359+
{ customLineItemId, customLineItemKey }: CartRemoveCustomLineItemAction,
360+
) {
361+
let customLineItem;
362+
363+
if (!customLineItemId && !customLineItemKey) {
364+
throw new CommercetoolsError<GeneralError>({
365+
code: "General",
366+
message:
367+
"Either customLineItemId or customLineItemKey needs to be provided.",
368+
});
369+
}
370+
371+
if (customLineItemId) {
372+
customLineItem = resource.customLineItems.find(
373+
(x) => x.id === customLineItemId,
374+
);
375+
if (!customLineItem) {
376+
throw new CommercetoolsError<GeneralError>({
377+
code: "General",
378+
message: `A custom line item with ID '${customLineItemId}' not found.`,
379+
});
380+
}
381+
resource.customLineItems = resource.customLineItems.filter(
382+
(x) => x.id !== customLineItemId,
383+
);
384+
}
385+
386+
if (customLineItemKey) {
387+
customLineItem = resource.customLineItems.find(
388+
(x) => x.key === customLineItemKey,
389+
);
390+
if (!customLineItem) {
391+
throw new CommercetoolsError<GeneralError>({
392+
code: "General",
393+
message: `A custom line item with key '${customLineItemKey}' not found.`,
394+
});
395+
}
396+
resource.customLineItems = resource.customLineItems.filter(
397+
(x) => x.key !== customLineItemKey,
398+
);
399+
}
400+
401+
resource.totalPrice.centAmount = calculateCartTotalPrice(resource);
402+
}
403+
404+
changeCustomLineItemQuantity(
405+
context: RepositoryContext,
406+
resource: Writable<Cart>,
407+
{
408+
customLineItemId,
409+
customLineItemKey,
410+
quantity,
411+
}: CartChangeCustomLineItemQuantityAction,
412+
) {
413+
let customLineItem;
414+
415+
if (!customLineItemId && !customLineItemKey) {
416+
throw new CommercetoolsError<GeneralError>({
417+
code: "General",
418+
message:
419+
"Either customLineItemId or customLineItemKey needs to be provided.",
420+
});
421+
}
422+
423+
const setQuantity = (
424+
customLineItem: Writable<CustomLineItem> | undefined,
425+
) => {
426+
if (!customLineItem) {
427+
throw new CommercetoolsError<GeneralError>({
428+
code: "General",
429+
message: `A custom line item with ${customLineItemId ? `ID '${customLineItemId}'` : `key '${customLineItemKey}'`} not found.`,
430+
});
431+
}
432+
customLineItem.quantity = quantity;
433+
customLineItem.totalPrice = createCentPrecisionMoney({
434+
...customLineItem.money,
435+
centAmount: (customLineItem.money.centAmount ?? 0) * quantity,
436+
});
437+
};
438+
439+
if (customLineItemId) {
440+
customLineItem = resource.customLineItems.find(
441+
(x) => x.id === customLineItemId,
442+
);
443+
setQuantity(customLineItem);
444+
}
445+
446+
if (customLineItemKey) {
447+
customLineItem = resource.customLineItems.find(
448+
(x) => x.key === customLineItemKey,
449+
);
450+
setQuantity(customLineItem);
451+
}
452+
453+
// Update cart total price
454+
resource.totalPrice.centAmount = calculateCartTotalPrice(resource);
455+
}
456+
457+
changeCustomLineItemMoney(
458+
context: RepositoryContext,
459+
resource: Writable<Cart>,
460+
{
461+
customLineItemId,
462+
customLineItemKey,
463+
money,
464+
}: CartChangeCustomLineItemMoneyAction,
465+
) {
466+
let customLineItem;
467+
468+
const setMoney = (customLineItem: Writable<CustomLineItem> | undefined) => {
469+
if (!customLineItem) {
470+
throw new CommercetoolsError<GeneralError>({
471+
code: "General",
472+
message: `A custom line item with ${customLineItemId ? `ID '${customLineItemId}'` : `key '${customLineItemKey}'`} not found.`,
473+
});
474+
}
475+
customLineItem.money = createTypedMoney(money);
476+
customLineItem.totalPrice = createCentPrecisionMoney({
477+
...money,
478+
centAmount: (money.centAmount ?? 0) * customLineItem.quantity,
479+
});
480+
};
481+
482+
if (customLineItemId) {
483+
customLineItem = resource.customLineItems.find(
484+
(x) => x.id === customLineItemId,
485+
);
486+
setMoney(customLineItem);
487+
}
488+
489+
if (customLineItemKey) {
490+
customLineItem = resource.customLineItems.find(
491+
(x) => x.key === customLineItemKey,
492+
);
493+
setMoney(customLineItem);
494+
}
495+
496+
// Update cart total price
497+
resource.totalPrice.centAmount = calculateCartTotalPrice(resource);
498+
}
499+
322500
setAnonymousId(
323501
_context: RepositoryContext,
324502
resource: Writable<Cart>,

0 commit comments

Comments
 (0)