feat:Allow updating prices through product update workflow (#8316)
* feat:Allow updating prices through product update workflow * fix:Changes based on PR feedback
This commit is contained in:
1 parent
ed67d44d28
commit
e98012a858
9 files changed
+382
-27
No files matched your search
@@ -217,7 +217,20 @@ medusaIntegrationTestRunner({
|
|||||||
title: "Test variant 2",
|
title: "Test variant 2",
|
||||||
allow_backorder: false,
|
allow_backorder: false,
|
||||||
manage_inventory: true,
|
manage_inventory: true,
|
||||||
// TODO: Since we are doing a product update, there won't be any prices created for the variant
|
prices: [
|
||||||
|
expect.objectContaining({
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 200,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
currency_code: "eur",
|
||||||
|
amount: 65,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
currency_code: "dkk",
|
||||||
|
amount: 50,
|
||||||
|
}),
|
||||||
|
],
|
||||||
options: [
|
options: [
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
value: "small",
|
value: "small",
|
||||||
|
|||||||
@@ -1390,7 +1390,20 @@ medusaIntegrationTestRunner({
|
|||||||
barcode: "test-barcode",
|
barcode: "test-barcode",
|
||||||
ean: "test-ean",
|
ean: "test-ean",
|
||||||
upc: "test-upc",
|
upc: "test-upc",
|
||||||
// BREAKING: Price updates are no longer supported through the product update endpoint. There is a batch variants endpoint for this purpose
|
prices: [
|
||||||
|
{
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
currency_code: "eur",
|
||||||
|
amount: 65,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
currency_code: "dkk",
|
||||||
|
amount: 50,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
tags: [{ value: "123" }],
|
tags: [{ value: "123" }],
|
||||||
@@ -1478,10 +1491,20 @@ medusaIntegrationTestRunner({
|
|||||||
origin_country: null,
|
origin_country: null,
|
||||||
prices: expect.arrayContaining([
|
prices: expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
amount: 100,
|
amount: 200,
|
||||||
created_at: expect.any(String),
|
created_at: expect.any(String),
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
}),
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 65,
|
||||||
|
created_at: expect.any(String),
|
||||||
|
currency_code: "eur",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 50,
|
||||||
|
created_at: expect.any(String),
|
||||||
|
currency_code: "dkk",
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
product_id: baseProduct.id,
|
product_id: baseProduct.id,
|
||||||
title: "New variant",
|
title: "New variant",
|
||||||
@@ -1492,6 +1515,88 @@ medusaIntegrationTestRunner({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("updates product variants (update price on existing variant, create new variant)", async () => {
|
||||||
|
const payload = {
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
id: baseProduct.variants[0].id,
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
currency_code: "dkk",
|
||||||
|
amount: 50,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "New variant",
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
currency_code: "dkk",
|
||||||
|
amount: 20,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.post(`/admin/products/${baseProduct.id}`, payload, adminHeaders)
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
|
||||||
|
expect(response.data.product).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: baseProduct.id,
|
||||||
|
variants: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: baseProduct.variants[0].id,
|
||||||
|
prices: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 200,
|
||||||
|
created_at: expect.any(String),
|
||||||
|
currency_code: "usd",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 50,
|
||||||
|
created_at: expect.any(String),
|
||||||
|
currency_code: "dkk",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
product_id: baseProduct.id,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
title: "New variant",
|
||||||
|
prices: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 150,
|
||||||
|
created_at: expect.any(String),
|
||||||
|
currency_code: "usd",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 20,
|
||||||
|
created_at: expect.any(String),
|
||||||
|
currency_code: "dkk",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
product_id: baseProduct.id,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it("updates product (removes images when empty array included)", async () => {
|
it("updates product (removes images when empty array included)", async () => {
|
||||||
const payload = {
|
const payload = {
|
||||||
images: [],
|
images: [],
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
import { UpdateProductsStepInput } from "./update-products"
|
||||||
|
import { IProductModuleService } from "@medusajs/types"
|
||||||
|
import { ModuleRegistrationName } from "@medusajs/utils"
|
||||||
|
|
||||||
|
export const getVariantIdsForProductsStepId = "get-variant-ids-for-products"
|
||||||
|
export const getVariantIdsForProductsStep = createStep(
|
||||||
|
getVariantIdsForProductsStepId,
|
||||||
|
async (data: UpdateProductsStepInput, { container }) => {
|
||||||
|
const service = container.resolve<IProductModuleService>(
|
||||||
|
ModuleRegistrationName.PRODUCT
|
||||||
|
)
|
||||||
|
let filters = {}
|
||||||
|
if ("products" in data) {
|
||||||
|
if (!data.products.length) {
|
||||||
|
return new StepResponse([])
|
||||||
|
}
|
||||||
|
|
||||||
|
filters = {
|
||||||
|
id: data.products.map((p) => p.id),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filters = data.selector
|
||||||
|
}
|
||||||
|
|
||||||
|
const products = await service.listProducts(filters, {
|
||||||
|
select: ["variants.id"],
|
||||||
|
relations: ["variants"],
|
||||||
|
take: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
return new StepResponse(
|
||||||
|
products.flatMap((p) => p.variants.map((v) => v.id))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -38,11 +38,6 @@ export const groupProductsForBatchStep = createStep(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Currently the update product workflow doesn't update variant pricing, but we should probably add support for it.
|
|
||||||
product.variants?.forEach((variant: any) => {
|
|
||||||
delete variant.prices
|
|
||||||
})
|
|
||||||
|
|
||||||
acc.toUpdate.push(
|
acc.toUpdate.push(
|
||||||
product as HttpTypes.AdminUpdateProduct & { id: string }
|
product as HttpTypes.AdminUpdateProduct & { id: string }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const waitConfirmationProductImportStep = createStep(
|
|||||||
name: waitConfirmationProductImportStepId,
|
name: waitConfirmationProductImportStepId,
|
||||||
async: true,
|
async: true,
|
||||||
// After an hour we want to timeout and cancel the import so we don't have orphaned workflows
|
// After an hour we want to timeout and cancel the import so we don't have orphaned workflows
|
||||||
timeout: 60 * 60 * 1 * 1000,
|
timeout: 60 * 60 * 1,
|
||||||
},
|
},
|
||||||
async () => {}
|
async () => {}
|
||||||
)
|
)
|
||||||
@@ -22,3 +22,4 @@ export * from "./update-product-variants"
|
|||||||
export * from "./update-products"
|
export * from "./update-products"
|
||||||
export * from "./export-products"
|
export * from "./export-products"
|
||||||
export * from "./import-products"
|
export * from "./import-products"
|
||||||
|
export * from "./upsert-variant-prices"
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import { updateProductsStep } from "../steps/update-products"
|
import { updateProductsStep } from "../steps/update-products"
|
||||||
|
|
||||||
import { ProductTypes } from "@medusajs/types"
|
import {
|
||||||
|
CreateMoneyAmountDTO,
|
||||||
|
ProductTypes,
|
||||||
|
UpdateProductVariantWorkflowInputDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
import { arrayDifference, Modules } from "@medusajs/utils"
|
import { arrayDifference, Modules } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
createWorkflow,
|
createWorkflow,
|
||||||
@@ -12,17 +16,21 @@ import {
|
|||||||
dismissRemoteLinkStep,
|
dismissRemoteLinkStep,
|
||||||
useRemoteQueryStep,
|
useRemoteQueryStep,
|
||||||
} from "../../common"
|
} from "../../common"
|
||||||
|
import { upsertVariantPricesWorkflow } from "./upsert-variant-prices"
|
||||||
|
import { getVariantIdsForProductsStep } from "../steps/get-variant-ids-for-products"
|
||||||
|
|
||||||
type UpdateProductsStepInputSelector = {
|
type UpdateProductsStepInputSelector = {
|
||||||
selector: ProductTypes.FilterableProductProps
|
selector: ProductTypes.FilterableProductProps
|
||||||
update: ProductTypes.UpdateProductDTO & {
|
update: Omit<ProductTypes.UpdateProductDTO, "variants"> & {
|
||||||
sales_channels?: { id: string }[]
|
sales_channels?: { id: string }[]
|
||||||
|
variants?: UpdateProductVariantWorkflowInputDTO[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateProductsStepInputProducts = {
|
type UpdateProductsStepInputProducts = {
|
||||||
products: (ProductTypes.UpsertProductDTO & {
|
products: (Omit<ProductTypes.UpsertProductDTO, "variants"> & {
|
||||||
sales_channels?: { id: string }[]
|
sales_channels?: { id: string }[]
|
||||||
|
variants?: UpdateProductVariantWorkflowInputDTO[]
|
||||||
})[]
|
})[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +54,10 @@ function prepareUpdateProductInput({
|
|||||||
products: input.products.map((p) => ({
|
products: input.products.map((p) => ({
|
||||||
...p,
|
...p,
|
||||||
sales_channels: undefined,
|
sales_channels: undefined,
|
||||||
|
variants: p.variants?.map((v) => ({
|
||||||
|
...v,
|
||||||
|
prices: undefined,
|
||||||
|
})),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,6 +67,10 @@ function prepareUpdateProductInput({
|
|||||||
update: {
|
update: {
|
||||||
...input.update,
|
...input.update,
|
||||||
sales_channels: undefined,
|
sales_channels: undefined,
|
||||||
|
variants: input.update?.variants?.map((v) => ({
|
||||||
|
...v,
|
||||||
|
prices: undefined,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,19 +136,67 @@ function prepareSalesChannelLinks({
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareToDeleteLinks({
|
function prepareVariantPrices({
|
||||||
currentLinks,
|
input,
|
||||||
|
updatedProducts,
|
||||||
}: {
|
}: {
|
||||||
currentLinks: {
|
updatedProducts: ProductTypes.ProductDTO[]
|
||||||
|
input: WorkflowInput
|
||||||
|
}): {
|
||||||
|
variant_id: string
|
||||||
|
product_id: string
|
||||||
|
prices?: CreateMoneyAmountDTO[]
|
||||||
|
}[] {
|
||||||
|
if ("products" in input) {
|
||||||
|
if (!input.products.length) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: We rely on the ordering of input and update here.
|
||||||
|
return input.products.flatMap((product, i) => {
|
||||||
|
if (!product.variants?.length) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedProduct = updatedProducts[i]
|
||||||
|
return product.variants.map((variant, j) => {
|
||||||
|
const updatedVariant = updatedProduct.variants[j]
|
||||||
|
|
||||||
|
return {
|
||||||
|
product_id: updatedProduct.id,
|
||||||
|
variant_id: updatedVariant.id,
|
||||||
|
prices: variant.prices,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.selector && input.update?.variants?.length) {
|
||||||
|
return updatedProducts.flatMap((p) => {
|
||||||
|
return input.update.variants!.map((variant, i) => ({
|
||||||
|
product_id: p.id,
|
||||||
|
variant_id: p.variants[i].id,
|
||||||
|
prices: variant.prices,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareToDeleteSalesChannelLinks({
|
||||||
|
currentSalesChannelLinks,
|
||||||
|
}: {
|
||||||
|
currentSalesChannelLinks: {
|
||||||
product_id: string
|
product_id: string
|
||||||
sales_channel_id: string
|
sales_channel_id: string
|
||||||
}[]
|
}[]
|
||||||
}) {
|
}) {
|
||||||
if (!currentLinks.length) {
|
if (!currentSalesChannelLinks.length) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentLinks.map(({ product_id, sales_channel_id }) => ({
|
return currentSalesChannelLinks.map(({ product_id, sales_channel_id }) => ({
|
||||||
[Modules.PRODUCT]: {
|
[Modules.PRODUCT]: {
|
||||||
product_id,
|
product_id,
|
||||||
},
|
},
|
||||||
@@ -148,7 +212,7 @@ export const updateProductsWorkflow = createWorkflow(
|
|||||||
(
|
(
|
||||||
input: WorkflowData<WorkflowInput>
|
input: WorkflowData<WorkflowInput>
|
||||||
): WorkflowData<ProductTypes.ProductDTO[]> => {
|
): WorkflowData<ProductTypes.ProductDTO[]> => {
|
||||||
// TODO: Delete price sets for removed variants
|
const previousVariantIds = getVariantIdsForProductsStep(input)
|
||||||
|
|
||||||
const toUpdateInput = transform({ input }, prepareUpdateProductInput)
|
const toUpdateInput = transform({ input }, prepareUpdateProductInput)
|
||||||
const updatedProducts = updateProductsStep(toUpdateInput)
|
const updatedProducts = updateProductsStep(toUpdateInput)
|
||||||
@@ -157,20 +221,32 @@ export const updateProductsWorkflow = createWorkflow(
|
|||||||
updateProductIds
|
updateProductIds
|
||||||
)
|
)
|
||||||
|
|
||||||
const currentLinks = useRemoteQueryStep({
|
|
||||||
entry_point: "product_sales_channel",
|
|
||||||
fields: ["product_id", "sales_channel_id"],
|
|
||||||
variables: { filters: { product_id: updatedProductIds } },
|
|
||||||
})
|
|
||||||
|
|
||||||
const toDeleteLinks = transform({ currentLinks }, prepareToDeleteLinks)
|
|
||||||
|
|
||||||
const salesChannelLinks = transform(
|
const salesChannelLinks = transform(
|
||||||
{ input, updatedProducts },
|
{ input, updatedProducts },
|
||||||
prepareSalesChannelLinks
|
prepareSalesChannelLinks
|
||||||
)
|
)
|
||||||
|
|
||||||
dismissRemoteLinkStep(toDeleteLinks)
|
const variantPrices = transform(
|
||||||
|
{ input, updatedProducts },
|
||||||
|
prepareVariantPrices
|
||||||
|
)
|
||||||
|
|
||||||
|
const currentSalesChannelLinks = useRemoteQueryStep({
|
||||||
|
entry_point: "product_sales_channel",
|
||||||
|
fields: ["product_id", "sales_channel_id"],
|
||||||
|
variables: { filters: { product_id: updatedProductIds } },
|
||||||
|
})
|
||||||
|
|
||||||
|
const toDeleteSalesChannelLinks = transform(
|
||||||
|
{ currentSalesChannelLinks },
|
||||||
|
prepareToDeleteSalesChannelLinks
|
||||||
|
)
|
||||||
|
|
||||||
|
upsertVariantPricesWorkflow.runAsStep({
|
||||||
|
input: { variantPrices, previousVariantIds },
|
||||||
|
})
|
||||||
|
|
||||||
|
dismissRemoteLinkStep(toDeleteSalesChannelLinks)
|
||||||
|
|
||||||
createRemoteLinkStep(salesChannelLinks)
|
createRemoteLinkStep(salesChannelLinks)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
import {
|
||||||
|
CreatePricesDTO,
|
||||||
|
UpdatePricesDTO,
|
||||||
|
CreatePriceSetDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import { Modules, arrayDifference } from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
WorkflowData,
|
||||||
|
createWorkflow,
|
||||||
|
transform,
|
||||||
|
} from "@medusajs/workflows-sdk"
|
||||||
|
import { removeRemoteLinkStep, useRemoteQueryStep } from "../../common"
|
||||||
|
import { createPriceSetsStep, updatePriceSetsStep } from "../../pricing"
|
||||||
|
import { createVariantPricingLinkStep } from "../steps"
|
||||||
|
|
||||||
|
type WorkflowInput = {
|
||||||
|
variantPrices: {
|
||||||
|
variant_id: string
|
||||||
|
product_id: string
|
||||||
|
prices?: (CreatePricesDTO | UpdatePricesDTO)[]
|
||||||
|
}[]
|
||||||
|
previousVariantIds: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const upsertVariantPricesWorkflowId = "upsert-variant-prices"
|
||||||
|
export const upsertVariantPricesWorkflow = createWorkflow(
|
||||||
|
upsertVariantPricesWorkflowId,
|
||||||
|
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
|
||||||
|
const removedVariantIds = transform({ input }, (data) => {
|
||||||
|
return arrayDifference(
|
||||||
|
data.input.previousVariantIds,
|
||||||
|
data.input.variantPrices.map((v) => v.variant_id)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
removeRemoteLinkStep({
|
||||||
|
[Modules.PRODUCT]: { variant_id: removedVariantIds },
|
||||||
|
}).config({ name: "remove-variant-link-step" })
|
||||||
|
|
||||||
|
const { newVariants, existingVariants } = transform({ input }, (data) => {
|
||||||
|
const previousMap = new Set(data.input.previousVariantIds.map((v) => v))
|
||||||
|
|
||||||
|
return {
|
||||||
|
existingVariants: data.input.variantPrices.filter((v) =>
|
||||||
|
previousMap.has(v.variant_id)
|
||||||
|
),
|
||||||
|
newVariants: data.input.variantPrices.filter(
|
||||||
|
(v) => !previousMap.has(v.variant_id)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const existingVariantIds = transform({ existingVariants }, (data) =>
|
||||||
|
data.existingVariants.map((v) => v.variant_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
const existingLinks = useRemoteQueryStep({
|
||||||
|
entry_point: "product_variant_price_set",
|
||||||
|
fields: ["variant_id", "price_set_id"],
|
||||||
|
variables: { filters: { variant_id: existingVariantIds } },
|
||||||
|
})
|
||||||
|
|
||||||
|
const pricesToUpdate = transform(
|
||||||
|
{ existingVariants, existingLinks },
|
||||||
|
(data) => {
|
||||||
|
const linksMap = new Map(
|
||||||
|
data.existingLinks.map((l) => [l.variant_id, l.price_set_id])
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
price_sets: data.existingVariants
|
||||||
|
.map((v) => {
|
||||||
|
const priceSetId = linksMap.get(v.variant_id)
|
||||||
|
|
||||||
|
if (!priceSetId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: priceSetId,
|
||||||
|
prices: v.prices,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
updatePriceSetsStep(pricesToUpdate)
|
||||||
|
|
||||||
|
// Note: We rely on the same order of input and output when creating variants here, make sure that assumption holds
|
||||||
|
const pricesToCreate = transform({ newVariants }, (data) =>
|
||||||
|
data.newVariants.map((v) => {
|
||||||
|
return {
|
||||||
|
prices: v.prices,
|
||||||
|
} as CreatePriceSetDTO
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const createdPriceSets = createPriceSetsStep(pricesToCreate)
|
||||||
|
|
||||||
|
const variantAndPriceSetLinks = transform(
|
||||||
|
{ newVariants, createdPriceSets },
|
||||||
|
(data) => {
|
||||||
|
return {
|
||||||
|
links: data.newVariants.map((variant, i) => ({
|
||||||
|
variant_id: variant.variant_id,
|
||||||
|
price_set_id: data.createdPriceSets[i].id,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
createVariantPricingLinkStep(variantAndPriceSetLinks)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
CreateMoneyAmountDTO,
|
CreateMoneyAmountDTO,
|
||||||
FilterableMoneyAmountProps,
|
FilterableMoneyAmountProps,
|
||||||
MoneyAmountDTO,
|
MoneyAmountDTO,
|
||||||
|
UpdateMoneyAmountDTO,
|
||||||
} from "./money-amount"
|
} from "./money-amount"
|
||||||
|
|
||||||
export interface PricingRepositoryService {
|
export interface PricingRepositoryService {
|
||||||
@@ -227,6 +228,18 @@ export interface CreatePricesDTO extends CreateMoneyAmountDTO {
|
|||||||
rules?: CreatePriceSetPriceRules
|
rules?: CreatePriceSetPriceRules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @interface
|
||||||
|
*
|
||||||
|
* The prices to create part of a price set.
|
||||||
|
*/
|
||||||
|
export interface UpdatePricesDTO extends UpdateMoneyAmountDTO {
|
||||||
|
/**
|
||||||
|
* The rules to add to the price. The object's keys are the attribute, and values are the value of that rule associated with this price.
|
||||||
|
*/
|
||||||
|
rules?: CreatePriceSetPriceRules
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @interface
|
* @interface
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in new issue
Block a user