feat(medusa): Separate money amount and variant (#4906)

* initial changes

* working test

* final changes to product tests

* update integration tests

* update price list integration tests

* update integration tests

* update unit tests

* update plugin integration tests

* remove catch from integration test

* undo change

* add andWhere

* update upsertCurrencyMoneyAmount method

* undo line item changes

* undo changes

* update deprecated method

* Update packages/medusa/src/migrations/1692953518123-drop_money_amount_constraints_for_pricing_module.ts

Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>

* rename joinTable

* update with joinTable entity

* update load methods

* remove await create

* re-add context test

* update price list behavior for prices

* update price list snapshots

* re-add admin seeder

* pr feedback

* fix unit tests

* fix plugin integration tests

* initial review changes

* redo changes to variant creation

---------

Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Philip Korsholm
2023-09-13 13:26:20 +02:00
committed by GitHub
co-authored by Carlos R. L. Rodrigues Oli Juhl
parent 3d68be2b6b
commit 5d10c46bb1
52 changed files with 2465 additions and 910 deletions
@@ -0,0 +1,36 @@
export const defaultPriceListData = [
{
name: 'pl-1',
description: 'pl-1',
prices: [ {
id: "money-amount-USD",
currency_code: "USD",
amount: 500,
min_quantity: 1,
max_quantity: 10,
price_list_id: 'pl-1'
},
{
id: "money-amount-EUR",
currency_code: "EUR",
amount: 400,
min_quantity: 1,
max_quantity: 5,
price_list_id: 'pl-1'
}]
},
{
id: 'pl-2',
name: 'pl-2',
description: 'pl-2',
prices: [{
id: "money-amount-CAD",
currency_code: "CAD",
amount: 600,
min_quantity: 1,
max_quantity: 8,
price_list_id: 'pl-2'
}]
}
]
@@ -0,0 +1,25 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { MoneyAmount, PriceList } from "@models"
import { defaultPriceListData } from "./data"
export async function createPriceLists(
manager: SqlEntityManager,
priceListsData: any[] = defaultPriceListData,
): Promise<MoneyAmount[]> {
const priceLists: PriceList[] = []
const moneyAmounts: MoneyAmount[] = []
for (let priceListdata of priceListsData) {
const { prices, ...rest } = priceListdata
const priceList = manager.create(MoneyAmount, rest)
priceLists.push(priceList)
const createdPrices = manager.create(MoneyAmount, prices)
moneyAmounts.push(createdPrices)
}
await manager.persistAndFlush(priceLists)
await manager.persistAndFlush(moneyAmounts)
return priceLists
}
@@ -0,0 +1,335 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency, MoneyAmount } from "@models"
import { MoneyAmountRepository } from "@repositories"
import { MoneyAmountService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { MikroOrmWrapper } from "../../../utils"
jest.setTimeout(30000)
describe("MoneyAmount Service", () => {
let service: MoneyAmountService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
let data!: MoneyAmount[]
let currencyData!: Currency[]
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const moneyAmountRepository = new MoneyAmountRepository({
manager: repositoryManager,
})
service = new MoneyAmountService({
moneyAmountRepository,
})
testManager = await MikroOrmWrapper.forkManager()
currencyData = await createCurrencies(testManager)
data = await createMoneyAmounts(testManager)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("list", () => {
it("list moneyAmounts", async () => {
const moneyAmountsResult = await service.list()
expect(moneyAmountsResult).toEqual([
expect.objectContaining({
id: "money-amount-USD",
amount: "500",
}),
expect.objectContaining({
id: "money-amount-EUR",
amount: "400",
}),
expect.objectContaining({
id: "money-amount-CAD",
amount: "600",
}),
])
})
it("list moneyAmounts by id", async () => {
const moneyAmountsResult = await service.list({
id: ["money-amount-USD"],
})
expect(moneyAmountsResult).toEqual([
expect.objectContaining({
id: "money-amount-USD",
}),
])
})
it("list moneyAmounts with relations and selects", async () => {
const moneyAmountsResult = await service.list(
{
id: ["money-amount-USD"],
},
{
select: ["id", "min_quantity", "currency.code"],
relations: ["currency"],
}
)
const serialized = JSON.parse(JSON.stringify(moneyAmountsResult))
expect(serialized).toEqual([
{
id: "money-amount-USD",
min_quantity: "1",
currency_code: "USD",
currency: {
code: "USD",
},
},
])
})
})
describe("listAndCount", () => {
it("should return moneyAmounts and count", async () => {
const [moneyAmountsResult, count] = await service.listAndCount()
expect(count).toEqual(3)
expect(moneyAmountsResult).toEqual([
expect.objectContaining({
id: "money-amount-USD",
}),
expect.objectContaining({
id: "money-amount-EUR",
}),
expect.objectContaining({
id: "money-amount-CAD",
}),
])
})
it("should return moneyAmounts and count when filtered", async () => {
const [moneyAmountsResult, count] = await service.listAndCount({
id: ["money-amount-USD"],
})
expect(count).toEqual(1)
expect(moneyAmountsResult).toEqual([
expect.objectContaining({
id: "money-amount-USD",
}),
])
})
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 serialized = JSON.parse(JSON.stringify(moneyAmountsResult))
expect(count).toEqual(1)
expect(serialized).toEqual([
{
id: "money-amount-USD",
min_quantity: "1",
currency_code: "USD",
currency: {
code: "USD",
},
},
])
})
it("should return moneyAmounts and count when using skip and take", async () => {
const [moneyAmountsResult, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(3)
expect(moneyAmountsResult).toEqual([
expect.objectContaining({
id: "money-amount-EUR",
}),
])
})
it("should return requested fields", async () => {
const [moneyAmountsResult, count] = await service.listAndCount(
{},
{
take: 1,
select: ["id"],
}
)
const serialized = JSON.parse(JSON.stringify(moneyAmountsResult))
expect(count).toEqual(3)
expect(serialized).toEqual([
{
id: "money-amount-USD",
},
])
})
})
describe("retrieve", () => {
const id = "money-amount-USD"
const amount = "500"
it("should return moneyAmount for the given id", async () => {
const moneyAmount = await service.retrieve(id)
expect(moneyAmount).toEqual(
expect.objectContaining({
id,
})
)
})
it("should throw an error when moneyAmount with id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"MoneyAmount 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('"moneyAmountId" must be defined')
})
it("should return moneyAmount based on config select param", async () => {
const moneyAmount = await service.retrieve(id, {
select: ["id", "amount"],
})
const serialized = JSON.parse(JSON.stringify(moneyAmount))
expect(serialized).toEqual({
id,
amount,
})
})
})
describe("delete", () => {
const id = "money-amount-USD"
it("should delete the moneyAmounts given an id successfully", async () => {
await service.delete([id])
const moneyAmounts = await service.list({
id: [id],
})
expect(moneyAmounts).toHaveLength(0)
})
})
describe("update", () => {
const id = "money-amount-USD"
it("should update the amount of the moneyAmount successfully", async () => {
await service.update([
{
id,
amount: 700,
},
])
const moneyAmount = await service.retrieve(id)
expect(moneyAmount.amount).toEqual("700")
})
it("should update the currency of the moneyAmount successfully", async () => {
await service.update([
{
id,
currency_code: "EUR",
},
])
const moneyAmount = await service.retrieve(id)
expect(moneyAmount.currency_code).toEqual("EUR")
expect(moneyAmount.currency?.code).toEqual("EUR")
})
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
amount: 666,
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'MoneyAmount with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a moneyAmount successfully", async () => {
await service.create([
{
id: "money-amount-TESM",
currency_code: "USD",
amount: 333,
min_quantity: 1,
max_quantity: 4,
},
])
const [moneyAmount] = await service.list({
id: ["money-amount-TESM"],
})
expect(moneyAmount).toEqual(
expect.objectContaining({
id: "money-amount-TESM",
currency_code: "USD",
amount: "333",
min_quantity: "1",
max_quantity: "4",
})
)
})
})
})