Add support for tax inclusivity to region and store (#7808)
This also includes rework of the currency model for the Store module. This change is breaking as existing stores won't have any supported currencies set, so users would need to go to the store settings again and choose the supported currencies there.
This commit is contained in:
1 parent
79d90fadc4
commit
e8d6025374
45 files changed
+580
-408
No files matched your search
@@ -8,4 +8,4 @@ export * from "./order-customer"
|
||||
export * from "./order-product"
|
||||
export * from "./order-region"
|
||||
export * from "./order-sales-channel"
|
||||
export * from "./store-default-currency"
|
||||
export * from "./store-currency"
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { Modules } from "@medusajs/utils"
|
||||
|
||||
export const StoreDefaultCurrency: ModuleJoinerConfig = {
|
||||
export const StoreCurrencies: ModuleJoinerConfig = {
|
||||
isLink: true,
|
||||
isReadOnlyLink: true,
|
||||
extends: [
|
||||
@@ -10,8 +10,8 @@ export const StoreDefaultCurrency: ModuleJoinerConfig = {
|
||||
relationship: {
|
||||
serviceName: Modules.CURRENCY,
|
||||
primaryKey: "code",
|
||||
foreignKey: "default_currency_code",
|
||||
alias: "default_currency",
|
||||
foreignKey: "supported_currencies.currency_code",
|
||||
alias: "currency",
|
||||
args: {
|
||||
methodSuffix: "Currencies",
|
||||
},
|
||||
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"namespaces": [
|
||||
"public"
|
||||
],
|
||||
"namespaces": ["public"],
|
||||
"name": "public",
|
||||
"tables": [
|
||||
{
|
||||
@@ -33,6 +31,16 @@
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"automatic_taxes": {
|
||||
"name": "automatic_taxes",
|
||||
"type": "boolean",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"default": "true",
|
||||
"mappedType": "boolean"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "metadata",
|
||||
"type": "jsonb",
|
||||
@@ -79,9 +87,7 @@
|
||||
"schema": "public",
|
||||
"indexes": [
|
||||
{
|
||||
"columnNames": [
|
||||
"deleted_at"
|
||||
],
|
||||
"columnNames": ["deleted_at"],
|
||||
"composite": false,
|
||||
"keyName": "IDX_region_deleted_at",
|
||||
"primary": false,
|
||||
@@ -89,9 +95,7 @@
|
||||
},
|
||||
{
|
||||
"keyName": "region_pkey",
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"columnNames": ["id"],
|
||||
"composite": false,
|
||||
"primary": true,
|
||||
"unique": true
|
||||
@@ -102,15 +106,6 @@
|
||||
},
|
||||
{
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"iso_2": {
|
||||
"name": "iso_2",
|
||||
"type": "text",
|
||||
@@ -171,9 +166,7 @@
|
||||
"indexes": [
|
||||
{
|
||||
"keyName": "region_country_pkey",
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"columnNames": ["iso_2"],
|
||||
"composite": false,
|
||||
"primary": true,
|
||||
"unique": true
|
||||
@@ -183,13 +176,9 @@
|
||||
"foreignKeys": {
|
||||
"region_country_region_id_foreign": {
|
||||
"constraintName": "region_country_region_id_foreign",
|
||||
"columnNames": [
|
||||
"region_id"
|
||||
],
|
||||
"columnNames": ["region_id"],
|
||||
"localTableName": "public.region_country",
|
||||
"referencedColumnNames": [
|
||||
"id"
|
||||
],
|
||||
"referencedColumnNames": ["id"],
|
||||
"referencedTableName": "public.region",
|
||||
"deleteRule": "set null",
|
||||
"updateRule": "cascade"
|
||||
|
||||
File renamed without changes.
@@ -2,7 +2,10 @@ import { StoreTypes } from "@medusajs/types"
|
||||
|
||||
export const createStoreFixture: StoreTypes.CreateStoreDTO = {
|
||||
name: "Test store",
|
||||
supported_currency_codes: ["usd", "eur"],
|
||||
supported_currencies: [
|
||||
{ currency_code: "usd" },
|
||||
{ currency_code: "eur", is_default: true },
|
||||
],
|
||||
default_sales_channel_id: "test-sales-channel",
|
||||
default_region_id: "test-region",
|
||||
metadata: {
|
||||
|
||||
@@ -16,7 +16,10 @@ moduleIntegrationTestRunner<IStoreModuleService>({
|
||||
expect(store).toEqual(
|
||||
expect.objectContaining({
|
||||
name: "Test store",
|
||||
supported_currency_codes: expect.arrayContaining(["eur", "usd"]),
|
||||
supported_currencies: expect.arrayContaining([
|
||||
expect.objectContaining({ currency_code: "eur" }),
|
||||
expect.objectContaining({ currency_code: "usd" }),
|
||||
]),
|
||||
default_sales_channel_id: "test-sales-channel",
|
||||
default_region_id: "test-region",
|
||||
metadata: {
|
||||
@@ -25,14 +28,19 @@ moduleIntegrationTestRunner<IStoreModuleService>({
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("should fail to get created if default currency code is not in list of supported currency codes", async function () {
|
||||
const err = await service
|
||||
.createStores({ ...createStoreFixture, default_currency_code: "jpy" })
|
||||
.catch((err) => err.message)
|
||||
it("should fail to get created if there is no default currency", async function () {
|
||||
const err = await service
|
||||
.createStores({
|
||||
...createStoreFixture,
|
||||
supported_currencies: [{ currency_code: "usd" }],
|
||||
})
|
||||
.catch((err) => err.message)
|
||||
|
||||
expect(err).toEqual("Store does not have currency: jpy")
|
||||
expect(err).toEqual(
|
||||
"There should be a default currency set for the store"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("upserting a store", () => {
|
||||
@@ -75,44 +83,46 @@ moduleIntegrationTestRunner<IStoreModuleService>({
|
||||
expect(updatedStore.name).toEqual("Updated store")
|
||||
})
|
||||
|
||||
it("should fail updating default currency code to an unsupported one", async function () {
|
||||
it("should fail updating currencies without a default one", async function () {
|
||||
const createdStore = await service.createStores(createStoreFixture)
|
||||
const updateErr = await service
|
||||
.updateStores(createdStore.id, {
|
||||
default_currency_code: "jpy",
|
||||
})
|
||||
.catch((err) => err.message)
|
||||
|
||||
expect(updateErr).toEqual("Store does not have currency: jpy")
|
||||
})
|
||||
|
||||
it("should fail updating default currency code to an unsupported one if the supported currencies are also updated", async function () {
|
||||
const createdStore = await service.createStores(createStoreFixture)
|
||||
const updateErr = await service
|
||||
.updateStores(createdStore.id, {
|
||||
supported_currency_codes: ["mkd"],
|
||||
default_currency_code: "jpy",
|
||||
})
|
||||
.catch((err) => err.message)
|
||||
|
||||
expect(updateErr).toEqual("Store does not have currency: jpy")
|
||||
})
|
||||
|
||||
it("should fail updating supported currencies if one of them is used as a default one", async function () {
|
||||
const createdStore = await service.createStores({
|
||||
...createStoreFixture,
|
||||
default_currency_code: "eur",
|
||||
})
|
||||
const updateErr = await service
|
||||
.updateStores(createdStore.id, {
|
||||
supported_currency_codes: ["jpy"],
|
||||
supported_currencies: [{ currency_code: "usd" }],
|
||||
})
|
||||
.catch((err) => err.message)
|
||||
|
||||
expect(updateErr).toEqual(
|
||||
"You are not allowed to remove default currency from store currencies without replacing it as well"
|
||||
"There should be a default currency set for the store"
|
||||
)
|
||||
})
|
||||
|
||||
it("should fail updating currencies where a duplicate currency code exists", async function () {
|
||||
const createdStore = await service.createStores(createStoreFixture)
|
||||
const updateErr = await service
|
||||
.updateStores(createdStore.id, {
|
||||
supported_currencies: [
|
||||
{ currency_code: "usd" },
|
||||
{ currency_code: "usd" },
|
||||
],
|
||||
})
|
||||
.catch((err) => err.message)
|
||||
|
||||
expect(updateErr).toEqual("Duplicate currency codes: usd")
|
||||
})
|
||||
|
||||
it("should fail updating currencies where there is more than 1 default currency", async function () {
|
||||
const createdStore = await service.createStores(createStoreFixture)
|
||||
const updateErr = await service
|
||||
.updateStores(createdStore.id, {
|
||||
supported_currencies: [
|
||||
{ currency_code: "usd", is_default: true },
|
||||
{ currency_code: "eur", is_default: true },
|
||||
],
|
||||
})
|
||||
.catch((err) => err.message)
|
||||
|
||||
expect(updateErr).toEqual("Only one default currency is allowed")
|
||||
})
|
||||
})
|
||||
|
||||
describe("deleting a store", () => {
|
||||
|
||||
@@ -25,25 +25,6 @@
|
||||
"default": "'Medusa Store'",
|
||||
"mappedType": "text"
|
||||
},
|
||||
"supported_currency_codes": {
|
||||
"name": "supported_currency_codes",
|
||||
"type": "text[]",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"default": "'{}'",
|
||||
"mappedType": "array"
|
||||
},
|
||||
"default_currency_code": {
|
||||
"name": "default_currency_code",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"default_sales_channel_id": {
|
||||
"name": "default_sales_channel_id",
|
||||
"type": "text",
|
||||
@@ -138,6 +119,118 @@
|
||||
],
|
||||
"checks": [],
|
||||
"foreignKeys": {}
|
||||
},
|
||||
{
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"currency_code": {
|
||||
"name": "currency_code",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"is_default": {
|
||||
"name": "is_default",
|
||||
"type": "boolean",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"default": "false",
|
||||
"mappedType": "boolean"
|
||||
},
|
||||
"store_id": {
|
||||
"name": "store_id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"length": 6,
|
||||
"default": "now()",
|
||||
"mappedType": "datetime"
|
||||
},
|
||||
"deleted_at": {
|
||||
"name": "deleted_at",
|
||||
"type": "timestamptz",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"length": 6,
|
||||
"mappedType": "datetime"
|
||||
}
|
||||
},
|
||||
"name": "store_currency",
|
||||
"schema": "public",
|
||||
"indexes": [
|
||||
{
|
||||
"keyName": "IDX_store_currency_deleted_at",
|
||||
"columnNames": [
|
||||
"deleted_at"
|
||||
],
|
||||
"composite": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_store_currency_deleted_at\" ON \"store_currency\" (deleted_at) WHERE deleted_at IS NOT NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "store_currency_pkey",
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"composite": false,
|
||||
"primary": true,
|
||||
"unique": true
|
||||
}
|
||||
],
|
||||
"checks": [],
|
||||
"foreignKeys": {
|
||||
"store_currency_store_id_foreign": {
|
||||
"constraintName": "store_currency_store_id_foreign",
|
||||
"columnNames": [
|
||||
"store_id"
|
||||
],
|
||||
"localTableName": "public.store_currency",
|
||||
"referencedColumnNames": [
|
||||
"id"
|
||||
],
|
||||
"referencedTableName": "public.store",
|
||||
"deleteRule": "cascade",
|
||||
"updateRule": "cascade"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Migration } from "@mikro-orm/migrations"
|
||||
|
||||
export class Migration20240621145944 extends Migration {
|
||||
async up(): Promise<void> {
|
||||
this.addSql(
|
||||
'create table if not exists "store_currency" ("id" text not null, "currency_code" text not null, "is_default" boolean not null default false, "store_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "store_currency_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'CREATE INDEX IF NOT EXISTS "IDX_store_currency_deleted_at" ON "store_currency" (deleted_at) WHERE deleted_at IS NOT NULL;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "store_currency" add constraint "store_currency_store_id_foreign" foreign key ("store_id") references "store" ("id") on update cascade on delete cascade;'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "store" drop column if exists "supported_currency_codes";'
|
||||
)
|
||||
this.addSql(
|
||||
'alter table if exists "store" drop column if exists "default_currency_code";'
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import {
|
||||
DALUtils,
|
||||
Searchable,
|
||||
createPsqlIndexStatementHelper,
|
||||
generateEntityId,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
OnInit,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
Filter,
|
||||
ManyToOne,
|
||||
} from "@mikro-orm/core"
|
||||
import Store from "./store"
|
||||
|
||||
const StoreCurrencyDeletedAtIndex = createPsqlIndexStatementHelper({
|
||||
tableName: "store_currency",
|
||||
columns: "deleted_at",
|
||||
where: "deleted_at IS NOT NULL",
|
||||
})
|
||||
|
||||
@Entity()
|
||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||
export default class StoreCurrency {
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id: string
|
||||
|
||||
@Searchable()
|
||||
@Property({ columnType: "text" })
|
||||
currency_code: string
|
||||
|
||||
@Property({ columnType: "boolean", default: false })
|
||||
is_default?: boolean
|
||||
|
||||
@ManyToOne(() => Store, {
|
||||
columnType: "text",
|
||||
fieldName: "store_id",
|
||||
mapToPk: true,
|
||||
nullable: true,
|
||||
onDelete: "cascade",
|
||||
})
|
||||
store_id: string | null
|
||||
|
||||
@ManyToOne(() => Store, {
|
||||
persist: false,
|
||||
nullable: true,
|
||||
})
|
||||
store: Store | null
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
created_at: Date
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
columnType: "timestamptz",
|
||||
defaultRaw: "now()",
|
||||
})
|
||||
updated_at: Date
|
||||
|
||||
@StoreCurrencyDeletedAtIndex.MikroORMIndex()
|
||||
@Property({ columnType: "timestamptz", nullable: true })
|
||||
deleted_at: Date | null = null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "stocur")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "stocur")
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export { default as Store } from "./store"
|
||||
export { default as StoreCurrency } from "./currency"
|
||||
@@ -15,7 +15,11 @@ import {
|
||||
Property,
|
||||
Filter,
|
||||
OptionalProps,
|
||||
OneToMany,
|
||||
Collection,
|
||||
Cascade,
|
||||
} from "@mikro-orm/core"
|
||||
import StoreCurrency from "./currency"
|
||||
|
||||
type StoreOptionalProps = DAL.SoftDeletableEntityDateColumns
|
||||
|
||||
@@ -37,11 +41,10 @@ export default class Store {
|
||||
@Property({ columnType: "text", default: "Medusa Store" })
|
||||
name: string
|
||||
|
||||
@Property({ type: "array", default: "{}" })
|
||||
supported_currency_codes: string[] = []
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
default_currency_code: string | null = null
|
||||
@OneToMany(() => StoreCurrency, (o) => o.store, {
|
||||
cascade: [Cascade.PERSIST, "soft-remove"] as any,
|
||||
})
|
||||
supported_currencies = new Collection<StoreCurrency>(this)
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
default_sales_channel_id: string | null = null
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
StoreTypes,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
getDuplicates,
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
isString,
|
||||
@@ -18,7 +19,7 @@ import {
|
||||
removeUndefined,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { Store } from "@models"
|
||||
import { Store, StoreCurrency } from "@models"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
import { UpdateStoreInput } from "@types"
|
||||
|
||||
@@ -30,7 +31,8 @@ type InjectedDependencies = {
|
||||
export default class StoreModuleService
|
||||
extends MedusaService<{
|
||||
Store: { dto: StoreTypes.StoreDTO }
|
||||
}>({ Store }, entityNameToLinkableKeysMap)
|
||||
StoreCurrency: { dto: StoreTypes.StoreCurrencyDTO }
|
||||
}>({ Store, StoreCurrency }, entityNameToLinkableKeysMap)
|
||||
implements IStoreModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
@@ -81,7 +83,13 @@ export default class StoreModuleService
|
||||
let normalizedInput = StoreModuleService.normalizeInput(data)
|
||||
StoreModuleService.validateCreateRequest(normalizedInput)
|
||||
|
||||
return await this.storeService_.create(normalizedInput, sharedContext)
|
||||
return (
|
||||
await this.storeService_.upsertWithReplace(
|
||||
normalizedInput,
|
||||
{ relations: ["supported_currencies"] },
|
||||
sharedContext
|
||||
)
|
||||
).entities
|
||||
}
|
||||
|
||||
async upsertStores(
|
||||
@@ -168,8 +176,15 @@ export default class StoreModuleService
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<Store[]> {
|
||||
const normalizedInput = StoreModuleService.normalizeInput(data)
|
||||
await this.validateUpdateRequest(normalizedInput)
|
||||
return await this.storeService_.update(normalizedInput, sharedContext)
|
||||
StoreModuleService.validateUpdateRequest(normalizedInput)
|
||||
|
||||
return (
|
||||
await this.storeService_.upsertWithReplace(
|
||||
normalizedInput,
|
||||
{ relations: ["supported_currencies"] },
|
||||
sharedContext
|
||||
)
|
||||
).entities
|
||||
}
|
||||
|
||||
private static normalizeInput<T extends StoreTypes.UpdateStoreDTO>(
|
||||
@@ -178,6 +193,10 @@ export default class StoreModuleService
|
||||
return stores.map((store) =>
|
||||
removeUndefined({
|
||||
...store,
|
||||
supported_currencies: store.supported_currencies?.map((c) => ({
|
||||
...c,
|
||||
currency_code: c.currency_code.toLowerCase(),
|
||||
})),
|
||||
name: store.name?.trim(),
|
||||
})
|
||||
)
|
||||
@@ -185,77 +204,42 @@ export default class StoreModuleService
|
||||
|
||||
private static validateCreateRequest(stores: StoreTypes.CreateStoreDTO[]) {
|
||||
for (const store of stores) {
|
||||
// If we are setting the default currency code on creating, make sure it is supported
|
||||
if (store.default_currency_code) {
|
||||
if (
|
||||
!store.supported_currency_codes?.includes(
|
||||
store.default_currency_code ?? ""
|
||||
)
|
||||
) {
|
||||
if (store.supported_currencies?.length) {
|
||||
const duplicates = getDuplicates(
|
||||
store.supported_currencies?.map((c) => c.currency_code)
|
||||
)
|
||||
|
||||
if (duplicates.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Store does not have currency: ${store.default_currency_code}`
|
||||
`Duplicate currency codes: ${duplicates.join(", ")}`
|
||||
)
|
||||
}
|
||||
|
||||
let seenDefault = false
|
||||
store.supported_currencies?.forEach((c) => {
|
||||
if (c.is_default) {
|
||||
if (seenDefault) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Only one default currency is allowed`
|
||||
)
|
||||
}
|
||||
seenDefault = true
|
||||
}
|
||||
})
|
||||
|
||||
if (!seenDefault) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`There should be a default currency set for the store`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async validateUpdateRequest(stores: UpdateStoreInput[]) {
|
||||
const dbStores = await this.storeService_.list(
|
||||
{ id: stores.map((s) => s.id) },
|
||||
{ take: null }
|
||||
)
|
||||
|
||||
const dbStoresMap = new Map<string, Store>(
|
||||
dbStores.map((dbStore) => [dbStore.id, dbStore])
|
||||
)
|
||||
|
||||
for (const store of stores) {
|
||||
const dbStore = dbStoresMap.get(store.id)
|
||||
|
||||
// If it is updating both the supported currency codes and the default one, look in that list
|
||||
if (store.supported_currency_codes && store.default_currency_code) {
|
||||
if (
|
||||
!store.supported_currency_codes.includes(
|
||||
store.default_currency_code ?? ""
|
||||
)
|
||||
) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Store does not have currency: ${store.default_currency_code}`
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If it is updating only the default currency code, look in the db store
|
||||
if (store.default_currency_code) {
|
||||
if (
|
||||
!dbStore?.supported_currency_codes?.includes(
|
||||
store.default_currency_code
|
||||
)
|
||||
) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Store does not have currency: ${store.default_currency_code}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// If it is updating only the supported currency codes, make sure one of them is not set as a default one
|
||||
if (store.supported_currency_codes) {
|
||||
if (
|
||||
!store.supported_currency_codes.includes(
|
||||
dbStore?.default_currency_code ?? ""
|
||||
)
|
||||
) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"You are not allowed to remove default currency from store currencies without replacing it as well"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
private static validateUpdateRequest(stores: UpdateStoreInput[]) {
|
||||
StoreModuleService.validateCreateRequest(stores)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user