fix(tax): Add indexes to enforce unique constraint on tax region (#8067)
This commit is contained in:
1 parent
74c19308a0
commit
256912f392
4 files changed
+226
-3
No files matched your search
@@ -1,8 +1,8 @@
|
|||||||
import { moduleIntegrationTestRunner } from "medusa-test-utils"
|
|
||||||
import { ITaxModuleService } from "@medusajs/types"
|
import { ITaxModuleService } from "@medusajs/types"
|
||||||
import { setupTaxStructure } from "../utils/setup-tax-structure"
|
|
||||||
import { Module, Modules } from "@medusajs/utils"
|
import { Module, Modules } from "@medusajs/utils"
|
||||||
import { TaxModuleService } from "@services"
|
import { TaxModuleService } from "@services"
|
||||||
|
import { moduleIntegrationTestRunner } from "medusa-test-utils"
|
||||||
|
import { setupTaxStructure } from "../utils/setup-tax-structure"
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
@@ -62,6 +62,191 @@ moduleIntegrationTestRunner<ITaxModuleService>({
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should create tax region", async () => {
|
||||||
|
const region = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(region).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: region.id,
|
||||||
|
country_code: "us",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should create two tax regions with the same country code but different province", async () => {
|
||||||
|
const regionOne = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
province_code: "CA",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const regionTwo = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
province_code: "NY",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(regionOne).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: regionOne.id,
|
||||||
|
country_code: "us",
|
||||||
|
province_code: "ca",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(regionTwo).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: regionTwo.id,
|
||||||
|
country_code: "us",
|
||||||
|
province_code: "ny",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should create two tax regions in a child-parent-like relationship", async () => {
|
||||||
|
const regionOne = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const regionTwo = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
parent_id: regionOne.id,
|
||||||
|
province_code: "NY",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(regionOne).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: regionOne.id,
|
||||||
|
country_code: "us",
|
||||||
|
province_code: null,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(regionTwo).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: regionTwo.id,
|
||||||
|
country_code: "us",
|
||||||
|
province_code: "ny",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should create three tax regions in a child-parent-like relationship", async () => {
|
||||||
|
const regionOne = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const regionTwo = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
parent_id: regionOne.id,
|
||||||
|
province_code: "NY",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const regionThree = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
parent_id: regionOne.id,
|
||||||
|
province_code: "NE",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(regionOne).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: regionOne.id,
|
||||||
|
country_code: "us",
|
||||||
|
province_code: null,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(regionTwo).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: regionTwo.id,
|
||||||
|
country_code: "us",
|
||||||
|
province_code: "ny",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(regionThree).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: regionThree.id,
|
||||||
|
country_code: "us",
|
||||||
|
province_code: "ne",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw when creating a tax region with a country code of an existing region", async () => {
|
||||||
|
await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const error = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
}).catch(e => e)
|
||||||
|
|
||||||
|
expect(error.message).toEqual("Tax region with country_code: us, already exists.")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw when creating a tax region with a country code and province code of an existing region", async () => {
|
||||||
|
await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
province_code: "CA",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const error = await service.createTaxRegions({
|
||||||
|
country_code: "US",
|
||||||
|
province_code: "CA",
|
||||||
|
default_tax_rate: {
|
||||||
|
name: "Test Rate",
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
}).catch(e => e)
|
||||||
|
|
||||||
|
expect(error.message).toEqual("Tax region with country_code: us, province_code: ca, already exists.")
|
||||||
|
})
|
||||||
|
|
||||||
it("should create tax rates and update them", async () => {
|
it("should create tax rates and update them", async () => {
|
||||||
const region = await service.createTaxRegions({
|
const region = await service.createTaxRegions({
|
||||||
country_code: "US",
|
country_code: "US",
|
||||||
|
|||||||
@@ -168,7 +168,15 @@
|
|||||||
"composite": false,
|
"composite": false,
|
||||||
"primary": false,
|
"primary": false,
|
||||||
"unique": false,
|
"unique": false,
|
||||||
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_tax_region_unique_country_province\" ON \"tax_region\" (country_code, province_code)"
|
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_tax_region_unique_country_province\" ON \"tax_region\" (country_code, province_code) WHERE deleted_at IS NULL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keyName": "IDX_tax_region_unique_country_nullable_province",
|
||||||
|
"columnNames": [],
|
||||||
|
"composite": false,
|
||||||
|
"primary": false,
|
||||||
|
"unique": false,
|
||||||
|
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_tax_region_unique_country_nullable_province\" ON \"tax_region\" (country_code) WHERE province_code IS NULL AND deleted_at IS NULL"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyName": "tax_region_pkey",
|
"keyName": "tax_region_pkey",
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Migration } from '@mikro-orm/migrations';
|
||||||
|
|
||||||
|
export class Migration20240710135844 extends Migration {
|
||||||
|
|
||||||
|
async up(): Promise<void> {
|
||||||
|
this.addSql('drop index if exists "IDX_tax_region_unique_country_province";');
|
||||||
|
this.addSql('CREATE UNIQUE INDEX IF NOT EXISTS "IDX_tax_region_unique_country_province" ON "tax_region" (country_code, province_code) WHERE deleted_at IS NULL;');
|
||||||
|
this.addSql('CREATE UNIQUE INDEX IF NOT EXISTS "IDX_tax_region_unique_country_nullable_province" ON "tax_region" (country_code) WHERE province_code IS NULL AND deleted_at IS NULL;');
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(): Promise<void> {
|
||||||
|
this.addSql('drop index if exists "IDX_tax_region_unique_country_province";');
|
||||||
|
this.addSql('drop index if exists "IDX_tax_region_unique_country_nullable_province";');
|
||||||
|
this.addSql('CREATE UNIQUE INDEX IF NOT EXISTS "IDX_tax_region_unique_country_province" ON "tax_region" (country_code, province_code);');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,8 @@ type OptionalTaxRegionProps = DAL.SoftDeletableModelDateColumns
|
|||||||
|
|
||||||
const TABLE_NAME = "tax_region"
|
const TABLE_NAME = "tax_region"
|
||||||
|
|
||||||
|
export const countryCodeNullProvinceIndexName =
|
||||||
|
"IDX_tax_region_unique_country_nullable_province"
|
||||||
export const countryCodeProvinceIndexName =
|
export const countryCodeProvinceIndexName =
|
||||||
"IDX_tax_region_unique_country_province"
|
"IDX_tax_region_unique_country_province"
|
||||||
const countryCodeProvinceIndexStatement = createPsqlIndexStatementHelper({
|
const countryCodeProvinceIndexStatement = createPsqlIndexStatementHelper({
|
||||||
@@ -34,6 +36,16 @@ const countryCodeProvinceIndexStatement = createPsqlIndexStatementHelper({
|
|||||||
tableName: TABLE_NAME,
|
tableName: TABLE_NAME,
|
||||||
columns: ["country_code", "province_code"],
|
columns: ["country_code", "province_code"],
|
||||||
unique: true,
|
unique: true,
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
})
|
||||||
|
|
||||||
|
const countryCodeNullableProvinceIndexStatement =
|
||||||
|
createPsqlIndexStatementHelper({
|
||||||
|
name: countryCodeNullProvinceIndexName,
|
||||||
|
tableName: TABLE_NAME,
|
||||||
|
columns: ["country_code"],
|
||||||
|
unique: true,
|
||||||
|
where: "province_code IS NULL AND deleted_at IS NULL",
|
||||||
})
|
})
|
||||||
|
|
||||||
export const taxRegionProviderTopLevelCheckName =
|
export const taxRegionProviderTopLevelCheckName =
|
||||||
@@ -49,6 +61,7 @@ export const taxRegionCountryTopLevelCheckName =
|
|||||||
name: taxRegionCountryTopLevelCheckName,
|
name: taxRegionCountryTopLevelCheckName,
|
||||||
expression: `parent_id IS NULL OR province_code IS NOT NULL`,
|
expression: `parent_id IS NULL OR province_code IS NOT NULL`,
|
||||||
})
|
})
|
||||||
|
@countryCodeNullableProvinceIndexStatement.MikroORMIndex()
|
||||||
@countryCodeProvinceIndexStatement.MikroORMIndex()
|
@countryCodeProvinceIndexStatement.MikroORMIndex()
|
||||||
@Entity({ tableName: TABLE_NAME })
|
@Entity({ tableName: TABLE_NAME })
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
|
|||||||
Reference in new issue
Block a user