From fcb6b4f510dba2757570625acb5da9476b7544fd Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Thu, 31 Aug 2023 15:03:10 +0200 Subject: [PATCH] feat(pricing, utils, types): adds money amount to pricing module (#4909) What: - Adds money amount service / repo / model - Adds money amount to entry service - Adds tests for services - Refreshes schema - Update joiner config to include money amounts RESOLVES CORE-1478 RESOLVES CORE-1479 Co-authored-by: Shahed Nasser <27354907+shahednasser@users.noreply.github.com> Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> --- .changeset/odd-coats-learn.md | 7 + .../link-modules/src/definitions/index.ts | 1 + .../product-variant-money-amount.ts | 60 ++++ packages/link-modules/src/initialize/index.ts | 6 +- packages/link-modules/src/links.ts | 6 + .../__fixtures__/money-amount/data.ts | 23 ++ .../__fixtures__/money-amount/index.ts | 20 ++ .../services/money-amount/index.spec.ts | 335 +++++++++++++++++ .../services/pricing-module/currency.spec.ts | 5 +- .../pricing-module/money-amount.spec.ts | 337 ++++++++++++++++++ packages/pricing/src/joiner-config.ts | 26 +- packages/pricing/src/loaders/container.ts | 10 +- .../.snapshot-medusa-pricing-1.json | 150 ++++++++ .../migrations/.snapshot-medusa-pricing.json | 63 ---- .../src/migrations/Migration20230828182018.ts | 9 - .../src/migrations/Migration20230830085850.ts | 14 + packages/pricing/src/models/index.ts | 1 + packages/pricing/src/models/money-amount.ts | 42 +++ packages/pricing/src/repositories/index.ts | 1 + .../pricing/src/repositories/money-amount.ts | 127 +++++++ packages/pricing/src/scripts/seed.ts | 35 +- packages/pricing/src/services/index.ts | 1 + packages/pricing/src/services/money-amount.ts | 111 ++++++ .../pricing/src/services/pricing-module.ts | 130 ++++++- packages/types/src/pricing/common/index.ts | 1 + .../types/src/pricing/common/money-amount.ts | 33 ++ packages/types/src/pricing/service.ts | 39 +- 27 files changed, 1481 insertions(+), 112 deletions(-) create mode 100644 .changeset/odd-coats-learn.md create mode 100644 packages/link-modules/src/definitions/product-variant-money-amount.ts create mode 100644 packages/pricing/integration-tests/__fixtures__/money-amount/data.ts create mode 100644 packages/pricing/integration-tests/__fixtures__/money-amount/index.ts create mode 100644 packages/pricing/integration-tests/__tests__/services/money-amount/index.spec.ts create mode 100644 packages/pricing/integration-tests/__tests__/services/pricing-module/money-amount.spec.ts create mode 100644 packages/pricing/src/migrations/.snapshot-medusa-pricing-1.json delete mode 100644 packages/pricing/src/migrations/.snapshot-medusa-pricing.json delete mode 100644 packages/pricing/src/migrations/Migration20230828182018.ts create mode 100644 packages/pricing/src/migrations/Migration20230830085850.ts create mode 100644 packages/pricing/src/models/money-amount.ts create mode 100644 packages/pricing/src/repositories/money-amount.ts create mode 100644 packages/pricing/src/services/money-amount.ts create mode 100644 packages/types/src/pricing/common/money-amount.ts diff --git a/.changeset/odd-coats-learn.md b/.changeset/odd-coats-learn.md new file mode 100644 index 0000000000..ea40c3513a --- /dev/null +++ b/.changeset/odd-coats-learn.md @@ -0,0 +1,7 @@ +--- +"@medusajs/pricing": patch +"@medusajs/types": patch +"@medusajs/utils": patch +--- + +feat(pricing, utils, types): adds money amount to pricing module diff --git a/packages/link-modules/src/definitions/index.ts b/packages/link-modules/src/definitions/index.ts index af95cb10df..26ce768728 100644 --- a/packages/link-modules/src/definitions/index.ts +++ b/packages/link-modules/src/definitions/index.ts @@ -1,2 +1,3 @@ export * from "./inventory-level-stock-location" export * from "./product-variant-inventory-item" +export * from "./product-variant-money-amount" diff --git a/packages/link-modules/src/definitions/product-variant-money-amount.ts b/packages/link-modules/src/definitions/product-variant-money-amount.ts new file mode 100644 index 0000000000..6d977d7f98 --- /dev/null +++ b/packages/link-modules/src/definitions/product-variant-money-amount.ts @@ -0,0 +1,60 @@ +import { Modules } from "@medusajs/modules-sdk" +import { ModuleJoinerConfig } from "@medusajs/types" +import { LINKS } from "../links" + +export const ProductVariantMoneyAmount: ModuleJoinerConfig = { + serviceName: LINKS.ProductVariantMoneyAmount, + isLink: true, + databaseConfig: { + tableName: "product_variant_money_amount", + idPrefix: "pvma", + }, + alias: [ + { + name: "product_variant_money_amount", + }, + { + name: "product_variant_money_amounts", + }, + ], + primaryKeys: ["id", "variant_id", "money_amount_id"], + relationships: [ + { + serviceName: Modules.PRODUCT, + primaryKey: "id", + foreignKey: "variant_id", + alias: "variant", + args: { + methodSuffix: "Variants", + }, + }, + { + serviceName: Modules.PRICING, + primaryKey: "id", + foreignKey: "money_amount_id", + alias: "money_amount", + deleteCascade: true, + }, + ], + extends: [ + { + serviceName: Modules.PRODUCT, + relationship: { + serviceName: LINKS.ProductVariantMoneyAmount, + primaryKey: "variant_id", + foreignKey: "id", + alias: "prices", + isList: true, + }, + }, + { + serviceName: Modules.PRICING, + relationship: { + serviceName: LINKS.ProductVariantMoneyAmount, + primaryKey: "money_amount_id", + foreignKey: "id", + alias: "variant_link", + }, + }, + ], +} diff --git a/packages/link-modules/src/initialize/index.ts b/packages/link-modules/src/initialize/index.ts index d4e3be2c0b..11e1f74de3 100644 --- a/packages/link-modules/src/initialize/index.ts +++ b/packages/link-modules/src/initialize/index.ts @@ -93,8 +93,7 @@ export const initialize = async ( !modulesLoadedKeys.includes(primary.serviceName) || !modulesLoadedKeys.includes(foreign.serviceName) ) { - // TODO: This should be uncommented when all modules are done - // continue + continue } const moduleDefinition = getLinkModuleDefinition( @@ -180,8 +179,7 @@ export async function runMigrations( !modulesLoadedKeys.includes(primary.serviceName) || !modulesLoadedKeys.includes(foreign.serviceName) ) { - // TODO: This should be uncommented when all modules are done - // continue + continue } const migrate = getMigration(definition, serviceKey, primary, foreign) diff --git a/packages/link-modules/src/links.ts b/packages/link-modules/src/links.ts index d59af9c986..c1745224da 100644 --- a/packages/link-modules/src/links.ts +++ b/packages/link-modules/src/links.ts @@ -8,4 +8,10 @@ export const LINKS = { Modules.INVENTORY, "inventory_item_id" ), + ProductVariantMoneyAmount: composeLinkName( + Modules.PRODUCT, + "variant_id", + Modules.PRICING, + "money_amount_id" + ), } diff --git a/packages/pricing/integration-tests/__fixtures__/money-amount/data.ts b/packages/pricing/integration-tests/__fixtures__/money-amount/data.ts new file mode 100644 index 0000000000..9b770b111a --- /dev/null +++ b/packages/pricing/integration-tests/__fixtures__/money-amount/data.ts @@ -0,0 +1,23 @@ +export const defaultMoneyAmountsData = [ + { + id: "money-amount-USD", + currency_code: "USD", + amount: 500, + min_quantity: 1, + max_quantity: 10, + }, + { + id: "money-amount-EUR", + currency_code: "EUR", + amount: 400, + min_quantity: 1, + max_quantity: 5, + }, + { + id: "money-amount-CAD", + currency_code: "CAD", + amount: 600, + min_quantity: 1, + max_quantity: 8, + }, +] diff --git a/packages/pricing/integration-tests/__fixtures__/money-amount/index.ts b/packages/pricing/integration-tests/__fixtures__/money-amount/index.ts new file mode 100644 index 0000000000..dbf895c7cd --- /dev/null +++ b/packages/pricing/integration-tests/__fixtures__/money-amount/index.ts @@ -0,0 +1,20 @@ +import { SqlEntityManager } from "@mikro-orm/postgresql" +import { MoneyAmount } from "@models" +import { defaultMoneyAmountsData } from "./data" + +export async function createMoneyAmounts( + manager: SqlEntityManager, + moneyAmountsData: any[] = defaultMoneyAmountsData +): Promise { + const moneyAmounts: MoneyAmount[] = [] + + for (let moneyAmountData of moneyAmountsData) { + const moneyAmount = manager.create(MoneyAmount, moneyAmountData) + + moneyAmounts.push(moneyAmount) + } + + await manager.persistAndFlush(moneyAmounts) + + return moneyAmounts +} diff --git a/packages/pricing/integration-tests/__tests__/services/money-amount/index.spec.ts b/packages/pricing/integration-tests/__tests__/services/money-amount/index.spec.ts new file mode 100644 index 0000000000..3e817b97b8 --- /dev/null +++ b/packages/pricing/integration-tests/__tests__/services/money-amount/index.spec.ts @@ -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", + }) + ) + }) + }) +}) diff --git a/packages/pricing/integration-tests/__tests__/services/pricing-module/currency.spec.ts b/packages/pricing/integration-tests/__tests__/services/pricing-module/currency.spec.ts index 399c444600..bf808c0f1a 100644 --- a/packages/pricing/integration-tests/__tests__/services/pricing-module/currency.spec.ts +++ b/packages/pricing/integration-tests/__tests__/services/pricing-module/currency.spec.ts @@ -1,11 +1,8 @@ -import { initialize } from "../../../../src" - import { IPricingModuleService } from "@medusajs/types" - import { SqlEntityManager } from "@mikro-orm/postgresql" - import { Currency } from "@models" +import { initialize } from "../../../../src" import { createCurrencies } from "../../../__fixtures__/currency" import { DB_URL, MikroOrmWrapper } from "../../../utils" diff --git a/packages/pricing/integration-tests/__tests__/services/pricing-module/money-amount.spec.ts b/packages/pricing/integration-tests/__tests__/services/pricing-module/money-amount.spec.ts new file mode 100644 index 0000000000..03d85972f0 --- /dev/null +++ b/packages/pricing/integration-tests/__tests__/services/pricing-module/money-amount.spec.ts @@ -0,0 +1,337 @@ +import { IPricingModuleService } from "@medusajs/types" +import { SqlEntityManager } from "@mikro-orm/postgresql" +import { Currency, MoneyAmount } from "@models" + +import { initialize } from "../../../../src" +import { createCurrencies } from "../../../__fixtures__/currency" +import { createMoneyAmounts } from "../../../__fixtures__/money-amount" +import { DB_URL, MikroOrmWrapper } from "../../../utils" + +jest.setTimeout(30000) + +describe("MoneyAmount Service", () => { + let service: IPricingModuleService + let testManager: SqlEntityManager + let repositoryManager: SqlEntityManager + let data!: MoneyAmount[] + let currencyData!: Currency[] + + 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() + + 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, { + relations: ["currency"], + }) + + 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", + }) + ) + }) + }) +}) diff --git a/packages/pricing/src/joiner-config.ts b/packages/pricing/src/joiner-config.ts index 76bb77d7c7..80e0c8dc83 100644 --- a/packages/pricing/src/joiner-config.ts +++ b/packages/pricing/src/joiner-config.ts @@ -1,27 +1,31 @@ import { Modules } from "@medusajs/modules-sdk" -import { JoinerServiceConfig } from "@medusajs/types" +import { ModuleJoinerConfig } from "@medusajs/types" import { MapToConfig } from "@medusajs/utils" -import { Currency } from "@models" +import { Currency, MoneyAmount } from "@models" export enum LinkableKeys { MONEY_AMOUNT_ID = "money_amount_id", - CURRENCY_CODE = "code", + CURRENCY_CODE = "currency_code", } export const entityNameToLinkableKeysMap: MapToConfig = { [Currency.name]: [{ mapTo: LinkableKeys.CURRENCY_CODE, valueFrom: "code" }], + [MoneyAmount.name]: [ + { mapTo: LinkableKeys.MONEY_AMOUNT_ID, valueFrom: "id" }, + ], } -export const joinerConfig: JoinerServiceConfig = { +export const joinerConfig: ModuleJoinerConfig = { serviceName: Modules.PRICING, - primaryKeys: ["code"], + primaryKeys: ["id", "currency_code"], + linkableKeys: Object.values(LinkableKeys), alias: [ - // { - // name: "money_amount", - // }, - // { - // name: "money_amounts", - // }, + { + name: "money_amount", + }, + { + name: "money_amounts", + }, { name: "currency", args: { diff --git a/packages/pricing/src/loaders/container.ts b/packages/pricing/src/loaders/container.ts index 5432813d7f..d4afa75721 100644 --- a/packages/pricing/src/loaders/container.ts +++ b/packages/pricing/src/loaders/container.ts @@ -1,7 +1,11 @@ import { ModulesSdkTypes } from "@medusajs/types" import * as defaultRepositories from "@repositories" -import { BaseRepository, CurrencyRepository } from "@repositories" -import { CurrencyService } from "@services" +import { + BaseRepository, + CurrencyRepository, + MoneyAmountRepository, +} from "@repositories" +import { CurrencyService, MoneyAmountService } from "@services" import { LoaderOptions } from "@medusajs/modules-sdk" import { loadCustomRepositories } from "@medusajs/utils" @@ -20,6 +24,7 @@ export default async ({ container.register({ currencyService: asClass(CurrencyService).singleton(), + moneyAmountService: asClass(MoneyAmountService).singleton(), }) if (customRepositories) { @@ -37,5 +42,6 @@ function loadDefaultRepositories({ container }) { container.register({ baseRepository: asClass(BaseRepository).singleton(), currencyRepository: asClass(CurrencyRepository).singleton(), + moneyAmountRepository: asClass(MoneyAmountRepository).singleton(), }) } diff --git a/packages/pricing/src/migrations/.snapshot-medusa-pricing-1.json b/packages/pricing/src/migrations/.snapshot-medusa-pricing-1.json new file mode 100644 index 0000000000..b1ed4609e9 --- /dev/null +++ b/packages/pricing/src/migrations/.snapshot-medusa-pricing-1.json @@ -0,0 +1,150 @@ +{ + "namespaces": [ + "public" + ], + "name": "public", + "tables": [ + { + "columns": { + "code": { + "name": "code", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "text" + }, + "symbol": { + "name": "symbol", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "text" + }, + "symbol_native": { + "name": "symbol_native", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "text" + }, + "name": { + "name": "name", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "text" + } + }, + "name": "currency", + "schema": "public", + "indexes": [ + { + "keyName": "currency_pkey", + "columnNames": [ + "code" + ], + "composite": false, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": {} + }, + { + "columns": { + "id": { + "name": "id", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "text" + }, + "currency_code": { + "name": "currency_code", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "text" + }, + "amount": { + "name": "amount", + "type": "numeric", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "decimal" + }, + "min_quantity": { + "name": "min_quantity", + "type": "numeric", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "decimal" + }, + "max_quantity": { + "name": "max_quantity", + "type": "numeric", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "decimal" + } + }, + "name": "money_amount", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "currency_code" + ], + "composite": false, + "keyName": "IDX_money_amount_currency_code", + "primary": false, + "unique": false + }, + { + "keyName": "money_amount_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "money_amount_currency_code_foreign": { + "constraintName": "money_amount_currency_code_foreign", + "columnNames": [ + "currency_code" + ], + "localTableName": "public.money_amount", + "referencedColumnNames": [ + "code" + ], + "referencedTableName": "public.currency", + "deleteRule": "set null", + "updateRule": "cascade" + } + } + } + ] +} diff --git a/packages/pricing/src/migrations/.snapshot-medusa-pricing.json b/packages/pricing/src/migrations/.snapshot-medusa-pricing.json deleted file mode 100644 index c34620bb72..0000000000 --- a/packages/pricing/src/migrations/.snapshot-medusa-pricing.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "namespaces": [ - "public" - ], - "name": "public", - "tables": [ - { - "columns": { - "code": { - "name": "code", - "type": "text", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "text" - }, - "symbol": { - "name": "symbol", - "type": "text", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "text" - }, - "symbol_native": { - "name": "symbol_native", - "type": "text", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "text" - }, - "name": { - "name": "name", - "type": "text", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "text" - } - }, - "name": "currency", - "schema": "public", - "indexes": [ - { - "keyName": "currency_pkey", - "columnNames": [ - "code" - ], - "composite": false, - "primary": true, - "unique": true - } - ], - "checks": [], - "foreignKeys": {} - } - ] -} diff --git a/packages/pricing/src/migrations/Migration20230828182018.ts b/packages/pricing/src/migrations/Migration20230828182018.ts deleted file mode 100644 index dc119b8223..0000000000 --- a/packages/pricing/src/migrations/Migration20230828182018.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Migration } from '@mikro-orm/migrations'; - -export class Migration20230828182018 extends Migration { - - async up(): Promise { - this.addSql('create table "currency" ("code" text not null, "symbol" text not null, "symbol_native" text not null, "name" text not null, constraint "currency_pkey" primary key ("code"));'); - } - -} diff --git a/packages/pricing/src/migrations/Migration20230830085850.ts b/packages/pricing/src/migrations/Migration20230830085850.ts new file mode 100644 index 0000000000..ca68e2698e --- /dev/null +++ b/packages/pricing/src/migrations/Migration20230830085850.ts @@ -0,0 +1,14 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20230830085850 extends Migration { + + async up(): Promise { + this.addSql('create table "currency" ("code" text not null, "symbol" text not null, "symbol_native" text not null, "name" text not null, constraint "currency_pkey" primary key ("code"));'); + + this.addSql('create table "money_amount" ("id" text not null, "currency_code" text null, "amount" numeric null, "min_quantity" numeric null, "max_quantity" numeric null, constraint "money_amount_pkey" primary key ("id"));'); + this.addSql('create index "IDX_money_amount_currency_code" on "money_amount" ("currency_code");'); + + this.addSql('alter table "money_amount" add constraint "money_amount_currency_code_foreign" foreign key ("currency_code") references "currency" ("code") on update cascade on delete set null;'); + } + +} diff --git a/packages/pricing/src/models/index.ts b/packages/pricing/src/models/index.ts index 6f1a80b652..fa2b5baf19 100644 --- a/packages/pricing/src/models/index.ts +++ b/packages/pricing/src/models/index.ts @@ -1 +1,2 @@ export { default as Currency } from "./currency" +export { default as MoneyAmount } from "./money-amount" diff --git a/packages/pricing/src/models/money-amount.ts b/packages/pricing/src/models/money-amount.ts new file mode 100644 index 0000000000..c9c53f6dc8 --- /dev/null +++ b/packages/pricing/src/models/money-amount.ts @@ -0,0 +1,42 @@ +import { generateEntityId } from "@medusajs/utils" +import { + BeforeCreate, + Entity, + ManyToOne, + PrimaryKey, + Property, +} from "@mikro-orm/core" + +import Currency from "./currency" + +@Entity() +class MoneyAmount { + @PrimaryKey({ columnType: "text" }) + id!: string + + @Property({ columnType: "text", nullable: true }) + currency_code?: string + + @ManyToOne(() => Currency, { + nullable: true, + index: "IDX_money_amount_currency_code", + fieldName: "currency_code", + }) + currency?: Currency + + @Property({ columnType: "numeric", nullable: true }) + amount?: number + + @Property({ columnType: "numeric", nullable: true }) + min_quantity?: number | null + + @Property({ columnType: "numeric", nullable: true }) + max_quantity?: number | null + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ma") + } +} + +export default MoneyAmount diff --git a/packages/pricing/src/repositories/index.ts b/packages/pricing/src/repositories/index.ts index dfaa814a72..adee24e032 100644 --- a/packages/pricing/src/repositories/index.ts +++ b/packages/pricing/src/repositories/index.ts @@ -1,2 +1,3 @@ export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils" export { CurrencyRepository } from "./currency" +export { MoneyAmountRepository } from "./money-amount" diff --git a/packages/pricing/src/repositories/money-amount.ts b/packages/pricing/src/repositories/money-amount.ts new file mode 100644 index 0000000000..3328b9c953 --- /dev/null +++ b/packages/pricing/src/repositories/money-amount.ts @@ -0,0 +1,127 @@ +import { + Context, + CreateMoneyAmountDTO, + DAL, + UpdateMoneyAmountDTO, +} from "@medusajs/types" +import { DALUtils, MedusaError } from "@medusajs/utils" +import { + LoadStrategy, + FilterQuery as MikroFilterQuery, + FindOptions as MikroOptions, +} from "@mikro-orm/core" +import { SqlEntityManager } from "@mikro-orm/postgresql" +import { MoneyAmount } from "@models" + +export class MoneyAmountRepository extends DALUtils.MikroOrmBaseRepository { + protected readonly manager_: SqlEntityManager + + constructor({ manager }: { manager: SqlEntityManager }) { + // @ts-ignore + // eslint-disable-next-line prefer-rest-params + super(...arguments) + this.manager_ = manager + } + + async find( + findOptions: DAL.FindOptions = { where: {} }, + context: Context = {} + ): Promise { + const manager = this.getActiveManager(context) + + const findOptions_ = { ...findOptions } + findOptions_.options ??= {} + + Object.assign(findOptions_.options, { + strategy: LoadStrategy.SELECT_IN, + }) + + return await manager.find( + MoneyAmount, + findOptions_.where as MikroFilterQuery, + findOptions_.options as MikroOptions + ) + } + + async findAndCount( + findOptions: DAL.FindOptions = { where: {} }, + context: Context = {} + ): Promise<[MoneyAmount[], number]> { + const manager = this.getActiveManager(context) + + const findOptions_ = { ...findOptions } + findOptions_.options ??= {} + + Object.assign(findOptions_.options, { + strategy: LoadStrategy.SELECT_IN, + }) + + return await manager.findAndCount( + MoneyAmount, + findOptions_.where as MikroFilterQuery, + findOptions_.options as MikroOptions + ) + } + + async delete(ids: string[], context: Context = {}): Promise { + const manager = this.getActiveManager(context) + await manager.nativeDelete(MoneyAmount, { id: { $in: ids } }, {}) + } + + async create( + data: CreateMoneyAmountDTO[], + context: Context = {} + ): Promise { + const manager = this.getActiveManager(context) + + const moneyAmounts = data.map((moneyAmountData) => { + return manager.create(MoneyAmount, moneyAmountData) + }) + + manager.persist(moneyAmounts) + + return moneyAmounts + } + + async update( + data: UpdateMoneyAmountDTO[], + context: Context = {} + ): Promise { + const manager = this.getActiveManager(context) + const moneyAmountIds = data.map((moneyAmountData) => moneyAmountData.id) + const existingMoneyAmounts = await this.find( + { + where: { + id: { + $in: moneyAmountIds, + }, + }, + }, + context + ) + + const existingMoneyAmountMap = new Map( + existingMoneyAmounts.map<[string, MoneyAmount]>((moneyAmount) => [ + moneyAmount.id, + moneyAmount, + ]) + ) + + const moneyAmounts = data.map((moneyAmountData) => { + const existingMoneyAmount = existingMoneyAmountMap.get(moneyAmountData.id) + + if (!existingMoneyAmount) { + throw new MedusaError( + MedusaError.Types.NOT_FOUND, + `MoneyAmount with id "${moneyAmountData.id}" not found` + ) + } + + return manager.assign(existingMoneyAmount, moneyAmountData) + }) + + manager.persist(moneyAmounts) + + return moneyAmounts + } +} diff --git a/packages/pricing/src/scripts/seed.ts b/packages/pricing/src/scripts/seed.ts index 9c003b24d8..e0a5762954 100644 --- a/packages/pricing/src/scripts/seed.ts +++ b/packages/pricing/src/scripts/seed.ts @@ -22,14 +22,14 @@ export async function run({ logger.info(`Loading seed data from ${path}...`) - const { currenciesData } = await import(resolve(process.cwd(), path)).catch( - (e) => { - logger?.error( - `Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following currenciesData.${EOL}${e}` - ) - throw e - } - ) + const { currenciesData, moneyAmountsData } = await import( + resolve(process.cwd(), path) + ).catch((e) => { + logger?.error( + `Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following: currenciesData, moneyAmountsData.${EOL}${e}` + ) + throw e + }) const dbData = ModulesSdkUtils.loadDatabaseConfig("pricing", options)! const entities = Object.values(PricingModels) as unknown as EntitySchema[] @@ -40,12 +40,14 @@ export async function run({ entities, pathToMigrations ) + const manager = orm.em.fork() try { - logger.info("Inserting currencies") + logger.info("Inserting currencies & money_amounts") await createCurrencies(manager, currenciesData) + await createMoneyAmounts(manager, moneyAmountsData) } catch (e) { logger.error( `Failed to insert the seed data in the PostgreSQL database ${dbData.clientUrl}.${EOL}${e}` @@ -59,7 +61,7 @@ async function createCurrencies( manager: SqlEntityManager, data: RequiredEntityData[] ) { - const currencies: any[] = data.map((currencyData) => { + const currencies = data.map((currencyData) => { return manager.create(PricingModels.Currency, currencyData) }) @@ -67,3 +69,16 @@ async function createCurrencies( return currencies } + +async function createMoneyAmounts( + manager: SqlEntityManager, + data: RequiredEntityData[] +) { + const moneyAmounts = data.map((moneyAmountData) => { + return manager.create(PricingModels.MoneyAmount, moneyAmountData) + }) + + await manager.persistAndFlush(moneyAmounts) + + return moneyAmounts +} diff --git a/packages/pricing/src/services/index.ts b/packages/pricing/src/services/index.ts index d605c402ad..2f9e5e521c 100644 --- a/packages/pricing/src/services/index.ts +++ b/packages/pricing/src/services/index.ts @@ -1,2 +1,3 @@ export { default as CurrencyService } from "./currency" +export { default as MoneyAmountService } from "./money-amount" export { default as PricingModuleService } from "./pricing-module" diff --git a/packages/pricing/src/services/money-amount.ts b/packages/pricing/src/services/money-amount.ts new file mode 100644 index 0000000000..46a6ae7e13 --- /dev/null +++ b/packages/pricing/src/services/money-amount.ts @@ -0,0 +1,111 @@ +import { Context, DAL, FindConfig, PricingTypes } from "@medusajs/types" +import { + InjectManager, + InjectTransactionManager, + MedusaContext, + ModulesSdkUtils, + retrieveEntity, +} from "@medusajs/utils" +import { MoneyAmount } from "@models" +import { MoneyAmountRepository } from "@repositories" + +import { doNotForceTransaction, shouldForceTransaction } from "@medusajs/utils" + +type InjectedDependencies = { + moneyAmountRepository: DAL.RepositoryService +} + +export default class MoneyAmountService< + TEntity extends MoneyAmount = MoneyAmount +> { + protected readonly moneyAmountRepository_: DAL.RepositoryService + + constructor({ moneyAmountRepository }: InjectedDependencies) { + this.moneyAmountRepository_ = moneyAmountRepository + } + + @InjectManager("moneyAmountRepository_") + async retrieve( + moneyAmountId: string, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await retrieveEntity({ + id: moneyAmountId, + entityName: MoneyAmount.name, + repository: this.moneyAmountRepository_, + config, + sharedContext, + })) as TEntity + } + + @InjectManager("moneyAmountRepository_") + async list( + filters: PricingTypes.FilterableMoneyAmountProps = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await this.moneyAmountRepository_.find( + this.buildQueryForList(filters, config), + sharedContext + )) as TEntity[] + } + + @InjectManager("moneyAmountRepository_") + async listAndCount( + filters: PricingTypes.FilterableMoneyAmountProps = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise<[TEntity[], number]> { + return (await this.moneyAmountRepository_.findAndCount( + this.buildQueryForList(filters, config), + sharedContext + )) as [TEntity[], number] + } + + private buildQueryForList( + filters: PricingTypes.FilterableMoneyAmountProps = {}, + config: FindConfig = {} + ) { + const queryOptions = ModulesSdkUtils.buildQuery( + filters, + config + ) + + if (filters.id) { + queryOptions.where["id"] = { $in: filters.id } + } + + return queryOptions + } + + @InjectTransactionManager(shouldForceTransaction, "moneyAmountRepository_") + async create( + data: PricingTypes.CreateMoneyAmountDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await (this.moneyAmountRepository_ as MoneyAmountRepository).create( + data, + sharedContext + )) as TEntity[] + } + + @InjectTransactionManager(shouldForceTransaction, "moneyAmountRepository_") + async update( + data: PricingTypes.UpdateMoneyAmountDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await (this.moneyAmountRepository_ as MoneyAmountRepository).update( + data, + sharedContext + )) as TEntity[] + } + + @InjectTransactionManager(doNotForceTransaction, "moneyAmountRepository_") + async delete( + ids: string[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + await this.moneyAmountRepository_.delete(ids, sharedContext) + } +} diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index c3a151051e..041e38ae18 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -3,11 +3,11 @@ import { DAL, FindConfig, InternalModuleDeclaration, - JoinerServiceConfig, + ModuleJoinerConfig, PricingTypes, } from "@medusajs/types" -import { Currency } from "@models" -import { CurrencyService } from "@services" +import { Currency, MoneyAmount } from "@models" +import { CurrencyService, MoneyAmountService } from "@services" import { InjectManager, @@ -21,26 +21,142 @@ import { joinerConfig } from "../joiner-config" type InjectedDependencies = { baseRepository: DAL.RepositoryService currencyService: CurrencyService + moneyAmountService: MoneyAmountService } -export default class PricingModuleService - implements PricingTypes.IPricingModuleService +export default class PricingModuleService< + TMoneyAmount extends MoneyAmount = MoneyAmount, + TCurrency extends Currency = Currency +> implements PricingTypes.IPricingModuleService { protected baseRepository_: DAL.RepositoryService protected readonly currencyService_: CurrencyService + protected readonly moneyAmountService_: MoneyAmountService constructor( - { baseRepository, currencyService }: InjectedDependencies, + { + baseRepository, + moneyAmountService, + currencyService, + }: InjectedDependencies, protected readonly moduleDeclaration: InternalModuleDeclaration ) { this.baseRepository_ = baseRepository this.currencyService_ = currencyService + this.moneyAmountService_ = moneyAmountService } - __joinerConfig(): JoinerServiceConfig { + __joinerConfig(): ModuleJoinerConfig { return joinerConfig } + @InjectManager("baseRepository_") + async retrieve( + id: string, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const moneyAmount = await this.moneyAmountService_.retrieve( + id, + config, + sharedContext + ) + + return this.baseRepository_.serialize( + moneyAmount, + { + populate: true, + } + ) + } + + @InjectManager("baseRepository_") + async list( + filters: PricingTypes.FilterableMoneyAmountProps = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const moneyAmounts = await this.moneyAmountService_.list( + filters, + config, + sharedContext + ) + + return this.baseRepository_.serialize( + moneyAmounts, + { + populate: true, + } + ) + } + + @InjectManager("baseRepository_") + async listAndCount( + filters: PricingTypes.FilterableMoneyAmountProps = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ): Promise<[PricingTypes.MoneyAmountDTO[], number]> { + const [moneyAmounts, count] = await this.moneyAmountService_.listAndCount( + filters, + config, + sharedContext + ) + + return [ + await this.baseRepository_.serialize( + moneyAmounts, + { + populate: true, + } + ), + count, + ] + } + + @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + async create( + data: PricingTypes.CreateMoneyAmountDTO[], + @MedusaContext() sharedContext: Context = {} + ) { + const moneyAmounts = await this.moneyAmountService_.create( + data, + sharedContext + ) + + return this.baseRepository_.serialize( + moneyAmounts, + { + populate: true, + } + ) + } + + @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + async update( + data: PricingTypes.UpdateMoneyAmountDTO[], + @MedusaContext() sharedContext: Context = {} + ) { + const moneyAmounts = await this.moneyAmountService_.update( + data, + sharedContext + ) + + return this.baseRepository_.serialize( + moneyAmounts, + { + populate: true, + } + ) + } + + @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + async delete( + ids: string[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + await this.moneyAmountService_.delete(ids, sharedContext) + } + @InjectManager("baseRepository_") async retrieveCurrency( code: string, diff --git a/packages/types/src/pricing/common/index.ts b/packages/types/src/pricing/common/index.ts index 68cb50031c..4baa6d178b 100644 --- a/packages/types/src/pricing/common/index.ts +++ b/packages/types/src/pricing/common/index.ts @@ -1 +1,2 @@ export * from "./currency" +export * from "./money-amount" diff --git a/packages/types/src/pricing/common/money-amount.ts b/packages/types/src/pricing/common/money-amount.ts new file mode 100644 index 0000000000..fc7d02c25a --- /dev/null +++ b/packages/types/src/pricing/common/money-amount.ts @@ -0,0 +1,33 @@ +import { BaseFilterable } from "../../dal" +import { CreateCurrencyDTO, CurrencyDTO } from "./currency" + +export interface MoneyAmountDTO { + id: string + currency_code?: string + currency?: CurrencyDTO + amount?: number + min_quantity?: number + max_quantity?: number +} + +export interface CreateMoneyAmountDTO { + id: string + currency_code: string + currency?: CreateCurrencyDTO + amount?: number + min_quantity?: number + max_quantity?: number +} + +export interface UpdateMoneyAmountDTO { + id: string + currency_code?: string + amount?: number + min_quantity?: number + max_quantity?: number +} + +export interface FilterableMoneyAmountProps + extends BaseFilterable { + id?: string[] +} diff --git a/packages/types/src/pricing/service.ts b/packages/types/src/pricing/service.ts index b126719ecf..e86195c2f8 100644 --- a/packages/types/src/pricing/service.ts +++ b/packages/types/src/pricing/service.ts @@ -1,14 +1,49 @@ import { FindConfig } from "../common" -import { JoinerServiceConfig } from "../joiner" +import { ModuleJoinerConfig } from "../modules-sdk" import { Context } from "../shared-context" import { CreateCurrencyDTO, + CreateMoneyAmountDTO, CurrencyDTO, FilterableCurrencyProps, + FilterableMoneyAmountProps, + MoneyAmountDTO, UpdateCurrencyDTO, + UpdateMoneyAmountDTO, } from "./common" + export interface IPricingModuleService { - __joinerConfig(): JoinerServiceConfig + __joinerConfig(): ModuleJoinerConfig + + retrieve( + id: string, + config?: FindConfig, + sharedContext?: Context + ): Promise + + list( + filters?: FilterableMoneyAmountProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + listAndCount( + filters?: FilterableMoneyAmountProps, + config?: FindConfig, + sharedContext?: Context + ): Promise<[MoneyAmountDTO[], number]> + + create( + data: CreateMoneyAmountDTO[], + sharedContext?: Context + ): Promise + + update( + data: UpdateMoneyAmountDTO[], + sharedContext?: Context + ): Promise + + delete(ids: string[], sharedContext?: Context): Promise retrieveCurrency( code: string,