feat: Add currency module and remove currency models from region and pricing modules (#6536)

What:
- Creates a new currency module
- Removes currency model from the pricing module
- Removes currency model from region module
This commit is contained in:
Stevche Radevski authored and GitHub committed 2024-02-29 15:09:59 +00:00
1 parent 06f706a51a
commit dc025302a1
102 files changed
+1502 -2128

No files matched your search

@@ -42,7 +42,7 @@ describe("API Keys - Admin", () => {
await createAdminUser(dbConnection, adminHeaders) await createAdminUser(dbConnection, adminHeaders)
// Used for testing cross-module authentication checks // Used for testing cross-module authentication checks
await regionService.createDefaultCountriesAndCurrencies() await regionService.createDefaultCountries()
}) })
afterEach(async () => { afterEach(async () => {
@@ -63,7 +63,7 @@ describe("Carts workflows", () => {
beforeEach(async () => { beforeEach(async () => {
await adminSeeder(dbConnection) await adminSeeder(dbConnection)
await regionModuleService.createDefaultCountriesAndCurrencies() await regionModuleService.createDefaultCountries()
// Here, so we don't have to create a region for each test // Here, so we don't have to create a region for each test
defaultRegion = await regionModuleService.create({ defaultRegion = await regionModuleService.create({
@@ -59,7 +59,7 @@ describe("Store Carts API", () => {
beforeEach(async () => { beforeEach(async () => {
await adminSeeder(dbConnection) await adminSeeder(dbConnection)
await regionModuleService.createDefaultCountriesAndCurrencies() await regionModuleService.createDefaultCountries()
// Here, so we don't have to create a region for each test // Here, so we don't have to create a region for each test
defaultRegion = await regionModuleService.create({ defaultRegion = await regionModuleService.create({
@@ -0,0 +1,67 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { ICurrencyModuleService } from "@medusajs/types"
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 { initDb, useDb } from "../../../../environment-helpers/use-db"
import { DataSource } from "typeorm"
import { createAdminUser } from "../../../helpers/create-admin-user"
jest.setTimeout(50000)
const env = { MEDUSA_FF_MEDUSA_V2: true }
const adminHeaders = {
headers: { "x-medusa-access-token": "test_token" },
}
describe("Currency - Admin", () => {
let dbConnection: DataSource
let appContainer
let shutdownServer
let service: ICurrencyModuleService
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
dbConnection = await initDb({ cwd, env } as any)
shutdownServer = await startBootstrapApp({ cwd, env })
appContainer = getContainer()
service = appContainer.resolve(ModuleRegistrationName.CURRENCY)
})
afterAll(async () => {
const db = useDb()
await db.shutdown()
await shutdownServer()
})
beforeEach(async () => {
await createAdminUser(dbConnection, adminHeaders)
})
afterEach(async () => {
const db = useDb()
await db.teardown()
})
it("should correctly retrieve and list currencies", async () => {
const api = useApi() as any
const listResp = await api.get("/admin/currencies", adminHeaders)
expect(listResp.data.currencies).toEqual(
expect.arrayContaining([
expect.objectContaining({
code: "aud",
}),
expect.objectContaining({
code: "cad",
}),
])
)
const retrieveResp = await api.get(`/admin/currencies/aud`, adminHeaders)
expect(retrieveResp.data.currency).toEqual(
listResp.data.currencies.find((c) => c.code === "aud")
)
})
})
@@ -0,0 +1,62 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { ICurrencyModuleService } from "@medusajs/types"
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 { initDb, useDb } from "../../../../environment-helpers/use-db"
import { DataSource } from "typeorm"
jest.setTimeout(50000)
const env = { MEDUSA_FF_MEDUSA_V2: true }
const storeHeaders = {
headers: {},
}
describe("Currency - Store", () => {
let dbConnection: DataSource
let appContainer
let shutdownServer
let service: ICurrencyModuleService
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
dbConnection = await initDb({ cwd, env } as any)
shutdownServer = await startBootstrapApp({ cwd, env })
appContainer = getContainer()
service = appContainer.resolve(ModuleRegistrationName.CURRENCY)
})
afterAll(async () => {
const db = useDb()
await db.shutdown()
await shutdownServer()
})
afterEach(async () => {
const db = useDb()
await db.teardown()
})
it("should correctly retrieve and list currencies", async () => {
const api = useApi() as any
const listResp = await api.get("/store/currencies", storeHeaders)
expect(listResp.data.currencies).toEqual(
expect.arrayContaining([
expect.objectContaining({
code: "aud",
}),
expect.objectContaining({
code: "cad",
}),
])
)
const retrieveResp = await api.get(`/store/currencies/aud`, storeHeaders)
expect(retrieveResp.data.currency).toEqual(
listResp.data.currencies.find((c) => c.code === "aud")
)
})
})
@@ -45,7 +45,7 @@ describe("Cart links", () => {
beforeEach(async () => { beforeEach(async () => {
// @ts-ignore // @ts-ignore
await regionModule.createDefaultCountriesAndCurrencies() await regionModule.createDefaultCountries()
}) })
afterEach(async () => { afterEach(async () => {
@@ -35,7 +35,7 @@ describe("Link: Cart Region", () => {
beforeEach(async () => { beforeEach(async () => {
// @ts-ignore // @ts-ignore
await regionModule.createDefaultCountriesAndCurrencies() await regionModule.createDefaultCountries()
}) })
afterEach(async () => { afterEach(async () => {
@@ -38,7 +38,7 @@ describe("Regions - Admin", () => {
beforeEach(async () => { beforeEach(async () => {
await createAdminUser(dbConnection, adminHeaders) await createAdminUser(dbConnection, adminHeaders)
await service.createDefaultCountriesAndCurrencies() await service.createDefaultCountries()
}) })
afterEach(async () => { afterEach(async () => {
@@ -127,25 +127,6 @@ describe("Regions - Admin", () => {
) )
}) })
it("should throw on unknown currency in create", async () => {
const api = useApi() as any
const error = await api
.post(
`/admin/regions`,
{
currency_code: "foo",
name: "Test Region",
},
adminHeaders
)
.catch((e) => e)
expect(error.response.status).toEqual(400)
expect(error.response.data.message).toEqual(
'Currencies with codes: "foo" were not found'
)
})
it("should throw on unknown properties in create", async () => { it("should throw on unknown properties in create", async () => {
const api = useApi() as any const api = useApi() as any
const error = await api const error = await api
@@ -128,5 +128,10 @@ module.exports = {
resources: "shared", resources: "shared",
resolve: "@medusajs/tax", resolve: "@medusajs/tax",
}, },
[Modules.CURRENCY]: {
scope: "internal",
resources: "shared",
resolve: "@medusajs/currency",
},
}, },
} }
+1
View File
@@ -12,6 +12,7 @@
"@medusajs/api-key": "workspace:^", "@medusajs/api-key": "workspace:^",
"@medusajs/auth": "workspace:*", "@medusajs/auth": "workspace:*",
"@medusajs/cache-inmemory": "workspace:*", "@medusajs/cache-inmemory": "workspace:*",
"@medusajs/currency": "workspace:^",
"@medusajs/customer": "workspace:^", "@medusajs/customer": "workspace:^",
"@medusajs/event-bus-local": "workspace:*", "@medusajs/event-bus-local": "workspace:*",
"@medusajs/inventory": "workspace:^", "@medusajs/inventory": "workspace:^",
+6
View File
@@ -0,0 +1,6 @@
/dist
node_modules
.DS_store
.env*
.env
*.sql
+1
View File
@@ -0,0 +1 @@
# Currency Module
Whitespace-only changes.
@@ -0,0 +1,199 @@
import { Modules } from "@medusajs/modules-sdk"
import { ICurrencyModuleService } from "@medusajs/types"
import { moduleIntegrationTestRunner, SuiteOptions } from "medusa-test-utils"
jest.setTimeout(100000)
moduleIntegrationTestRunner({
moduleName: Modules.CURRENCY,
testSuite: ({
MikroOrmWrapper,
service,
}: SuiteOptions<ICurrencyModuleService>) => {
describe("Currency Module Service", () => {
describe("list", () => {
it("list currencies", async () => {
const currenciesResult = await service.list({}, { take: null })
expect(currenciesResult).toEqual(
expect.arrayContaining([
expect.objectContaining({
code: "cad",
name: "Canadian Dollar",
}),
expect.objectContaining({
code: "usd",
name: "US Dollar",
}),
])
)
})
it("list currencies by code", async () => {
const currenciesResult = await service.list(
{ code: ["usd"] },
{ take: null }
)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "usd",
name: "US Dollar",
}),
])
})
it("list currencies by code regardless of case-sensitivity", async () => {
const currenciesResult = await service.list(
{ code: ["Usd"] },
{ take: null }
)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "usd",
name: "US Dollar",
}),
])
})
})
describe("listAndCount", () => {
it("should return currencies and count", async () => {
const [currenciesResult, count] = await service.listAndCount(
{},
{ take: null }
)
expect(count).toEqual(120)
expect(currenciesResult).toEqual(
expect.arrayContaining([
expect.objectContaining({
code: "cad",
name: "Canadian Dollar",
}),
expect.objectContaining({
code: "usd",
name: "US Dollar",
}),
])
)
})
it("should return currencies and count when filtered", async () => {
const [currenciesResult, count] = await service.listAndCount(
{
code: ["usd"],
},
{ take: null }
)
expect(count).toEqual(1)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "usd",
name: "US Dollar",
}),
])
})
it("should return currencies and count when using skip and take", async () => {
const [currenciesResult, count] = await service.listAndCount(
{},
{ skip: 5, take: 1 }
)
expect(count).toEqual(120)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "aud",
name: "Australian Dollar",
}),
])
})
it("should return requested fields", async () => {
const [currenciesResult, count] = await service.listAndCount(
{},
{
take: 1,
select: ["code"],
}
)
const serialized = JSON.parse(JSON.stringify(currenciesResult))
expect(count).toEqual(120)
expect(serialized).toEqual([
{
code: "aed",
},
])
})
})
describe("retrieve", () => {
const code = "usd"
const name = "US Dollar"
it("should return currency for the given code", async () => {
const currency = await service.retrieve(code)
expect(currency).toEqual(
expect.objectContaining({
code,
})
)
})
it("should return currency for the given code in a case-insensitive manner", async () => {
const currency = await service.retrieve(code.toUpperCase())
expect(currency).toEqual(
expect.objectContaining({
code,
})
)
})
it("should throw an error when currency with code does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"Currency with code: does-not-exist was not found"
)
})
it("should throw an error when a code is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual("currency - code must be defined")
})
it("should return currency based on config select param", async () => {
const currency = await service.retrieve(code, {
select: ["code", "name"],
})
const serialized = JSON.parse(JSON.stringify(currency))
expect(serialized).toEqual({
code,
name,
})
})
})
})
},
})
+20
View File
@@ -0,0 +1,20 @@
module.exports = {
moduleNameMapper: {
"^@models": "<rootDir>/src/models",
"^@services": "<rootDir>/src/services",
"^@repositories": "<rootDir>/src/repositories",
"^@types": "<rootDir>/src/types",
},
transform: {
"^.+\\.[jt]s?$": [
"ts-jest",
{
tsConfig: "tsconfig.spec.json",
isolatedModules: true,
},
],
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `ts`],
modulePathIgnorePatterns: ["dist/"],
}
@@ -0,0 +1,8 @@
import * as entities from "./src/models"
module.exports = {
entities: Object.values(entities),
schema: "public",
clientUrl: "postgres://postgres@localhost/medusa-currency",
type: "postgresql",
}
+61
View File
@@ -0,0 +1,61 @@
{
"name": "@medusajs/currency",
"version": "0.1.0",
"description": "Medusa Currency module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"engines": {
"node": ">=16"
},
"bin": {
"medusa-currency-seed": "dist/scripts/bin/run-seed.js"
},
"repository": {
"type": "git",
"url": "https://github.com/medusajs/medusa",
"directory": "packages/currency"
},
"publishConfig": {
"access": "public"
},
"author": "Medusa",
"license": "MIT",
"scripts": {
"watch": "tsc --build --watch",
"watch:test": "tsc --build tsconfig.spec.json --watch",
"prepublishOnly": "cross-env NODE_ENV=production tsc --build && tsc-alias -p tsconfig.json",
"build": "rimraf dist && tsc --build && tsc-alias -p tsconfig.json",
"test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts",
"test:integration": "jest --runInBand --forceExit -- integration-tests/**/__tests__/**/*.ts",
"migration:generate": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:generate",
"migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial",
"migration:create": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create",
"migration:up": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:up",
"orm:cache:clear": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm cache:clear"
},
"devDependencies": {
"@mikro-orm/cli": "5.9.7",
"cross-env": "^5.2.1",
"jest": "^29.6.3",
"medusa-test-utils": "workspace:^",
"rimraf": "^3.0.2",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tsc-alias": "^1.8.6",
"typescript": "^5.1.6"
},
"dependencies": {
"@medusajs/modules-sdk": "^1.12.4",
"@medusajs/types": "^1.11.8",
"@medusajs/utils": "^1.11.1",
"@mikro-orm/core": "5.9.7",
"@mikro-orm/migrations": "5.9.7",
"@mikro-orm/postgresql": "5.9.7",
"awilix": "^8.0.0",
"dotenv": "^16.1.4",
"knex": "2.4.2"
}
}
+14
View File
@@ -0,0 +1,14 @@
import { moduleDefinition } from "./module-definition"
import { initializeFactory, Modules } from "@medusajs/modules-sdk"
export * from "./types"
export * from "./models"
export * from "./services"
export const initialize = initializeFactory({
moduleName: Modules.CURRENCY,
moduleDefinition,
})
export const runMigrations = moduleDefinition.runMigrations
export const revertMigration = moduleDefinition.revertMigration
export default moduleDefinition
+29
View File
@@ -0,0 +1,29 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types"
import { MapToConfig } from "@medusajs/utils"
import Currency from "./models/currency"
export const LinkableKeys: Record<string, string> = {}
const entityLinkableKeysMap: MapToConfig = {}
Object.entries(LinkableKeys).forEach(([key, value]) => {
entityLinkableKeysMap[value] ??= []
entityLinkableKeysMap[value].push({
mapTo: key,
valueFrom: key.split("_").pop()!,
})
})
export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap
export const joinerConfig: ModuleJoinerConfig = {
serviceName: Modules.CURRENCY,
primaryKeys: ["code"],
linkableKeys: LinkableKeys,
alias: [
{
name: ["currency", "currencies"],
args: { entity: Currency.name },
},
],
} as ModuleJoinerConfig
@@ -0,0 +1,30 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { ModulesSdkTypes, LoaderOptions } from "@medusajs/types"
import { defaultCurrencies } from "@medusajs/utils"
import { Currency } from "@models"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
try {
const {
currencyService_,
}: { currencyService_: ModulesSdkTypes.InternalModuleService<Currency> } =
container.resolve(ModuleRegistrationName.CURRENCY)
const normalizedCurrencies = Object.values(defaultCurrencies).map((c) => ({
...c,
code: c.code.toLowerCase(),
}))
const resp = await currencyService_.upsert(normalizedCurrencies)
console.log(`Loaded ${resp.length} currencies`)
} catch (error) {
console.error(
`Failed to load currencies, skipping loader. Original error: ${error.message}`
)
}
}
@@ -0,0 +1,63 @@
{
"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": {}
}
]
}
@@ -0,0 +1,9 @@
import { Migration } from "@mikro-orm/migrations"
export class InitialSetup20240228133303 extends Migration {
async up(): Promise<void> {
this.addSql(`create table if not exists "currency"
("code" text not null, "symbol" text not null, "symbol_native" text not null, "name" text not null,
constraint "currency_pkey" primary key ("code"));`)
}
}
+1
View File
@@ -0,0 +1 @@
export { default as Currency } from "./currency"
@@ -0,0 +1,45 @@
import { ModuleExports } from "@medusajs/types"
import * as ModuleServices from "@services"
import { CurrencyModuleService } from "@services"
import { Modules } from "@medusajs/modules-sdk"
import * as Models from "@models"
import * as ModuleModels from "@models"
import { ModulesSdkUtils } from "@medusajs/utils"
import * as ModuleRepositories from "@repositories"
import initialDataLoader from "./loaders/initial-data"
const migrationScriptOptions = {
moduleName: Modules.CURRENCY,
models: Models,
pathToMigrations: __dirname + "/migrations",
}
const runMigrations = ModulesSdkUtils.buildMigrationScript(
migrationScriptOptions
)
const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
migrationScriptOptions
)
const containerLoader = ModulesSdkUtils.moduleContainerLoaderFactory({
moduleModels: ModuleModels,
moduleRepositories: ModuleRepositories,
moduleServices: ModuleServices,
})
const connectionLoader = ModulesSdkUtils.mikroOrmConnectionLoaderFactory({
moduleName: Modules.CURRENCY,
moduleModels: Object.values(Models),
migrationsPath: __dirname + "/migrations",
})
const service = CurrencyModuleService
const loaders = [containerLoader, connectionLoader, initialDataLoader] as any
export const moduleDefinition: ModuleExports = {
service,
loaders,
revertMigration,
runMigrations,
}
@@ -0,0 +1 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
@@ -0,0 +1,29 @@
#!/usr/bin/env node
import { ModulesSdkUtils } from "@medusajs/utils"
import { Modules } from "@medusajs/modules-sdk"
import * as Models from "@models"
import { EOL } from "os"
const args = process.argv
const path = args.pop() as string
export default (async () => {
const { config } = await import("dotenv")
config()
if (!path) {
throw new Error(
`filePath is required.${EOL}Example: medusa-currency-seed <filePath>`
)
}
const run = ModulesSdkUtils.buildSeedScript({
moduleName: Modules.CURRENCY,
models: Models,
pathToMigrations: __dirname + "/../../migrations",
seedHandler: async ({ manager, data }) => {
// TODO: Add seed logic
},
})
await run({ path })
})()
@@ -0,0 +1,5 @@
describe("noop", function () {
it("should run", function () {
expect(true).toBe(true)
})
})
@@ -0,0 +1,131 @@
import {
DAL,
InternalModuleDeclaration,
ModuleJoinerConfig,
ModulesSdkTypes,
ICurrencyModuleService,
CurrencyTypes,
Context,
FindConfig,
FilterableCurrencyProps,
BaseFilterable,
} from "@medusajs/types"
import { ModulesSdkUtils } from "@medusajs/utils"
import { Currency } from "@models"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
const generateMethodForModels = []
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
currencyService: ModulesSdkTypes.InternalModuleService<any>
}
export default class CurrencyModuleService<TEntity extends Currency = Currency>
extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies,
CurrencyTypes.CurrencyDTO,
{
Currency: { dto: CurrencyTypes.CurrencyDTO }
}
>(Currency, generateMethodForModels, entityNameToLinkableKeysMap)
implements ICurrencyModuleService
{
protected baseRepository_: DAL.RepositoryService
protected readonly currencyService_: ModulesSdkTypes.InternalModuleService<TEntity>
constructor(
{ baseRepository, currencyService }: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
// @ts-ignore
super(...arguments)
this.baseRepository_ = baseRepository
this.currencyService_ = currencyService
}
__joinerConfig(): ModuleJoinerConfig {
return joinerConfig
}
retrieve(
code: string,
config?: FindConfig<CurrencyTypes.CurrencyDTO>,
sharedContext?: Context
): Promise<CurrencyTypes.CurrencyDTO> {
return this.currencyService_.retrieve(
code?.toLowerCase(),
config,
sharedContext
)
}
list(
filters?: FilterableCurrencyProps,
config?: FindConfig<CurrencyTypes.CurrencyDTO>,
sharedContext?: Context
): Promise<CurrencyTypes.CurrencyDTO[]> {
return this.currencyService_.list(
CurrencyModuleService.normalizeFilters(filters),
config,
sharedContext
)
}
listAndCount(
filters?: FilterableCurrencyProps,
config?: FindConfig<CurrencyTypes.CurrencyDTO>,
sharedContext?: Context
): Promise<[CurrencyTypes.CurrencyDTO[], number]> {
return this.currencyService_.listAndCount(
CurrencyModuleService.normalizeFilters(filters),
config,
sharedContext
)
}
protected static normalizeFilters(
filters: FilterableCurrencyProps | undefined
): FilterableCurrencyProps | undefined {
return normalizeFilterable<
CurrencyTypes.CurrencyDTO,
FilterableCurrencyProps
>(filters, (fieldName, value) => {
if (fieldName === "code" && !!value) {
return value.toLowerCase()
}
return value
})
}
}
// TODO: Move normalizer support to `buildQuery` so we don't even need to override the list/retrieve methods just for normalization
const normalizeFilterable = <TModel, TFilter extends BaseFilterable<TFilter>>(
filters: TFilter | undefined,
normalizer: (fieldName: keyof TModel, value: any) => any
): TFilter | undefined => {
if (!filters) {
return filters
}
const normalizedFilters = {} as TFilter
for (const key in filters) {
if (key === "$and" || key === "$or") {
normalizedFilters[key] = (filters[key] as any).map((filter) =>
normalizeFilterable(filter, normalizer)
)
} else if (filters[key] !== undefined) {
if (Array.isArray(filters[key])) {
normalizedFilters[key] = (filters[key] as any).map((val) =>
normalizer(key as any, val)
)
} else {
normalizedFilters[key] = normalizer(key as any, filters[key])
}
}
}
return normalizedFilters
}
+1
View File
@@ -0,0 +1 @@
export { default as CurrencyModuleService } from "./currency-module-service"
+6
View File
@@ -0,0 +1,6 @@
import { IEventBusModuleService, Logger } from "@medusajs/types"
export type InitializeModuleInjectableDependencies = {
logger?: Logger
eventBusService?: IEventBusModuleService
}
+37
View File
@@ -0,0 +1,37 @@
{
"compilerOptions": {
"lib": ["es2020"],
"target": "es2020",
"outDir": "./dist",
"esModuleInterop": true,
"declaration": true,
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": false,
"noImplicitReturns": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitThis": true,
"allowJs": true,
"skipLibCheck": true,
"downlevelIteration": true, // to use ES5 specific tooling
"baseUrl": ".",
"resolveJsonModule": true,
"paths": {
"@models": ["./src/models"],
"@services": ["./src/services"],
"@repositories": ["./src/repositories"],
"@types": ["./src/types"]
}
},
"include": ["src"],
"exclude": [
"dist",
"./src/**/__tests__",
"./src/**/__mocks__",
"./src/**/__fixtures__",
"node_modules"
]
}
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": ["src", "integration-tests"],
"exclude": ["node_modules", "dist"],
"compilerOptions": {
"sourceMap": true
}
}
@@ -0,0 +1,18 @@
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
import { defaultAdminCurrencyFields } from "../query-config"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const variables = { code: req.params.code }
const queryObject = remoteQueryObjectFromString({
entryPoint: "currency",
variables,
fields: defaultAdminCurrencyFields,
})
const [currency] = await remoteQuery(queryObject)
res.status(200).json({ currency })
}
@@ -0,0 +1,36 @@
import { transformQuery } from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import { authenticate } from "../../../utils/authenticate-middleware"
import * as QueryConfig from "./query-config"
import {
AdminGetCurrenciesCurrencyParams,
AdminGetCurrenciesParams,
} from "./validators"
export const adminCurrencyRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["ALL"],
matcher: "/admin/currencies*",
middlewares: [authenticate("admin", ["bearer", "session", "api-key"])],
},
{
method: ["GET"],
matcher: "/admin/currencies",
middlewares: [
transformQuery(
AdminGetCurrenciesParams,
QueryConfig.listTransformQueryConfig
),
],
},
{
method: ["GET"],
matcher: "/admin/currencies/:code",
middlewares: [
transformQuery(
AdminGetCurrenciesCurrencyParams,
QueryConfig.retrieveTransformQueryConfig
),
],
},
]
@@ -0,0 +1,20 @@
export const defaultAdminCurrencyRelations = []
export const allowedAdminCurrencyRelations = []
export const defaultAdminCurrencyFields = [
"code",
"name",
"symbol",
"symbol_native",
]
export const retrieveTransformQueryConfig = {
defaultFields: defaultAdminCurrencyFields,
defaultRelations: defaultAdminCurrencyRelations,
allowedRelations: allowedAdminCurrencyRelations,
isList: false,
}
export const listTransformQueryConfig = {
defaultLimit: 50,
isList: true,
}
@@ -0,0 +1,27 @@
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
import { defaultAdminCurrencyFields } from "./query-config"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const queryObject = remoteQueryObjectFromString({
entryPoint: "currency",
variables: {
filters: req.filterableFields,
order: req.listConfig.order,
skip: req.listConfig.skip,
take: req.listConfig.take,
},
fields: defaultAdminCurrencyFields,
})
const { rows: currencies, metadata } = await remoteQuery(queryObject)
res.json({
currencies,
count: metadata.count,
offset: metadata.skip,
limit: metadata.take,
})
}
@@ -0,0 +1,30 @@
import { Type } from "class-transformer"
import { IsOptional, IsString, ValidateNested } from "class-validator"
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
export class AdminGetCurrenciesCurrencyParams extends FindParams {}
/**
* Parameters used to filter and configure the pagination of the retrieved currencies.
*/
export class AdminGetCurrenciesParams extends extendedFindParamsMixin({
limit: 50,
offset: 0,
}) {
/**
* Search parameter for currencies.
*/
@IsString({ each: true })
@IsOptional()
code?: string | string[]
// Additional filters from BaseFilterable
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AdminGetCurrenciesParams)
$and?: AdminGetCurrenciesParams[]
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AdminGetCurrenciesParams)
$or?: AdminGetCurrenciesParams[]
}
@@ -1,5 +1,5 @@
export const defaultAdminRegionRelations = ["countries", "currency"] export const defaultAdminRegionRelations = ["countries"]
export const allowedAdminRegionRelations = ["countries", "currency"] export const allowedAdminRegionRelations = ["countries"]
export const defaultAdminRegionFields = [ export const defaultAdminRegionFields = [
"id", "id",
"name", "name",
@@ -13,10 +13,6 @@ export const defaultAdminRegionFields = [
"countries.iso_3", "countries.iso_3",
"countries.num_code", "countries.num_code",
"countries.name", "countries.name",
"currency.code",
"currency.symbol",
"currency.symbol_native",
"currency.name",
] ]
export const retrieveTransformQueryConfig = { export const retrieveTransformQueryConfig = {
@@ -16,6 +16,8 @@ import { storeCartRoutesMiddlewares } from "./store/carts/middlewares"
import { storeCustomerRoutesMiddlewares } from "./store/customers/middlewares" import { storeCustomerRoutesMiddlewares } from "./store/customers/middlewares"
import { storeRegionRoutesMiddlewares } from "./store/regions/middlewares" import { storeRegionRoutesMiddlewares } from "./store/regions/middlewares"
import { hooksRoutesMiddlewares } from "./hooks/middlewares" import { hooksRoutesMiddlewares } from "./hooks/middlewares"
import { adminCurrencyRoutesMiddlewares } from "./admin/currencies/middlewares"
import { storeCurrencyRoutesMiddlewares } from "./store/currencies/middlewares"
export const config: MiddlewaresConfig = { export const config: MiddlewaresConfig = {
routes: [ routes: [
@@ -37,5 +39,7 @@ export const config: MiddlewaresConfig = {
...adminApiKeyRoutesMiddlewares, ...adminApiKeyRoutesMiddlewares,
...hooksRoutesMiddlewares, ...hooksRoutesMiddlewares,
...adminStoreRoutesMiddlewares, ...adminStoreRoutesMiddlewares,
...adminCurrencyRoutesMiddlewares,
...storeCurrencyRoutesMiddlewares,
], ],
} }
@@ -0,0 +1,18 @@
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
import { defaultStoreCurrencyFields } from "../query-config"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const variables = { code: req.params.code }
const queryObject = remoteQueryObjectFromString({
entryPoint: "currency",
variables,
fields: defaultStoreCurrencyFields,
})
const [currency] = await remoteQuery(queryObject)
res.status(200).json({ currency })
}
@@ -0,0 +1,31 @@
import { transformQuery } from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import { authenticate } from "../../../utils/authenticate-middleware"
import * as QueryConfig from "./query-config"
import {
StoreGetCurrenciesCurrencyParams,
StoreGetCurrenciesParams,
} from "./validators"
export const storeCurrencyRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["GET"],
matcher: "/store/currencies",
middlewares: [
transformQuery(
StoreGetCurrenciesParams,
QueryConfig.listTransformQueryConfig
),
],
},
{
method: ["GET"],
matcher: "/store/currencies/:code",
middlewares: [
transformQuery(
StoreGetCurrenciesCurrencyParams,
QueryConfig.retrieveTransformQueryConfig
),
],
},
]
@@ -0,0 +1,20 @@
export const defaultStoreCurrencyRelations = []
export const allowedStoreCurrencyRelations = []
export const defaultStoreCurrencyFields = [
"code",
"name",
"symbol",
"symbol_native",
]
export const retrieveTransformQueryConfig = {
defaultFields: defaultStoreCurrencyFields,
defaultRelations: defaultStoreCurrencyRelations,
allowedRelations: allowedStoreCurrencyRelations,
isList: false,
}
export const listTransformQueryConfig = {
defaultLimit: 20,
isList: true,
}
@@ -0,0 +1,27 @@
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
import { defaultStoreCurrencyFields } from "./query-config"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const queryObject = remoteQueryObjectFromString({
entryPoint: "currency",
variables: {
filters: req.filterableFields,
order: req.listConfig.order,
skip: req.listConfig.skip,
take: req.listConfig.take,
},
fields: defaultStoreCurrencyFields,
})
const { rows: currencies, metadata } = await remoteQuery(queryObject)
res.json({
currencies,
count: metadata.count,
offset: metadata.skip,
limit: metadata.take,
})
}
@@ -0,0 +1,30 @@
import { Type } from "class-transformer"
import { IsOptional, IsString, ValidateNested } from "class-validator"
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
export class StoreGetCurrenciesCurrencyParams extends FindParams {}
/**
* Parameters used to filter and configure the pagination of the retrieved currencies.
*/
export class StoreGetCurrenciesParams extends extendedFindParamsMixin({
limit: 50,
offset: 0,
}) {
/**
* Search parameter for currencies.
*/
@IsString({ each: true })
@IsOptional()
code?: string | string[]
// Additional filters from BaseFilterable
@IsOptional()
@ValidateNested({ each: true })
@Type(() => StoreGetCurrenciesParams)
$and?: StoreGetCurrenciesParams[]
@IsOptional()
@ValidateNested({ each: true })
@Type(() => StoreGetCurrenciesParams)
$or?: StoreGetCurrenciesParams[]
}
@@ -176,33 +176,6 @@ const migratePriceLists = async (container: AwilixContainer) => {
} }
} }
const ensureCurrencies = async (container: AwilixContainer) => {
const currenciesService: CurrencyService =
container.resolve("currencyService")
const pricingModuleService: IPricingModuleService = container.resolve(
"pricingModuleService"
)
const [coreCurrencies, totalCurrencies] =
await currenciesService.listAndCount({}, {})
const moduleCurrencies = await pricingModuleService.listCurrencies(
{},
{ take: 100000 }
)
const moduleCurrenciesSet = new Set(moduleCurrencies.map(({ code }) => code))
const currenciesToCreate = coreCurrencies
.filter(({ code }) => {
return !moduleCurrenciesSet.has(code)
})
.map(({ includes_tax, ...currency }) => currency)
await pricingModuleService.createCurrencies(currenciesToCreate)
}
const migrate = async function ({ directory }) { const migrate = async function ({ directory }) {
const app = express() const app = express()
@@ -212,11 +185,6 @@ const migrate = async function ({ directory }) {
isTest: false, isTest: false,
}) })
Logger.info("-----------------------------------------------")
Logger.info("------------- Creating currencies -------------")
Logger.info("-----------------------------------------------")
await ensureCurrencies(container)
Logger.info("-----------------------------------------------") Logger.info("-----------------------------------------------")
Logger.info("--------- Creating default rule types ---------") Logger.info("--------- Creating default rule types ---------")
Logger.info("-----------------------------------------------") Logger.info("-----------------------------------------------")
+16
View File
@@ -28,6 +28,7 @@ export enum Modules {
ORDER = "order", ORDER = "order",
API_KEY = "apiKey", API_KEY = "apiKey",
STORE = "store", STORE = "store",
CURRENCY = "currency",
} }
export enum ModuleRegistrationName { export enum ModuleRegistrationName {
@@ -51,6 +52,7 @@ export enum ModuleRegistrationName {
ORDER = "orderModuleService", ORDER = "orderModuleService",
API_KEY = "apiKeyModuleService", API_KEY = "apiKeyModuleService",
STORE = "storeModuleService", STORE = "storeModuleService",
CURRENCY = "currencyModuleService",
} }
export const MODULE_PACKAGE_NAMES = { export const MODULE_PACKAGE_NAMES = {
@@ -75,6 +77,7 @@ export const MODULE_PACKAGE_NAMES = {
[Modules.ORDER]: "@medusajs/order", [Modules.ORDER]: "@medusajs/order",
[Modules.API_KEY]: "@medusajs/api-key", [Modules.API_KEY]: "@medusajs/api-key",
[Modules.STORE]: "@medusajs/store", [Modules.STORE]: "@medusajs/store",
[Modules.CURRENCY]: "@medusajs/currency",
} }
export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } = export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
@@ -340,6 +343,19 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
resources: MODULE_RESOURCE_TYPE.SHARED, resources: MODULE_RESOURCE_TYPE.SHARED,
}, },
}, },
[Modules.CURRENCY]: {
key: Modules.CURRENCY,
registrationName: ModuleRegistrationName.CURRENCY,
defaultPackage: false,
label: upperCaseFirst(ModuleRegistrationName.CURRENCY),
isRequired: false,
isQueryable: true,
dependencies: ["logger"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
} }
export const MODULE_DEFINITIONS: ModuleDefinition[] = export const MODULE_DEFINITIONS: ModuleDefinition[] =
@@ -1,20 +0,0 @@
export const defaultCurrencyData = [
{
symbol: "$",
name: "US Dollar",
symbol_native: "$",
code: "USD",
},
{
symbol: "CA$",
name: "Canadian Dollar",
symbol_native: "$",
code: "CAD",
},
{
symbol: "€",
name: "Euro",
symbol_native: "€",
code: "EUR",
},
]
@@ -1,22 +0,0 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency } from "@models"
import { defaultCurrencyData } from "./data"
export * from "./data"
export async function createCurrencies(
manager: SqlEntityManager,
currencyData: any[] = defaultCurrencyData
): Promise<Currency[]> {
const currencies: Currency[] = []
for (let curr of currencyData) {
const currency = manager.create(Currency, curr)
currencies.push(currency)
}
await manager.persistAndFlush(currencies)
return currencies
}
@@ -1,6 +1,5 @@
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { createCurrencies, defaultCurrencyData } from "./currency"
import { createMoneyAmounts, defaultMoneyAmountsData } from "./money-amount" import { createMoneyAmounts, defaultMoneyAmountsData } from "./money-amount"
import { createPriceRules, defaultPriceRuleData } from "./price-rule" import { createPriceRules, defaultPriceRuleData } from "./price-rule"
import { createPriceSets, defaultPriceSetsData } from "./price-set" import { createPriceSets, defaultPriceSetsData } from "./price-set"
@@ -21,14 +20,12 @@ export async function seedPriceData(
{ {
moneyAmountsData = defaultMoneyAmountsData, moneyAmountsData = defaultMoneyAmountsData,
priceSetsData = defaultPriceSetsData, priceSetsData = defaultPriceSetsData,
currencyData = defaultCurrencyData,
priceRuleData = defaultPriceRuleData, priceRuleData = defaultPriceRuleData,
priceSetMoneyAmountsData = defaultPriceSetMoneyAmountsData, priceSetMoneyAmountsData = defaultPriceSetMoneyAmountsData,
priceSetMoneyAmountRulesData = defaultPriceSetMoneyAmountRulesData, priceSetMoneyAmountRulesData = defaultPriceSetMoneyAmountRulesData,
ruleTypesData = defaultRuleTypesData, ruleTypesData = defaultRuleTypesData,
} = {} } = {}
) { ) {
await createCurrencies(testManager, currencyData)
await createMoneyAmounts(testManager, moneyAmountsData) await createMoneyAmounts(testManager, moneyAmountsData)
await createPriceSets(testManager, priceSetsData) await createPriceSets(testManager, priceSetsData)
await createPriceSetMoneyAmounts(testManager, priceSetMoneyAmountsData) await createPriceSetMoneyAmounts(testManager, priceSetMoneyAmountsData)
@@ -1,278 +0,0 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency } from "@models"
import { createCurrencies } from "../../../__fixtures__/currency"
import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
import { ModulesSdkTypes } from "@medusajs/types"
jest.setTimeout(30000)
describe("Currency Service", () => {
let service: ModulesSdkTypes.InternalModuleService<any>
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
let data!: Currency[]
const currencyData = [
{
symbol: "$",
name: "US Dollar",
symbol_native: "$",
code: "USD",
},
{
symbol: "CA$",
name: "Canadian Dollar",
symbol_native: "$",
code: "CAD",
},
]
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
const container = createMedusaContainer()
container.register("manager", asValue(repositoryManager))
await ContainerLoader({ container })
service = container.resolve("currencyService")
testManager = await MikroOrmWrapper.forkManager()
data = await createCurrencies(testManager, currencyData)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("list", () => {
it("list currencies", async () => {
const currenciesResult = await service.list()
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "CAD",
name: "Canadian Dollar",
}),
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
it("list currencies by code", async () => {
const currenciesResult = await service.list({ code: ["USD"] })
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
})
describe("listAndCount", () => {
it("should return currencies and count", async () => {
const [currenciesResult, count] = await service.listAndCount()
expect(count).toEqual(2)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "CAD",
name: "Canadian Dollar",
}),
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
it("should return currencies and count when filtered", async () => {
const [currenciesResult, count] = await service.listAndCount({
code: ["USD"],
})
expect(count).toEqual(1)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
it("should return currencies and count when using skip and take", async () => {
const [currenciesResult, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(2)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
it("should return requested fields", async () => {
const [currenciesResult, count] = await service.listAndCount(
{},
{
take: 1,
select: ["code"],
}
)
const serialized = JSON.parse(JSON.stringify(currenciesResult))
expect(count).toEqual(2)
expect(serialized).toEqual([
{
code: "CAD",
},
])
})
})
describe("retrieve", () => {
const code = "USD"
const name = "US Dollar"
it("should return currency for the given code", async () => {
const currency = await service.retrieve(code)
expect(currency).toEqual(
expect.objectContaining({
code,
})
)
})
it("should throw an error when currency with code does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"Currency with code: does-not-exist was not found"
)
})
it("should throw an error when a code is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual("currency - code must be defined")
})
it("should return currency based on config select param", async () => {
const currency = await service.retrieve(code, {
select: ["code", "name"],
})
const serialized = JSON.parse(JSON.stringify(currency))
expect(serialized).toEqual({
code,
name,
})
})
})
describe("delete", () => {
const code = "USD"
it("should delete the currencies given an code successfully", async () => {
await service.delete([code])
const currencies = await service.list({
code: [code],
})
expect(currencies).toHaveLength(0)
})
})
describe("update", () => {
const code = "USD"
it("should update the name of the currency successfully", async () => {
await service.update([
{
code,
name: "United States Pounds",
},
])
const currency = await service.retrieve(code)
expect(currency.name).toEqual("United States Pounds")
})
it("should throw an error when a code does not exist", async () => {
let error
try {
await service.update([
{
code: "does-not-exist",
name: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'Currency with code "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a currency successfully", async () => {
await service.create([
{
code: "TES",
name: "Test Dollars",
symbol: "TES1",
symbol_native: "TES2",
},
])
const [currency] = await service.list({
code: ["TES"],
})
expect(currency).toEqual(
expect.objectContaining({
code: "TES",
name: "Test Dollars",
symbol: "TES1",
symbol_native: "TES2",
})
)
})
})
})
@@ -3,7 +3,6 @@ import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency, MoneyAmount } from "@models" import { Currency, MoneyAmount } from "@models"
import { MoneyAmountService } from "@services" import { MoneyAmountService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount" import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { MikroOrmWrapper } from "../../../utils" import { MikroOrmWrapper } from "../../../utils"
import { createMedusaContainer } from "@medusajs/utils" import { createMedusaContainer } from "@medusajs/utils"
@@ -17,7 +16,6 @@ describe("MoneyAmount Service", () => {
let testManager: SqlEntityManager let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager let repositoryManager: SqlEntityManager
let data!: MoneyAmount[] let data!: MoneyAmount[]
let currencyData!: Currency[]
beforeEach(async () => { beforeEach(async () => {
await MikroOrmWrapper.setupDatabase() await MikroOrmWrapper.setupDatabase()
@@ -31,7 +29,6 @@ describe("MoneyAmount Service", () => {
service = container.resolve("moneyAmountService") service = container.resolve("moneyAmountService")
testManager = await MikroOrmWrapper.forkManager() testManager = await MikroOrmWrapper.forkManager()
currencyData = await createCurrencies(testManager)
data = await createMoneyAmounts(testManager) data = await createMoneyAmounts(testManager)
}) })
@@ -79,8 +76,7 @@ describe("MoneyAmount Service", () => {
id: ["money-amount-USD"], id: ["money-amount-USD"],
}, },
{ {
select: ["id", "min_quantity", "currency.code", "amount"], select: ["id", "min_quantity", "currency_code", "amount"],
relations: ["currency"],
} }
) )
@@ -92,9 +88,6 @@ describe("MoneyAmount Service", () => {
amount: 500, amount: 500,
min_quantity: "1", min_quantity: "1",
currency_code: "USD", currency_code: "USD",
currency: {
code: "USD",
},
}, },
]) ])
}) })
@@ -105,8 +98,7 @@ describe("MoneyAmount Service", () => {
currency_code: ["USD"], currency_code: ["USD"],
}, },
{ {
select: ["id", "min_quantity", "currency.code", "amount"], select: ["id", "min_quantity", "currency_code", "amount"],
relations: ["currency"],
} }
) )
@@ -118,9 +110,6 @@ describe("MoneyAmount Service", () => {
min_quantity: "1", min_quantity: "1",
currency_code: "USD", currency_code: "USD",
amount: 500, amount: 500,
currency: {
code: "USD",
},
}, },
]) ])
}) })
@@ -165,8 +154,7 @@ describe("MoneyAmount Service", () => {
id: ["money-amount-USD"], id: ["money-amount-USD"],
}, },
{ {
select: ["id", "min_quantity", "currency.code", "amount"], select: ["id", "min_quantity", "currency_code", "amount"],
relations: ["currency"],
} }
) )
@@ -179,9 +167,6 @@ describe("MoneyAmount Service", () => {
amount: 500, amount: 500,
min_quantity: "1", min_quantity: "1",
currency_code: "USD", currency_code: "USD",
currency: {
code: "USD",
},
}, },
]) ])
}) })
@@ -316,7 +301,6 @@ describe("MoneyAmount Service", () => {
const moneyAmount = await service.retrieve(id) const moneyAmount = await service.retrieve(id)
expect(moneyAmount.currency_code).toEqual("EUR") expect(moneyAmount.currency_code).toEqual("EUR")
expect(moneyAmount.currency?.code).toEqual("EUR")
}) })
it("should throw an error when a id does not exist", async () => { it("should throw an error when a id does not exist", async () => {
@@ -3,7 +3,6 @@ import { PriceSetMoneyAmount } from "@models"
import { CreatePriceRuleDTO } from "@medusajs/types" import { CreatePriceRuleDTO } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { PriceRuleService } from "@services" import { PriceRuleService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount" import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { createPriceRules } from "../../../__fixtures__/price-rule" import { createPriceRules } from "../../../__fixtures__/price-rule"
import { createPriceSets } from "../../../__fixtures__/price-set" import { createPriceSets } from "../../../__fixtures__/price-set"
@@ -34,7 +33,6 @@ describe("PriceRule Service", () => {
service = container.resolve("priceRuleService") service = container.resolve("priceRuleService")
await createCurrencies(testManager)
await createMoneyAmounts(testManager) await createMoneyAmounts(testManager)
await createPriceSets(testManager) await createPriceSets(testManager)
await createRuleTypes(testManager) await createRuleTypes(testManager)
@@ -3,7 +3,6 @@ import { SqlEntityManager } from "@mikro-orm/postgresql"
import { MoneyAmount, PriceSet } from "@models" import { MoneyAmount, PriceSet } from "@models"
import { PriceSetService } from "@services" import { PriceSetService } from "@services"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount" import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { createPriceSets } from "../../../__fixtures__/price-set" import { createPriceSets } from "../../../__fixtures__/price-set"
import { MikroOrmWrapper } from "../../../utils" import { MikroOrmWrapper } from "../../../utils"
@@ -63,8 +62,6 @@ describe("PriceSet Service", () => {
service = container.resolve("priceSetService") service = container.resolve("priceSetService")
await createCurrencies(testManager)
moneyAmountsData = await createMoneyAmounts( moneyAmountsData = await createMoneyAmounts(
testManager, testManager,
moneyAmountsInputData moneyAmountsInputData
@@ -85,21 +85,6 @@ describe("PricingModule Service - Calculate Price", () => {
describe("calculatePrices", () => { describe("calculatePrices", () => {
beforeEach(async () => { beforeEach(async () => {
const currencyData = [
{
symbol: "zł",
name: "Polish Zloty",
symbol_native: "zł",
code: "PLN",
},
{
symbol: "€",
name: "Euro",
symbol_native: "€",
code: "EUR",
},
]
const moneyAmountsData = [ const moneyAmountsData = [
{ {
id: "money-amount-PLN", id: "money-amount-PLN",
@@ -373,7 +358,6 @@ describe("PricingModule Service - Calculate Price", () => {
] as unknown as CreatePriceRuleDTO[] ] as unknown as CreatePriceRuleDTO[]
await seedPriceData(MikroOrmWrapper.forkManager(), { await seedPriceData(MikroOrmWrapper.forkManager(), {
currencyData,
moneyAmountsData, moneyAmountsData,
priceSetsData, priceSetsData,
priceSetMoneyAmountsData, priceSetMoneyAmountsData,
@@ -1,277 +0,0 @@
import { IPricingModuleService } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency } from "@models"
import { createCurrencies } from "../../../__fixtures__/currency"
import { MikroOrmWrapper } from "../../../utils"
import { getInitModuleConfig } from "../../../utils/get-init-module-config"
import { Modules } from "@medusajs/modules-sdk"
import { initModules } from "medusa-test-utils"
describe("PricingModule Service - Currency", () => {
let service: IPricingModuleService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
let data!: Currency[]
let shutdownFunc: () => Promise<void>
beforeAll(async () => {
const initModulesConfig = getInitModuleConfig()
const { medusaApp, shutdown } = await initModules(initModulesConfig)
service = medusaApp.modules[Modules.PRICING]
shutdownFunc = shutdown
})
afterAll(async () => {
await shutdownFunc()
})
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = MikroOrmWrapper.forkManager()
testManager = MikroOrmWrapper.forkManager()
data = await createCurrencies(testManager)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("listCurrencies", () => {
it("list currencies", async () => {
const currenciesResult = await service.listCurrencies()
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "CAD",
name: "Canadian Dollar",
}),
expect.objectContaining({
code: "EUR",
name: "Euro",
}),
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
it("list currencies by code", async () => {
const currenciesResult = await service.listCurrencies({ code: ["USD"] })
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
})
describe("listAndCountCurrencies", () => {
it("should return currencies and count", async () => {
const [currenciesResult, count] = await service.listAndCountCurrencies()
expect(count).toEqual(3)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "CAD",
name: "Canadian Dollar",
}),
expect.objectContaining({
code: "EUR",
name: "Euro",
}),
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
it("should return currencies and count when filtered", async () => {
const [currenciesResult, count] = await service.listAndCountCurrencies({
code: ["USD"],
})
expect(count).toEqual(1)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "USD",
name: "US Dollar",
}),
])
})
it("should return currencies and count when using skip and take", async () => {
const [currenciesResult, count] = await service.listAndCountCurrencies(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(3)
expect(currenciesResult).toEqual([
expect.objectContaining({
code: "EUR",
name: "Euro",
symbol: "€",
symbol_native: "€",
}),
])
})
it("should return requested fields", async () => {
const [currenciesResult, count] = await service.listAndCountCurrencies(
{},
{
take: 1,
select: ["code"],
}
)
const serialized = JSON.parse(JSON.stringify(currenciesResult))
expect(count).toEqual(3)
expect(serialized).toEqual([
{
code: "CAD",
},
])
})
})
describe("retrieveCurrency", () => {
const code = "USD"
const name = "US Dollar"
it("should return currency for the given code", async () => {
const currency = await service.retrieveCurrency(code)
expect(currency).toEqual(
expect.objectContaining({
code,
})
)
})
it("should throw an error when currency with code does not exist", async () => {
let error
try {
await service.retrieveCurrency("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"Currency with code: does-not-exist was not found"
)
})
it("should throw an error when a code is not provided", async () => {
let error
try {
await service.retrieveCurrency(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual("currency - code must be defined")
})
it("should return currency based on config select param", async () => {
const currency = await service.retrieveCurrency(code, {
select: ["code", "name"],
})
const serialized = JSON.parse(JSON.stringify(currency))
expect(serialized).toEqual({
code,
name,
})
})
})
describe("deleteCurrencies", () => {
const code = "USD"
it("should delete the currencies given an code successfully", async () => {
await service.deleteCurrencies([code])
const currencies = await service.listCurrencies({
code: [code],
})
expect(currencies).toHaveLength(0)
})
})
describe("updateCurrencies", () => {
const code = "USD"
it("should update the name of the currency successfully", async () => {
await service.updateCurrencies([
{
code,
name: "United States Pounds",
},
])
const currency = await service.retrieveCurrency(code)
expect(currency.name).toEqual("United States Pounds")
})
it("should throw an error when a code does not exist", async () => {
let error
try {
await service.updateCurrencies([
{
code: "does-not-exist",
name: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'Currency with code "does-not-exist" not found'
)
})
})
describe("createCurrencies", () => {
it("should create a currency successfully", async () => {
await service.createCurrencies([
{
code: "TES",
name: "Test Dollars",
symbol: "TES1",
symbol_native: "TES2",
},
])
const [currency] = await service.listCurrencies({
code: ["TES"],
})
expect(currency).toEqual(
expect.objectContaining({
code: "TES",
name: "Test Dollars",
symbol: "TES1",
symbol_native: "TES2",
})
)
})
})
})
@@ -1,7 +1,6 @@
import { IPricingModuleService } from "@medusajs/types" import { IPricingModuleService } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Currency, MoneyAmount } from "@models" import { MoneyAmount } from "@models"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount" import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { MikroOrmWrapper } from "../../../utils" import { MikroOrmWrapper } from "../../../utils"
import { createPriceSetMoneyAmounts } from "../../../__fixtures__/price-set-money-amount" import { createPriceSetMoneyAmounts } from "../../../__fixtures__/price-set-money-amount"
@@ -20,7 +19,6 @@ describe("PricingModule Service - MoneyAmount", () => {
let testManager: SqlEntityManager let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager let repositoryManager: SqlEntityManager
let data!: MoneyAmount[] let data!: MoneyAmount[]
let currencyData!: Currency[]
let shutdownFunc: () => Promise<void> let shutdownFunc: () => Promise<void>
beforeAll(async () => { beforeAll(async () => {
@@ -42,7 +40,6 @@ describe("PricingModule Service - MoneyAmount", () => {
repositoryManager = MikroOrmWrapper.forkManager() repositoryManager = MikroOrmWrapper.forkManager()
testManager = MikroOrmWrapper.forkManager() testManager = MikroOrmWrapper.forkManager()
currencyData = await createCurrencies(testManager)
data = await createMoneyAmounts(testManager) data = await createMoneyAmounts(testManager)
}) })
@@ -90,8 +87,7 @@ describe("PricingModule Service - MoneyAmount", () => {
id: ["money-amount-USD"], id: ["money-amount-USD"],
}, },
{ {
select: ["id", "min_quantity", "currency.code"], select: ["id", "min_quantity", "currency_code"],
relations: ["currency"],
} }
) )
@@ -103,9 +99,6 @@ describe("PricingModule Service - MoneyAmount", () => {
amount: null, amount: null,
min_quantity: "1", min_quantity: "1",
currency_code: "USD", currency_code: "USD",
currency: {
code: "USD",
},
}, },
]) ])
}) })
@@ -153,8 +146,7 @@ describe("PricingModule Service - MoneyAmount", () => {
id: ["money-amount-USD"], id: ["money-amount-USD"],
}, },
{ {
select: ["id", "min_quantity", "currency.code", "amount"], select: ["id", "min_quantity", "currency_code", "amount"],
relations: ["currency"],
} }
) )
@@ -167,9 +159,6 @@ describe("PricingModule Service - MoneyAmount", () => {
amount: 500, amount: 500,
min_quantity: "1", min_quantity: "1",
currency_code: "USD", currency_code: "USD",
currency: {
code: "USD",
},
}, },
]) ])
}) })
@@ -392,12 +381,9 @@ describe("PricingModule Service - MoneyAmount", () => {
}, },
]) ])
const moneyAmount = await service.retrieveMoneyAmount(id, { const moneyAmount = await service.retrieveMoneyAmount(id, {})
relations: ["currency"],
})
expect(moneyAmount.currency_code).toEqual("EUR") expect(moneyAmount.currency_code).toEqual("EUR")
expect(moneyAmount.currency?.code).toEqual("EUR")
}) })
it("should throw an error when a id does not exist", async () => { it("should throw an error when a id does not exist", async () => {
@@ -2,7 +2,6 @@ import { MikroOrmWrapper } from "../../../utils"
import { IPricingModuleService } from "@medusajs/types" import { IPricingModuleService } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createPriceLists } from "../../../__fixtures__/price-list" import { createPriceLists } from "../../../__fixtures__/price-list"
import { createPriceSets } from "../../../__fixtures__/price-set" import { createPriceSets } from "../../../__fixtures__/price-set"
import { Modules } from "@medusajs/modules-sdk" import { Modules } from "@medusajs/modules-sdk"
@@ -35,7 +34,6 @@ describe("PriceList Service", () => {
await MikroOrmWrapper.forkManager() await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager() testManager = await MikroOrmWrapper.forkManager()
await createCurrencies(testManager)
await createPriceSets(testManager) await createPriceSets(testManager)
await createPriceLists(testManager) await createPriceLists(testManager)
await service.createRuleTypes([ await service.createRuleTypes([
@@ -2,7 +2,6 @@ import { CreatePriceRuleDTO, IPricingModuleService } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { PriceSetMoneyAmount } from "../../../../src" import { PriceSetMoneyAmount } from "../../../../src"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount" import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { createPriceRules } from "../../../__fixtures__/price-rule" import { createPriceRules } from "../../../__fixtures__/price-rule"
import { createPriceSets } from "../../../__fixtures__/price-set" import { createPriceSets } from "../../../__fixtures__/price-set"
@@ -39,7 +38,6 @@ describe("PricingModule Service - PriceRule", () => {
await MikroOrmWrapper.setupDatabase() await MikroOrmWrapper.setupDatabase()
testManager = MikroOrmWrapper.forkManager() testManager = MikroOrmWrapper.forkManager()
await createCurrencies(testManager)
await createMoneyAmounts(testManager) await createMoneyAmounts(testManager)
await createPriceSets(testManager) await createPriceSets(testManager)
await createRuleTypes(testManager) await createRuleTypes(testManager)
@@ -1,6 +1,5 @@
import { IPricingModuleService } from "@medusajs/types" import { IPricingModuleService } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql" import { SqlEntityManager } from "@mikro-orm/postgresql"
import { createCurrencies } from "../../../__fixtures__/currency"
import { createMoneyAmounts } from "../../../__fixtures__/money-amount" import { createMoneyAmounts } from "../../../__fixtures__/money-amount"
import { createPriceSets } from "../../../__fixtures__/price-set" import { createPriceSets } from "../../../__fixtures__/price-set"
import { createPriceSetMoneyAmounts } from "../../../__fixtures__/price-set-money-amount" import { createPriceSetMoneyAmounts } from "../../../__fixtures__/price-set-money-amount"
@@ -38,7 +37,6 @@ describe("PricingModule Service - PriceSetMoneyAmountRules", () => {
repositoryManager = await MikroOrmWrapper.forkManager() repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager() testManager = await MikroOrmWrapper.forkManager()
await createCurrencies(testManager)
await createMoneyAmounts(testManager) await createMoneyAmounts(testManager)
await createPriceSets(testManager) await createPriceSets(testManager)
await createRuleTypes(testManager) await createRuleTypes(testManager)
+1 -15
View File
@@ -1,18 +1,11 @@
import { Modules } from "@medusajs/modules-sdk" import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types" import { ModuleJoinerConfig } from "@medusajs/types"
import { MapToConfig } from "@medusajs/utils" import { MapToConfig } from "@medusajs/utils"
import { import { MoneyAmount, PriceList, PriceSet, PriceSetMoneyAmount } from "@models"
Currency,
MoneyAmount,
PriceList,
PriceSet,
PriceSetMoneyAmount,
} from "@models"
import schema from "./schema" import schema from "./schema"
export const LinkableKeys = { export const LinkableKeys = {
money_amount_id: MoneyAmount.name, money_amount_id: MoneyAmount.name,
currency_code: Currency.name,
price_set_id: PriceSet.name, price_set_id: PriceSet.name,
price_list_id: PriceList.name, price_list_id: PriceList.name,
price_set_money_amount_id: PriceSetMoneyAmount.name, price_set_money_amount_id: PriceSetMoneyAmount.name,
@@ -48,13 +41,6 @@ export const joinerConfig: ModuleJoinerConfig = {
entity: "MoneyAmount", entity: "MoneyAmount",
}, },
}, },
{
name: ["currency", "currencies"],
args: {
methodSuffix: "Currencies",
entity: "Currency",
},
},
{ {
name: ["price_list", "price_lists"], name: ["price_list", "price_lists"],
args: { args: {
@@ -4,61 +4,6 @@
], ],
"name": "public", "name": "public",
"tables": [ "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": { "columns": {
"id": { "id": {
@@ -172,19 +117,6 @@
], ],
"checks": [], "checks": [],
"foreignKeys": { "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"
}
} }
}, },
{ {
@@ -2,10 +2,6 @@ import { Migration } from "@mikro-orm/migrations"
export class Migration20230929122253 extends Migration { export class Migration20230929122253 extends Migration {
async up(): Promise<void> { async up(): Promise<void> {
this.addSql(
'create table if not exists "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( this.addSql(
'create table if not exists "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"));' 'create table if not exists "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"));'
) )
@@ -67,10 +63,6 @@ export class Migration20230929122253 extends Migration {
'create index "IDX_price_rule_price_set_money_amount_id" on "price_rule" ("price_set_money_amount_id");' 'create index "IDX_price_rule_price_set_money_amount_id" on "price_rule" ("price_set_money_amount_id");'
) )
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;'
)
this.addSql( this.addSql(
'alter table "price_set_money_amount" add constraint "price_set_money_amount_price_set_id_foreign" foreign key ("price_set_id") references "price_set" ("id") on update cascade on delete cascade;' 'alter table "price_set_money_amount" add constraint "price_set_money_amount_price_set_id_foreign" foreign key ("price_set_id") references "price_set" ("id") on update cascade on delete cascade;'
) )
-1
View File
@@ -1,4 +1,3 @@
export { default as Currency } from "./currency"
export { default as MoneyAmount } from "./money-amount" export { default as MoneyAmount } from "./money-amount"
export { default as PriceList } from "./price-list" export { default as PriceList } from "./price-list"
export { default as PriceListRule } from "./price-list-rule" export { default as PriceListRule } from "./price-list-rule"
@@ -14,7 +14,6 @@ import {
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import Currency from "./currency"
import { PriceSetMoneyAmount } from "./index" import { PriceSetMoneyAmount } from "./index"
import PriceSet from "./price-set" import PriceSet from "./price-set"
@@ -47,13 +46,6 @@ class MoneyAmount {
}) })
price_set_money_amount: PriceSetMoneyAmount price_set_money_amount: PriceSetMoneyAmount
@ManyToOne(() => Currency, {
nullable: true,
index: "IDX_money_amount_currency_code",
fieldName: "currency_code",
})
currency: Currency
@Property({ @Property({
columnType: "numeric", columnType: "numeric",
nullable: true, nullable: true,
-1
View File
@@ -7,7 +7,6 @@ type PriceSet {
type MoneyAmount { type MoneyAmount {
id: String! id: String!
currency_code: String currency_code: String
currency: Currency
amount: Float amount: Float
min_quantity: Float min_quantity: Float
max_quantity: Float max_quantity: Float
+8 -26
View File
@@ -22,17 +22,13 @@ export async function run({
logger.info(`Loading seed data from ${path}...`) logger.info(`Loading seed data from ${path}...`)
const { const { moneyAmountsData, priceSetsData, priceSetMoneyAmountsData } =
currenciesData, await import(resolve(process.cwd(), path)).catch((e) => {
moneyAmountsData, logger?.error(
priceSetsData, `Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following: priceSetsData, moneyAmountsData and priceSetMoneyAmountsData.${EOL}${e}`
priceSetMoneyAmountsData, )
} = await import(resolve(process.cwd(), path)).catch((e) => { throw e
logger?.error( })
`Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following: priceSetsData, currenciesData, moneyAmountsData and priceSetMoneyAmountsData.${EOL}${e}`
)
throw e
})
const dbData = ModulesSdkUtils.loadDatabaseConfig("pricing", options)! const dbData = ModulesSdkUtils.loadDatabaseConfig("pricing", options)!
const entities = Object.values(PricingModels) as unknown as EntitySchema[] const entities = Object.values(PricingModels) as unknown as EntitySchema[]
@@ -47,9 +43,8 @@ export async function run({
const manager = orm.em.fork() const manager = orm.em.fork()
try { try {
logger.info("Inserting price_sets, currencies & money_amounts") logger.info("Inserting price_sets & money_amounts")
await createCurrencies(manager as any, currenciesData)
await createMoneyAmounts(manager as any, moneyAmountsData) await createMoneyAmounts(manager as any, moneyAmountsData)
await createPriceSets(manager as any, priceSetsData) await createPriceSets(manager as any, priceSetsData)
await createPriceSetMoneyAmounts(manager as any, priceSetMoneyAmountsData) await createPriceSetMoneyAmounts(manager as any, priceSetMoneyAmountsData)
@@ -62,19 +57,6 @@ export async function run({
await orm.close(true) await orm.close(true)
} }
async function createCurrencies(
manager: SqlEntityManager<PostgreSqlDriver>,
data: RequiredEntityData<PricingModels.Currency>[]
) {
const currencies = data.map((currencyData) => {
return manager.create(PricingModels.Currency, currencyData)
})
await manager.persistAndFlush(currencies)
return currencies
}
async function createMoneyAmounts( async function createMoneyAmounts(
manager: SqlEntityManager<PostgreSqlDriver>, manager: SqlEntityManager<PostgreSqlDriver>,
data: RequiredEntityData<PricingModels.MoneyAmount>[] data: RequiredEntityData<PricingModels.MoneyAmount>[]
@@ -1,24 +0,0 @@
import { Currency } from "@models"
import { asValue } from "awilix"
;(Currency as any).meta = {
/**
* Need to mock the Currency model as well to expose the primary keys when it is different than `id`
*/
primaryKeys: ["code"],
}
export const nonExistingCurrencyCode = "non-existing-code"
export const currencyRepositoryMock = {
currencyRepository: asValue({
find: jest.fn().mockImplementation(async ({ where: { code } }) => {
if (code === nonExistingCurrencyCode) {
return []
}
return [{}]
}),
findAndCount: jest.fn().mockResolvedValue([[], 0]),
getFreshManager: jest.fn().mockResolvedValue({}),
}),
}
@@ -1,228 +0,0 @@
import {
currencyRepositoryMock,
nonExistingCurrencyCode,
} from "../__fixtures__/currency"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../loaders/container"
import { MedusaContainer } from "@medusajs/types"
const code = "existing-currency"
describe("Currency service", function () {
let container: MedusaContainer
beforeEach(async function () {
jest.clearAllMocks()
container = createMedusaContainer()
container.register("manager", asValue({}))
await ContainerLoader({ container })
container.register(currencyRepositoryMock)
})
it("should retrieve a currency", async function () {
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
await currencyService.retrieve(code)
expect(currencyRepository.find).toHaveBeenCalledWith(
{
where: {
code,
},
options: {
fields: undefined,
limit: 15,
offset: 0,
populate: [],
},
},
expect.any(Object)
)
})
it("should fail to retrieve a currency", async function () {
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const err = await currencyService
.retrieve(nonExistingCurrencyCode)
.catch((e) => e)
expect(currencyRepository.find).toHaveBeenCalledWith(
{
where: {
code: nonExistingCurrencyCode,
},
options: {
fields: undefined,
limit: 15,
offset: 0,
populate: [],
withDeleted: undefined,
},
},
expect.any(Object)
)
expect(err.message).toBe(
`Currency with code: ${nonExistingCurrencyCode} was not found`
)
})
it("should list currencys", async function () {
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {}
const config = {
relations: [],
}
await currencyService.list(filters, config)
expect(currencyRepository.find).toHaveBeenCalledWith(
{
where: {},
options: {
fields: undefined,
limit: 15,
offset: 0,
orderBy: {
code: "ASC",
},
populate: [],
withDeleted: undefined,
},
},
expect.any(Object)
)
})
it("should list currencys with filters", async function () {
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {
tags: {
value: {
$in: ["test"],
},
},
}
const config = {
relations: [],
}
await currencyService.list(filters, config)
expect(currencyRepository.find).toHaveBeenCalledWith(
{
where: {
tags: {
value: {
$in: ["test"],
},
},
},
options: {
fields: undefined,
limit: 15,
offset: 0,
orderBy: {
code: "ASC",
},
populate: [],
withDeleted: undefined,
},
},
expect.any(Object)
)
})
it("should list currencys with filters and relations", async function () {
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {
tags: {
value: {
$in: ["test"],
},
},
}
const config = {
relations: ["tags"],
}
await currencyService.list(filters, config)
expect(currencyRepository.find).toHaveBeenCalledWith(
{
where: {
tags: {
value: {
$in: ["test"],
},
},
},
options: {
fields: undefined,
limit: 15,
offset: 0,
orderBy: {
code: "ASC",
},
withDeleted: undefined,
populate: ["tags"],
},
},
expect.any(Object)
)
})
it("should list and count the currencies with filters and relations", async function () {
const currencyService = container.resolve("currencyService")
const currencyRepository = container.resolve("currencyRepository")
const filters = {
tags: {
value: {
$in: ["test"],
},
},
}
const config = {
relations: ["tags"],
}
await currencyService.listAndCount(filters, config)
expect(currencyRepository.findAndCount).toHaveBeenCalledWith(
{
where: {
tags: {
value: {
$in: ["test"],
},
},
},
options: {
fields: undefined,
limit: 15,
offset: 0,
orderBy: {
code: "ASC",
},
withDeleted: undefined,
populate: ["tags"],
},
},
expect.any(Object)
)
})
})
@@ -0,0 +1,6 @@
describe("Noop test", () => {
it("noop check", async () => {
expect(true).toBe(true)
})
})
@@ -28,7 +28,6 @@ import {
} from "@medusajs/utils" } from "@medusajs/utils"
import { import {
Currency,
MoneyAmount, MoneyAmount,
PriceList, PriceList,
PriceListRule, PriceListRule,
@@ -55,7 +54,6 @@ import { ServiceTypes } from "@types"
type InjectedDependencies = { type InjectedDependencies = {
baseRepository: DAL.RepositoryService baseRepository: DAL.RepositoryService
pricingRepository: PricingRepositoryService pricingRepository: PricingRepositoryService
currencyService: ModulesSdkTypes.InternalModuleService<any>
moneyAmountService: ModulesSdkTypes.InternalModuleService<any> moneyAmountService: ModulesSdkTypes.InternalModuleService<any>
priceSetService: ModulesSdkTypes.InternalModuleService<any> priceSetService: ModulesSdkTypes.InternalModuleService<any>
priceSetMoneyAmountRulesService: ModulesSdkTypes.InternalModuleService<any> priceSetMoneyAmountRulesService: ModulesSdkTypes.InternalModuleService<any>
@@ -69,7 +67,6 @@ type InjectedDependencies = {
} }
const generateMethodForModels = [ const generateMethodForModels = [
Currency,
MoneyAmount, MoneyAmount,
PriceList, PriceList,
PriceListRule, PriceListRule,
@@ -84,7 +81,6 @@ const generateMethodForModels = [
export default class PricingModuleService< export default class PricingModuleService<
TPriceSet extends PriceSet = PriceSet, TPriceSet extends PriceSet = PriceSet,
TMoneyAmount extends MoneyAmount = MoneyAmount, TMoneyAmount extends MoneyAmount = MoneyAmount,
TCurrency extends Currency = Currency,
TRuleType extends RuleType = RuleType, TRuleType extends RuleType = RuleType,
TPriceSetMoneyAmountRules extends PriceSetMoneyAmountRules = PriceSetMoneyAmountRules, TPriceSetMoneyAmountRules extends PriceSetMoneyAmountRules = PriceSetMoneyAmountRules,
TPriceRule extends PriceRule = PriceRule, TPriceRule extends PriceRule = PriceRule,
@@ -98,7 +94,6 @@ export default class PricingModuleService<
InjectedDependencies, InjectedDependencies,
PricingTypes.PriceSetDTO, PricingTypes.PriceSetDTO,
{ {
Currency: { dto: PricingTypes.CurrencyDTO }
MoneyAmount: { dto: PricingTypes.MoneyAmountDTO } MoneyAmount: { dto: PricingTypes.MoneyAmountDTO }
PriceSetMoneyAmount: { dto: PricingTypes.PriceSetMoneyAmountDTO } PriceSetMoneyAmount: { dto: PricingTypes.PriceSetMoneyAmountDTO }
PriceSetMoneyAmountRules: { PriceSetMoneyAmountRules: {
@@ -114,7 +109,6 @@ export default class PricingModuleService<
{ {
protected baseRepository_: DAL.RepositoryService protected baseRepository_: DAL.RepositoryService
protected readonly pricingRepository_: PricingRepositoryService protected readonly pricingRepository_: PricingRepositoryService
protected readonly currencyService_: ModulesSdkTypes.InternalModuleService<TCurrency>
protected readonly moneyAmountService_: ModulesSdkTypes.InternalModuleService<TMoneyAmount> protected readonly moneyAmountService_: ModulesSdkTypes.InternalModuleService<TMoneyAmount>
protected readonly ruleTypeService_: RuleTypeService<TRuleType> protected readonly ruleTypeService_: RuleTypeService<TRuleType>
protected readonly priceSetService_: ModulesSdkTypes.InternalModuleService<TPriceSet> protected readonly priceSetService_: ModulesSdkTypes.InternalModuleService<TPriceSet>
@@ -131,7 +125,6 @@ export default class PricingModuleService<
baseRepository, baseRepository,
pricingRepository, pricingRepository,
moneyAmountService, moneyAmountService,
currencyService,
ruleTypeService, ruleTypeService,
priceSetService, priceSetService,
priceSetMoneyAmountRulesService, priceSetMoneyAmountRulesService,
@@ -149,7 +142,6 @@ export default class PricingModuleService<
this.baseRepository_ = baseRepository this.baseRepository_ = baseRepository
this.pricingRepository_ = pricingRepository this.pricingRepository_ = pricingRepository
this.currencyService_ = currencyService
this.moneyAmountService_ = moneyAmountService this.moneyAmountService_ = moneyAmountService
this.ruleTypeService_ = ruleTypeService this.ruleTypeService_ = ruleTypeService
this.priceSetService_ = priceSetService this.priceSetService_ = priceSetService
@@ -749,36 +741,6 @@ export default class PricingModuleService<
) )
} }
@InjectTransactionManager("baseRepository_")
async createCurrencies(
data: PricingTypes.CreateCurrencyDTO[],
@MedusaContext() sharedContext: Context = {}
) {
const currencies = await this.currencyService_.create(data, sharedContext)
return await this.baseRepository_.serialize<PricingTypes.CurrencyDTO[]>(
currencies,
{
populate: true,
}
)
}
@InjectTransactionManager("baseRepository_")
async updateCurrencies(
data: PricingTypes.UpdateCurrencyDTO[],
@MedusaContext() sharedContext: Context = {}
) {
const currencies = await this.currencyService_.update(data, sharedContext)
return await this.baseRepository_.serialize<PricingTypes.CurrencyDTO[]>(
currencies,
{
populate: true,
}
)
}
@InjectTransactionManager("baseRepository_") @InjectTransactionManager("baseRepository_")
async createRuleTypes( async createRuleTypes(
data: PricingTypes.CreateRuleTypeDTO[], data: PricingTypes.CreateRuleTypeDTO[],
@@ -1,13 +0,0 @@
export interface CreateCurrencyDTO {
code: string
symbol: string
symbol_native: string
name: string
}
export interface UpdateCurrencyDTO {
code: string
symbol?: string
symbol_native?: string
name?: string
}
@@ -1,4 +1,3 @@
export * from "./currency"
export * from "./money-amount" export * from "./money-amount"
export * from "./price-list-rule-value" export * from "./price-list-rule-value"
export * from "./price-list-rule" export * from "./price-list-rule"
@@ -1,9 +1,6 @@
import { Currency } from "@models"
export interface CreateMoneyAmountDTO { export interface CreateMoneyAmountDTO {
id?: string id?: string
currency_code: string currency_code: string
currency?: Currency
amount: number amount: number
min_quantity?: number | null min_quantity?: number | null
max_quantity?: number | null max_quantity?: number | null
@@ -1,27 +0,0 @@
import { BaseFilterable } from "@medusajs/types"
export interface CreateCurrencyDTO {
code: string
symbol: string
symbol_native: string
name: string
}
export interface UpdateCurrencyDTO {
code: string
symbol?: string
symbol_native?: string
name?: string
}
export interface FilterableCurrencyProps
extends BaseFilterable<FilterableCurrencyProps> {
code?: string[]
}
export interface CurrencyDTO {
code: string
symbol?: string
symbol_native?: string
name?: string
}
+1 -2
View File
@@ -1,4 +1,3 @@
export * from "./currency"
export * from "./money-amount" export * from "./money-amount"
export * from "./price-list-rule-value" export * from "./price-list-rule-value"
export * from "./price-list-rule" export * from "./price-list-rule"
@@ -9,4 +8,4 @@ export * from "./price-set-money-amount"
export * from "./price-set-rule-type" export * from "./price-set-rule-type"
export * from "./price-set" export * from "./price-set"
export * from "./pricing" export * from "./pricing"
export * from "./rule-type" export * from "./rule-type"
@@ -1,14 +1,8 @@
import { import { BaseFilterable, PriceSetMoneyAmountDTO } from "@medusajs/types"
BaseFilterable,
CreateCurrencyDTO,
CurrencyDTO,
PriceSetMoneyAmountDTO,
} from "@medusajs/types"
export interface CreateMoneyAmountDTO { export interface CreateMoneyAmountDTO {
id?: string id?: string
currency_code: string currency_code: string
currency?: CreateCurrencyDTO
amount: number amount: number
min_quantity?: number | null min_quantity?: number | null
max_quantity?: number | null max_quantity?: number | null
@@ -25,7 +19,6 @@ export interface UpdateMoneyAmountDTO {
export interface MoneyAmountDTO { export interface MoneyAmountDTO {
id: string id: string
currency_code?: string currency_code?: string
currency?: CurrencyDTO
amount?: number amount?: number
min_quantity?: number min_quantity?: number
max_quantity?: number max_quantity?: number
@@ -26,12 +26,9 @@ describe("Region Module Service", () => {
await shutdownFunc() await shutdownFunc()
}) })
it("should create countries and currencies on application start", async () => { it("should create countries on application start", async () => {
const countries = await service.listCountries() const countries = await service.listCountries()
const currencies = await service.listCurrencies()
expect(countries.length).toBeGreaterThan(0) expect(countries.length).toBeGreaterThan(0)
expect(currencies.length).toBeGreaterThan(0)
}) })
it("should create countries added to default ones", async () => { it("should create countries added to default ones", async () => {
@@ -47,7 +44,7 @@ describe("Region Module Service", () => {
numeric: "420", numeric: "420",
}) })
await service.createDefaultCountriesAndCurrencies() await service.createDefaultCountries()
const [, newCount] = await service.listAndCountCountries() const [, newCount] = await service.listAndCountCountries()
expect(newCount).toEqual(initialCountries + 1) expect(newCount).toEqual(initialCountries + 1)
@@ -69,7 +66,7 @@ describe("Region Module Service", () => {
) )
const region = await service.retrieve(createdRegion.id, { const region = await service.retrieve(createdRegion.id, {
relations: ["currency", "countries"], relations: ["countries"],
}) })
expect(region).toEqual( expect(region).toEqual(
@@ -77,10 +74,6 @@ describe("Region Module Service", () => {
id: region.id, id: region.id,
name: "Europe", name: "Europe",
currency_code: "eur", currency_code: "eur",
currency: expect.objectContaining({
code: "eur",
name: "Euro",
}),
countries: [], countries: [],
}) })
) )
@@ -94,7 +87,7 @@ describe("Region Module Service", () => {
}) })
const region = await service.retrieve(createdRegion.id, { const region = await service.retrieve(createdRegion.id, {
relations: ["countries", "currency"], relations: ["countries"],
}) })
expect(region).toEqual( expect(region).toEqual(
@@ -102,10 +95,6 @@ describe("Region Module Service", () => {
id: region.id, id: region.id,
name: "North America", name: "North America",
currency_code: "usd", currency_code: "usd",
currency: expect.objectContaining({
code: "usd",
name: "US Dollar",
}),
countries: [ countries: [
expect.objectContaining({ expect.objectContaining({
display_name: "Canada", display_name: "Canada",
@@ -182,7 +171,7 @@ describe("Region Module Service", () => {
}) })
const latestRegion = await service.retrieve(createdRegion.id, { const latestRegion = await service.retrieve(createdRegion.id, {
relations: ["currency", "countries"], relations: ["countries"],
}) })
expect(latestRegion).toMatchObject({ expect(latestRegion).toMatchObject({
@@ -243,7 +232,7 @@ describe("Region Module Service", () => {
}) })
const latestRegion = await service.retrieve(createdRegion.id, { const latestRegion = await service.retrieve(createdRegion.id, {
relations: ["currency", "countries"], relations: ["countries"],
}) })
expect(latestRegion).toMatchObject({ expect(latestRegion).toMatchObject({
@@ -268,7 +257,7 @@ describe("Region Module Service", () => {
}) })
const updatedRegion = await service.retrieve(createdRegion.id, { const updatedRegion = await service.retrieve(createdRegion.id, {
relations: ["currency", "countries"], relations: ["countries"],
}) })
expect(updatedRegion).toMatchObject({ expect(updatedRegion).toMatchObject({
@@ -294,7 +283,7 @@ describe("Region Module Service", () => {
}) })
const updatedRegion = await service.retrieve(createdRegion.id, { const updatedRegion = await service.retrieve(createdRegion.id, {
relations: ["currency", "countries"], relations: ["countries"],
}) })
expect(updatedRegion).toMatchObject({ expect(updatedRegion).toMatchObject({
@@ -306,23 +295,6 @@ describe("Region Module Service", () => {
expect(updatedRegion.countries).toHaveLength(0) expect(updatedRegion.countries).toHaveLength(0)
}) })
it("should fail updating the region currency to a non-existent one", async () => {
const createdRegion = await service.create({
name: "North America",
currency_code: "USD",
countries: ["us", "ca"],
})
await expect(
service.update(
{ id: createdRegion.id },
{
currency_code: "DOGECOIN",
}
)
).rejects.toThrowError('Currencies with codes: "dogecoin" were not found')
})
it("should fail updating the region countries to non-existent ones", async () => { it("should fail updating the region countries to non-existent ones", async () => {
const createdRegion = await service.create({ const createdRegion = await service.create({
name: "North America", name: "North America",
@@ -384,13 +356,4 @@ describe("Region Module Service", () => {
'Countries with codes: "mx" are already assigned to a region' 'Countries with codes: "mx" are already assigned to a region'
) )
}) })
it("should fail when currency does not exist", async () => {
await expect(
service.create({
name: "Europe",
currency_code: "DOGECOIN",
})
).rejects.toThrowError('Currencies with codes: "dogecoin" were not found')
})
}) })
+1 -6
View File
@@ -1,11 +1,10 @@
import { Modules } from "@medusajs/modules-sdk" import { Modules } from "@medusajs/modules-sdk"
import { ModuleJoinerConfig } from "@medusajs/types" import { ModuleJoinerConfig } from "@medusajs/types"
import { MapToConfig } from "@medusajs/utils" import { MapToConfig } from "@medusajs/utils"
import { Country, Currency, Region } from "@models" import { Country, Region } from "@models"
export const LinkableKeys = { export const LinkableKeys = {
region_id: Region.name, region_id: Region.name,
currency_code: Country.name,
country_id: Region.name, country_id: Region.name,
} }
@@ -29,10 +28,6 @@ export const joinerConfig: ModuleJoinerConfig = {
name: ["region", "regions"], name: ["region", "regions"],
args: { entity: Region.name }, args: { entity: Region.name },
}, },
{
name: ["currency", "currencies"],
args: { entity: Currency.name },
},
{ {
name: ["country", "countries"], name: ["country", "countries"],
args: { entity: Country.name }, args: { entity: Country.name },
+1 -1
View File
@@ -8,6 +8,6 @@ export default async ({ container }: LoaderOptions): Promise<void> => {
// TODO: Remove when legacy modules have been migrated // TODO: Remove when legacy modules have been migrated
if (!!process.env.MEDUSA_FF_MEDUSA_V2) { if (!!process.env.MEDUSA_FF_MEDUSA_V2) {
await service.createDefaultCountriesAndCurrencies() await service.createDefaultCountries()
} }
} }
@@ -1,64 +1,7 @@
{ {
"namespaces": [ "namespaces": ["public"],
"public"
],
"name": "public", "name": "public",
"tables": [ "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": "region_currency",
"schema": "public",
"indexes": [
{
"keyName": "region_currency_pkey",
"columnNames": [
"code"
],
"composite": false,
"primary": true,
"unique": true
}
],
"checks": [],
"foreignKeys": {}
},
{ {
"columns": { "columns": {
"id": { "id": {
@@ -134,18 +77,7 @@
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"columnNames": [ "columnNames": ["deleted_at"],
"currency_code"
],
"composite": false,
"keyName": "IDX_region_currency_code",
"primary": false,
"unique": false
},
{
"columnNames": [
"deleted_at"
],
"composite": false, "composite": false,
"keyName": "IDX_region_deleted_at", "keyName": "IDX_region_deleted_at",
"primary": false, "primary": false,
@@ -153,30 +85,14 @@
}, },
{ {
"keyName": "region_pkey", "keyName": "region_pkey",
"columnNames": [ "columnNames": ["id"],
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
} }
], ],
"checks": [], "checks": [],
"foreignKeys": { "foreignKeys": {}
"region_currency_code_foreign": {
"constraintName": "region_currency_code_foreign",
"columnNames": [
"currency_code"
],
"localTableName": "public.region",
"referencedColumnNames": [
"code"
],
"referencedTableName": "public.region_currency",
"deleteRule": "set null",
"updateRule": "cascade"
}
}
}, },
{ {
"columns": { "columns": {
@@ -249,9 +165,7 @@
"indexes": [ "indexes": [
{ {
"keyName": "region_country_pkey", "keyName": "region_country_pkey",
"columnNames": [ "columnNames": ["id"],
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -261,13 +175,9 @@
"foreignKeys": { "foreignKeys": {
"region_country_region_id_foreign": { "region_country_region_id_foreign": {
"constraintName": "region_country_region_id_foreign", "constraintName": "region_country_region_id_foreign",
"columnNames": [ "columnNames": ["region_id"],
"region_id"
],
"localTableName": "public.region_country", "localTableName": "public.region_country",
"referencedColumnNames": [ "referencedColumnNames": ["id"],
"id"
],
"referencedTableName": "public.region", "referencedTableName": "public.region",
"deleteRule": "set null", "deleteRule": "set null",
"updateRule": "cascade" "updateRule": "cascade"
@@ -16,15 +16,6 @@ CREATE TABLE IF NOT EXISTS "region" (
CONSTRAINT "region_pkey" PRIMARY KEY ("id") CONSTRAINT "region_pkey" PRIMARY KEY ("id")
); );
-- Create or update "region_currency" table
CREATE TABLE IF NOT EXISTS "region_currency" (
"code" text NOT NULL,
"symbol" text NOT NULL,
"symbol_native" text NOT NULL,
"name" text NOT NULL,
CONSTRAINT "region_currency_pkey" PRIMARY KEY ("code")
);
-- Adjust "region" table -- Adjust "region" table
ALTER TABLE "region" DROP CONSTRAINT IF EXISTS "FK_3bdd5896ec93be2f1c62a3309a5"; ALTER TABLE "region" DROP CONSTRAINT IF EXISTS "FK_3bdd5896ec93be2f1c62a3309a5";
ALTER TABLE "region" DROP CONSTRAINT IF EXISTS "FK_91f88052197680f9790272aaf5b"; ALTER TABLE "region" DROP CONSTRAINT IF EXISTS "FK_91f88052197680f9790272aaf5b";
@@ -35,9 +26,6 @@ ${generatePostgresAlterColummnIfExistStatement(
"DROP NOT NULL" "DROP NOT NULL"
)} )}
ALTER TABLE "region" ADD CONSTRAINT "region_currency_code_foreign" FOREIGN KEY ("currency_code") REFERENCES "region_currency" ("code") ON UPDATE CASCADE;
CREATE INDEX IF NOT EXISTS "IDX_region_currency_code" ON "region" ("currency_code");
CREATE INDEX IF NOT EXISTS "IDX_region_deleted_at" ON "region" ("deleted_at") WHERE "deleted_at" IS NOT NULL; CREATE INDEX IF NOT EXISTS "IDX_region_deleted_at" ON "region" ("deleted_at") WHERE "deleted_at" IS NOT NULL;
-- Create or update "region_country" table -- Create or update "region_country" table
-16
View File
@@ -1,16 +0,0 @@
import { Entity, PrimaryKey, Property } from "@mikro-orm/core"
@Entity({ tableName: "region_currency" })
export default class Currency {
@PrimaryKey({ columnType: "text" })
code: string
@Property({ columnType: "text" })
symbol: string
@Property({ columnType: "text" })
symbol_native: string
@Property({ columnType: "text" })
name: string
}
-2
View File
@@ -1,4 +1,2 @@
export { default as Country } from "./country" export { default as Country } from "./country"
export { default as Currency } from "./currency"
export { default as Region } from "./region" export { default as Region } from "./region"
+1 -12
View File
@@ -14,12 +14,8 @@ import {
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import Country from "./country" import Country from "./country"
import Currency from "./currency"
type RegionOptionalProps = type RegionOptionalProps = "countries" | DAL.SoftDeletableEntityDateColumns
| "currency"
| "countries"
| DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "region" }) @Entity({ tableName: "region" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
@@ -35,13 +31,6 @@ export default class Region {
@Property({ columnType: "text" }) @Property({ columnType: "text" })
currency_code: string currency_code: string
@ManyToOne({
entity: () => Currency,
index: "IDX_region_currency_code",
nullable: true,
})
currency?: Currency
@OneToMany(() => Country, (country) => country.region) @OneToMany(() => Country, (country) => country.region)
countries = new Collection<Country>(this) countries = new Collection<Country>(this)
+9 -95
View File
@@ -8,7 +8,6 @@ import {
ModuleJoinerConfig, ModuleJoinerConfig,
ModulesSdkTypes, ModulesSdkTypes,
RegionCountryDTO, RegionCountryDTO,
RegionCurrencyDTO,
RegionDTO, RegionDTO,
UpdateRegionDTO, UpdateRegionDTO,
UpsertRegionDTO, UpsertRegionDTO,
@@ -27,9 +26,9 @@ import {
getDuplicates, getDuplicates,
} from "@medusajs/utils" } from "@medusajs/utils"
import { Country, Currency, Region } from "@models" import { Country, Region } from "@models"
import { CreateCountryDTO, CreateCurrencyDTO, UpdateRegionInput } from "@types" import { CreateCountryDTO, UpdateRegionInput } from "@types"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config" import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
const COUNTRIES_LIMIT = 1000 const COUNTRIES_LIMIT = 1000
@@ -38,15 +37,13 @@ type InjectedDependencies = {
baseRepository: DAL.RepositoryService baseRepository: DAL.RepositoryService
regionService: ModulesSdkTypes.InternalModuleService<any> regionService: ModulesSdkTypes.InternalModuleService<any>
countryService: ModulesSdkTypes.InternalModuleService<any> countryService: ModulesSdkTypes.InternalModuleService<any>
currencyService: ModulesSdkTypes.InternalModuleService<any>
} }
const generateMethodForModels = [Country, Currency] const generateMethodForModels = [Country]
export default class RegionModuleService< export default class RegionModuleService<
TRegion extends Region = Region, TRegion extends Region = Region,
TCountry extends Country = Country, TCountry extends Country = Country
TCurrency extends Currency = Currency
> >
extends ModulesSdkUtils.abstractModuleServiceFactory< extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies, InjectedDependencies,
@@ -55,9 +52,6 @@ export default class RegionModuleService<
Country: { Country: {
dto: RegionCountryDTO dto: RegionCountryDTO
} }
Currency: {
dto: RegionCurrencyDTO
}
} }
>(Region, generateMethodForModels, entityNameToLinkableKeysMap) >(Region, generateMethodForModels, entityNameToLinkableKeysMap)
implements IRegionModuleService implements IRegionModuleService
@@ -65,15 +59,9 @@ export default class RegionModuleService<
protected baseRepository_: DAL.RepositoryService protected baseRepository_: DAL.RepositoryService
protected readonly regionService_: ModulesSdkTypes.InternalModuleService<TRegion> protected readonly regionService_: ModulesSdkTypes.InternalModuleService<TRegion>
protected readonly countryService_: ModulesSdkTypes.InternalModuleService<TCountry> protected readonly countryService_: ModulesSdkTypes.InternalModuleService<TCountry>
protected readonly currencyService_: ModulesSdkTypes.InternalModuleService<TCurrency>
constructor( constructor(
{ { baseRepository, regionService, countryService }: InjectedDependencies,
baseRepository,
regionService,
countryService,
currencyService,
}: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration protected readonly moduleDeclaration: InternalModuleDeclaration
) { ) {
// @ts-ignore // @ts-ignore
@@ -81,7 +69,6 @@ export default class RegionModuleService<
this.baseRepository_ = baseRepository this.baseRepository_ = baseRepository
this.regionService_ = regionService this.regionService_ = regionService
this.countryService_ = countryService this.countryService_ = countryService
this.currencyService_ = currencyService
} }
__joinerConfig(): ModuleJoinerConfig { __joinerConfig(): ModuleJoinerConfig {
@@ -118,10 +105,6 @@ export default class RegionModuleService<
let normalizedInput = RegionModuleService.normalizeInput(data) let normalizedInput = RegionModuleService.normalizeInput(data)
const validations = [ const validations = [
this.validateCurrencies(
normalizedInput.map((r) => r.currency_code),
sharedContext
),
this.validateCountries( this.validateCountries(
normalizedInput.map((r) => r.countries ?? []).flat(), normalizedInput.map((r) => r.countries ?? []).flat(),
sharedContext sharedContext
@@ -129,7 +112,7 @@ export default class RegionModuleService<
] as const ] as const
// Assign the full country object so the ORM updates the relationship // Assign the full country object so the ORM updates the relationship
const [, dbCountries] = await promiseAll(validations) const [dbCountries] = await promiseAll(validations)
const dbCountriesMap = new Map(dbCountries.map((d) => [d.iso_2, d])) const dbCountriesMap = new Map(dbCountries.map((d) => [d.iso_2, d]))
let normalizedDbRegions = normalizedInput.map((region) => let normalizedDbRegions = normalizedInput.map((region) =>
removeUndefined({ removeUndefined({
@@ -246,10 +229,6 @@ export default class RegionModuleService<
} }
const validations = [ const validations = [
this.validateCurrencies(
normalizedInput.map((d) => d.currency_code),
sharedContext
),
this.validateCountries( this.validateCountries(
normalizedInput.map((d) => d.countries ?? []).flat(), normalizedInput.map((d) => d.countries ?? []).flat(),
sharedContext sharedContext
@@ -257,7 +236,7 @@ export default class RegionModuleService<
] as const ] as const
// Assign the full country object so the ORM updates the relationship // Assign the full country object so the ORM updates the relationship
const [, dbCountries] = await promiseAll(validations) const [dbCountries] = await promiseAll(validations)
const dbCountriesMap = new Map(dbCountries.map((d) => [d.iso_2, d])) const dbCountriesMap = new Map(dbCountries.map((d) => [d.iso_2, d]))
let normalizedDbRegions = normalizedInput.map((region) => let normalizedDbRegions = normalizedInput.map((region) =>
removeUndefined({ removeUndefined({
@@ -280,41 +259,6 @@ export default class RegionModuleService<
) )
} }
private async validateCurrencies(
currencyCodes: (string | undefined)[] | undefined,
sharedContext: Context
): Promise<void> {
const normalizedCurrencyCodes = currencyCodes
?.filter((c) => c !== undefined)
.map((c) => c!.toLowerCase())
if (!normalizedCurrencyCodes?.length) {
return
}
const uniqueCurrencyCodes = Array.from(new Set(normalizedCurrencyCodes))
const dbCurrencies = await this.currencyService_.list(
{ code: uniqueCurrencyCodes },
{},
sharedContext
)
const dbCurrencyCodes = dbCurrencies.map((c) => c.code.toLowerCase())
if (uniqueCurrencyCodes.length !== dbCurrencyCodes.length) {
const missingCurrencies = arrayDifference(
uniqueCurrencyCodes,
dbCurrencyCodes
)
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Currencies with codes: "${missingCurrencies.join(
", "
)}" were not found`
)
}
}
private async validateCountries( private async validateCountries(
countries: string[] | undefined, countries: string[] | undefined,
sharedContext: Context sharedContext: Context
@@ -369,13 +313,10 @@ export default class RegionModuleService<
} }
@InjectManager("baseRepository_") @InjectManager("baseRepository_")
public async createDefaultCountriesAndCurrencies( public async createDefaultCountries(
@MedusaContext() sharedContext: Context = {} @MedusaContext() sharedContext: Context = {}
): Promise<void> { ): Promise<void> {
await promiseAll([ await this.maybeCreateCountries(sharedContext)
await this.maybeCreateCountries(sharedContext),
await this.maybeCreateCurrencies(sharedContext),
])
} }
@InjectTransactionManager("baseRepository_") @InjectTransactionManager("baseRepository_")
@@ -409,31 +350,4 @@ export default class RegionModuleService<
await this.countryService_.create(countsToCreate, sharedContext) await this.countryService_.create(countsToCreate, sharedContext)
} }
} }
@InjectTransactionManager("baseRepository_")
private async maybeCreateCurrencies(
@MedusaContext() sharedContext: Context
): Promise<void> {
const [currency] = await this.currencyService_.list(
{},
{ select: ["code"], take: 1 },
sharedContext
)
let currsToCreate: CreateCurrencyDTO[] = []
if (!currency) {
currsToCreate = Object.entries(DefaultsUtils.defaultCurrencies).map(
([code, currency]) => ({
code: code.toLowerCase(),
symbol: currency.symbol,
symbol_native: currency.symbol_native,
name: currency.name,
})
)
}
if (currsToCreate.length) {
await this.currencyService_.create(currsToCreate, sharedContext)
}
}
} }
-7
View File
@@ -10,13 +10,6 @@ export type UpdateCountryRegion = {
region_id: string region_id: string
} }
export type CreateCurrencyDTO = {
code: string
symbol: string
name: string
symbol_native: string
}
export type CreateCountryDTO = { export type CreateCountryDTO = {
iso_2: string iso_2: string
iso_3: string iso_3: string
+1
View File
@@ -24,3 +24,4 @@ export * as UserTypes from "./user"
export * as WorkflowTypes from "./workflow" export * as WorkflowTypes from "./workflow"
export * as ApiKeyTypes from "./api-key" export * as ApiKeyTypes from "./api-key"
export * as StoreTypes from "./store" export * as StoreTypes from "./store"
export * as CurrencyTypes from "./currency"
@@ -0,0 +1,38 @@
import { BaseFilterable } from "../../dal"
/**
* @interface
*
* A currency's data.
*/
export interface CurrencyDTO {
/**
* The ISO 3 code of the currency.
*/
code: string
/**
* The symbol of the currency.
*/
symbol: string
/**
* The symbol of the currecy in its native form. This is typically the symbol used when displaying a price.
*/
symbol_native: string
/**
* The name of the currency.
*/
name: string
}
/**
* @interface
*
* Filters to apply on a currency.
*/
export interface FilterableCurrencyProps
extends BaseFilterable<FilterableCurrencyProps> {
/**
* The codes to filter the currencies by.
*/
code?: string[]
}
@@ -0,0 +1 @@
export * from "./currency"
+2
View File
@@ -0,0 +1,2 @@
export * from "./common"
export * from "./service"
+238
View File
@@ -0,0 +1,238 @@
import { FindConfig } from "../common"
import { RestoreReturn, SoftDeleteReturn } from "../dal"
import { IModuleService } from "../modules-sdk"
import { Context } from "../shared-context"
import { FilterableCurrencyProps, CurrencyDTO } from "./common"
/**
* The main service interface for the currency module.
*/
export interface ICurrencyModuleService extends IModuleService {
/**
* This method retrieves a currency by its code and and optionally based on the provided configurations.
*
* @param {string} code - The code of the currency to retrieve.
* @param {FindConfig<CurrencyDTO>} config -
* The configurations determining how the currency is retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a currency.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<CurrencyDTO>} The retrieved currency.
*
* @example
* A simple example that retrieves a currency by its code:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrency (code: string) {
* const currencyModule = await initializeCurrencyModule()
*
* const currency = await currencyModule.retrieve(
* code
* )
*
* // do something with the currency or return it
* }
* ```
*
* To specify attributes that should be retrieved:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrency (code: string) {
* const currencyModule = await initializeCurrencyModule()
*
* const currency = await currencyModule.retrieve(
* code,
* {
* select: ["symbol_native"]
* }
* )
*
* // do something with the currency or return it
* }
* ```
*/
retrieve(
code: string,
config?: FindConfig<CurrencyDTO>,
sharedContext?: Context
): Promise<CurrencyDTO>
/**
* This method is used to retrieve a paginated list of currencies based on optional filters and configuration.
*
* @param {FilterableCurrencyProps} filters - The filters to apply on the retrieved currencies.
* @param {FindConfig<CurrencyDTO>} config -
* The configurations determining how the currencies are retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a currency.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<CurrencyDTO[]>} The list of currencies.
*
* @example
*
* To retrieve a list of currencies using their codes:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrencies (codes: string[]) {
* const currencyModule = await initializeCurrencyModule()
*
* const currencies = await currencyModule.list(
* {
* code: codes
* },
* )
*
* // do something with the currencies or return them
* }
* ```
*
* To specify attributes that should be retrieved within the money amounts:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrencies (codes: string[]) {
* const currencyModule = await initializeCurrencyModule()
*
* const currencies = await currencyModule.list(
* {
* code: codes
* },
* {
* select: ["symbol_native"]
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*
* By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrencies (codes: string[], skip: number, take: number) {
* const currencyModule = await initializeCurrencyModule()
*
* const currencies = await currencyModule.list(
* {
* code: codes
* },
* {
* select: ["symbol_native"],
* skip,
* take
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*/
list(
filters?: FilterableCurrencyProps,
config?: FindConfig<CurrencyDTO>,
sharedContext?: Context
): Promise<CurrencyDTO[]>
/**
* This method is used to retrieve a paginated list of currencies along with the total count of available currencies satisfying the provided filters.
*
* @param {FilterableCurrencyProps} filters - The filters to apply on the retrieved currencies.
* @param {FindConfig<CurrencyDTO>} config -
* The configurations determining how the currencies are retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a currency.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<[CurrencyDTO[], number]>} The list of currencies along with the total count.
*
* @example
*
* To retrieve a list of currencies using their codes:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrencies (codes: string[]) {
* const currencyModule = await initializeCurrencyModule()
*
* const [currencies, count] = await currencyModule.listAndCount(
* {
* code: codes
* },
* )
*
* // do something with the currencies or return them
* }
* ```
*
* To specify attributes that should be retrieved within the money amounts:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrencies (codes: string[]) {
* const currencyModule = await initializeCurrencyModule()
*
* const [currencies, count] = await currencyModule.listAndCount(
* {
* code: codes
* },
* {
* select: ["symbol_native"]
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*
* By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter:
*
* ```ts
* import {
* initialize as initializeCurrencyModule,
* } from "@medusajs/currency"
*
* async function retrieveCurrencies (codes: string[], skip: number, take: number) {
* const currencyModule = await initializeCurrencyModule()
*
* const [currencies, count] = await currencyModule.listAndCount(
* {
* code: codes
* },
* {
* select: ["symbol_native"],
* skip,
* take
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*/
listAndCount(
filters?: FilterableCurrencyProps,
config?: FindConfig<CurrencyDTO>,
sharedContext?: Context
): Promise<[CurrencyDTO[], number]>
}
+1
View File
@@ -34,3 +34,4 @@ export * from "./totals"
export * from "./transaction-base" export * from "./transaction-base"
export * from "./user" export * from "./user"
export * from "./workflow" export * from "./workflow"
export * from "./currency"
@@ -1,86 +0,0 @@
import { BaseFilterable } from "../../dal"
/**
* @interface
*
* A currency's data.
*/
export interface CurrencyDTO {
/**
* The code of the currency.
*/
code: string
/**
* The symbol of the currency.
*/
symbol?: string
/**
* The symbol of the currecy in its native form. This is typically the symbol used when displaying a price.
*/
symbol_native?: string
/**
* The name of the currency.
*/
name?: string
}
/**
* @interface
*
* A currency to create.
*/
export interface CreateCurrencyDTO {
/**
* The code of the currency.
*/
code: string
/**
* The symbol of the currency.
*/
symbol: string
/**
* The symbol of the currecy in its native form. This is typically the symbol used when displaying a price.
*/
symbol_native: string
/**
* The name of the currency.
*/
name: string
}
/**
* @interface
*
* The data to update in a currency. The `code` is used to identify which currency to update.
*/
export interface UpdateCurrencyDTO {
/**
* The code of the currency to update.
*/
code: string
/**
* The symbol of the currency.
*/
symbol?: string
/**
* The symbol of the currecy in its native form. This is typically the symbol used when displaying a price.
*/
symbol_native?: string
/**
* The name of the currency.
*/
name?: string
}
/**
* @interface
*
* Filters to apply on a currency.
*/
export interface FilterableCurrencyProps
extends BaseFilterable<FilterableCurrencyProps> {
/**
* The codes to filter the currencies by.
*/
code?: string[]
}
@@ -1,4 +1,3 @@
export * from "./currency"
export * from "./money-amount" export * from "./money-amount"
export * from "./price-rule" export * from "./price-rule"
export * from "./price-set" export * from "./price-set"
@@ -1,6 +1,5 @@
import { BaseFilterable } from "../../dal"; import { BaseFilterable } from "../../dal"
import { CreateCurrencyDTO, CurrencyDTO } from "./currency"; import { PriceSetMoneyAmountDTO } from "./price-set-money-amount"
import { PriceSetMoneyAmountDTO } from "./price-set-money-amount";
/** /**
* @interface * @interface
@@ -16,12 +15,6 @@ export interface MoneyAmountDTO {
* The currency code of this money amount. * The currency code of this money amount.
*/ */
currency_code?: string currency_code?: string
/**
* The money amount's currency.
*
* @expandable
*/
currency?: CurrencyDTO
/** /**
* The price of this money amount. * The price of this money amount.
*/ */
@@ -66,10 +59,6 @@ export interface CreateMoneyAmountDTO {
* The currency code of this money amount. * The currency code of this money amount.
*/ */
currency_code: string currency_code: string
/**
* The currency of this money amount.
*/
currency?: CreateCurrencyDTO
/** /**
* The amount of this money amount. * The amount of this money amount.
*/ */
@@ -1,6 +1,5 @@
import { BaseFilterable } from "../../dal" import { BaseFilterable } from "../../dal"
import { PriceSetDTO } from "./price-set" import { PriceSetDTO } from "./price-set"
import { PriceSetMoneyAmountDTO } from "./price-set-money-amount"
import { RuleTypeDTO } from "./rule-type" import { RuleTypeDTO } from "./rule-type"
export interface PriceSetRuleTypeDTO { export interface PriceSetRuleTypeDTO {
+7 -325
View File
@@ -3,7 +3,6 @@ import {
AddPricesDTO, AddPricesDTO,
AddRulesDTO, AddRulesDTO,
CalculatedPriceSet, CalculatedPriceSet,
CreateCurrencyDTO,
CreateMoneyAmountDTO, CreateMoneyAmountDTO,
CreatePriceListDTO, CreatePriceListDTO,
CreatePriceListRuleDTO, CreatePriceListRuleDTO,
@@ -11,8 +10,6 @@ import {
CreatePriceSetDTO, CreatePriceSetDTO,
CreatePriceSetMoneyAmountRulesDTO, CreatePriceSetMoneyAmountRulesDTO,
CreateRuleTypeDTO, CreateRuleTypeDTO,
CurrencyDTO,
FilterableCurrencyProps,
FilterableMoneyAmountProps, FilterableMoneyAmountProps,
FilterablePriceListProps, FilterablePriceListProps,
FilterablePriceListRuleProps, FilterablePriceListRuleProps,
@@ -34,7 +31,6 @@ import {
RemovePriceSetRulesDTO, RemovePriceSetRulesDTO,
RuleTypeDTO, RuleTypeDTO,
SetPriceListRulesDTO, SetPriceListRulesDTO,
UpdateCurrencyDTO,
UpdateMoneyAmountDTO, UpdateMoneyAmountDTO,
UpdatePriceListDTO, UpdatePriceListDTO,
UpdatePriceListRuleDTO, UpdatePriceListRuleDTO,
@@ -935,7 +931,7 @@ export interface IPricingModuleService extends IModuleService {
* const moneyAmount = await pricingService.retrieveMoneyAmount( * const moneyAmount = await pricingService.retrieveMoneyAmount(
* moneyAmountId, * moneyAmountId,
* { * {
* relations: ["currency"] * relations: ["price_set_money_amount"]
* } * }
* ) * )
* *
@@ -996,7 +992,7 @@ export interface IPricingModuleService extends IModuleService {
* id: moneyAmountIds * id: moneyAmountIds
* }, * },
* { * {
* relations: ["currency"] * relations: ["price_set_money_amount"]
* } * }
* ) * )
* *
@@ -1019,7 +1015,7 @@ export interface IPricingModuleService extends IModuleService {
* id: moneyAmountIds * id: moneyAmountIds
* }, * },
* { * {
* relations: ["currency"], * relations: ["price_set_money_amount"],
* skip, * skip,
* take * take
* } * }
@@ -1051,7 +1047,7 @@ export interface IPricingModuleService extends IModuleService {
* ] * ]
* }, * },
* { * {
* relations: ["currency"], * relations: ["price_set_money_amount"],
* skip, * skip,
* take * take
* } * }
@@ -1114,7 +1110,7 @@ export interface IPricingModuleService extends IModuleService {
* id: moneyAmountIds * id: moneyAmountIds
* }, * },
* { * {
* relations: ["currency"] * relations: ["price_set_money_amount"]
* } * }
* ) * )
* *
@@ -1137,7 +1133,7 @@ export interface IPricingModuleService extends IModuleService {
* id: moneyAmountIds * id: moneyAmountIds
* }, * },
* { * {
* relations: ["currency"], * relations: ["price_set_money_amount"],
* skip, * skip,
* take * take
* } * }
@@ -1169,7 +1165,7 @@ export interface IPricingModuleService extends IModuleService {
* ] * ]
* }, * },
* { * {
* relations: ["currency"], * relations: ["price_set_money_amount"],
* skip, * skip,
* take * take
* } * }
@@ -1333,320 +1329,6 @@ export interface IPricingModuleService extends IModuleService {
sharedContext?: Context sharedContext?: Context
): Promise<Record<string, string[]> | void> ): Promise<Record<string, string[]> | void>
/**
* This method retrieves a currency by its code and and optionally based on the provided configurations.
*
* @param {string} code - The code of the currency to retrieve.
* @param {FindConfig<CurrencyDTO>} config -
* The configurations determining how the currency is retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a currency.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<CurrencyDTO>} The retrieved currency.
*
* @example
* A simple example that retrieves a currency by its code:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrency (code: string) {
* const pricingService = await initializePricingModule()
*
* const currency = await pricingService.retrieveCurrency(
* code
* )
*
* // do something with the currency or return it
* }
* ```
*
* To specify attributes that should be retrieved:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrency (code: string) {
* const pricingService = await initializePricingModule()
*
* const currency = await pricingService.retrieveCurrency(
* code,
* {
* select: ["symbol_native"]
* }
* )
*
* // do something with the currency or return it
* }
* ```
*/
retrieveCurrency(
code: string,
config?: FindConfig<CurrencyDTO>,
sharedContext?: Context
): Promise<CurrencyDTO>
/**
* This method is used to retrieve a paginated list of currencies based on optional filters and configuration.
*
* @param {FilterableCurrencyProps} filters - The filters to apply on the retrieved currencies.
* @param {FindConfig<CurrencyDTO>} config -
* The configurations determining how the currencies are retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a currency.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<CurrencyDTO[]>} The list of currencies.
*
* @example
*
* To retrieve a list of currencies using their codes:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrencies (codes: string[]) {
* const pricingService = await initializePricingModule()
*
* const currencies = await pricingService.listCurrencies(
* {
* code: codes
* },
* )
*
* // do something with the currencies or return them
* }
* ```
*
* To specify attributes that should be retrieved within the money amounts:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrencies (codes: string[]) {
* const pricingService = await initializePricingModule()
*
* const currencies = await pricingService.listCurrencies(
* {
* code: codes
* },
* {
* select: ["symbol_native"]
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*
* By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrencies (codes: string[], skip: number, take: number) {
* const pricingService = await initializePricingModule()
*
* const currencies = await pricingService.listCurrencies(
* {
* code: codes
* },
* {
* select: ["symbol_native"],
* skip,
* take
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*/
listCurrencies(
filters?: FilterableCurrencyProps,
config?: FindConfig<CurrencyDTO>,
sharedContext?: Context
): Promise<CurrencyDTO[]>
/**
* This method is used to retrieve a paginated list of currencies along with the total count of available currencies satisfying the provided filters.
*
* @param {FilterableCurrencyProps} filters - The filters to apply on the retrieved currencies.
* @param {FindConfig<CurrencyDTO>} config -
* The configurations determining how the currencies are retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a currency.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<[CurrencyDTO[], number]>} The list of currencies along with the total count.
*
* @example
*
* To retrieve a list of currencies using their codes:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrencies (codes: string[]) {
* const pricingService = await initializePricingModule()
*
* const [currencies, count] = await pricingService.listAndCountCurrencies(
* {
* code: codes
* },
* )
*
* // do something with the currencies or return them
* }
* ```
*
* To specify attributes that should be retrieved within the money amounts:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrencies (codes: string[]) {
* const pricingService = await initializePricingModule()
*
* const [currencies, count] = await pricingService.listAndCountCurrencies(
* {
* code: codes
* },
* {
* select: ["symbol_native"]
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*
* By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter:
*
* ```ts
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function retrieveCurrencies (codes: string[], skip: number, take: number) {
* const pricingService = await initializePricingModule()
*
* const [currencies, count] = await pricingService.listAndCountCurrencies(
* {
* code: codes
* },
* {
* select: ["symbol_native"],
* skip,
* take
* }
* )
*
* // do something with the currencies or return them
* }
* ```
*/
listAndCountCurrencies(
filters?: FilterableCurrencyProps,
config?: FindConfig<CurrencyDTO>,
sharedContext?: Context
): Promise<[CurrencyDTO[], number]>
/**
* This method is used to create new currencies.
*
* @param {CreateCurrencyDTO[]} data - The currencies to create.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<CurrencyDTO[]>} The list of created currencies.
*
* @example
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function createCurrencies () {
* const pricingService = await initializePricingModule()
*
* const currencies = await pricingService.createCurrencies([
* {
* code: "USD",
* symbol: "$",
* symbol_native: "$",
* name: "US Dollar",
* }
* ])
*
* // do something with the currencies or return them
* }
*/
createCurrencies(
data: CreateCurrencyDTO[],
sharedContext?: Context
): Promise<CurrencyDTO[]>
/**
* This method is used to update existing currencies with the provided data. In each currency object, the currency code must be provided to identify which currency to update.
*
* @param {UpdateCurrencyDTO[]} data - The currencies to update, each having the attributes that should be updated in a currency.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<CurrencyDTO[]>} The list of updated currencies.
*
* @example
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function updateCurrencies () {
* const pricingService = await initializePricingModule()
*
* const currencies = await pricingService.updateCurrencies([
* {
* code: "USD",
* symbol: "$",
* }
* ])
*
* // do something with the currencies or return them
* }
*/
updateCurrencies(
data: UpdateCurrencyDTO[],
sharedContext?: Context
): Promise<CurrencyDTO[]>
/**
* This method is used to delete currencies based on their currency code.
*
* @param {string[]} currencyCodes - Currency codes of the currencies to delete.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<void>} Resolves once the currencies are deleted.
*
* @example
* import {
* initialize as initializePricingModule,
* } from "@medusajs/pricing"
*
* async function deleteCurrencies () {
* const pricingService = await initializePricingModule()
*
* await pricingService.deleteCurrencies(["USD"])
*
* }
*/
deleteCurrencies(
currencyCodes: string[],
sharedContext?: Context
): Promise<void>
/** /**
* This method is used to retrieve a rule type by its ID and and optionally based on the provided configurations. * This method is used to retrieve a rule type by its ID and and optionally based on the provided configurations.
* *
+2 -98
View File
@@ -19,15 +19,10 @@ export interface RegionDTO {
*/ */
currency_code: string currency_code: string
/**
* The associated region currency.
*/
currency: RegionCurrencyDTO
/** /**
* The countries of the region. * The countries of the region.
*/ */
countries: CountryDTO[] countries: RegionCountryDTO[]
metadata?: Record<string, any> metadata?: Record<string, any>
created_at: string created_at: string
updated_at: string updated_at: string
@@ -36,7 +31,7 @@ export interface RegionDTO {
/** /**
* The country details. * The country details.
*/ */
export interface CountryDTO { export interface RegionCountryDTO {
/** /**
* The ID of the country. * The ID of the country.
*/ */
@@ -99,97 +94,6 @@ export interface FilterableRegionProps
updated_at?: OperatorMap<string> updated_at?: OperatorMap<string>
} }
/**
* The details of a region's country.
*/
export interface RegionCountryDTO {
/**
* The ID of the country.
*/
id: string
/**
* The ISO 2 code of the country.
*/
iso_2: string
/**
* The ISO 3 code of the country.
*/
iso_3: string
/**
* The code number of the country.
*/
num_code: number
/**
* The name of the country.
*/
name: string
/**
* The display name of the country.
*/
display_name: string
}
/**
* The details of a region's currency
*/
export interface RegionCurrencyDTO {
/**
* The code of the currency.
*/
code: string
/**
* The symbol of the currency.
*/
symbol: string
/**
* The name of the currency.
*/
name: string
/**
* The symbol native of the currency.
*/
symbol_native: string
}
/**
* The filters to apply on the retrieved region's currencies.
*/
export interface FilterableRegionCurrencyProps
extends BaseFilterable<FilterableRegionCurrencyProps> {
/**
* The IDs to filter the currencies by.
*/
id?: string[] | string
/**
* Filter currencies by their code.
*/
code?: string[] | string
/**
* Filter currencies by their symbol.
*/
symbol?: string[] | string
/**
* Filter currencies by their name.
*/
name?: string[] | string
/**
* Filter currencies by their native symbol.
*/
symbol_native?: string[] | string
}
/** /**
* The filters to apply on the retrieved region's countries. * The filters to apply on the retrieved region's countries.
*/ */
-2
View File
@@ -1,5 +1,3 @@
import { RegionCurrencyDTO } from "./common"
/** /**
* The region to be created. * The region to be created.
*/ */
Loaded 100 of 102 files, more files were not shown because too many files have changed in this diff. Show more