feat(medusa,types,workflows,utils,product): PricingModule Integration of PriceLists into Core (#5536)
This commit is contained in:
@@ -32,6 +32,8 @@ const keepTables = [
|
||||
"payment_provider",
|
||||
"country",
|
||||
"currency",
|
||||
"migrations",
|
||||
"mikro_orm_migrations",
|
||||
]
|
||||
|
||||
const DbTestUtil = {
|
||||
@@ -52,21 +54,23 @@ const DbTestUtil = {
|
||||
|
||||
teardown: async function ({ forceDelete } = {}) {
|
||||
forceDelete = forceDelete || []
|
||||
const entities = this.db_.entityMetadatas
|
||||
const manager = this.db_.manager
|
||||
|
||||
await manager.query(`SET session_replication_role = 'replica';`)
|
||||
const tableNames = await manager.query(`SELECT table_name
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public';`)
|
||||
|
||||
for (const entity of entities) {
|
||||
for (const { table_name } of tableNames) {
|
||||
if (
|
||||
keepTables.includes(entity.tableName) &&
|
||||
!forceDelete.includes(entity.tableName)
|
||||
keepTables.includes(table_name) &&
|
||||
!forceDelete.includes(table_name)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
await manager.query(`DELETE
|
||||
FROM "${entity.tableName}";`)
|
||||
FROM "${table_name}";`)
|
||||
}
|
||||
|
||||
await manager.query(`SET session_replication_role = 'origin';`)
|
||||
|
||||
@@ -2,6 +2,7 @@ export * from "./simple-batch-job-factory"
|
||||
export * from "./simple-cart-factory"
|
||||
export * from "./simple-custom-shipping-option-factory"
|
||||
export * from "./simple-customer-factory"
|
||||
export * from "./simple-customer-group-factory"
|
||||
export * from "./simple-discount-factory"
|
||||
export * from "./simple-gift-card-factory"
|
||||
export * from "./simple-line-item-factory"
|
||||
@@ -22,5 +23,5 @@ export * from "./simple-shipping-method-factory"
|
||||
export * from "./simple-shipping-option-factory"
|
||||
export * from "./simple-shipping-profile-factory"
|
||||
export * from "./simple-shipping-tax-rate-factory"
|
||||
export * from "./simple-tax-rate-factory"
|
||||
export * from "./simple-store-factory"
|
||||
export * from "./simple-tax-rate-factory"
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("POST /admin/price-lists/:id/prices/batch", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update money amounts if variant id is present in prices", async () => {
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
},
|
||||
])
|
||||
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
prices: [
|
||||
{
|
||||
variant_id: variant.id,
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(
|
||||
`admin/price-lists/${priceList.id}/prices/batch`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,191 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleCustomerGroupFactory,
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("POST /admin/price-lists", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
await simpleCustomerGroupFactory(dbConnection, {
|
||||
id: "customer-group-1",
|
||||
name: "Test Group",
|
||||
})
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create price list and money amounts", async () => {
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [{ id: "customer-group-1" }],
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
|
||||
let response = await api.get(
|
||||
`/admin/price-lists/${result.data.price_list.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: null,
|
||||
ends_at: null,
|
||||
customer_groups: [
|
||||
{
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "Test Group",
|
||||
metadata: null,
|
||||
},
|
||||
],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 400,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
import { AxiosInstance } from "axios"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("DELETE /admin/price-lists/:id/products/:productId/batch", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant1
|
||||
let priceSet
|
||||
let priceListId
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant1 = product.variants[0]
|
||||
|
||||
priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant1.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [],
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant1.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const priceListResult = await api.post(
|
||||
`admin/price-lists`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
priceListId = priceListResult.data.price_list.id
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete prices in batch based on product ids", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
let priceSetMoneyAmounts =
|
||||
await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
expect(priceSetMoneyAmounts.length).toEqual(2)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/products/prices/batch`,
|
||||
{
|
||||
headers: adminHeaders.headers,
|
||||
data: {
|
||||
product_ids: [product.id],
|
||||
},
|
||||
}
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
|
||||
expect(priceSetMoneyAmounts.length).toEqual(1)
|
||||
expect(priceSetMoneyAmounts).toEqual([
|
||||
expect.objectContaining({
|
||||
price_list: null,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should delete prices based on single product id", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
let priceSetMoneyAmounts =
|
||||
await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
expect(priceSetMoneyAmounts.length).toEqual(2)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/products/${product.id}/prices`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_set_id: [priceSet.id],
|
||||
})
|
||||
|
||||
expect(priceSetMoneyAmounts.length).toEqual(1)
|
||||
expect(priceSetMoneyAmounts).toEqual([
|
||||
expect.objectContaining({
|
||||
price_list: null,
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("DELETE /admin/price-lists/:id/variants/:variantId/prices", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete all prices based on product variant ids", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [],
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
const priceListId = result.data.price_list.id
|
||||
|
||||
let psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(1)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/variants/${variant.id}/prices`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,146 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("DELETE /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete price list prices by money amount ids", async () => {
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
{
|
||||
amount: 4000,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const res = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
|
||||
const priceListId = res.data.price_list.id
|
||||
let psmas = await pricingModuleService.listPriceSetMoneyAmounts(
|
||||
{
|
||||
price_list_id: [priceListId],
|
||||
},
|
||||
{ relations: ["money_amount"] }
|
||||
)
|
||||
|
||||
expect(psmas.length).toEqual(2)
|
||||
|
||||
const deletePrice = psmas[0].money_amount
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}/prices/batch`,
|
||||
{
|
||||
data: {
|
||||
price_ids: [deletePrice?.id],
|
||||
},
|
||||
...adminHeaders,
|
||||
}
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(1)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,145 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("DELETE /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should delete price list and money amounts", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
customer_groups: [],
|
||||
status: "active",
|
||||
prices: [
|
||||
{
|
||||
amount: 400,
|
||||
variant_id: variant.id,
|
||||
currency_code: "usd",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const result = await api.post(`admin/price-lists`, data, adminHeaders)
|
||||
const priceListId = result.data.price_list.id
|
||||
|
||||
const getResponse = await api.get(
|
||||
`/admin/price-lists/${priceListId}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(getResponse.status).toEqual(200)
|
||||
|
||||
let psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(1)
|
||||
|
||||
const deleteRes = await api.delete(
|
||||
`/admin/price-lists/${priceListId}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(deleteRes.status).toEqual(200)
|
||||
|
||||
const afterDelete = await api
|
||||
.get(`/admin/price-lists/${priceListId}`, adminHeaders)
|
||||
.catch((err) => {
|
||||
return err
|
||||
})
|
||||
expect(afterDelete.response.status).toEqual(404)
|
||||
|
||||
psmas = await pricingModuleService.listPriceSetMoneyAmounts({
|
||||
price_list_id: [priceListId],
|
||||
})
|
||||
expect(psmas.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,204 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("GET /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get price list and its money amounts with variants", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list 1",
|
||||
description: "test 1",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an error when price list is not found", async () => {
|
||||
const api = useApi() as any
|
||||
|
||||
const error = await api
|
||||
.get(`/admin/price-lists/does-not-exist`, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toBe(404)
|
||||
expect(error.response.data).toEqual({
|
||||
type: "not_found",
|
||||
message: "Price list with id: does-not-exist was not found",
|
||||
})
|
||||
})
|
||||
})
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("GET /admin/price-lists/:id/products", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let product2
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
title: "uniquely fun product",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
|
||||
product2 = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant-2",
|
||||
title: "uniquely fun product 2",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-2", value: "test 2" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-2",
|
||||
title: "Test option 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should list all products in a price list", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
let response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: expect.any(String),
|
||||
handle: expect.any(String),
|
||||
subtitle: null,
|
||||
description: null,
|
||||
is_giftcard: false,
|
||||
status: "draft",
|
||||
thumbnail: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
origin_country: null,
|
||||
hs_code: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
collection_id: null,
|
||||
collection: null,
|
||||
type_id: null,
|
||||
type: null,
|
||||
discountable: true,
|
||||
external_id: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
metadata: null,
|
||||
}),
|
||||
])
|
||||
|
||||
response = await api.get(
|
||||
`/admin/products?price_list_id[]=${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: expect.any(String),
|
||||
handle: expect.any(String),
|
||||
subtitle: null,
|
||||
description: null,
|
||||
is_giftcard: false,
|
||||
status: "draft",
|
||||
thumbnail: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
origin_country: null,
|
||||
hs_code: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
collection_id: null,
|
||||
collection: null,
|
||||
type_id: null,
|
||||
type: null,
|
||||
discountable: true,
|
||||
external_id: null,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
metadata: null,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should list all products constrained by search query in a price list", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
let response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products?q=shouldnotreturnanything`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(0)
|
||||
expect(response.data.products).toEqual([])
|
||||
|
||||
response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products?q=uniquely`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
])
|
||||
|
||||
response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}/products?q=`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.products).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,170 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import { simpleProductFactory } from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("GET /admin/price-lists", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get price list and its money amounts with variants", async () => {
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
price_set_id: priceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
const api = useApi() as any
|
||||
|
||||
const response = await api.get(`/admin/price-lists`, adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.price_lists).toEqual([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [],
|
||||
prices: [
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: expect.any(String),
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
title: expect.any(String),
|
||||
product_id: expect.any(String),
|
||||
sku: null,
|
||||
barcode: null,
|
||||
ean: null,
|
||||
upc: null,
|
||||
variant_rank: 0,
|
||||
inventory_quantity: 10,
|
||||
allow_backorder: false,
|
||||
manage_inventory: true,
|
||||
hs_code: null,
|
||||
origin_country: null,
|
||||
mid_code: null,
|
||||
material: null,
|
||||
weight: null,
|
||||
length: null,
|
||||
height: null,
|
||||
width: null,
|
||||
metadata: null,
|
||||
}),
|
||||
variant_id: expect.any(String),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,226 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleCustomerGroupFactory,
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("POST /admin/price-lists/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let variant2
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
await simpleCustomerGroupFactory(dbConnection, {
|
||||
id: "customer-group-2",
|
||||
name: "Test Group 2",
|
||||
})
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
{
|
||||
options: [{ option_id: "test-product-option-2", value: "test 2" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
{
|
||||
id: "test-product-option-2",
|
||||
title: "Test option 2",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
variant2 = product.variants[1]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should update price lists successfully with prices", async () => {
|
||||
const var2PriceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant2.id,
|
||||
prices: [],
|
||||
})
|
||||
|
||||
const [priceList] = await pricingModuleService.createPriceLists([
|
||||
{
|
||||
title: "test price list",
|
||||
description: "test",
|
||||
ends_at: new Date(),
|
||||
starts_at: new Date(),
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.OVERRIDE,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
price_set_id: var2PriceSet.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const api = useApi() as any
|
||||
const data = {
|
||||
name: "new price list name",
|
||||
description: "new price list description",
|
||||
customer_groups: [{ id: "customer-group-2" }],
|
||||
prices: [
|
||||
{
|
||||
variant_id: variant.id,
|
||||
amount: 5000,
|
||||
currency_code: "usd",
|
||||
},
|
||||
{
|
||||
id: priceList?.price_set_money_amounts?.[0].money_amount?.id,
|
||||
amount: 6000,
|
||||
currency_code: "usd",
|
||||
variant_id: variant2.id,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders)
|
||||
|
||||
const response = await api.get(
|
||||
`/admin/price-lists/${priceList.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.price_list).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "new price list name",
|
||||
description: "new price list description",
|
||||
type: "override",
|
||||
status: "active",
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
customer_groups: [
|
||||
{
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
name: "Test Group 2",
|
||||
metadata: null,
|
||||
},
|
||||
],
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceList.id,
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: variant.id,
|
||||
}),
|
||||
variant_id: variant.id,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
currency_code: "usd",
|
||||
amount: 6000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceList.id,
|
||||
region_id: null,
|
||||
variant: expect.objectContaining({
|
||||
id: variant2.id,
|
||||
}),
|
||||
variant_id: variant2.id,
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,289 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleCustomerFactory,
|
||||
simpleCustomerGroupFactory,
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import {
|
||||
IPricingModuleService,
|
||||
PriceListStatus,
|
||||
PriceListType,
|
||||
} from "@medusajs/types"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
import { createVariantPriceSet } from "../../../helpers/create-variant-price-set"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("GET /store/products/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
let priceSetId
|
||||
let pricingModuleService: IPricingModuleService
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
pricingModuleService = appContainer.resolve("pricingModuleService")
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
status: "published",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
|
||||
const priceSet = await createVariantPriceSet({
|
||||
container: appContainer,
|
||||
variantId: variant.id,
|
||||
prices: [
|
||||
{
|
||||
amount: 3000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
amount: 4000,
|
||||
currency_code: "usd",
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
rules: [],
|
||||
})
|
||||
|
||||
priceSetId = priceSet.id
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should get product and its prices from price-list created through the price list workflow", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const priceListResponse = await api.post(
|
||||
`/admin/price-lists`,
|
||||
{
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.SALE,
|
||||
prices: [
|
||||
{
|
||||
amount: 2500,
|
||||
currency_code: "usd",
|
||||
variant_id: variant.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let response = await api.get(
|
||||
`/store/products/${product.id}?currency_code=usd`
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants[0].prices).toHaveLength(2)
|
||||
expect(response.data.product.variants[0].prices).toEqual([
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 3000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: null,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 2500,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceListResponse.data.price_list.id,
|
||||
}),
|
||||
])
|
||||
expect(response.data.product.variants[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
original_price: 3000,
|
||||
calculated_price: 2500,
|
||||
calculated_price_type: "sale",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should not list prices from price-list with customer groups if not logged in", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
const { id: customerGroupId } = await simpleCustomerGroupFactory(
|
||||
dbConnection
|
||||
)
|
||||
|
||||
const priceListResponse = await api.post(
|
||||
`/admin/price-lists`,
|
||||
{
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.SALE,
|
||||
prices: [
|
||||
{
|
||||
amount: 2500,
|
||||
currency_code: "usd",
|
||||
variant_id: variant.id,
|
||||
},
|
||||
],
|
||||
customer_groups: [{ id: customerGroupId }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let response = await api.get(
|
||||
`/store/products/${product.id}?currency_code=usd`
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants[0].prices).toEqual([
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 3000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: null,
|
||||
}),
|
||||
])
|
||||
expect(response.data.product.variants[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
original_price: 3000,
|
||||
calculated_price: 3000,
|
||||
calculated_price_type: null,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should list prices from price-list with customer groups", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
|
||||
await simpleCustomerFactory(dbConnection, {
|
||||
id: "test-customer-5-pl",
|
||||
email: "test5@email-pl.com",
|
||||
first_name: "John",
|
||||
last_name: "Deere",
|
||||
password_hash:
|
||||
"c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test"
|
||||
has_account: true,
|
||||
groups: [{ id: "customer-group-1" }],
|
||||
})
|
||||
|
||||
const authResponse = await api.post("/store/auth", {
|
||||
email: "test5@email-pl.com",
|
||||
password: "test",
|
||||
})
|
||||
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";")
|
||||
|
||||
const priceListResponse = await api.post(
|
||||
`/admin/price-lists`,
|
||||
{
|
||||
name: "test price list",
|
||||
description: "test",
|
||||
status: PriceListStatus.ACTIVE,
|
||||
type: PriceListType.SALE,
|
||||
prices: [
|
||||
{
|
||||
amount: 2500,
|
||||
currency_code: "usd",
|
||||
variant_id: variant.id,
|
||||
},
|
||||
],
|
||||
customer_groups: [{ id: "customer-group-1" }],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let response = await api.get(
|
||||
`/store/products/${product.id}?currency_code=usd`,
|
||||
{
|
||||
headers: {
|
||||
Cookie: authCookie,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants[0].prices).toHaveLength(2)
|
||||
expect(response.data.product.variants[0].prices).toEqual([
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 3000,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: null,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
currency_code: "usd",
|
||||
amount: 2500,
|
||||
min_quantity: null,
|
||||
max_quantity: null,
|
||||
price_list_id: priceListResponse.data.price_list.id,
|
||||
}),
|
||||
])
|
||||
expect(response.data.product.variants[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
original_price: 3000,
|
||||
calculated_price: 2500,
|
||||
calculated_price_type: "sale",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -8,6 +8,7 @@ import path from "path"
|
||||
import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app"
|
||||
import { getContainer } from "../../../environment-helpers/use-container"
|
||||
import adminSeeder from "../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../helpers/create-default-rule-types"
|
||||
|
||||
jest.setTimeout(5000000)
|
||||
|
||||
@@ -46,6 +47,7 @@ describe("Link Modules", () => {
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await createDefaultRuleTypes(medusaContainer)
|
||||
await adminSeeder(dbConnection)
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "region-1",
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
import {
|
||||
simpleProductFactory,
|
||||
simpleRegionFactory,
|
||||
} from "../../../../factories"
|
||||
|
||||
import { PricingModuleService } from "@medusajs/pricing"
|
||||
import { ProductModuleService } from "@medusajs/product"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
"x-medusa-access-token": "test_token",
|
||||
},
|
||||
}
|
||||
|
||||
const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("POST /admin/products/:id/variants", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
let product
|
||||
let variant
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
|
||||
dbConnection = await initDb({ cwd, env } as any)
|
||||
shutdownServer = await startBootstrapApp({ cwd, env })
|
||||
appContainer = getContainer()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
await shutdownServer()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(appContainer)
|
||||
|
||||
await simpleRegionFactory(dbConnection, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
product = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-with-variant",
|
||||
variants: [
|
||||
{
|
||||
options: [{ option_id: "test-product-option-1", value: "test" }],
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
id: "test-product-option-1",
|
||||
title: "Test option 1",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
variant = product.variants[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should create a product variant with its price sets and prices through the workflow", async () => {
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [{ option_id: "test-product-option-1", value: "test option" }],
|
||||
}
|
||||
|
||||
let response = await api.post(
|
||||
`/admin/products/${product.id}/variants`,
|
||||
data,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
title: "test variant create",
|
||||
prices: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 66600,
|
||||
currency_code: "usd",
|
||||
region_id: "test-region",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should compensate creating product variants when error throws in future step", async () => {
|
||||
jest
|
||||
.spyOn(PricingModuleService.prototype, "create")
|
||||
.mockImplementation(() => {
|
||||
throw new Error("Random Error")
|
||||
})
|
||||
|
||||
const productSpy = jest.spyOn(
|
||||
ProductModuleService.prototype,
|
||||
"deleteVariants"
|
||||
)
|
||||
|
||||
const api = useApi()! as AxiosInstance
|
||||
const data = {
|
||||
title: "test variant create",
|
||||
prices: [
|
||||
{
|
||||
amount: 66600,
|
||||
region_id: "test-region",
|
||||
},
|
||||
{
|
||||
amount: 55500,
|
||||
currency_code: "usd",
|
||||
region_id: null,
|
||||
},
|
||||
],
|
||||
material: "boo",
|
||||
mid_code: "234asdfadsf",
|
||||
hs_code: "asdfasdf234",
|
||||
origin_country: "DE",
|
||||
sku: "asdf",
|
||||
ean: "234",
|
||||
upc: "234",
|
||||
barcode: "asdf",
|
||||
inventory_quantity: 234,
|
||||
manage_inventory: true,
|
||||
allow_backorder: true,
|
||||
weight: 234,
|
||||
width: 234,
|
||||
height: 234,
|
||||
length: 234,
|
||||
metadata: { asdf: "asdf" },
|
||||
options: [{ option_id: "test-product-option-1", value: "test option" }],
|
||||
}
|
||||
|
||||
await api
|
||||
.post(`/admin/products/${product.id}/variants`, data, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(productSpy).toBeCalledWith([expect.any(String)])
|
||||
|
||||
const getProductResponse = await api.get(
|
||||
`/admin/products/${product.id}`,
|
||||
adminHeaders
|
||||
)
|
||||
expect(getProductResponse.data.product.variants).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
@@ -1,11 +1,13 @@
|
||||
import { initDb, useDb } from "../../../../environment-helpers/use-db"
|
||||
|
||||
import { Region } from "@medusajs/medusa"
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { AxiosInstance } from "axios"
|
||||
import path from "path"
|
||||
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
|
||||
import { useApi } from "../../../../environment-helpers/use-api"
|
||||
import { getContainer } from "../../../../environment-helpers/use-container"
|
||||
import { simpleSalesChannelFactory } from "../../../../factories"
|
||||
import adminSeeder from "../../../../helpers/admin-seeder"
|
||||
import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types"
|
||||
|
||||
@@ -21,7 +23,7 @@ const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("[Product & Pricing Module] POST /admin/products", () => {
|
||||
describe("POST /admin/products", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
@@ -50,6 +52,8 @@ describe("[Product & Pricing Module] POST /admin/products", () => {
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, { is_default: true })
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -110,5 +114,12 @@ describe("[Product & Pricing Module] POST /admin/products", () => {
|
||||
]),
|
||||
}),
|
||||
})
|
||||
|
||||
const pricingModuleService: IPricingModuleService = appContainer.resolve(
|
||||
"pricingModuleService"
|
||||
)
|
||||
|
||||
const [_, count] = await pricingModuleService.listAndCount()
|
||||
expect(count).toEqual(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -441,6 +441,7 @@ describe("/admin/products", () => {
|
||||
beforeEach(async () => {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
await createDefaultRuleTypes(medusaContainer)
|
||||
|
||||
await simpleSalesChannelFactory(dbConnection, {
|
||||
name: "Default channel",
|
||||
|
||||
@@ -25,7 +25,7 @@ const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("[Product & Pricing Module] POST /admin/products/:id/variants/:id", () => {
|
||||
describe("POST /admin/products/:id/variants/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
|
||||
@@ -23,7 +23,7 @@ const env = {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
}
|
||||
|
||||
describe("[Product & Pricing Module] POST /admin/products/:id", () => {
|
||||
describe("POST /admin/products/:id", () => {
|
||||
let dbConnection
|
||||
let appContainer
|
||||
let shutdownServer
|
||||
@@ -109,10 +109,11 @@ describe("[Product & Pricing Module] POST /admin/products/:id", () => {
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product.variants).toHaveLength(1)
|
||||
expect(response.data.product).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
variants: expect.arrayContaining([
|
||||
variants: [
|
||||
expect.objectContaining({
|
||||
id: variant.id,
|
||||
title: "test variant update",
|
||||
@@ -128,7 +129,7 @@ describe("[Product & Pricing Module] POST /admin/products/:id", () => {
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
@@ -10,5 +10,9 @@ export const createDefaultRuleTypes = async (container) => {
|
||||
name: "region_id",
|
||||
rule_attribute: "region_id",
|
||||
},
|
||||
{
|
||||
name: "customer_group_id",
|
||||
rule_attribute: "customer_group_id",
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user