chore: add compare_at_unit_price when price list price is retrieved (#9564)

* chore: add compare_at_unit_price when price list price is retrieved

* chore: add test for update item + more fixes along the way

* chore: fix tests

* chore: add refresh spec

* Apply suggestions from code review

Co-authored-by: Adrien de Peretti <adrien.deperetti@gmail.com>

* chore: use undefined checker

* chore: switch to map

---------

Co-authored-by: Adrien de Peretti <adrien.deperetti@gmail.com>
This commit is contained in:
Riqwan Thamir
2024-10-15 13:05:14 +02:00
committed by GitHub
parent 827b32cffd
commit 537567b679
31 changed files with 2161 additions and 1772 deletions

View File

@@ -48,8 +48,8 @@ export const getLineItemActionsStep = createStep(
if (existingItem && metadataMatches) {
const quantity = MathBN.sum(
existingItem.quantity as number,
item.quantity || 1
).toNumber()
item.quantity ?? 1
)
itemsToUpdate.push({
selector: { id: existingItem.id },
@@ -57,6 +57,9 @@ export const getLineItemActionsStep = createStep(
id: existingItem.id,
quantity: quantity,
variant_id: item.variant_id!,
unit_price: item.unit_price ?? existingItem.unit_price,
compare_at_unit_price:
item.compare_at_unit_price ?? existingItem.compare_at_unit_price,
},
})
} else {

View File

@@ -1,10 +1,13 @@
export const cartFieldsForRefreshSteps = [
"id",
"currency_code",
"quantity",
"subtotal",
"item_subtotal",
"shipping_subtotal",
"region_id",
"currency_code",
"metadata",
"completed_at",
"region.*",
"items.*",
@@ -20,6 +23,7 @@ export const cartFieldsForRefreshSteps = [
"shipping_methods.tax_lines.*",
"customer.*",
"customer.groups.*",
"promotions.code",
]
export const completeCartFields = [
@@ -113,8 +117,7 @@ export const productVariantsFields = [
"product.collection.title",
"product.handle",
"product.discountable",
"calculated_price.calculated_amount",
"calculated_price.is_calculated_price_tax_inclusive",
"calculated_price.*",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.requires_shipping",

View File

@@ -6,16 +6,24 @@ import {
InventoryItemDTO,
ProductVariantDTO,
} from "@medusajs/framework/types"
import { isDefined } from "@medusajs/framework/utils"
import { isDefined, MathBN, PriceListType } from "@medusajs/framework/utils"
interface Input {
item?: CartLineItemDTO
quantity: BigNumberInput
metadata?: Record<string, any>
unitPrice: BigNumberInput
compareAtUnitPrice?: BigNumberInput | null
isTaxInclusive?: boolean
variant: ProductVariantDTO & {
inventory_items: { inventory: InventoryItemDTO }[]
calculated_price: {
calculated_price: {
price_list_type: string
}
original_amount: BigNumberInput
calculated_amount: BigNumberInput
}
}
taxLines?: CreateOrderLineItemTaxLineDTO[]
adjustments?: CreateOrderAdjustmentDTO[]
@@ -39,6 +47,20 @@ export function prepareLineItemData(data: Input) {
throw new Error("Variant does not have a product")
}
let compareAtUnitPrice = data.compareAtUnitPrice
if (
!isDefined(compareAtUnitPrice) &&
variant.calculated_price.calculated_price.price_list_type ===
PriceListType.SALE &&
!MathBN.eq(
variant.calculated_price.original_amount,
variant.calculated_price.calculated_amount
)
) {
compareAtUnitPrice = variant.calculated_price.original_amount
}
// Note: If any of the items require shipping, we enable fulfillment
// unless explicitly set to not require shipping by the item in the request
const { inventory_items: inventoryItems } = variant
@@ -78,7 +100,9 @@ export function prepareLineItemData(data: Input) {
requires_shipping: requiresShipping,
unit_price: unitPrice,
compare_at_unit_price: compareAtUnitPrice,
is_tax_inclusive: !!isTaxInclusive,
metadata,
}

View File

@@ -1,6 +1,6 @@
import {
CartWorkflowDTO,
UsageComputedActions
UsageComputedActions,
} from "@medusajs/framework/types"
import {
Modules,
@@ -85,20 +85,19 @@ export const completeCartWorkflow = createWorkflow(
})
const { variants, sales_channel_id } = transform({ cart }, (data) => {
const allItems: any[] = []
const allVariants: any[] = []
const variantsMap: Record<string, any> = {}
const allItems = data.cart?.items?.map((item) => {
variantsMap[item.variant_id] = item.variant
data.cart?.items?.forEach((item) => {
allItems.push({
id: item.id,
variant_id: item.variant_id,
quantity: item.quantity,
return {
id: item.id,
variant_id: item.variant_id,
quantity: item.quantity,
}
})
allVariants.push(item.variant)
})
return {
variants: allVariants,
variants: Object.values(variantsMap),
items: allItems,
sales_channel_id: data.cart.sales_channel_id,
}
@@ -110,6 +109,8 @@ export const completeCartWorkflow = createWorkflow(
item,
variant: item.variant,
unitPrice: item.raw_unit_price ?? item.unit_price,
compareAtUnitPrice:
item.raw_compare_at_unit_price ?? item.compare_at_unit_price,
isTaxInclusive: item.is_tax_inclusive,
quantity: item.raw_quantity ?? item.quantity,
metadata: item?.metadata,

View File

@@ -0,0 +1,131 @@
import { isDefined, PromotionActions } from "@medusajs/framework/utils"
import {
createWorkflow,
transform,
WorkflowData,
WorkflowResponse,
} from "@medusajs/framework/workflows-sdk"
import { useRemoteQueryStep } from "../../common/steps/use-remote-query"
import { refreshCartShippingMethodsStep, updateLineItemsStep } from "../steps"
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
import {
cartFieldsForRefreshSteps,
productVariantsFields,
} from "../utils/fields"
import { prepareLineItemData } from "../utils/prepare-line-item-data"
import { refreshPaymentCollectionForCartWorkflow } from "./refresh-payment-collection"
import { updateCartPromotionsWorkflow } from "./update-cart-promotions"
import { updateTaxLinesWorkflow } from "./update-tax-lines"
export const refreshCartItemsWorkflowId = "refresh-cart-items"
/**
* This workflow refreshes a cart's items
*/
export const refreshCartItemsWorkflow = createWorkflow(
refreshCartItemsWorkflowId,
(
input: WorkflowData<{
cart_id: string
promo_codes?: string[]
}>
) => {
const cart = useRemoteQueryStep({
entry_point: "cart",
fields: cartFieldsForRefreshSteps,
variables: { id: input.cart_id },
list: false,
})
const variantIds = transform({ cart }, (data) => {
return (data.cart.items ?? []).map((i) => i.variant_id)
})
const pricingContext = transform(
{ cart },
({ cart: { currency_code, region_id, customer_id } }) => {
return {
currency_code,
region_id,
customer_id,
}
}
)
const variants = useRemoteQueryStep({
entry_point: "variants",
fields: productVariantsFields,
variables: {
id: variantIds,
calculated_price: {
context: pricingContext,
},
},
throw_if_key_not_found: true,
}).config({ name: "fetch-variants" })
validateVariantPricesStep({ variants })
const lineItems = transform({ cart, variants }, ({ cart, variants }) => {
const items = cart.items.map((item) => {
const variant = variants.find((v) => v.id === item.variant_id)!
const preparedItem = prepareLineItemData({
variant: variant,
unitPrice: variant.calculated_price.calculated_amount,
isTaxInclusive:
variant.calculated_price.is_calculated_price_tax_inclusive,
quantity: item.quantity,
metadata: item.metadata,
cartId: cart.id,
})
return {
selector: { id: item.id },
data: preparedItem,
}
})
return items
})
const items = updateLineItemsStep({
id: cart.id,
items: lineItems,
})
const refetchedCart = useRemoteQueryStep({
entry_point: "cart",
fields: cartFieldsForRefreshSteps,
variables: { id: cart.id },
list: false,
}).config({ name: "refetchcart" })
refreshCartShippingMethodsStep({ cart: refetchedCart })
updateTaxLinesWorkflow.runAsStep({
input: { cart_id: cart.id, items },
})
const cartPromoCodes = transform({ cart, input }, ({ cart, input }) => {
if (isDefined(input.promo_codes)) {
return input.promo_codes
} else {
return cart.promotions.map((p) => p.code)
}
})
updateCartPromotionsWorkflow.runAsStep({
input: {
cart_id: cart.id,
promo_codes: cartPromoCodes,
action: PromotionActions.REPLACE,
},
})
refreshPaymentCollectionForCartWorkflow.runAsStep({
input: { cart_id: cart.id },
})
return new WorkflowResponse(refetchedCart)
}
)

View File

@@ -2,7 +2,7 @@ import {
AdditionalData,
UpdateCartWorkflowInputDTO,
} from "@medusajs/framework/types"
import { MedusaError, PromotionActions } from "@medusajs/framework/utils"
import { MedusaError } from "@medusajs/framework/utils"
import {
createHook,
createWorkflow,
@@ -16,13 +16,9 @@ import { useRemoteQueryStep } from "../../common"
import {
findOrCreateCustomerStep,
findSalesChannelStep,
refreshCartShippingMethodsStep,
updateCartsStep,
} from "../steps"
import { cartFieldsForRefreshSteps } from "../utils/fields"
import { refreshPaymentCollectionForCartWorkflow } from "./refresh-payment-collection"
import { updateCartPromotionsWorkflow } from "./update-cart-promotions"
import { updateTaxLinesWorkflow } from "./update-tax-lines"
import { refreshCartItemsWorkflow } from "./refresh-cart-items"
export const updateCartWorkflowId = "update-cart"
/**
@@ -133,35 +129,10 @@ export const updateCartWorkflow = createWorkflow(
}
)
const carts = updateCartsStep([cartInput])
updateCartsStep([cartInput])
const cart = useRemoteQueryStep({
entry_point: "cart",
fields: cartFieldsForRefreshSteps,
variables: { id: cartInput.id },
list: false,
}).config({ name: "refetchcart" })
refreshCartShippingMethodsStep({ cart })
updateTaxLinesWorkflow.runAsStep({
input: {
cart_id: carts[0].id,
},
})
updateCartPromotionsWorkflow.runAsStep({
input: {
cart_id: input.id,
promo_codes: input.promo_codes,
action: PromotionActions.REPLACE,
},
})
refreshPaymentCollectionForCartWorkflow.runAsStep({
input: {
cart_id: input.id,
},
const cart = refreshCartItemsWorkflow.runAsStep({
input: { cart_id: cartInput.id, promo_codes: input.promo_codes },
})
const cartUpdated = createHook("cartUpdated", {

View File

@@ -13,7 +13,7 @@ export const productVariantsFields = [
"product.type.value",
"product.collection.title",
"product.handle",
"calculated_price.calculated_amount",
"calculated_price.*",
"inventory_items.inventory_item_id",
"inventory_items.required_quantity",
"inventory_items.inventory.requires_shipping",

View File

@@ -171,6 +171,10 @@ export const confirmOrderEditRequestWorkflow = createWorkflow(
const unitPrice: BigNumberInput =
itemAction.raw_unit_price ?? itemAction.unit_price
const compareAtUnitPrice: BigNumberInput | undefined =
itemAction.raw_compare_at_unit_price ??
itemAction.compare_at_unit_price
const updateAction = itemAction.actions!.find(
(a) => a.action === ChangeActionType.ITEM_UPDATE
)
@@ -196,6 +200,7 @@ export const confirmOrderEditRequestWorkflow = createWorkflow(
variant_id: ordItem.variant_id,
quantity: reservationQuantity,
unit_price: unitPrice,
compare_at_unit_price: compareAtUnitPrice,
})
allVariants.push(ordItem.variant)
})

View File

@@ -104,6 +104,9 @@ export const orderEditAddNewItemWorkflow = createWorkflow(
reference_id: lineItems[index].id,
quantity: item.quantity,
unit_price: item.unit_price ?? lineItems[index].unit_price,
compare_at_unit_price:
item.compare_at_unit_price ??
lineItems[index].compare_at_unit_price,
metadata: item.metadata,
},
}))

View File

@@ -85,6 +85,7 @@ export const orderEditUpdateItemQuantityWorkflow = createWorkflow(
reference_id: item.id,
quantity: item.quantity,
unit_price: item.unit_price,
compare_at_unit_price: item.compare_at_unit_price,
},
}))
}

View File

@@ -105,6 +105,9 @@ export const updateOrderEditAddItemWorkflow = createWorkflow(
details: {
quantity: data.quantity ?? originalAction.details?.quantity,
unit_price: data.unit_price ?? originalAction.details?.unit_price,
compare_at_unit_price:
data.compare_at_unit_price ??
originalAction.details?.compare_at_unit_price,
},
internal_note: data.internal_note,
}