Feat/tax dml (#10525)

Fixes: FRMW-2842

There are zero breaking changes and the users will have to run the migrations
This commit is contained in:
Harminder Virk
2024-12-12 09:35:11 +00:00
committed by GitHub
parent bf6d14cb54
commit e021c9258c
9 changed files with 389 additions and 546 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/tax": patch
---
Feat/tax dml
@@ -1,5 +1,5 @@
import { ITaxModuleService } from "@medusajs/framework/types" import { ITaxModuleService } from "@medusajs/framework/types"
import { Module, Modules } from "@medusajs/framework/utils" import { Module, Modules, toMikroORMEntity } from "@medusajs/framework/utils"
import { TaxModuleService } from "@services" import { TaxModuleService } from "@services"
import { moduleIntegrationTestRunner } from "@medusajs/test-utils" import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
import { setupTaxStructure } from "../utils/setup-tax-structure" import { setupTaxStructure } from "../utils/setup-tax-structure"
@@ -11,7 +11,7 @@ moduleIntegrationTestRunner<ITaxModuleService>({
testSuite: ({ service }) => { testSuite: ({ service }) => {
describe("TaxModuleService", function () { describe("TaxModuleService", function () {
it(`should export the appropriate linkable configuration`, () => { it(`should export the appropriate linkable configuration`, () => {
const linkable = Module(Modules.TAX, { const linkable = Module(toMikroORMEntity(Modules.TAX), {
service: TaxModuleService, service: TaxModuleService,
}).linkable }).linkable
@@ -1,5 +1,7 @@
{ {
"namespaces": ["public"], "namespaces": [
"public"
],
"name": "public", "name": "public",
"tables": [ "tables": [
{ {
@@ -22,77 +24,6 @@
"nullable": false, "nullable": false,
"default": "true", "default": "true",
"mappedType": "boolean" "mappedType": "boolean"
}
},
"name": "tax_provider",
"schema": "public",
"indexes": [
{
"keyName": "tax_provider_pkey",
"columnNames": ["id"],
"composite": false,
"primary": true,
"unique": true
}
],
"checks": [],
"foreignKeys": {}
},
{
"columns": {
"id": {
"name": "id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"provider_id": {
"name": "provider_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"country_code": {
"name": "country_code",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"province_code": {
"name": "province_code",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"parent_id": {
"name": "parent_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
}, },
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
@@ -116,6 +47,79 @@
"default": "now()", "default": "now()",
"mappedType": "datetime" "mappedType": "datetime"
}, },
"deleted_at": {
"name": "deleted_at",
"type": "timestamptz",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"length": 6,
"mappedType": "datetime"
}
},
"name": "tax_provider",
"schema": "public",
"indexes": [
{
"keyName": "IDX_tax_provider_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_provider_deleted_at\" ON \"tax_provider\" (deleted_at) WHERE deleted_at IS NULL"
},
{
"keyName": "tax_provider_pkey",
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
}
],
"checks": [],
"foreignKeys": {}
},
{
"columns": {
"id": {
"name": "id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"country_code": {
"name": "country_code",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"province_code": {
"name": "province_code",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"created_by": { "created_by": {
"name": "created_by", "name": "created_by",
"type": "text", "type": "text",
@@ -125,6 +129,46 @@
"nullable": true, "nullable": true,
"mappedType": "text" "mappedType": "text"
}, },
"provider_id": {
"name": "provider_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"parent_id": {
"name": "parent_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": { "deleted_at": {
"name": "deleted_at", "name": "deleted_at",
"type": "timestamptz", "type": "timestamptz",
@@ -140,19 +184,28 @@
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"columnNames": ["parent_id"], "keyName": "IDX_tax_region_provider_id",
"composite": false, "columnNames": [],
"keyName": "IDX_tax_region_parent_id",
"primary": false,
"unique": false
},
{
"keyName": "IDX_tax_region_deleted_at",
"columnNames": ["deleted_at"],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_region_deleted_at\" ON \"tax_region\" (deleted_at) WHERE deleted_at IS NOT NULL" "expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_region_provider_id\" ON \"tax_region\" (provider_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_tax_region_parent_id",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_region_parent_id\" ON \"tax_region\" (parent_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_tax_region_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_region_deleted_at\" ON \"tax_region\" (deleted_at) WHERE deleted_at IS NULL"
}, },
{ {
"keyName": "IDX_tax_region_unique_country_province", "keyName": "IDX_tax_region_unique_country_province",
@@ -172,39 +225,49 @@
}, },
{ {
"keyName": "tax_region_pkey", "keyName": "tax_region_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
} }
], ],
"checks": [ "checks": [
{
"name": "CK_tax_region_country_top_level",
"expression": "parent_id IS NULL OR province_code IS NOT NULL",
"definition": "check ((parent_id IS NULL OR province_code IS NOT NULL))"
},
{ {
"name": "CK_tax_region_provider_top_level", "name": "CK_tax_region_provider_top_level",
"expression": "parent_id IS NULL OR provider_id IS NULL", "expression": "parent_id IS NULL OR provider_id IS NULL",
"definition": "check ((parent_id IS NULL OR provider_id IS NULL))" "definition": "check ((parent_id IS NULL OR provider_id IS NULL))"
},
{
"name": "CK_tax_region_country_top_level",
"expression": "parent_id IS NULL OR province_code IS NOT NULL",
"definition": "check ((parent_id IS NULL OR province_code IS NOT NULL))"
} }
], ],
"foreignKeys": { "foreignKeys": {
"tax_region_provider_id_foreign": { "tax_region_provider_id_foreign": {
"constraintName": "tax_region_provider_id_foreign", "constraintName": "tax_region_provider_id_foreign",
"columnNames": ["provider_id"], "columnNames": [
"provider_id"
],
"localTableName": "public.tax_region", "localTableName": "public.tax_region",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.tax_provider", "referencedTableName": "public.tax_provider",
"deleteRule": "set null", "deleteRule": "set null",
"updateRule": "cascade" "updateRule": "cascade"
}, },
"tax_region_parent_id_foreign": { "tax_region_parent_id_foreign": {
"constraintName": "tax_region_parent_id_foreign", "constraintName": "tax_region_parent_id_foreign",
"columnNames": ["parent_id"], "columnNames": [
"parent_id"
],
"localTableName": "public.tax_region", "localTableName": "public.tax_region",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.tax_region", "referencedTableName": "public.tax_region",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -228,7 +291,7 @@
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": true,
"mappedType": "float" "mappedType": "float"
}, },
"code": { "code": {
@@ -251,7 +314,7 @@
}, },
"is_default": { "is_default": {
"name": "is_default", "name": "is_default",
"type": "bool", "type": "boolean",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
@@ -261,7 +324,7 @@
}, },
"is_combinable": { "is_combinable": {
"name": "is_combinable", "name": "is_combinable",
"type": "bool", "type": "boolean",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
@@ -287,6 +350,15 @@
"nullable": true, "nullable": true,
"mappedType": "json" "mappedType": "json"
}, },
"created_by": {
"name": "created_by",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
"type": "timestamptz", "type": "timestamptz",
@@ -309,15 +381,6 @@
"default": "now()", "default": "now()",
"mappedType": "datetime" "mappedType": "datetime"
}, },
"created_by": {
"name": "created_by",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"deleted_at": { "deleted_at": {
"name": "deleted_at", "name": "deleted_at",
"type": "timestamptz", "type": "timestamptz",
@@ -334,7 +397,7 @@
"indexes": [ "indexes": [
{ {
"keyName": "IDX_tax_rate_tax_region_id", "keyName": "IDX_tax_rate_tax_region_id",
"columnNames": ["tax_region_id"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
@@ -342,11 +405,11 @@
}, },
{ {
"keyName": "IDX_tax_rate_deleted_at", "keyName": "IDX_tax_rate_deleted_at",
"columnNames": ["deleted_at"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_deleted_at\" ON \"tax_rate\" (deleted_at) WHERE deleted_at IS NOT NULL" "expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_deleted_at\" ON \"tax_rate\" (deleted_at) WHERE deleted_at IS NULL"
}, },
{ {
"keyName": "IDX_single_default_region", "keyName": "IDX_single_default_region",
@@ -358,7 +421,9 @@
}, },
{ {
"keyName": "tax_rate_pkey", "keyName": "tax_rate_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -368,9 +433,13 @@
"foreignKeys": { "foreignKeys": {
"tax_rate_tax_region_id_foreign": { "tax_rate_tax_region_id_foreign": {
"constraintName": "tax_rate_tax_region_id_foreign", "constraintName": "tax_rate_tax_region_id_foreign",
"columnNames": ["tax_region_id"], "columnNames": [
"tax_region_id"
],
"localTableName": "public.tax_rate", "localTableName": "public.tax_rate",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.tax_region", "referencedTableName": "public.tax_region",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -388,17 +457,26 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"tax_rate_id": { "metadata": {
"name": "tax_rate_id", "name": "metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"created_by": {
"name": "created_by",
"type": "text", "type": "text",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": true,
"mappedType": "text" "mappedType": "text"
}, },
"reference_id": { "tax_rate_id": {
"name": "reference_id", "name": "tax_rate_id",
"type": "text", "type": "text",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
@@ -415,14 +493,14 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"metadata": { "reference_id": {
"name": "metadata", "name": "reference_id",
"type": "jsonb", "type": "text",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": true, "nullable": false,
"mappedType": "json" "mappedType": "text"
}, },
"created_at": { "created_at": {
"name": "created_at", "name": "created_at",
@@ -446,15 +524,6 @@
"default": "now()", "default": "now()",
"mappedType": "datetime" "mappedType": "datetime"
}, },
"created_by": {
"name": "created_by",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"deleted_at": { "deleted_at": {
"name": "deleted_at", "name": "deleted_at",
"type": "timestamptz", "type": "timestamptz",
@@ -471,28 +540,28 @@
"indexes": [ "indexes": [
{ {
"keyName": "IDX_tax_rate_rule_tax_rate_id", "keyName": "IDX_tax_rate_rule_tax_rate_id",
"columnNames": ["tax_rate_id"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_rule_tax_rate_id\" ON \"tax_rate_rule\" (tax_rate_id) WHERE deleted_at IS NULL" "expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_rule_tax_rate_id\" ON \"tax_rate_rule\" (tax_rate_id) WHERE deleted_at IS NULL"
}, },
{
"keyName": "IDX_tax_rate_rule_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_rule_deleted_at\" ON \"tax_rate_rule\" (deleted_at) WHERE deleted_at IS NULL"
},
{ {
"keyName": "IDX_tax_rate_rule_reference_id", "keyName": "IDX_tax_rate_rule_reference_id",
"columnNames": ["reference_id"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_rule_reference_id\" ON \"tax_rate_rule\" (reference_id) WHERE deleted_at IS NULL" "expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_rule_reference_id\" ON \"tax_rate_rule\" (reference_id) WHERE deleted_at IS NULL"
}, },
{
"keyName": "IDX_tax_rate_rule_deleted_at",
"columnNames": ["deleted_at"],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_tax_rate_rule_deleted_at\" ON \"tax_rate_rule\" (deleted_at) WHERE deleted_at IS NOT NULL"
},
{ {
"keyName": "IDX_tax_rate_rule_unique_rate_reference", "keyName": "IDX_tax_rate_rule_unique_rate_reference",
"columnNames": [], "columnNames": [],
@@ -503,7 +572,9 @@
}, },
{ {
"keyName": "tax_rate_rule_pkey", "keyName": "tax_rate_rule_pkey",
"columnNames": ["id"], "columnNames": [
"id"
],
"composite": false, "composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -513,9 +584,13 @@
"foreignKeys": { "foreignKeys": {
"tax_rate_rule_tax_rate_id_foreign": { "tax_rate_rule_tax_rate_id_foreign": {
"constraintName": "tax_rate_rule_tax_rate_id_foreign", "constraintName": "tax_rate_rule_tax_rate_id_foreign",
"columnNames": ["tax_rate_id"], "columnNames": [
"tax_rate_id"
],
"localTableName": "public.tax_rate_rule", "localTableName": "public.tax_rate_rule",
"referencedColumnNames": ["id"], "referencedColumnNames": [
"id"
],
"referencedTableName": "public.tax_rate", "referencedTableName": "public.tax_rate",
"deleteRule": "cascade", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
@@ -0,0 +1,27 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20241212052837 extends Migration {
async up(): Promise<void> {
this.addSql('alter table if exists "tax_provider" add column if not exists "created_at" timestamptz not null default now(), add column if not exists "updated_at" timestamptz not null default now(), add column if not exists "deleted_at" timestamptz null;');
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_tax_provider_deleted_at" ON "tax_provider" (deleted_at) WHERE deleted_at IS NULL;');
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_tax_region_provider_id" ON "tax_region" (provider_id) WHERE deleted_at IS NULL;');
this.addSql('alter table if exists "tax_rate" alter column "rate" type real using ("rate"::real);');
this.addSql('alter table if exists "tax_rate" alter column "rate" drop not null;');
}
async down(): Promise<void> {
this.addSql('drop index if exists "IDX_tax_provider_deleted_at";');
this.addSql('alter table if exists "tax_provider" drop column if exists "created_at";');
this.addSql('alter table if exists "tax_provider" drop column if exists "updated_at";');
this.addSql('alter table if exists "tax_provider" drop column if exists "deleted_at";');
this.addSql('drop index if exists "IDX_tax_region_provider_id";');
this.addSql('alter table if exists "tax_rate" alter column "rate" type real using ("rate"::real);');
this.addSql('alter table if exists "tax_rate" alter column "rate" set not null;');
}
}
+10 -14
View File
@@ -1,16 +1,12 @@
import { Entity, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core" import { model } from "@medusajs/framework/utils"
import { TaxRegion } from "@models"
const TABLE_NAME = "tax_provider" const TaxProvider = model.define("TaxProvider", {
@Entity({ tableName: TABLE_NAME }) id: model.id().primaryKey(),
export default class TaxProvider { is_enabled: model.boolean().default(true),
[OptionalProps]?: "is_enabled" regions: model.hasMany(() => TaxRegion, {
mappedBy: "provider",
}),
})
@PrimaryKey({ columnType: "text" }) export default TaxProvider
id: string
@Property({
default: true,
columnType: "boolean",
})
is_enabled: boolean = true
}
+25 -113
View File
@@ -1,117 +1,29 @@
import { DAL } from "@medusajs/framework/types" import { model } from "@medusajs/framework/utils"
import {
createPsqlIndexStatementHelper,
DALUtils,
generateEntityId,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Entity,
Filter,
ManyToOne,
OnInit,
OptionalProps,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import TaxRate from "./tax-rate" import TaxRate from "./tax-rate"
const TABLE_NAME = "tax_rate_rule" const TaxRateRule = model
.define("TaxRateRule", {
type OptionalRuleProps = DAL.SoftDeletableModelDateColumns id: model.id({ prefix: "txrule" }).primaryKey(),
metadata: model.json().nullable(),
const taxRateIdIndexName = "IDX_tax_rate_rule_tax_rate_id" created_by: model.text().nullable(),
const taxRateIdIndexStatement = createPsqlIndexStatementHelper({ tax_rate: model.belongsTo(() => TaxRate, {
name: taxRateIdIndexName, mappedBy: "rules",
tableName: TABLE_NAME, }),
columns: "tax_rate_id", reference: model.text(),
where: "deleted_at IS NULL", reference_id: model.text(),
})
const deletedAtIndexStatement = createPsqlIndexStatementHelper({
tableName: TABLE_NAME,
columns: "deleted_at",
where: "deleted_at IS NOT NULL",
})
const referenceIdIndexName = "IDX_tax_rate_rule_reference_id"
const referenceIdIndexStatement = createPsqlIndexStatementHelper({
name: referenceIdIndexName,
tableName: TABLE_NAME,
columns: "reference_id",
where: "deleted_at IS NULL",
})
export const uniqueRateReferenceIndexName =
"IDX_tax_rate_rule_unique_rate_reference"
const uniqueRateReferenceIndexStatement = createPsqlIndexStatementHelper({
name: uniqueRateReferenceIndexName,
tableName: TABLE_NAME,
columns: ["tax_rate_id", "reference_id"],
unique: true,
where: "deleted_at IS NULL",
})
@Entity({ tableName: TABLE_NAME })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
@uniqueRateReferenceIndexStatement.MikroORMIndex()
export default class TaxRateRule {
[OptionalProps]?: OptionalRuleProps
@PrimaryKey({ columnType: "text" })
id!: string
@ManyToOne(() => TaxRate, {
type: "text",
fieldName: "tax_rate_id",
mapToPk: true,
onDelete: "cascade",
}) })
@taxRateIdIndexStatement.MikroORMIndex() .indexes([
tax_rate_id: string {
name: "IDX_tax_rate_rule_reference_id",
on: ["reference_id"],
where: "deleted_at IS NULL",
},
{
name: "IDX_tax_rate_rule_unique_rate_reference",
on: ["tax_rate_id", "reference_id"],
unique: true,
where: "deleted_at IS NULL",
},
])
@Property({ columnType: "text" }) export default TaxRateRule
@referenceIdIndexStatement.MikroORMIndex()
reference_id: string
@Property({ columnType: "text" })
reference: string
@ManyToOne(() => TaxRate, { persist: false })
tax_rate: Rel<TaxRate>
@Property({ columnType: "jsonb", nullable: true })
metadata: Record<string, unknown> | null = 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
@Property({ columnType: "text", nullable: true })
created_by: string | null = null
@deletedAtIndexStatement.MikroORMIndex()
@Property({ columnType: "timestamptz", nullable: true })
deleted_at: Date | null = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "txrule")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "txrule")
}
}
+33 -122
View File
@@ -1,128 +1,39 @@
import { DAL } from "@medusajs/framework/types" import { model } from "@medusajs/framework/utils"
import {
createPsqlIndexStatementHelper,
DALUtils,
generateEntityId,
Searchable,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Cascade,
Collection,
Entity,
Filter,
ManyToOne,
OneToMany,
OnInit,
OptionalProps,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import TaxRateRule from "./tax-rate-rule" import TaxRateRule from "./tax-rate-rule"
import TaxRegion from "./tax-region" import TaxRegion from "./tax-region"
type OptionalTaxRateProps = DAL.SoftDeletableModelDateColumns const TaxRate = model
.define("TaxRate", {
const TABLE_NAME = "tax_rate" id: model.id({ prefix: "txr" }).primaryKey(),
rate: model.float().nullable(),
export const singleDefaultRegionIndexName = "IDX_single_default_region" code: model.text().searchable(),
const singleDefaultRegionIndexStatement = createPsqlIndexStatementHelper({ name: model.text().searchable(),
name: singleDefaultRegionIndexName, is_default: model.boolean().default(false),
tableName: TABLE_NAME, is_combinable: model.boolean().default(false),
columns: "tax_region_id", tax_region: model.belongsTo(() => TaxRegion, {
unique: true, mappedBy: "tax_rates",
where: "is_default = true AND deleted_at IS NULL", }),
}) rules: model.hasMany(() => TaxRateRule, {
mappedBy: "tax_rate",
const taxRegionIdIndexName = "IDX_tax_rate_tax_region_id" }),
const taxRegionIdIndexStatement = createPsqlIndexStatementHelper({ metadata: model.json().nullable(),
name: taxRegionIdIndexName, created_by: model.text().nullable(),
tableName: TABLE_NAME,
columns: "tax_region_id",
where: "deleted_at IS NULL",
})
const deletedAtIndexStatement = createPsqlIndexStatementHelper({
tableName: TABLE_NAME,
columns: "deleted_at",
where: "deleted_at IS NOT NULL",
})
@singleDefaultRegionIndexStatement.MikroORMIndex()
@Entity({ tableName: TABLE_NAME })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
export default class TaxRate {
[OptionalProps]?: OptionalTaxRateProps
@PrimaryKey({ columnType: "text" })
id!: string
@Property({ columnType: "real", nullable: true })
rate: number | null = null
@Searchable()
@Property({ columnType: "text" })
code: string
@Searchable()
@Property({ columnType: "text" })
name: string
@Property({ columnType: "bool", default: false })
is_default: boolean = false
@Property({ columnType: "bool", default: false })
is_combinable: boolean = false
@ManyToOne(() => TaxRegion, {
columnType: "text",
fieldName: "tax_region_id",
mapToPk: true,
onDelete: "cascade",
}) })
@taxRegionIdIndexStatement.MikroORMIndex() .indexes([
tax_region_id: string {
name: "IDX_tax_rate_tax_region_id",
@ManyToOne({ entity: () => TaxRegion, persist: false }) on: ["tax_region_id"],
tax_region: Rel<TaxRegion> where: "deleted_at IS NULL",
},
@OneToMany(() => TaxRateRule, (rule) => rule.tax_rate, { {
cascade: ["soft-remove" as Cascade], name: "IDX_single_default_region",
on: ["tax_region_id"],
unique: true,
where: "is_default = true AND deleted_at IS NULL",
},
])
.cascades({
delete: ["rules"],
}) })
rules = new Collection<Rel<TaxRateRule>>(this)
@Property({ columnType: "jsonb", nullable: true }) export default TaxRate
metadata: Record<string, unknown> | null = 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
@Property({ columnType: "text", nullable: true })
created_by: string | null = null
@deletedAtIndexStatement.MikroORMIndex()
@Property({ columnType: "timestamptz", nullable: true })
deleted_at: Date | null = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "txr")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "txr")
}
}
+51 -143
View File
@@ -1,153 +1,61 @@
import { DAL } from "@medusajs/framework/types" import { model } from "@medusajs/framework/utils"
import {
createPsqlIndexStatementHelper,
DALUtils,
generateEntityId,
Searchable,
} from "@medusajs/framework/utils"
import {
BeforeCreate,
Cascade,
Check,
Collection,
Entity,
Filter,
ManyToOne,
OneToMany,
OnInit,
OptionalProps,
PrimaryKey,
Property,
Rel,
} from "@mikro-orm/core"
import TaxProvider from "./tax-provider" import TaxProvider from "./tax-provider"
import TaxRate from "./tax-rate" import TaxRate from "./tax-rate"
type OptionalTaxRegionProps = DAL.SoftDeletableModelDateColumns
const TABLE_NAME = "tax_region"
export const countryCodeNullProvinceIndexName =
"IDX_tax_region_unique_country_nullable_province"
export const countryCodeProvinceIndexName =
"IDX_tax_region_unique_country_province"
const countryCodeProvinceIndexStatement = createPsqlIndexStatementHelper({
name: countryCodeProvinceIndexName,
tableName: TABLE_NAME,
columns: ["country_code", "province_code"],
unique: true,
where: "deleted_at IS NULL",
})
const deletedAtIndexStatement = createPsqlIndexStatementHelper({
tableName: TABLE_NAME,
columns: "deleted_at",
where: "deleted_at IS NOT 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 =
"CK_tax_region_provider_top_level" "CK_tax_region_provider_top_level"
export const taxRegionCountryTopLevelCheckName = export const taxRegionCountryTopLevelCheckName =
"CK_tax_region_country_top_level" "CK_tax_region_country_top_level"
@Check({ const TaxRegion = model
name: taxRegionProviderTopLevelCheckName, .define("TaxRegion", {
expression: `parent_id IS NULL OR provider_id IS NULL`, id: model.id({ prefix: "txreg" }).primaryKey(),
}) country_code: model.text().searchable(),
@Check({ province_code: model.text().searchable().nullable(),
name: taxRegionCountryTopLevelCheckName, metadata: model.json().nullable(),
expression: `parent_id IS NULL OR province_code IS NOT NULL`, created_by: model.text().nullable(),
}) provider: model
@countryCodeNullableProvinceIndexStatement.MikroORMIndex() .belongsTo(() => TaxProvider, {
@countryCodeProvinceIndexStatement.MikroORMIndex() mappedBy: "regions",
@Entity({ tableName: TABLE_NAME }) })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) .nullable(),
export default class TaxRegion { parent: model
[OptionalProps]?: OptionalTaxRegionProps .belongsTo(() => TaxRegion, {
mappedBy: "children",
@PrimaryKey({ columnType: "text" }) })
id!: string .nullable(),
children: model.hasMany(() => TaxRegion, {
@ManyToOne(() => TaxProvider, { mappedBy: "parent",
fieldName: "provider_id", }),
mapToPk: true, tax_rates: model.hasMany(() => TaxRate, {
nullable: true, mappedBy: "tax_region",
}),
}) })
provider_id: string | null = null .checks([
{
@ManyToOne(() => TaxProvider, { persist: false }) name: taxRegionProviderTopLevelCheckName,
provider: Rel<TaxProvider> expression: `parent_id IS NULL OR provider_id IS NULL`,
},
@Searchable() {
@Property({ columnType: "text" }) name: taxRegionCountryTopLevelCheckName,
country_code: string expression: `parent_id IS NULL OR province_code IS NOT NULL`,
},
@Searchable() ])
@Property({ columnType: "text", nullable: true }) .indexes([
province_code: string | null = null {
name: "IDX_tax_region_unique_country_province",
@ManyToOne(() => TaxRegion, { on: ["country_code", "province_code"],
index: "IDX_tax_region_parent_id", unique: true,
fieldName: "parent_id", where: "deleted_at IS NULL",
onDelete: "cascade", },
mapToPk: true, {
nullable: true, name: "IDX_tax_region_unique_country_nullable_province",
on: ["country_code"],
unique: true,
where: "province_code IS NULL AND deleted_at IS NULL",
},
])
.cascades({
delete: ["children", "tax_rates"],
}) })
parent_id: string | null = null export default TaxRegion
@ManyToOne(() => TaxRegion, { persist: false })
parent: Rel<TaxRegion>
@OneToMany(() => TaxRate, (label) => label.tax_region, {
cascade: ["soft-remove" as Cascade],
})
tax_rates = new Collection<TaxRate>(this)
@OneToMany(() => TaxRegion, (label) => label.parent, {
cascade: ["soft-remove" as Cascade],
})
children = new Collection<Rel<TaxRegion>>(this)
@Property({ columnType: "jsonb", nullable: true })
metadata: Record<string, unknown> | null = 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
@Property({ columnType: "text", nullable: true })
created_by: string | null = null
@deletedAtIndexStatement.MikroORMIndex()
@Property({ columnType: "timestamptz", nullable: true })
deleted_at: Date | null = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "txreg")
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "txreg")
}
}
@@ -1,6 +1,7 @@
import { import {
Context, Context,
DAL, DAL,
InferEntityType,
InternalModuleDeclaration, InternalModuleDeclaration,
ITaxModuleService, ITaxModuleService,
ITaxProvider, ITaxProvider,
@@ -32,7 +33,7 @@ type InjectedDependencies = {
const generateForModels = { TaxRate, TaxRegion, TaxRateRule, TaxProvider } const generateForModels = { TaxRate, TaxRegion, TaxRateRule, TaxProvider }
type ItemWithRates = { type ItemWithRates = {
rates: TaxRate[] rates: InferEntityType<typeof TaxRate>[]
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO
} }
@@ -47,10 +48,18 @@ export default class TaxModuleService
{ {
protected readonly container_: InjectedDependencies protected readonly container_: InjectedDependencies
protected baseRepository_: DAL.RepositoryService protected baseRepository_: DAL.RepositoryService
protected taxRateService_: ModulesSdkTypes.IMedusaInternalService<TaxRate> protected taxRateService_: ModulesSdkTypes.IMedusaInternalService<
protected taxRegionService_: ModulesSdkTypes.IMedusaInternalService<TaxRegion> InferEntityType<typeof TaxRate>
protected taxRateRuleService_: ModulesSdkTypes.IMedusaInternalService<TaxRateRule> >
protected taxProviderService_: ModulesSdkTypes.IMedusaInternalService<TaxProvider> protected taxRegionService_: ModulesSdkTypes.IMedusaInternalService<
InferEntityType<typeof TaxRegion>
>
protected taxRateRuleService_: ModulesSdkTypes.IMedusaInternalService<
InferEntityType<typeof TaxRateRule>
>
protected taxProviderService_: ModulesSdkTypes.IMedusaInternalService<
InferEntityType<typeof TaxProvider>
>
constructor( constructor(
{ {
@@ -568,8 +577,8 @@ export default class TaxModuleService
private async getTaxRatesForItem( private async getTaxRatesForItem(
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO, item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO,
rates: TaxRate[] rates: InferEntityType<typeof TaxRate>[]
): Promise<TaxRate[]> { ): Promise<InferEntityType<typeof TaxRate>[]> {
if (!rates.length) { if (!rates.length) {
return [] return []
} }
@@ -630,7 +639,7 @@ export default class TaxModuleService
} }
private checkRuleMatches( private checkRuleMatches(
rate: TaxRate, rate: InferEntityType<typeof TaxRate>,
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO
) { ) {
if (rate.rules.length === 0) { if (rate.rules.length === 0) {
@@ -670,7 +679,7 @@ export default class TaxModuleService
} }
private prioritizeRates( private prioritizeRates(
rates: TaxRate[], rates: InferEntityType<typeof TaxRate>[],
item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO item: TaxTypes.TaxableItemDTO | TaxTypes.TaxableShippingDTO
) { ) {
const decoratedRates = rates.map((rate) => { const decoratedRates = rates.map((rate) => {
@@ -700,7 +709,7 @@ export default class TaxModuleService
} }
return decoratedRate return decoratedRate
}) as (TaxRate & { }) as (InferEntityType<typeof TaxRate> & {
priority_score: number priority_score: number
})[] })[]