feat(core-flows,types,utils,medusa): Update existing line items when adding the same variant to cart (#7470)
* feat(core-flows,types,utils,medusa): Update existing line items when adding the same variant to cart * chore: split steps into 2 for add-to-cart * chore: split steps into 2 for add-to-cart * chore: iterate safely * chore: parallelize upsert
This commit is contained in:
1 parent
81c27e3524
commit
7baedf73d5
16 files changed
+339
-49
No files matched your search
@@ -17,6 +17,7 @@ import {
|
|||||||
IRegionModuleService,
|
IRegionModuleService,
|
||||||
ISalesChannelModuleService,
|
ISalesChannelModuleService,
|
||||||
ITaxModuleService,
|
ITaxModuleService,
|
||||||
|
ProductStatus,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
@@ -1166,14 +1167,65 @@ medusaIntegrationTestRunner({
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe("POST /store/carts/:id/line-items", () => {
|
describe("POST /store/carts/:id/line-items", () => {
|
||||||
it.skip("should add item to cart", async () => {
|
let region
|
||||||
|
const productData = {
|
||||||
|
title: "Medusa T-Shirt",
|
||||||
|
handle: "t-shirt",
|
||||||
|
status: ProductStatus.PUBLISHED,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: "Size",
|
||||||
|
values: ["S"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Color",
|
||||||
|
values: ["Black", "White"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
title: "S / Black",
|
||||||
|
sku: "SHIRT-S-BLACK",
|
||||||
|
options: {
|
||||||
|
Size: "S",
|
||||||
|
Color: "Black",
|
||||||
|
},
|
||||||
|
manage_inventory: false,
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
amount: 1500,
|
||||||
|
currency_code: "usd",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "S / White",
|
||||||
|
sku: "SHIRT-S-WHITE",
|
||||||
|
options: {
|
||||||
|
Size: "S",
|
||||||
|
Color: "White",
|
||||||
|
},
|
||||||
|
manage_inventory: false,
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
amount: 1500,
|
||||||
|
currency_code: "usd",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
await setupTaxStructure(taxModule)
|
await setupTaxStructure(taxModule)
|
||||||
|
|
||||||
const region = await regionModule.create({
|
region = await regionModule.create({
|
||||||
name: "US",
|
name: "US",
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should add item to cart", async () => {
|
||||||
const customer = await customerModule.create({
|
const customer = await customerModule.create({
|
||||||
email: "tony@stark-industries.com",
|
email: "tony@stark-industries.com",
|
||||||
})
|
})
|
||||||
@@ -1357,6 +1409,82 @@ medusaIntegrationTestRunner({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("adding an existing variant should update or create line item depending on metadata", async () => {
|
||||||
|
const product = (
|
||||||
|
await api.post(`/admin/products`, productData, adminHeaders)
|
||||||
|
).data.product
|
||||||
|
|
||||||
|
const cart = (
|
||||||
|
await api.post(`/store/carts`, {
|
||||||
|
email: "tony@stark.com",
|
||||||
|
currency_code: region.currency_code,
|
||||||
|
region_id: region.id,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
metadata: {
|
||||||
|
Size: "S",
|
||||||
|
Color: "Black",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
).data.cart
|
||||||
|
|
||||||
|
let response = await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
metadata: {
|
||||||
|
Size: "S",
|
||||||
|
Color: "Black",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.cart).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
items: [
|
||||||
|
expect.objectContaining({
|
||||||
|
unit_price: 1500,
|
||||||
|
quantity: 2,
|
||||||
|
title: "S / Black",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
subtotal: 3000,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
response = await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
metadata: {
|
||||||
|
Size: "S",
|
||||||
|
Color: "White",
|
||||||
|
Special: "attribute",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.cart).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
items: [
|
||||||
|
expect.objectContaining({
|
||||||
|
unit_price: 1500,
|
||||||
|
quantity: 2,
|
||||||
|
title: "S / Black",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
unit_price: 1500,
|
||||||
|
quantity: 1,
|
||||||
|
title: "S / Black",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
subtotal: 4500,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("POST /store/payment-collections", () => {
|
describe("POST /store/payment-collections", () => {
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
|
||||||
import { CreateLineItemForCartDTO, ICartModuleService } from "@medusajs/types"
|
|
||||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
|
||||||
|
|
||||||
interface StepInput {
|
|
||||||
items: CreateLineItemForCartDTO[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const addToCartStepId = "add-to-cart-step"
|
|
||||||
export const addToCartStep = createStep(
|
|
||||||
addToCartStepId,
|
|
||||||
async (data: StepInput, { container }) => {
|
|
||||||
const cartService = container.resolve<ICartModuleService>(
|
|
||||||
ModuleRegistrationName.CART
|
|
||||||
)
|
|
||||||
|
|
||||||
const items = await cartService.addLineItems(data.items)
|
|
||||||
|
|
||||||
return new StepResponse(items, items)
|
|
||||||
},
|
|
||||||
async (createdLineItems, { container }) => {
|
|
||||||
const cartService: ICartModuleService = container.resolve(
|
|
||||||
ModuleRegistrationName.CART
|
|
||||||
)
|
|
||||||
if (!createdLineItems?.length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
await cartService.deleteLineItems(createdLineItems.map((c) => c.id))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import { CreateLineItemForCartDTO, ICartModuleService } from "@medusajs/types"
|
||||||
|
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
interface StepInput {
|
||||||
|
id: string
|
||||||
|
items: CreateLineItemForCartDTO[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createLineItemsStepId = "create-line-items-step"
|
||||||
|
export const createLineItemsStep = createStep(
|
||||||
|
createLineItemsStepId,
|
||||||
|
async (data: StepInput, { container }) => {
|
||||||
|
const cartModule = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
const createdItems = data.items.length
|
||||||
|
? await cartModule.addLineItems(data.items)
|
||||||
|
: []
|
||||||
|
|
||||||
|
return new StepResponse(createdItems, createdItems)
|
||||||
|
},
|
||||||
|
async (createdItems, { container }) => {
|
||||||
|
if (!createdItems?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const cartModule: ICartModuleService = container.resolve(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
await cartModule.deleteLineItems(createdItems.map((c) => c.id))
|
||||||
|
}
|
||||||
|
)
|
||||||
Whitespace-only changes.
@@ -0,0 +1,59 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
CartLineItemDTO,
|
||||||
|
CreateLineItemForCartDTO,
|
||||||
|
ICartModuleService,
|
||||||
|
UpdateLineItemWithSelectorDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import { deepEqualObj, isPresent, MathBN } from "@medusajs/utils"
|
||||||
|
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
interface StepInput {
|
||||||
|
id: string
|
||||||
|
items: CreateLineItemForCartDTO[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getLineItemActionsStepId = "get-line-item-actions-step"
|
||||||
|
export const getLineItemActionsStep = createStep(
|
||||||
|
getLineItemActionsStepId,
|
||||||
|
async (data: StepInput, { container }) => {
|
||||||
|
const cartModule = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
const existingVariantItems = await cartModule.listLineItems({
|
||||||
|
cart_id: data.id,
|
||||||
|
variant_id: data.items.map((d) => d.variant_id!),
|
||||||
|
})
|
||||||
|
|
||||||
|
const variantItemMap = new Map<string, CartLineItemDTO>(
|
||||||
|
existingVariantItems.map((item) => [item.variant_id!, item])
|
||||||
|
)
|
||||||
|
|
||||||
|
const itemsToCreate: CreateLineItemForCartDTO[] = []
|
||||||
|
const itemsToUpdate: UpdateLineItemWithSelectorDTO[] = []
|
||||||
|
|
||||||
|
for (const item of data.items) {
|
||||||
|
const existingItem = variantItemMap.get(item.variant_id!)
|
||||||
|
const metadataMatches =
|
||||||
|
(!isPresent(existingItem?.metadata) && !isPresent(item.metadata)) ||
|
||||||
|
deepEqualObj(existingItem?.metadata, item.metadata)
|
||||||
|
|
||||||
|
if (existingItem && metadataMatches) {
|
||||||
|
const quantity = MathBN.sum(
|
||||||
|
existingItem.quantity as number,
|
||||||
|
item.quantity || 1
|
||||||
|
).toNumber()
|
||||||
|
|
||||||
|
itemsToUpdate.push({
|
||||||
|
selector: { id: existingItem.id },
|
||||||
|
data: { id: existingItem.id, quantity: quantity },
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
itemsToCreate.push(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StepResponse({ itemsToCreate, itemsToUpdate }, null)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
export * from "./add-shipping-method-to-cart"
|
export * from "./add-shipping-method-to-cart"
|
||||||
export * from "./add-to-cart"
|
|
||||||
export * from "./confirm-inventory"
|
export * from "./confirm-inventory"
|
||||||
export * from "./create-carts"
|
export * from "./create-carts"
|
||||||
export * from "./create-line-item-adjustments"
|
export * from "./create-line-item-adjustments"
|
||||||
|
export * from "./create-line-items"
|
||||||
export * from "./create-order-from-cart"
|
export * from "./create-order-from-cart"
|
||||||
export * from "./create-shipping-method-adjustments"
|
export * from "./create-shipping-method-adjustments"
|
||||||
export * from "./find-one-or-any-region"
|
export * from "./find-one-or-any-region"
|
||||||
@@ -10,6 +10,7 @@ export * from "./find-or-create-customer"
|
|||||||
export * from "./find-sales-channel"
|
export * from "./find-sales-channel"
|
||||||
export * from "./get-actions-to-compute-from-promotions"
|
export * from "./get-actions-to-compute-from-promotions"
|
||||||
export * from "./get-item-tax-lines"
|
export * from "./get-item-tax-lines"
|
||||||
|
export * from "./get-line-item-actions"
|
||||||
export * from "./get-promotion-codes-to-apply"
|
export * from "./get-promotion-codes-to-apply"
|
||||||
export * from "./get-variant-price-sets"
|
export * from "./get-variant-price-sets"
|
||||||
export * from "./get-variants"
|
export * from "./get-variants"
|
||||||
@@ -22,6 +23,7 @@ export * from "./retrieve-cart-with-links"
|
|||||||
export * from "./set-tax-lines-for-items"
|
export * from "./set-tax-lines-for-items"
|
||||||
export * from "./update-cart-promotions"
|
export * from "./update-cart-promotions"
|
||||||
export * from "./update-carts"
|
export * from "./update-carts"
|
||||||
|
export * from "./update-line-items"
|
||||||
export * from "./validate-cart-payments"
|
export * from "./validate-cart-payments"
|
||||||
export * from "./validate-cart-shipping-options"
|
export * from "./validate-cart-shipping-options"
|
||||||
export * from "./validate-variant-prices"
|
export * from "./validate-variant-prices"
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
ICartModuleService,
|
||||||
|
UpdateLineItemWithSelectorDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import { getSelectsAndRelationsFromObjectArray } from "@medusajs/utils"
|
||||||
|
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
interface StepInput {
|
||||||
|
id: string
|
||||||
|
items: UpdateLineItemWithSelectorDTO[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateLineItemsStepId = "update-line-items-step"
|
||||||
|
export const updateLineItemsStep = createStep(
|
||||||
|
updateLineItemsStepId,
|
||||||
|
async (input: StepInput, { container }) => {
|
||||||
|
const { id, items = [] } = input
|
||||||
|
|
||||||
|
if (!items?.length) {
|
||||||
|
return new StepResponse([], [])
|
||||||
|
}
|
||||||
|
|
||||||
|
const cartModule = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
const { selects, relations } = getSelectsAndRelationsFromObjectArray(
|
||||||
|
items.map((item) => item.data)
|
||||||
|
)
|
||||||
|
|
||||||
|
const itemsBeforeUpdate = await cartModule.listLineItems(
|
||||||
|
{ id: items.map((d) => d.selector.id!) },
|
||||||
|
{ select: selects, relations }
|
||||||
|
)
|
||||||
|
|
||||||
|
const updatedItems = items.length
|
||||||
|
? await cartModule.updateLineItems(items)
|
||||||
|
: []
|
||||||
|
|
||||||
|
return new StepResponse(updatedItems, itemsBeforeUpdate)
|
||||||
|
},
|
||||||
|
async (itemsBeforeUpdate, { container }) => {
|
||||||
|
if (!itemsBeforeUpdate?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const cartModule: ICartModuleService = container.resolve(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
if (itemsBeforeUpdate.length) {
|
||||||
|
const itemsToUpdate: UpdateLineItemWithSelectorDTO[] = []
|
||||||
|
|
||||||
|
for (const item of itemsBeforeUpdate) {
|
||||||
|
const { id, ...data } = item
|
||||||
|
|
||||||
|
itemsToUpdate.push({ selector: { id }, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
await cartModule.updateLineItems(itemsToUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -5,10 +5,16 @@ import {
|
|||||||
import {
|
import {
|
||||||
WorkflowData,
|
WorkflowData,
|
||||||
createWorkflow,
|
createWorkflow,
|
||||||
|
parallelize,
|
||||||
transform,
|
transform,
|
||||||
} from "@medusajs/workflows-sdk"
|
} from "@medusajs/workflows-sdk"
|
||||||
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
|
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
|
||||||
import { addToCartStep, refreshCartShippingMethodsStep } from "../steps"
|
import {
|
||||||
|
createLineItemsStep,
|
||||||
|
getLineItemActionsStep,
|
||||||
|
refreshCartShippingMethodsStep,
|
||||||
|
updateLineItemsStep,
|
||||||
|
} from "../steps"
|
||||||
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
||||||
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
import { updateTaxLinesStep } from "../steps/update-tax-lines"
|
||||||
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
|
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
|
||||||
@@ -78,7 +84,25 @@ export const addToCartWorkflow = createWorkflow(
|
|||||||
return items
|
return items
|
||||||
})
|
})
|
||||||
|
|
||||||
const items = addToCartStep({ items: lineItems })
|
const { itemsToCreate = [], itemsToUpdate = [] } = getLineItemActionsStep({
|
||||||
|
id: input.cart.id,
|
||||||
|
items: lineItems,
|
||||||
|
})
|
||||||
|
|
||||||
|
const [createdItems, updatedItems] = parallelize(
|
||||||
|
createLineItemsStep({
|
||||||
|
id: input.cart.id,
|
||||||
|
items: itemsToCreate,
|
||||||
|
}),
|
||||||
|
updateLineItemsStep({
|
||||||
|
id: input.cart.id,
|
||||||
|
items: itemsToUpdate,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const items = transform({ createdItems, updatedItems }, (data) => {
|
||||||
|
return [...(data.createdItems || []), ...(data.updatedItems || [])]
|
||||||
|
})
|
||||||
|
|
||||||
const cart = useRemoteQueryStep({
|
const cart = useRemoteQueryStep({
|
||||||
entry_point: "cart",
|
entry_point: "cart",
|
||||||
@@ -88,9 +112,7 @@ export const addToCartWorkflow = createWorkflow(
|
|||||||
}).config({ name: "refetch–cart" })
|
}).config({ name: "refetch–cart" })
|
||||||
|
|
||||||
refreshCartShippingMethodsStep({ cart })
|
refreshCartShippingMethodsStep({ cart })
|
||||||
// TODO: since refreshCartShippingMethodsStep potentially removes cart shipping methods, we need the updated cart here
|
updateTaxLinesStep({ cart_or_cart_id: input.cart.id, items })
|
||||||
// for the following 2 steps as they act upon final cart shape
|
|
||||||
updateTaxLinesStep({ cart_or_cart_id: cart, items })
|
|
||||||
refreshCartPromotionsStep({ id: input.cart.id })
|
refreshCartPromotionsStep({ id: input.cart.id })
|
||||||
refreshPaymentCollectionForCartStep({ cart_id: input.cart.id })
|
refreshPaymentCollectionForCartStep({ cart_id: input.cart.id })
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
transform,
|
transform,
|
||||||
} from "@medusajs/workflows-sdk"
|
} from "@medusajs/workflows-sdk"
|
||||||
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
|
import { useRemoteQueryStep } from "../../../common/steps/use-remote-query"
|
||||||
import { updateLineItemsStep } from "../../line-item/steps"
|
import { updateLineItemsStepWithSelector } from "../../line-item/steps"
|
||||||
import { refreshCartShippingMethodsStep } from "../steps"
|
import { refreshCartShippingMethodsStep } from "../steps"
|
||||||
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
import { refreshCartPromotionsStep } from "../steps/refresh-cart-promotions"
|
||||||
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
|
import { validateVariantPricesStep } from "../steps/validate-variant-prices"
|
||||||
@@ -77,7 +77,7 @@ export const updateLineItemInCartWorkflow = createWorkflow(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const result = updateLineItemsStep(lineItemUpdate)
|
const result = updateLineItemsStepWithSelector(lineItemUpdate)
|
||||||
|
|
||||||
const cart = useRemoteQueryStep({
|
const cart = useRemoteQueryStep({
|
||||||
entry_point: "cart",
|
entry_point: "cart",
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ import {
|
|||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
export const updateLineItemsStepId = "update-line-items"
|
export const updateLineItemsStepWithSelectorId =
|
||||||
export const updateLineItemsStep = createStep(
|
"update-line-items-with-selector"
|
||||||
updateLineItemsStepId,
|
export const updateLineItemsStepWithSelector = createStep(
|
||||||
|
updateLineItemsStepWithSelectorId,
|
||||||
async (input: UpdateLineItemWithSelectorDTO, { container }) => {
|
async (input: UpdateLineItemWithSelectorDTO, { container }) => {
|
||||||
const service = container.resolve<ICartModuleService>(
|
const service = container.resolve<ICartModuleService>(
|
||||||
ModuleRegistrationName.CART
|
ModuleRegistrationName.CART
|
||||||
|
|||||||
@@ -560,6 +560,11 @@ export interface CreateLineItemDTO {
|
|||||||
* The adjustments of the line item.
|
* The adjustments of the line item.
|
||||||
*/
|
*/
|
||||||
adjustments?: CreateAdjustmentDTO[]
|
adjustments?: CreateAdjustmentDTO[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds custom data in key-value pairs.
|
||||||
|
*/
|
||||||
|
metadata?: Record<string, unknown> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export interface CreateCartCreateLineItemDTO {
|
|||||||
compare_at_unit_price?: BigNumberInput
|
compare_at_unit_price?: BigNumberInput
|
||||||
unit_price?: BigNumberInput
|
unit_price?: BigNumberInput
|
||||||
|
|
||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateLineItemInCartWorkflowInputDTO {
|
export interface UpdateLineItemInCartWorkflowInputDTO {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export function deepEqualObj(obj1: object, obj2: object): boolean {
|
export function deepEqualObj(obj1: unknown, obj2: unknown): boolean {
|
||||||
if (typeof obj1 !== typeof obj2) {
|
if (typeof obj1 !== typeof obj2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,10 @@ export function deepEqualObj(obj1: object, obj2: object): boolean {
|
|||||||
return obj1 === obj2
|
return obj1 === obj2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof obj2 !== "object" || obj2 === null) {
|
||||||
|
return obj2 === obj1
|
||||||
|
}
|
||||||
|
|
||||||
const obj1Keys = Object.keys(obj1)
|
const obj1Keys = Object.keys(obj1)
|
||||||
const obj2Keys = Object.keys(obj2)
|
const obj2Keys = Object.keys(obj2)
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export const defaultStoreCartFields = [
|
|||||||
"items.variant_sku",
|
"items.variant_sku",
|
||||||
"items.variant_barcode",
|
"items.variant_barcode",
|
||||||
"items.variant_title",
|
"items.variant_title",
|
||||||
|
"items.metadata",
|
||||||
"items.created_at",
|
"items.created_at",
|
||||||
"items.updated_at",
|
"items.updated_at",
|
||||||
"items.title",
|
"items.title",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const StoreGetCartsCart = createSelectParams()
|
|||||||
const ItemSchema = z.object({
|
const ItemSchema = z.object({
|
||||||
variant_id: z.string(),
|
variant_id: z.string(),
|
||||||
quantity: z.number(),
|
quantity: z.number(),
|
||||||
|
metadata: z.record(z.unknown()).optional().nullable(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type StoreCreateCartType = z.infer<typeof StoreCreateCart>
|
export type StoreCreateCartType = z.infer<typeof StoreCreateCart>
|
||||||
@@ -62,7 +63,7 @@ export type StoreAddCartLineItemType = z.infer<typeof StoreAddCartLineItem>
|
|||||||
export const StoreAddCartLineItem = z.object({
|
export const StoreAddCartLineItem = z.object({
|
||||||
variant_id: z.string(),
|
variant_id: z.string(),
|
||||||
quantity: z.number(),
|
quantity: z.number(),
|
||||||
metadata: z.record(z.unknown()).optional(),
|
metadata: z.record(z.unknown()).optional().nullable(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type StoreUpdateCartLineItemType = z.infer<
|
export type StoreUpdateCartLineItemType = z.infer<
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ import {
|
|||||||
CreateShippingMethodDTO,
|
CreateShippingMethodDTO,
|
||||||
CreateShippingMethodTaxLineDTO,
|
CreateShippingMethodTaxLineDTO,
|
||||||
UpdateLineItemDTO,
|
UpdateLineItemDTO,
|
||||||
UpdateLineItemTaxLineDTO,
|
|
||||||
UpdateShippingMethodTaxLineDTO,
|
UpdateShippingMethodTaxLineDTO,
|
||||||
} from "@types"
|
} from "@types"
|
||||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||||
@@ -1034,7 +1033,7 @@ export default class CartModuleService<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await this.lineItemTaxLineService_.upsert(
|
const result = await this.lineItemTaxLineService_.upsert(
|
||||||
taxLines as UpdateLineItemTaxLineDTO[],
|
taxLines,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user