diff --git a/packages/region/integration-tests/__tests__/region-module.spec.ts b/packages/region/integration-tests/__tests__/region-module.spec.ts index 261e6f3147..0ae7072c7d 100644 --- a/packages/region/integration-tests/__tests__/region-module.spec.ts +++ b/packages/region/integration-tests/__tests__/region-module.spec.ts @@ -196,6 +196,12 @@ moduleIntegrationTestRunner({ countries: ["us", "ca"], }) + const shouldNotBeChangedRegion = await service.create({ + name: "Europe", + currency_code: "EUR", + countries: ["hr"], + }) + await service.update(createdRegion.id, { name: "Americas", currency_code: "MXN", @@ -206,13 +212,26 @@ moduleIntegrationTestRunner({ relations: ["countries"], }) + const shouldNotBeChangedRegionAfter = await service.retrieve( + shouldNotBeChangedRegion.id, + { + relations: ["countries"], + } + ) + expect(latestRegion).toMatchObject({ id: createdRegion.id, name: "Americas", 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 () => { @@ -340,12 +359,16 @@ moduleIntegrationTestRunner({ await service.delete(createdRegion.id) - const resp = await service.create({ + const newRegion = await service.create({ name: "North America", currency_code: "USD", countries: ["us", "ca"], }) + const resp = await service.retrieve(newRegion.id, { + relations: ["countries"], + }) + expect(resp.countries).toHaveLength(2) }) }) diff --git a/packages/region/src/services/region-module.ts b/packages/region/src/services/region-module.ts index 6e8140b1ae..f387fcbfa6 100644 --- a/packages/region/src/services/region-module.ts +++ b/packages/region/src/services/region-module.ts @@ -101,25 +101,36 @@ export default class RegionModuleService< ): Promise { 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) => removeUndefined({ ...region, - countries: region.countries?.map((c) => dbCountriesMap.get(c)), + countries: undefined, }) ) - // Create the regions and update the country region_id - return await this.regionService_.create(normalizedDbRegions, sharedContext) + const result = await this.regionService_.create( + 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( @@ -213,6 +224,13 @@ export default class RegionModuleService< .map((region) => region.id) .flat() + let normalizedDbRegions = normalizedInput.map((region) => + removeUndefined({ + ...region, + countries: undefined, // -> delete countries if passed because we want to do update "manually" + }) + ) + if (regionsWithCountryUpdate.length) { await this.countryService_.update( { @@ -223,24 +241,22 @@ export default class RegionModuleService< }, sharedContext ) - } - const validations = [ - this.validateCountries( + await this.validateCountries( normalizedInput.map((d) => d.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) => - removeUndefined({ - ...region, - countries: region.countries?.map((c) => dbCountriesMap.get(c)), - }) - ) + await this.countryService_.update( + normalizedInput.map((region) => ({ + selector: { iso_2: region.countries }, + data: { + region_id: region.id, + }, + })), + 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( countries: string[] | undefined, sharedContext: Context