feat(dashboard, js-sdk, medusa, tax, types): custom tax providers (#12297)

* wip: setup loaders, add endpoints, module work, types, js sdk

* fix: tax module provider loader

* feat: select provider on region create, fix enpoint middleware registration

* feat: edit form

* fix: rename param

* chore: changeset

* fix: don't default to system provider

* fix: admin fixes, dispalt tax provider

* fix: some tests and types

* fix: remove provider from province regions in test

* fix: more tests, optional provider for sublevel regions, fix few types

* fix: OE test

* feat: edit tax region admin, update tax region core flow changes

* feat: migrate script

* fix: refactor

* chore: use query graph

* feat: provider section
This commit is contained in:
Frane Polić
2025-05-06 19:26:33 +02:00
committed by GitHub
parent 405ee7f7f3
commit 9cedeb182d
48 changed files with 847 additions and 116 deletions
@@ -0,0 +1,19 @@
import * as QueryConfig from "./query-config"
import { validateAndTransformQuery } from "@medusajs/framework"
import { MiddlewareRoute } from "@medusajs/framework/http"
import { AdminGetTaxProvidersParams } from "./validators"
export const adminTaxProviderRoutesMiddlewares: MiddlewareRoute[] = [
{
method: "GET",
matcher: "/admin/tax-providers",
middlewares: [
validateAndTransformQuery(
AdminGetTaxProvidersParams,
QueryConfig.listTransformQueryConfig
),
],
},
]
@@ -0,0 +1,11 @@
export const defaults = ["id", "is_enabled"]
export const retrieveTransformQueryConfig = {
defaults,
isList: false,
}
export const listTransformQueryConfig = {
...retrieveTransformQueryConfig,
isList: true,
}
@@ -0,0 +1,28 @@
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { HttpTypes } from "@medusajs/framework/types"
export const GET = async (
req: AuthenticatedMedusaRequest<HttpTypes.AdminGetTaxProvidersParams>,
res: MedusaResponse<HttpTypes.AdminTaxProviderListResponse>
) => {
const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)
const result = await query.graph({
entity: "tax_providers",
filters: req.filterableFields,
pagination: req.queryConfig.pagination,
fields: req.queryConfig.fields,
})
res.status(200).json({
tax_providers: result.data,
count: result.metadata?.count ?? 0,
offset: result.metadata?.skip ?? 0,
limit: result.metadata?.take ?? 0,
})
}
@@ -0,0 +1,22 @@
import { z } from "zod"
import { createFindParams } from "../../utils/validators"
import { applyAndAndOrOperators } from "../../utils/common-validators"
export const AdminGetTaxProvidersParamsFields = z.object({
id: z.union([z.string(), z.array(z.string())]).optional(),
is_enabled: z.boolean().optional(),
})
export type AdminGetTaxProvidersParamsFieldsType = z.infer<
typeof AdminGetTaxProvidersParamsFields
>
export type AdminGetTaxProvidersParamsType = z.infer<
typeof AdminGetTaxProvidersParams
>
export const AdminGetTaxProvidersParams = createFindParams({
limit: 20,
offset: 0,
})
.merge(AdminGetTaxProvidersParamsFields)
.merge(applyAndAndOrOperators(AdminGetTaxProvidersParamsFields))
@@ -14,7 +14,7 @@ import {
import { AdminUpdateTaxRegionType } from "../validators"
export const GET = async (
req: AuthenticatedMedusaRequest,
req: AuthenticatedMedusaRequest<HttpTypes.AdminUpdateTaxRegion>,
res: MedusaResponse<HttpTypes.AdminTaxRegionResponse>
) => {
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
@@ -42,6 +42,7 @@ export const AdminGetTaxRegionsParams = createFindParams({
export type AdminCreateTaxRegionType = z.infer<typeof AdminCreateTaxRegion>
export const AdminCreateTaxRegion = z.object({
country_code: z.string(),
provider_id: z.string().nullish(),
province_code: z.string().nullish(),
parent_id: z.string().nullish(),
default_tax_rate: z
@@ -59,5 +60,6 @@ export const AdminCreateTaxRegion = z.object({
export type AdminUpdateTaxRegionType = z.infer<typeof AdminUpdateTaxRegion>
export const AdminUpdateTaxRegion = z.object({
province_code: z.string().nullish(),
provider_id: z.string().optional(),
metadata: z.record(z.unknown()).nullish(),
})