feat(pricing, types): PriceSets as entry point to pricing module (#4978)

What:
- Adds PriceSet, PriceSetMoneyAmount, updates schema
- Adds service/repo for PriceSet
- Shifts entry point to use PriceSet
- Updates link/joiner config

RESOLVES CORE-1495
This commit is contained in:
Riqwan Thamir
2023-09-11 17:24:31 +00:00
committed by GitHub
parent adf4903003
commit 834da5c41a
29 changed files with 1853 additions and 113 deletions
@@ -0,0 +1,388 @@
import { CreatePriceSetDTO } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { MoneyAmount, PriceSet } from "@models"
import { PriceSetRepository } from "@repositories"
import { PriceSetService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { createPriceSets } from "../../../__fixtures__/price-set"
import { MikroOrmWrapper } from "../../../utils"
jest.setTimeout(30000)
describe("PriceSet Service", () => {
let service: PriceSetService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
let data!: PriceSet[]
let moneyAmountsData!: MoneyAmount[]
const moneyAmountsInputData = [
{
id: "money-amount-USD",
currency_code: "USD",
amount: 500,
min_quantity: 1,
max_quantity: 10,
},
]
const priceSetInputData = [
{
id: "price-set-1",
money_amounts: [{ id: "money-amount-USD" }],
},
{
id: "price-set-2",
money_amounts: [],
},
{
id: "price-set-3",
money_amounts: [],
},
]
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const priceSetRepository = new PriceSetRepository({
manager: repositoryManager,
})
service = new PriceSetService({
priceSetRepository,
})
await createCurrencies(testManager)
moneyAmountsData = await createMoneyAmounts(
testManager,
moneyAmountsInputData
)
data = await createPriceSets(testManager, priceSetInputData)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("list", () => {
it("should list priceSets", async () => {
const priceSetsResult = await service.list()
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(serialized).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
expect.objectContaining({
id: "price-set-2",
}),
expect.objectContaining({
id: "price-set-3",
}),
])
})
it("should list priceSets by id", async () => {
const priceSetsResult = await service.list({
id: ["price-set-1"],
})
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
])
})
it("should list priceSets with relations and selects", async () => {
const priceSetsResult = await service.list(
{
id: ["price-set-1"],
},
{
select: ["id", "money_amounts.id"],
relations: ["money_amounts"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(serialized).toEqual([
{
id: "price-set-1",
money_amounts: [
{
id: "money-amount-USD",
},
],
},
])
})
it("should scope priceSets with currency_code of money amounts", async () => {
const priceSetsResult = await service.list(
{
money_amounts: {
currency_code: ["USD"],
},
},
{
select: ["id", "money_amounts.id"],
relations: ["money_amounts"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(serialized).toEqual([
{
id: "price-set-1",
money_amounts: [
{
id: "money-amount-USD",
},
],
},
])
})
})
it("should not return price sets if money amounts with a currency code dont exist", async () => {
const priceSetsResult = await service.list(
{
money_amounts: {
currency_code: ["DOESNOTEXIST"],
},
},
{
select: ["id", "money_amounts.id"],
relations: ["money_amounts"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(serialized).toEqual([])
})
describe("listAndCount", () => {
it("should return priceSets and count", async () => {
const [priceSetsResult, count] = await service.listAndCount()
expect(count).toEqual(3)
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
expect.objectContaining({
id: "price-set-2",
}),
expect.objectContaining({
id: "price-set-3",
}),
])
})
it("should return priceSets and count when filtered", async () => {
const [priceSetsResult, count] = await service.listAndCount({
id: ["price-set-1"],
})
expect(count).toEqual(1)
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
])
})
it("should list priceSets with relations and selects", async () => {
const [priceSetsResult, count] = await service.listAndCount(
{
id: ["price-set-1"],
},
{
select: ["id", "min_quantity", "money_amounts.id"],
relations: ["money_amounts"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(count).toEqual(1)
expect(serialized).toEqual([
{
id: "price-set-1",
money_amounts: [
{
id: "money-amount-USD",
},
],
},
])
})
it("should return priceSets and count when using skip and take", async () => {
const [priceSetsResult, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(3)
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-2",
}),
])
})
it("should return requested fields", async () => {
const [priceSetsResult, count] = await service.listAndCount(
{},
{
take: 1,
select: ["id"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(count).toEqual(3)
expect(serialized).toEqual([
{
id: "price-set-1",
},
])
})
})
describe("retrieve", () => {
const id = "price-set-1"
it("should return priceSet for the given id", async () => {
const priceSet = await service.retrieve(id)
expect(priceSet).toEqual(
expect.objectContaining({
id,
})
)
})
it("should throw an error when priceSet with id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"PriceSet with id: does-not-exist was not found"
)
})
it("should throw an error when a id is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual('"priceSetId" must be defined')
})
it("should return priceSet based on config select param", async () => {
const priceSet = await service.retrieve(id, {
select: ["id"],
})
const serialized = JSON.parse(JSON.stringify(priceSet))
expect(serialized).toEqual({
id,
})
})
})
describe("delete", () => {
const id = "price-set-1"
it("should delete the priceSets given an id successfully", async () => {
await service.delete([id])
const priceSets = await service.list({
id: [id],
})
expect(priceSets).toHaveLength(0)
})
})
describe("update", () => {
const id = "price-set-1"
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'PriceSet with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.update([
{
random: "does-not-exist",
} as any,
])
} catch (e) {
error = e
}
expect(error.message).toEqual('PriceSet with id "undefined" not found')
})
it("should create a priceSet successfully", async () => {
await service.create([
{
id: "price-set-new",
} as unknown as CreatePriceSetDTO,
])
const [priceSet] = await service.list({
id: ["price-set-new"],
})
expect(priceSet).toEqual(
expect.objectContaining({
id: "price-set-new",
} as unknown as CreatePriceSetDTO)
)
})
})
})
@@ -6,7 +6,7 @@ import { initialize } from "../../../../src"
import { createCurrencies } from "../../../__fixtures__/currency"
import { DB_URL, MikroOrmWrapper } from "../../../utils"
describe("PricingModuleService currency", () => {
describe("PricingModule Service - Currency", () => {
let service: IPricingModuleService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
@@ -9,7 +9,7 @@ import { DB_URL, MikroOrmWrapper } from "../../../utils"
jest.setTimeout(30000)
describe("MoneyAmount Service", () => {
describe("PricingModule Service - MoneyAmount", () => {
let service: IPricingModuleService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
@@ -38,9 +38,9 @@ describe("MoneyAmount Service", () => {
await MikroOrmWrapper.clearDatabase()
})
describe("list", () => {
describe("listMoneyAmounts", () => {
it("list moneyAmounts", async () => {
const moneyAmountsResult = await service.list()
const moneyAmountsResult = await service.listMoneyAmounts()
expect(moneyAmountsResult).toEqual([
expect.objectContaining({
@@ -58,8 +58,8 @@ describe("MoneyAmount Service", () => {
])
})
it("list moneyAmounts by id", async () => {
const moneyAmountsResult = await service.list({
it("should list moneyAmounts by id", async () => {
const moneyAmountsResult = await service.listMoneyAmounts({
id: ["money-amount-USD"],
})
@@ -70,8 +70,8 @@ describe("MoneyAmount Service", () => {
])
})
it("list moneyAmounts with relations and selects", async () => {
const moneyAmountsResult = await service.list(
it("should list moneyAmounts with relations and selects", async () => {
const moneyAmountsResult = await service.listMoneyAmounts(
{
id: ["money-amount-USD"],
},
@@ -96,9 +96,10 @@ describe("MoneyAmount Service", () => {
})
})
describe("listAndCount", () => {
describe("listAndCountMoneyAmounts", () => {
it("should return moneyAmounts and count", async () => {
const [moneyAmountsResult, count] = await service.listAndCount()
const [moneyAmountsResult, count] =
await service.listAndCountMoneyAmounts()
expect(count).toEqual(3)
expect(moneyAmountsResult).toEqual([
@@ -115,9 +116,10 @@ describe("MoneyAmount Service", () => {
})
it("should return moneyAmounts and count when filtered", async () => {
const [moneyAmountsResult, count] = await service.listAndCount({
id: ["money-amount-USD"],
})
const [moneyAmountsResult, count] =
await service.listAndCountMoneyAmounts({
id: ["money-amount-USD"],
})
expect(count).toEqual(1)
expect(moneyAmountsResult).toEqual([
@@ -128,15 +130,16 @@ describe("MoneyAmount Service", () => {
})
it("list moneyAmounts with relations and selects", async () => {
const [moneyAmountsResult, count] = await service.listAndCount(
{
id: ["money-amount-USD"],
},
{
select: ["id", "min_quantity", "currency.code"],
relations: ["currency"],
}
)
const [moneyAmountsResult, count] =
await service.listAndCountMoneyAmounts(
{
id: ["money-amount-USD"],
},
{
select: ["id", "min_quantity", "currency.code"],
relations: ["currency"],
}
)
const serialized = JSON.parse(JSON.stringify(moneyAmountsResult))
@@ -154,10 +157,8 @@ describe("MoneyAmount Service", () => {
})
it("should return moneyAmounts and count when using skip and take", async () => {
const [moneyAmountsResult, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
const [moneyAmountsResult, count] =
await service.listAndCountMoneyAmounts({}, { skip: 1, take: 1 })
expect(count).toEqual(3)
expect(moneyAmountsResult).toEqual([
@@ -168,13 +169,14 @@ describe("MoneyAmount Service", () => {
})
it("should return requested fields", async () => {
const [moneyAmountsResult, count] = await service.listAndCount(
{},
{
take: 1,
select: ["id"],
}
)
const [moneyAmountsResult, count] =
await service.listAndCountMoneyAmounts(
{},
{
take: 1,
select: ["id"],
}
)
const serialized = JSON.parse(JSON.stringify(moneyAmountsResult))
@@ -187,12 +189,12 @@ describe("MoneyAmount Service", () => {
})
})
describe("retrieve", () => {
describe("retrieveMoneyAmount", () => {
const id = "money-amount-USD"
const amount = "500"
it("should return moneyAmount for the given id", async () => {
const moneyAmount = await service.retrieve(id)
const moneyAmount = await service.retrieveMoneyAmount(id)
expect(moneyAmount).toEqual(
expect.objectContaining({
@@ -205,7 +207,7 @@ describe("MoneyAmount Service", () => {
let error
try {
await service.retrieve("does-not-exist")
await service.retrieveMoneyAmount("does-not-exist")
} catch (e) {
error = e
}
@@ -219,7 +221,7 @@ describe("MoneyAmount Service", () => {
let error
try {
await service.retrieve(undefined as unknown as string)
await service.retrieveMoneyAmount(undefined as unknown as string)
} catch (e) {
error = e
}
@@ -228,7 +230,7 @@ describe("MoneyAmount Service", () => {
})
it("should return moneyAmount based on config select param", async () => {
const moneyAmount = await service.retrieve(id, {
const moneyAmount = await service.retrieveMoneyAmount(id, {
select: ["id", "amount"],
})
@@ -241,13 +243,13 @@ describe("MoneyAmount Service", () => {
})
})
describe("delete", () => {
describe("deleteMoneyAmounts", () => {
const id = "money-amount-USD"
it("should delete the moneyAmounts given an id successfully", async () => {
await service.delete([id])
await service.deleteMoneyAmounts([id])
const moneyAmounts = await service.list({
const moneyAmounts = await service.listMoneyAmounts({
id: [id],
})
@@ -255,31 +257,31 @@ describe("MoneyAmount Service", () => {
})
})
describe("update", () => {
describe("updateMoneyAmounts", () => {
const id = "money-amount-USD"
it("should update the amount of the moneyAmount successfully", async () => {
await service.update([
await service.updateMoneyAmounts([
{
id,
amount: 700,
},
])
const moneyAmount = await service.retrieve(id)
const moneyAmount = await service.retrieveMoneyAmount(id)
expect(moneyAmount.amount).toEqual("700")
})
it("should update the currency of the moneyAmount successfully", async () => {
await service.update([
await service.updateMoneyAmounts([
{
id,
currency_code: "EUR",
},
])
const moneyAmount = await service.retrieve(id, {
const moneyAmount = await service.retrieveMoneyAmount(id, {
relations: ["currency"],
})
@@ -291,7 +293,7 @@ describe("MoneyAmount Service", () => {
let error
try {
await service.update([
await service.updateMoneyAmounts([
{
id: "does-not-exist",
amount: 666,
@@ -307,9 +309,9 @@ describe("MoneyAmount Service", () => {
})
})
describe("create", () => {
describe("createMoneyAmounts", () => {
it("should create a moneyAmount successfully", async () => {
await service.create([
await service.createMoneyAmounts([
{
id: "money-amount-TESM",
currency_code: "USD",
@@ -319,7 +321,7 @@ describe("MoneyAmount Service", () => {
},
])
const [moneyAmount] = await service.list({
const [moneyAmount] = await service.listMoneyAmounts({
id: ["money-amount-TESM"],
})
@@ -0,0 +1,404 @@
import { CreatePriceSetDTO, IPricingModuleService } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { PriceSet } from "@models"
import { initialize } from "../../../../src"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { createPriceSets } from "../../../__fixtures__/price-set"
import { DB_URL, MikroOrmWrapper } from "../../../utils"
jest.setTimeout(30000)
describe("PricingModule Service - PriceSet", () => {
let service: IPricingModuleService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
let data!: PriceSet[]
const moneyAmountsInputData = [
{
id: "money-amount-USD",
currency_code: "USD",
amount: 500,
min_quantity: 1,
max_quantity: 10,
},
{
id: "money-amount-EUR",
currency_code: "EUR",
amount: 500,
min_quantity: 1,
max_quantity: 10,
},
]
const priceSetInputData = [
{
id: "price-set-1",
money_amounts: [{ id: "money-amount-USD" }],
},
{
id: "price-set-2",
money_amounts: [{ id: "money-amount-EUR" }],
},
{
id: "price-set-3",
money_amounts: [],
},
]
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = MikroOrmWrapper.forkManager()
service = await initialize({
database: {
clientUrl: DB_URL,
schema: process.env.MEDUSA_PRICING_DB_SCHEMA,
},
})
testManager = MikroOrmWrapper.forkManager()
await createCurrencies(testManager)
await createMoneyAmounts(testManager, moneyAmountsInputData)
data = await createPriceSets(testManager, priceSetInputData)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("calculatePrices", () => {
it("retrieves the calculated prices when no context is set", async () => {
const priceSetsResult = await service.calculatePrices(
["price-set-1", "price-set-2"],
{}
)
expect(priceSetsResult).toEqual([
{
id: "price-set-1",
amount: null,
currency_code: null,
min_quantity: null,
max_quantity: null,
},
{
id: "price-set-2",
amount: null,
currency_code: null,
min_quantity: null,
max_quantity: null,
},
])
})
it("retrieves the calculated prices when a context is set", async () => {
const priceSetsResult = await service.calculatePrices(
["price-set-1", "price-set-2"],
{
currency_code: "USD",
}
)
expect(priceSetsResult).toEqual([
{
id: "price-set-1",
amount: "500",
currency_code: "USD",
min_quantity: "1",
max_quantity: "10",
},
{
id: "price-set-2",
amount: null,
currency_code: null,
min_quantity: null,
max_quantity: null,
},
])
})
it("retrieves the calculated prices only when id exists in the database", async () => {
const priceSetsResult = await service.calculatePrices(
["price-set-doesnotexist", "price-set-1"],
{
currency_code: "USD",
}
)
expect(priceSetsResult).toEqual([
{
id: "price-set-1",
amount: "500",
currency_code: "USD",
min_quantity: "1",
max_quantity: "10",
},
])
})
})
describe("list", () => {
it("list priceSets", async () => {
const priceSetsResult = await service.list()
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
expect.objectContaining({
id: "price-set-2",
}),
expect.objectContaining({
id: "price-set-3",
}),
])
})
it("list priceSets by id", async () => {
const priceSetsResult = await service.list({
id: ["price-set-1"],
})
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
])
})
it("list priceSets with relations and selects", async () => {
const priceSetsResult = await service.list(
{
id: ["price-set-1"],
},
{
select: ["id", "money_amounts.id", "money_amounts.amount"],
relations: ["money_amounts"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(serialized).toEqual([
{
id: "price-set-1",
money_amounts: [{ id: "money-amount-USD", amount: "500" }],
},
])
})
})
describe("listAndCount", () => {
it("should return priceSets and count", async () => {
const [priceSetsResult, count] = await service.listAndCount()
expect(count).toEqual(3)
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
expect.objectContaining({
id: "price-set-2",
}),
expect.objectContaining({
id: "price-set-3",
}),
])
})
it("should return priceSets and count when filtered", async () => {
const [priceSetsResult, count] = await service.listAndCount({
id: ["price-set-1"],
})
expect(count).toEqual(1)
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-1",
}),
])
})
it("list priceSets with relations and selects", async () => {
const [priceSetsResult, count] = await service.listAndCount(
{
id: ["price-set-1"],
},
{
select: ["id", "min_quantity", "money_amounts.id"],
relations: ["money_amounts"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(count).toEqual(1)
expect(serialized).toEqual([
{
id: "price-set-1",
money_amounts: [{ id: "money-amount-USD" }],
},
])
})
it("should return priceSets and count when using skip and take", async () => {
const [priceSetsResult, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(3)
expect(priceSetsResult).toEqual([
expect.objectContaining({
id: "price-set-2",
}),
])
})
it("should return requested fields", async () => {
const [priceSetsResult, count] = await service.listAndCount(
{},
{
take: 1,
select: ["id"],
}
)
const serialized = JSON.parse(JSON.stringify(priceSetsResult))
expect(count).toEqual(3)
expect(serialized).toEqual([
{
id: "price-set-1",
},
])
})
})
describe("retrieve", () => {
const id = "price-set-1"
it("should return priceSet for the given id", async () => {
const priceSet = await service.retrieve(id)
expect(priceSet).toEqual(
expect.objectContaining({
id,
})
)
})
it("should throw an error when priceSet with id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"PriceSet with id: does-not-exist was not found"
)
})
it("should throw an error when a id is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual('"priceSetId" must be defined')
})
it("should return priceSet based on config select param", async () => {
const priceSet = await service.retrieve(id, {
select: ["id"],
})
const serialized = JSON.parse(JSON.stringify(priceSet))
expect(serialized).toEqual({
id,
})
})
})
describe("delete", () => {
const id = "price-set-1"
it("should delete the priceSets given an id successfully", async () => {
await service.delete([id])
const priceSets = await service.list({
id: [id],
})
expect(priceSets).toHaveLength(0)
})
})
describe("update", () => {
const id = "price-set-1"
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'PriceSet with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.update([
{
random: "does-not-exist",
} as any,
])
} catch (e) {
error = e
}
expect(error.message).toEqual('PriceSet with id "undefined" not found')
})
it("should create a priceSet successfully", async () => {
await service.create([
{
id: "price-set-new",
} as unknown as CreatePriceSetDTO,
])
const [priceSet] = await service.list({
id: ["price-set-new"],
})
expect(priceSet).toEqual(
expect.objectContaining({
id: "price-set-new",
})
)
})
})
})