feat(region): Create region with countries (#6372)
This commit is contained in:
@@ -86,6 +86,87 @@ describe("Region Module Service", () => {
|
||||
)
|
||||
})
|
||||
|
||||
it("should create a region with countries", async () => {
|
||||
const createdRegion = await service.create({
|
||||
name: "North America",
|
||||
currency_code: "USD",
|
||||
countries: ["us", "ca"],
|
||||
})
|
||||
|
||||
const region = await service.retrieve(createdRegion.id, {
|
||||
relations: ["countries", "currency"],
|
||||
})
|
||||
|
||||
expect(region).toEqual(
|
||||
expect.objectContaining({
|
||||
id: region.id,
|
||||
name: "North America",
|
||||
currency_code: "usd",
|
||||
currency: expect.objectContaining({
|
||||
code: "usd",
|
||||
name: "US Dollar",
|
||||
}),
|
||||
countries: [
|
||||
expect.objectContaining({
|
||||
display_name: "Canada",
|
||||
iso_2: "ca",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
display_name: "United States",
|
||||
iso_2: "us",
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw when country doesn't exist", async () => {
|
||||
await expect(
|
||||
service.create({
|
||||
name: "North America",
|
||||
currency_code: "USD",
|
||||
countries: ["neverland"],
|
||||
})
|
||||
).rejects.toThrowError("Countries with codes neverland does not exist")
|
||||
})
|
||||
|
||||
it("should throw when country is already assigned to a region", async () => {
|
||||
await service.create({
|
||||
name: "North America",
|
||||
currency_code: "USD",
|
||||
countries: ["us"],
|
||||
})
|
||||
|
||||
await expect(
|
||||
service.create({
|
||||
name: "United States",
|
||||
currency_code: "USD",
|
||||
countries: ["us"],
|
||||
})
|
||||
).rejects.toThrowError(
|
||||
"Country with code us is already assigned to a region"
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw when country is being assigned to multiple regions", async () => {
|
||||
await expect(
|
||||
service.create([
|
||||
{
|
||||
name: "United States",
|
||||
currency_code: "USD",
|
||||
countries: ["us"],
|
||||
},
|
||||
{
|
||||
name: "North America",
|
||||
currency_code: "USD",
|
||||
countries: ["us"],
|
||||
},
|
||||
])
|
||||
).rejects.toThrowError(
|
||||
"Country with code us is already assigned to a region"
|
||||
)
|
||||
})
|
||||
|
||||
it("should fail when currency does not exist", async () => {
|
||||
await expect(
|
||||
service.create({
|
||||
|
||||
@@ -30,13 +30,15 @@ export default class Country {
|
||||
@Property({ columnType: "text" })
|
||||
display_name: string
|
||||
|
||||
@Property({ columnType: "text", nullable: true })
|
||||
region_id?: string | null = null
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => Region,
|
||||
fieldName: "region_id",
|
||||
index: "IDX_country_region_id",
|
||||
nullable: true,
|
||||
})
|
||||
region: Region | null = null
|
||||
region?: Region | null
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
|
||||
@@ -23,7 +23,11 @@ import {
|
||||
import { Country, Currency, Region } from "@models"
|
||||
|
||||
import { DefaultsUtils } from "@medusajs/utils"
|
||||
import { CreateCountryDTO, CreateCurrencyDTO } from "@types"
|
||||
import {
|
||||
CreateCountryDTO,
|
||||
CreateCurrencyDTO,
|
||||
CreateRegionDTO as InternalCreateRegionDTO,
|
||||
} from "@types"
|
||||
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
|
||||
|
||||
const COUNTRIES_LIMIT = 1000
|
||||
@@ -115,20 +119,70 @@ export default class RegionModuleService<
|
||||
sharedContext
|
||||
)
|
||||
|
||||
let currencyMap = new Map(currencies.map((c) => [c.code.toLowerCase(), c]))
|
||||
for (const reg of data) {
|
||||
const lowerCasedCurrency = reg.currency_code.toLowerCase()
|
||||
const countriesInDb = await this.countryService_.list(
|
||||
{ iso_2: data.map((d) => d.countries).flat() },
|
||||
{ select: ["iso_2", "region_id"] },
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const countriesInDbMap = new Map<string, Country>(
|
||||
countriesInDb.map((c) => [c.iso_2, c])
|
||||
)
|
||||
|
||||
const currencyMap = new Map(
|
||||
currencies.map((c) => [c.code.toLowerCase(), c])
|
||||
)
|
||||
|
||||
const toCreate: InternalCreateRegionDTO[] = []
|
||||
const seenCountries = new Set<string>()
|
||||
for (const region of data) {
|
||||
const reg = { ...region } as InternalCreateRegionDTO
|
||||
const countriesToAdd = region.countries || []
|
||||
|
||||
if (countriesToAdd) {
|
||||
const notInDb = countriesToAdd.filter(
|
||||
(c) => !countriesInDbMap.has(c.toLowerCase())
|
||||
)
|
||||
|
||||
if (notInDb.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Countries with codes ${countriesToAdd.join(", ")} does not exist`
|
||||
)
|
||||
}
|
||||
|
||||
const regionCountries = countriesToAdd.map((code) => {
|
||||
const country = countriesInDbMap.get(code.toLowerCase())
|
||||
|
||||
if (country?.region_id || seenCountries.has(code.toLowerCase())) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Country with code ${code} is already assigned to a region`
|
||||
)
|
||||
}
|
||||
|
||||
seenCountries.add(code.toLowerCase())
|
||||
|
||||
return country
|
||||
}) as unknown as TCountry[]
|
||||
|
||||
reg.countries = regionCountries
|
||||
}
|
||||
|
||||
const lowerCasedCurrency = region.currency_code.toLowerCase()
|
||||
if (!currencyMap.has(lowerCasedCurrency)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Currency with code: ${reg.currency_code} was not found`
|
||||
`Currency with code: ${region.currency_code} was not found`
|
||||
)
|
||||
}
|
||||
|
||||
reg.currency_code = lowerCasedCurrency
|
||||
|
||||
toCreate.push(reg as InternalCreateRegionDTO)
|
||||
}
|
||||
|
||||
const result = await this.regionService_.create(data, sharedContext)
|
||||
const result = await this.regionService_.create(toCreate, sharedContext)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Logger } from "@medusajs/types"
|
||||
import { Country } from "@models"
|
||||
|
||||
export type InitializeModuleInjectableDependencies = {
|
||||
logger?: Logger
|
||||
@@ -22,4 +23,10 @@ export type CreateCountryDTO = {
|
||||
num_code: string
|
||||
name: string
|
||||
display_name: string
|
||||
}
|
||||
|
||||
export type CreateRegionDTO = {
|
||||
name: string
|
||||
currency_code: string
|
||||
countries?: Country[]
|
||||
}
|
||||
@@ -4,6 +4,7 @@ export interface CreateRegionDTO {
|
||||
name: string
|
||||
currency_code: string
|
||||
currency?: RegionCurrencyDTO
|
||||
countries?: string[]
|
||||
tax_code?: string
|
||||
tax_rate?: number
|
||||
tax_provider_id?: string
|
||||
@@ -13,6 +14,7 @@ export interface UpdateRegionDTO {
|
||||
id: string
|
||||
currency_code?: string
|
||||
currency?: RegionCurrencyDTO
|
||||
countries: string[]
|
||||
name?: string
|
||||
tax_code?: string
|
||||
tax_rate?: number
|
||||
|
||||
Reference in New Issue
Block a user