Makes product variant operations go through product service
This commit is contained in:
@@ -3,7 +3,6 @@ import middlewares from "../../middlewares"
|
||||
import authRoutes from "./auth"
|
||||
import productRoutes from "./products"
|
||||
import userRoutes from "./users"
|
||||
import productVariantRoutes from "./product-variants"
|
||||
import regionRoutes from "./regions"
|
||||
import shippingOptionRoutes from "./shipping-options"
|
||||
import shippingProfileRoutes from "./shipping-profiles"
|
||||
@@ -36,7 +35,6 @@ export default (app, container) => {
|
||||
shippingProfileRoutes(route)
|
||||
discountRoutes(route)
|
||||
orderRoutes(route)
|
||||
productVariantRoutes(route)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("POST /admin/product-variants/:id/options", () => {
|
||||
describe("successful add option value", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}/options`,
|
||||
{
|
||||
payload: {
|
||||
option_id: IdMap.getId("testOption"),
|
||||
value: "test",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service addOption", () => {
|
||||
expect(ProductVariantServiceMock.addOptionValue).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.addOptionValue).toHaveBeenCalledWith(
|
||||
IdMap.getId("testVariant"),
|
||||
IdMap.getId("testOption"),
|
||||
"test"
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("POST /admin/product-variants", () => {
|
||||
describe("successful creation", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/product-variants", {
|
||||
payload: {
|
||||
title: "Test Product Variant",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "DKK",
|
||||
amount: 1234,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("returns created product draft", () => {
|
||||
expect(subject.body._id).toEqual(IdMap.getId("testVariant"))
|
||||
})
|
||||
|
||||
it("calls service createDraft", () => {
|
||||
expect(ProductVariantServiceMock.createDraft).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.createDraft).toHaveBeenCalledWith({
|
||||
title: "Test Product Variant",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "DKK",
|
||||
amount: 1234,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("invalid data returns error details", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/products", {
|
||||
payload: {
|
||||
image: "image",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
|
||||
it("returns error details", () => {
|
||||
expect(subject.body.name).toEqual("invalid_data")
|
||||
expect(subject.body.message[0].message).toEqual(`"title" is required`)
|
||||
})
|
||||
})
|
||||
})
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("DELETE /admin/product-variants/:id/options", () => {
|
||||
describe("successfully deletes option value", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"DELETE",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}/options`,
|
||||
{
|
||||
payload: {
|
||||
option_id: IdMap.getId("testOption"),
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
it("calls service deleteOptionValue", () => {
|
||||
expect(ProductVariantServiceMock.deleteOptionValue).toHaveBeenCalledTimes(
|
||||
1
|
||||
)
|
||||
expect(ProductVariantServiceMock.deleteOptionValue).toHaveBeenCalledWith(
|
||||
IdMap.getId("testVariant"),
|
||||
IdMap.getId("testOption")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("DELETE /admin/product-variants/:id", () => {
|
||||
describe("successfully deletes a product variant", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"DELETE",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls ProductVariantService delete", () => {
|
||||
expect(ProductVariantServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.delete).toHaveBeenCalledWith(
|
||||
IdMap.getId("testVariant")
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("returns correct delete data", () => {
|
||||
expect(subject.body).toEqual({
|
||||
id: IdMap.getId("testVariant"),
|
||||
object: "productVariant",
|
||||
deleted: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("GET /admin/product-variants/:id", () => {
|
||||
describe("successfully gets a product variant", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"GET",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls productVariantService retrieve", () => {
|
||||
expect(ProductVariantServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.retrieve).toHaveBeenCalledWith(
|
||||
IdMap.getId("testVariant")
|
||||
)
|
||||
})
|
||||
|
||||
it("returns product", () => {
|
||||
expect(subject.body._id).toEqual(IdMap.getId("testVariant"))
|
||||
})
|
||||
})
|
||||
})
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("GET /admin/product-variants", () => {
|
||||
describe("successfully lists product variants", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("GET", `/admin/product-variants`, {
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("calls ProductVariantService list", () => {
|
||||
expect(ProductVariantServiceMock.list).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it("returns 200 and product variants", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
expect(subject.body[0]._id).toEqual(IdMap.getId("testVariant"))
|
||||
})
|
||||
})
|
||||
})
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("POST /admin/product-variants/:id/publish", () => {
|
||||
describe("successful publish", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/product-variants/${IdMap.getId("publish")}/publish`,
|
||||
{
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("returns product with published flag true", () => {
|
||||
expect(subject.body.published).toEqual(true)
|
||||
})
|
||||
|
||||
it("calls service publish", () => {
|
||||
expect(ProductVariantServiceMock.publish).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.publish).toHaveBeenCalledWith(
|
||||
IdMap.getId("publish")
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,77 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("POST /admin/product-variants/:id/prices", () => {
|
||||
describe("successfully sets region price", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}/prices`,
|
||||
{
|
||||
payload: {
|
||||
region_id: IdMap.getId("region-fr"),
|
||||
amount: 100,
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service setCurrencyPrice", () => {
|
||||
expect(ProductVariantServiceMock.setRegionPrice).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.setRegionPrice).toHaveBeenCalledWith(
|
||||
IdMap.getId("testVariant"),
|
||||
IdMap.getId("region-fr"),
|
||||
100
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("successfully sets currency price", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}/prices`,
|
||||
{
|
||||
payload: {
|
||||
currency_code: "EUR",
|
||||
amount: 100,
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service setCurrencyPrice", () => {
|
||||
expect(ProductVariantServiceMock.setCurrencyPrice).toHaveBeenCalledTimes(
|
||||
1
|
||||
)
|
||||
expect(ProductVariantServiceMock.setCurrencyPrice).toHaveBeenCalledWith(
|
||||
IdMap.getId("testVariant"),
|
||||
"EUR",
|
||||
100
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("POST /admin/product-variants/:id", () => {
|
||||
describe("successful update", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}`,
|
||||
{
|
||||
payload: {
|
||||
title: "Test Product Variant Updated",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "DKK",
|
||||
amount: 1234,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service update", () => {
|
||||
expect(ProductVariantServiceMock.update).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.update).toHaveBeenCalledWith(
|
||||
IdMap.getId("testVariant"),
|
||||
{
|
||||
title: "Test Product Variant Updated",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "DKK",
|
||||
amount: 1234,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("handles failed update operation", () => {
|
||||
it("throws if metadata is to be updated", async () => {
|
||||
try {
|
||||
await request(
|
||||
"POST",
|
||||
`/admin/product-variants/${IdMap.getId("testVariant")}`,
|
||||
{
|
||||
payload: {
|
||||
_id: IdMap.getId("testVariant"),
|
||||
title: "Product 1",
|
||||
metadata: "Test Description",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
} catch (error) {
|
||||
expect(error.status).toEqual(400)
|
||||
expect(error.message).toEqual(
|
||||
"Use setMetadata to update metadata fields"
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,28 +0,0 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
option_id: Validator.objectId().required(),
|
||||
value: Validator.string().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariant = await productVariantService.addOptionValue(
|
||||
id,
|
||||
value.option_id,
|
||||
value.value
|
||||
)
|
||||
|
||||
res.status(200).json(productVariant)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object()
|
||||
.keys({
|
||||
region_id: Validator.string(),
|
||||
currency_code: Validator.string(),
|
||||
amount: Validator.number().required(),
|
||||
})
|
||||
.xor("region_id", "currency_code")
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
|
||||
if (value.region_id) {
|
||||
const productVariant = await productVariantService.setRegionPrice(
|
||||
id,
|
||||
value.region_id,
|
||||
value.amount
|
||||
)
|
||||
|
||||
res.status(200).json(productVariant)
|
||||
} else {
|
||||
const productVariant = await productVariantService.setCurrencyPrice(
|
||||
id,
|
||||
value.currency_code,
|
||||
value.amount
|
||||
)
|
||||
|
||||
res.status(200).json(productVariant)
|
||||
}
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
option_id: Validator.objectId().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariant = await productVariantService.deleteOptionValue(
|
||||
id,
|
||||
value.option_id
|
||||
)
|
||||
|
||||
res.status(200).json(productVariant)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
await productVariantService.delete(id)
|
||||
|
||||
res.json({
|
||||
id: id,
|
||||
object: "productVariant",
|
||||
deleted: true,
|
||||
})
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariant = await productVariantService.retrieve(id)
|
||||
|
||||
res.json(productVariant)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { Router } from "express"
|
||||
import middlewares from "../../../middlewares"
|
||||
|
||||
const route = Router()
|
||||
|
||||
export default app => {
|
||||
app.use("/product-variants", route)
|
||||
|
||||
route.post("/", middlewares.wrap(require("./create-product-variant").default))
|
||||
route.post(
|
||||
"/:id",
|
||||
middlewares.wrap(require("./update-product-variant").default)
|
||||
)
|
||||
|
||||
route.post(
|
||||
"/:id/publish",
|
||||
middlewares.wrap(require("./publish-product-variant").default)
|
||||
)
|
||||
|
||||
route.post("/:id/prices", middlewares.wrap(require("./add-price").default))
|
||||
|
||||
route.post(
|
||||
"/:id/options",
|
||||
middlewares.wrap(require("./add-option-value").default)
|
||||
)
|
||||
|
||||
route.delete(
|
||||
"/:id/options",
|
||||
middlewares.wrap(require("./delete-option-value").default)
|
||||
)
|
||||
|
||||
route.delete(
|
||||
"/:id",
|
||||
middlewares.wrap(require("./delete-product-variant").default)
|
||||
)
|
||||
|
||||
route.get("/:id", middlewares.wrap(require("./get-product-variant").default))
|
||||
route.get("/", middlewares.wrap(require("./list-product-variants").default))
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
export default async (req, res) => {
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariants = await productVariantService.list({})
|
||||
|
||||
res.json(productVariants)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariant = await productVariantService.publish(id)
|
||||
|
||||
res.json(productVariant)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
region_id: Validator.objectId().required(),
|
||||
amount: Validator.number().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariant = await productVariantService.setRegionPrice(
|
||||
id,
|
||||
value.regionId,
|
||||
value.amount
|
||||
)
|
||||
|
||||
res.status(200).json(productVariant)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
title: Validator.string().optional(),
|
||||
prices: Validator.array()
|
||||
.items({
|
||||
currency_code: Validator.string().required(),
|
||||
amount: Validator.number().required(),
|
||||
})
|
||||
.optional(),
|
||||
options: Validator.array()
|
||||
.items({
|
||||
option_id: Validator.objectId().required(),
|
||||
value: Validator.string().required(),
|
||||
})
|
||||
.optional(),
|
||||
image: Validator.string().optional(),
|
||||
inventory_quantity: Validator.number().optional(),
|
||||
allow_backorder: Validator.boolean().optional(),
|
||||
manage_inventory: Validator.boolean().optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariant = await productVariantService.update(id, value)
|
||||
|
||||
res.status(200).json(productVariant)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
+22
-7
@@ -2,17 +2,24 @@ import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductServiceMock } from "../../../../../services/__mocks__/product"
|
||||
|
||||
describe("POST /admin/products/:id/variants/:variantId", () => {
|
||||
describe("POST /admin/products/:id/variants", () => {
|
||||
describe("successful add variant", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/products/${IdMap.getId(
|
||||
"productWithOptions"
|
||||
)}/variants/${IdMap.getId("variant2")}`,
|
||||
`/admin/products/${IdMap.getId("productWithOptions")}/variants`,
|
||||
{
|
||||
payload: {
|
||||
title: "Test Product Variant",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "DKK",
|
||||
amount: 1234,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
@@ -27,10 +34,18 @@ describe("POST /admin/products/:id/variants/:variantId", () => {
|
||||
})
|
||||
|
||||
it("calls service addVariant", () => {
|
||||
expect(ProductServiceMock.addVariant).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.addVariant).toHaveBeenCalledWith(
|
||||
expect(ProductServiceMock.createVariant).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.createVariant).toHaveBeenCalledWith(
|
||||
IdMap.getId("productWithOptions"),
|
||||
IdMap.getId("variant2")
|
||||
{
|
||||
title: "Test Product Variant",
|
||||
prices: [
|
||||
{
|
||||
currency_code: "DKK",
|
||||
amount: 1234,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@ describe("POST /admin/products/:id/variants/:variantId", () => {
|
||||
})
|
||||
|
||||
it("calls service removeVariant", () => {
|
||||
expect(ProductServiceMock.removeVariant).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.removeVariant).toHaveBeenCalledWith(
|
||||
expect(ProductServiceMock.deleteVariant).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.deleteVariant).toHaveBeenCalledWith(
|
||||
IdMap.getId("productWithOptions"),
|
||||
IdMap.getId("variant1")
|
||||
)
|
||||
@@ -0,0 +1,172 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { ProductServiceMock } from "../../../../../services/__mocks__/product"
|
||||
import { ProductVariantServiceMock } from "../../../../../services/__mocks__/product-variant"
|
||||
|
||||
describe("POST /admin/products/:id/variants/:variantId", () => {
|
||||
describe("successful updates variant prices", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/products/${IdMap.getId(
|
||||
"productWithOptions"
|
||||
)}/variants/${IdMap.getId("variant1")}`,
|
||||
{
|
||||
payload: {
|
||||
title: "hi",
|
||||
prices: [
|
||||
{
|
||||
region_id: IdMap.getId("region-fr"),
|
||||
amount: 100,
|
||||
},
|
||||
{
|
||||
currency_code: "DKK",
|
||||
amount: 100,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service removeVariant", () => {
|
||||
expect(ProductVariantServiceMock.setCurrencyPrice).toHaveBeenCalledTimes(
|
||||
1
|
||||
)
|
||||
expect(ProductVariantServiceMock.setCurrencyPrice).toHaveBeenCalledWith(
|
||||
IdMap.getId("variant1"),
|
||||
"DKK",
|
||||
100
|
||||
)
|
||||
|
||||
expect(ProductVariantServiceMock.setRegionPrice).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.setRegionPrice).toHaveBeenCalledWith(
|
||||
IdMap.getId("variant1"),
|
||||
IdMap.getId("region-fr"),
|
||||
100
|
||||
)
|
||||
})
|
||||
|
||||
it("filters prices", () => {
|
||||
expect(ProductVariantServiceMock.update).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.update).toHaveBeenCalledWith(
|
||||
IdMap.getId("variant1"),
|
||||
{
|
||||
title: "hi",
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns decorated product with variant removed", () => {
|
||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
||||
expect(subject.body.decorated).toEqual(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("successful updates options", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/products/${IdMap.getId(
|
||||
"productWithOptions"
|
||||
)}/variants/${IdMap.getId("variant1")}`,
|
||||
{
|
||||
payload: {
|
||||
options: [
|
||||
{
|
||||
option_id: IdMap.getId("option_id"),
|
||||
value: 100,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service removeVariant", () => {
|
||||
expect(ProductServiceMock.updateOptionValue).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.updateOptionValue).toHaveBeenCalledWith(
|
||||
IdMap.getId("productWithOptions"),
|
||||
IdMap.getId("variant1"),
|
||||
IdMap.getId("option_id"),
|
||||
100
|
||||
)
|
||||
})
|
||||
|
||||
it("returns decorated product with variant removed", () => {
|
||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
||||
expect(subject.body.decorated).toEqual(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("successful updates variant", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/products/${IdMap.getId(
|
||||
"productWithOptions"
|
||||
)}/variants/${IdMap.getId("variant1")}`,
|
||||
{
|
||||
payload: {
|
||||
title: "hi",
|
||||
inventory_quantity: 123,
|
||||
allow_backorder: true,
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls variant update", () => {
|
||||
expect(ProductVariantServiceMock.update).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.update).toHaveBeenCalledWith(
|
||||
IdMap.getId("variant1"),
|
||||
{
|
||||
title: "hi",
|
||||
inventory_quantity: 123,
|
||||
allow_backorder: true,
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns decorated product with variant removed", () => {
|
||||
expect(subject.body._id).toEqual(IdMap.getId("productWithOptions"))
|
||||
expect(subject.body.decorated).toEqual(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
+14
-4
@@ -1,6 +1,7 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
const schema = Validator.object().keys({
|
||||
title: Validator.string().required(),
|
||||
prices: Validator.array()
|
||||
@@ -26,10 +27,19 @@ export default async (req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
const productVariant = await productVariantService.createDraft(value)
|
||||
|
||||
res.status(200).json(productVariant)
|
||||
const productService = req.scope.resolve("productService")
|
||||
const product = await productService.createVariant(id, value)
|
||||
const data = await productService.decorate(product, [
|
||||
"title",
|
||||
"description",
|
||||
"tags",
|
||||
"handle",
|
||||
"images",
|
||||
"options",
|
||||
"variants",
|
||||
"published",
|
||||
])
|
||||
res.json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
+2
-2
@@ -3,7 +3,7 @@ export default async (req, res) => {
|
||||
|
||||
try {
|
||||
const productService = req.scope.resolve("productService")
|
||||
const product = await productService.addVariant(id, variantId)
|
||||
const product = await productService.deleteVariant(id, variantId)
|
||||
const data = await productService.decorate(product, [
|
||||
"title",
|
||||
"description",
|
||||
@@ -14,7 +14,7 @@ export default async (req, res) => {
|
||||
"variants",
|
||||
"published",
|
||||
])
|
||||
res.json(data)
|
||||
res.json(product)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
@@ -12,10 +12,17 @@ export default app => {
|
||||
"/:id/publish",
|
||||
middlewares.wrap(require("./publish-product").default)
|
||||
)
|
||||
|
||||
route.post(
|
||||
"/:id/variants/:variantId",
|
||||
middlewares.wrap(require("./add-variant").default)
|
||||
"/:id/variants",
|
||||
middlewares.wrap(require("./create-variant").default)
|
||||
)
|
||||
|
||||
route.post(
|
||||
"/:id/variants/:variant_id",
|
||||
middlewares.wrap(require("./update-variant").default)
|
||||
)
|
||||
|
||||
route.post(
|
||||
"/:id/options/:optionId",
|
||||
middlewares.wrap(require("./update-option").default)
|
||||
@@ -24,7 +31,7 @@ export default app => {
|
||||
|
||||
route.delete(
|
||||
"/:id/variants/:variantId",
|
||||
middlewares.wrap(require("./remove-variant").default)
|
||||
middlewares.wrap(require("./delete-variant").default)
|
||||
)
|
||||
route.delete("/:id", middlewares.wrap(require("./delete-product").default))
|
||||
route.delete(
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
export default async (req, res) => {
|
||||
const { id, variantId } = req.params
|
||||
|
||||
try {
|
||||
const productService = req.scope.resolve("productService")
|
||||
await productService.removeVariant(id, variantId)
|
||||
let updatedProduct = await productService.retrieve(id)
|
||||
updatedProduct = await productService.decorate(updatedProduct, [
|
||||
"title",
|
||||
"description",
|
||||
"tags",
|
||||
"handle",
|
||||
"images",
|
||||
"options",
|
||||
"variants",
|
||||
"published",
|
||||
])
|
||||
res.json(updatedProduct)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import _ from "lodash"
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { id, variant_id } = req.params
|
||||
const schema = Validator.object().keys({
|
||||
title: Validator.string().optional(),
|
||||
prices: Validator.array().items(
|
||||
Validator.object()
|
||||
.keys({
|
||||
region_id: Validator.string(),
|
||||
currency_code: Validator.string(),
|
||||
amount: Validator.number().required(),
|
||||
})
|
||||
.xor("region_id", "currency_code")
|
||||
),
|
||||
options: Validator.array().items({
|
||||
option_id: Validator.objectId().required(),
|
||||
value: Validator.alternatives(
|
||||
Validator.string(),
|
||||
Validator.number()
|
||||
).required(),
|
||||
}),
|
||||
image: Validator.string().optional(),
|
||||
inventory_quantity: Validator.number().optional(),
|
||||
allow_backorder: Validator.boolean().optional(),
|
||||
manage_inventory: Validator.boolean().optional(),
|
||||
metadata: Validator.object().optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const productService = req.scope.resolve("productService")
|
||||
const productVariantService = req.scope.resolve("productVariantService")
|
||||
|
||||
if (value.prices && value.prices.length) {
|
||||
for (const price of value.prices) {
|
||||
if (price.region_id) {
|
||||
await productVariantService.setRegionPrice(
|
||||
variant_id,
|
||||
price.region_id,
|
||||
price.amount
|
||||
)
|
||||
} else {
|
||||
await productVariantService.setCurrencyPrice(
|
||||
variant_id,
|
||||
price.currency_code,
|
||||
price.amount
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.options && value.options.length) {
|
||||
for (const option of value.options) {
|
||||
await productService.updateOptionValue(
|
||||
id,
|
||||
variant_id,
|
||||
option.option_id,
|
||||
option.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
delete value.prices
|
||||
delete value.options
|
||||
|
||||
if (!_.isEmpty(value)) {
|
||||
await productVariantService.update(variant_id, value)
|
||||
}
|
||||
|
||||
const product = await productService.retrieve(id)
|
||||
const data = await productService.decorate(product, [
|
||||
"title",
|
||||
"description",
|
||||
"tags",
|
||||
"handle",
|
||||
"images",
|
||||
"options",
|
||||
"variants",
|
||||
"published",
|
||||
])
|
||||
res.json(data)
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user