fix(medusa): Delete ProductOption on Product without Variants (#1846)
**What** Solves admin issue [166](https://github.com/medusajs/admin/issues/166) Deleting a product option on a product without variants currently throws, because we are cleaning up variant options as well. **How** Only do variant clean up, if product has variants
This commit is contained in:
1 parent
37056b8066
commit
d14a0398fb
3 files changed
+86
-23
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes an error thrown when deleting product options on a product without variants
|
||||||
@@ -12,6 +12,7 @@ const {
|
|||||||
MoneyAmount,
|
MoneyAmount,
|
||||||
} = require("@medusajs/medusa")
|
} = require("@medusajs/medusa")
|
||||||
const priceListSeeder = require("../../helpers/price-list-seeder")
|
const priceListSeeder = require("../../helpers/price-list-seeder")
|
||||||
|
const { simpleProductFactory } = require("../../factories")
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
jest.setTimeout(50000)
|
||||||
|
|
||||||
@@ -1433,6 +1434,58 @@ describe("/admin/products", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("DELETE /admin/products/:id/options/:option_id", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
try {
|
||||||
|
await simpleProductFactory(dbConnection, {
|
||||||
|
id: "test-product-without-variants",
|
||||||
|
variants: [],
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
id: "test-product-option",
|
||||||
|
title: "Test option",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("deletes a product option", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api
|
||||||
|
.delete(
|
||||||
|
"/admin/products/test-product-without-variants/options/test-product-option",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.product).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
options: [],
|
||||||
|
id: "test-product-without-variants",
|
||||||
|
variants: [],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("GET /admin/products/:id/variants", () => {
|
describe("GET /admin/products/:id/variants", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await productSeeder(dbConnection)
|
await productSeeder(dbConnection)
|
||||||
|
|||||||
@@ -818,32 +818,37 @@ class ProductService extends TransactionBaseService {
|
|||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the option we want to delete, make sure that all variants have the
|
// In case the product does not contain variants, we can safely delete the option
|
||||||
// same option values. The reason for doing is, that we want to avoid
|
// If it does contain variants, we need to make sure no variant exist for the
|
||||||
// duplicate variants. For example, if we have a product with size and
|
// product option to delete
|
||||||
// color options, that has four variants: (black, 1), (black, 2),
|
if (product?.variants?.length) {
|
||||||
// (blue, 1), (blue, 2) and we delete the size option from the product,
|
// For the option we want to delete, make sure that all variants have the
|
||||||
// we would end up with four variants: (black), (black), (blue), (blue).
|
// same option values. The reason for doing is, that we want to avoid
|
||||||
// We now have two duplicate variants. To ensure that this does not
|
// duplicate variants. For example, if we have a product with size and
|
||||||
// happen, we will force the user to select which variants to keep.
|
// color options, that has four variants: (black, 1), (black, 2),
|
||||||
const firstVariant = product.variants[0]
|
// (blue, 1), (blue, 2) and we delete the size option from the product,
|
||||||
|
// we would end up with four variants: (black), (black), (blue), (blue).
|
||||||
|
// We now have two duplicate variants. To ensure that this does not
|
||||||
|
// happen, we will force the user to select which variants to keep.
|
||||||
|
const firstVariant = product.variants[0]
|
||||||
|
|
||||||
const valueToMatch = firstVariant.options.find(
|
const valueToMatch = firstVariant.options.find(
|
||||||
(o) => o.option_id === optionId
|
(o) => o.option_id === optionId
|
||||||
)?.value
|
)?.value
|
||||||
|
|
||||||
const equalsFirst = await Promise.all(
|
const equalsFirst = await Promise.all(
|
||||||
product.variants.map(async (v) => {
|
product.variants.map(async (v) => {
|
||||||
const option = v.options.find((o) => o.option_id === optionId)
|
const option = v.options.find((o) => o.option_id === optionId)
|
||||||
return option?.value === valueToMatch
|
return option?.value === valueToMatch
|
||||||
})
|
})
|
||||||
)
|
|
||||||
|
|
||||||
if (!equalsFirst.every((v) => v)) {
|
|
||||||
throw new MedusaError(
|
|
||||||
MedusaError.Types.INVALID_DATA,
|
|
||||||
`To delete an option, first delete all variants, such that when an option is deleted, no duplicate variants will exist.`
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!equalsFirst.every((v) => v)) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`To delete an option, first delete all variants, such that when an option is deleted, no duplicate variants will exist.`
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we reach this point, we can safely delete the product option
|
// If we reach this point, we can safely delete the product option
|
||||||
|
|||||||
Reference in new issue
Block a user