fix(region): update regions countries (#6970)

* fix: update regions countries

* fix: test case
This commit is contained in:
Frane Polić
2024-04-06 09:50:46 +02:00
committed by GitHub
parent cbf2e6300d
commit 01759cae65
2 changed files with 76 additions and 29 deletions
@@ -196,6 +196,12 @@ moduleIntegrationTestRunner({
countries: ["us", "ca"], countries: ["us", "ca"],
}) })
const shouldNotBeChangedRegion = await service.create({
name: "Europe",
currency_code: "EUR",
countries: ["hr"],
})
await service.update(createdRegion.id, { await service.update(createdRegion.id, {
name: "Americas", name: "Americas",
currency_code: "MXN", currency_code: "MXN",
@@ -206,13 +212,26 @@ moduleIntegrationTestRunner({
relations: ["countries"], relations: ["countries"],
}) })
const shouldNotBeChangedRegionAfter = await service.retrieve(
shouldNotBeChangedRegion.id,
{
relations: ["countries"],
}
)
expect(latestRegion).toMatchObject({ expect(latestRegion).toMatchObject({
id: createdRegion.id, id: createdRegion.id,
name: "Americas", name: "Americas",
currency_code: "mxn", currency_code: "mxn",
}) })
expect(latestRegion.countries.map((c) => c.iso_2)).toEqual(["mx", "us"]) expect(
shouldNotBeChangedRegionAfter.countries.map((c) => c.iso_2)
).toEqual(["hr"])
expect(latestRegion.countries.map((c) => c.iso_2)).toEqual(
expect.arrayContaining(["mx", "us"])
)
}) })
it("should update the region without affecting countries if countries are undefined", async () => { it("should update the region without affecting countries if countries are undefined", async () => {
@@ -340,12 +359,16 @@ moduleIntegrationTestRunner({
await service.delete(createdRegion.id) await service.delete(createdRegion.id)
const resp = await service.create({ const newRegion = await service.create({
name: "North America", name: "North America",
currency_code: "USD", currency_code: "USD",
countries: ["us", "ca"], countries: ["us", "ca"],
}) })
const resp = await service.retrieve(newRegion.id, {
relations: ["countries"],
})
expect(resp.countries).toHaveLength(2) expect(resp.countries).toHaveLength(2)
}) })
}) })
+51 -27
View File
@@ -101,25 +101,36 @@ export default class RegionModuleService<
): Promise<Region[]> { ): Promise<Region[]> {
let normalizedInput = RegionModuleService.normalizeInput(data) let normalizedInput = RegionModuleService.normalizeInput(data)
const validations = [
this.validateCountries(
normalizedInput.map((r) => r.countries ?? []).flat(),
sharedContext
),
] as const
// Assign the full country object so the ORM updates the relationship
const [dbCountries] = await promiseAll(validations)
const dbCountriesMap = new Map(dbCountries.map((d) => [d.iso_2, d]))
let normalizedDbRegions = normalizedInput.map((region) => let normalizedDbRegions = normalizedInput.map((region) =>
removeUndefined({ removeUndefined({
...region, ...region,
countries: region.countries?.map((c) => dbCountriesMap.get(c)), countries: undefined,
}) })
) )
// Create the regions and update the country region_id const result = await this.regionService_.create(
return await this.regionService_.create(normalizedDbRegions, sharedContext) normalizedDbRegions,
sharedContext
)
if (data.some((input) => input.countries?.length)) {
await this.validateCountries(
normalizedInput.map((r) => r.countries ?? []).flat(),
sharedContext
)
await this.countryService_.update(
normalizedInput.map((region, i) => ({
selector: { iso_2: region.countries },
data: {
region_id: result[i].id,
},
})),
sharedContext
)
}
return result
} }
async upsert( async upsert(
@@ -213,6 +224,13 @@ export default class RegionModuleService<
.map((region) => region.id) .map((region) => region.id)
.flat() .flat()
let normalizedDbRegions = normalizedInput.map((region) =>
removeUndefined({
...region,
countries: undefined, // -> delete countries if passed because we want to do update "manually"
})
)
if (regionsWithCountryUpdate.length) { if (regionsWithCountryUpdate.length) {
await this.countryService_.update( await this.countryService_.update(
{ {
@@ -223,24 +241,22 @@ export default class RegionModuleService<
}, },
sharedContext sharedContext
) )
}
const validations = [ await this.validateCountries(
this.validateCountries(
normalizedInput.map((d) => d.countries ?? []).flat(), normalizedInput.map((d) => d.countries ?? []).flat(),
sharedContext sharedContext
), )
] as const
// Assign the full country object so the ORM updates the relationship await this.countryService_.update(
const [dbCountries] = await promiseAll(validations) normalizedInput.map((region) => ({
const dbCountriesMap = new Map(dbCountries.map((d) => [d.iso_2, d])) selector: { iso_2: region.countries },
let normalizedDbRegions = normalizedInput.map((region) => data: {
removeUndefined({ region_id: region.id,
...region, },
countries: region.countries?.map((c) => dbCountriesMap.get(c)), })),
}) sharedContext
) )
}
return await this.regionService_.update(normalizedDbRegions, sharedContext) return await this.regionService_.update(normalizedDbRegions, sharedContext)
} }
@@ -256,6 +272,14 @@ export default class RegionModuleService<
) )
} }
/**
* Validate that countries can be assigned to a region.
*
* NOTE: this method relies on countries of the regions that we are assigning to need to be unassigned first.
* @param countries
* @param sharedContext
* @private
*/
private async validateCountries( private async validateCountries(
countries: string[] | undefined, countries: string[] | undefined,
sharedContext: Context sharedContext: Context