feat(core-flows,types,medusa): Add tax region update API (#9634)
* feat(core-flows,types,medusa): Add tax region update API * chore: added specs
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||
import { createAdminUser } from "../../../../helpers/create-admin-user"
|
||||
|
||||
jest.setTimeout(50000)
|
||||
|
||||
const env = { MEDUSA_FF_MEDUSA_V2: true }
|
||||
const adminHeaders = {
|
||||
headers: { "x-medusa-access-token": "test_token" },
|
||||
}
|
||||
|
||||
medusaIntegrationTestRunner({
|
||||
env,
|
||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||
describe("/admin/tax-regions", () => {
|
||||
beforeEach(async () => {
|
||||
await createAdminUser(dbConnection, adminHeaders, getContainer())
|
||||
})
|
||||
|
||||
describe("POST /admin/tax-regions/:id", () => {
|
||||
let taxRegion
|
||||
|
||||
beforeEach(async () => {
|
||||
taxRegion = (
|
||||
await api.post(
|
||||
"/admin/tax-regions",
|
||||
{
|
||||
country_code: "us",
|
||||
province_code: "tx",
|
||||
metadata: { test: "created" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.tax_region
|
||||
})
|
||||
|
||||
it("should successfully update a tax region's fieleds", async () => {
|
||||
let taxRegionResponse = await api.post(
|
||||
`/admin/tax-regions/${taxRegion.id}`,
|
||||
{
|
||||
province_code: "ny",
|
||||
metadata: { test: "updated" },
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(taxRegionResponse.status).toEqual(200)
|
||||
expect(taxRegionResponse.data.tax_region).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
province_code: "ny",
|
||||
metadata: { test: "updated" },
|
||||
})
|
||||
)
|
||||
|
||||
taxRegionResponse = await api.post(
|
||||
`/admin/tax-regions/${taxRegion.id}`,
|
||||
{ metadata: { test: "updated 2" } },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(taxRegionResponse.status).toEqual(200)
|
||||
expect(taxRegionResponse.data.tax_region).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
province_code: "ny",
|
||||
metadata: { test: "updated 2" },
|
||||
})
|
||||
)
|
||||
|
||||
taxRegionResponse = await api.post(
|
||||
`/admin/tax-regions/${taxRegion.id}`,
|
||||
{ province_code: "ca" },
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(taxRegionResponse.status).toEqual(200)
|
||||
expect(taxRegionResponse.data.tax_region).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
province_code: "ca",
|
||||
metadata: { test: "updated 2" },
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw if tax region does not exist", async () => {
|
||||
const {
|
||||
response: { status, data },
|
||||
} = await api
|
||||
.post(
|
||||
`/admin/tax-regions/does-not-exist`,
|
||||
{ province_code: "ny", metadata: { test: "updated" } },
|
||||
adminHeaders
|
||||
)
|
||||
.catch((err) => err)
|
||||
|
||||
expect(status).toEqual(404)
|
||||
expect(data).toEqual({
|
||||
message: 'TaxRegion with id "does-not-exist" not found',
|
||||
type: "not_found",
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
58
packages/core/core-flows/src/tax/steps/update-tax-regions.ts
Normal file
58
packages/core/core-flows/src/tax/steps/update-tax-regions.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
ITaxModuleService,
|
||||
UpdateTaxRegionDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
import {
|
||||
Modules,
|
||||
getSelectsAndRelationsFromObjectArray,
|
||||
removeUndefined,
|
||||
} from "@medusajs/framework/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
|
||||
|
||||
export const updateTaxRegionsStepId = "update-tax-regions"
|
||||
/**
|
||||
* This step updates tax regions
|
||||
*/
|
||||
export const updateTaxRegionsStep = createStep(
|
||||
updateTaxRegionsStepId,
|
||||
async (data: UpdateTaxRegionDTO[], { container }) => {
|
||||
const service = container.resolve<ITaxModuleService>(Modules.TAX)
|
||||
const { selects, relations } = getSelectsAndRelationsFromObjectArray(data)
|
||||
|
||||
const prevData = await service.listTaxRegions(
|
||||
{ id: data.map((d) => d.id) },
|
||||
{
|
||||
select: selects,
|
||||
relations,
|
||||
}
|
||||
)
|
||||
|
||||
const updateData = removeUndefined(
|
||||
data.map((d) => ({
|
||||
id: d.id,
|
||||
province_code: d.province_code,
|
||||
metadata: d.metadata,
|
||||
}))
|
||||
)
|
||||
|
||||
const taxRegions = await service.updateTaxRegions(updateData)
|
||||
|
||||
return new StepResponse(taxRegions, prevData)
|
||||
},
|
||||
async (prevData, { container }) => {
|
||||
if (!prevData?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const service = container.resolve<ITaxModuleService>(Modules.TAX)
|
||||
const updateData = removeUndefined(
|
||||
prevData.map((d) => ({
|
||||
id: d.id,
|
||||
province_code: d.province_code,
|
||||
metadata: d.metadata,
|
||||
}))
|
||||
)
|
||||
|
||||
await service.updateTaxRegions(updateData)
|
||||
}
|
||||
)
|
||||
@@ -1,8 +1,9 @@
|
||||
export * from "./create-tax-regions"
|
||||
export * from "./delete-tax-regions"
|
||||
export * from "./create-tax-rates"
|
||||
export * from "./update-tax-rates"
|
||||
export * from "./delete-tax-rates"
|
||||
export * from "./set-tax-rate-rules"
|
||||
export * from "./create-tax-rate-rules"
|
||||
export * from "./create-tax-rates"
|
||||
export * from "./create-tax-regions"
|
||||
export * from "./delete-tax-rate-rules"
|
||||
export * from "./delete-tax-rates"
|
||||
export * from "./delete-tax-regions"
|
||||
export * from "./set-tax-rate-rules"
|
||||
export * from "./update-tax-rates"
|
||||
export * from "./update-tax-regions"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { TaxRegionDTO, UpdateTaxRegionDTO } from "@medusajs/framework/types"
|
||||
import {
|
||||
WorkflowData,
|
||||
WorkflowResponse,
|
||||
createWorkflow,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
import { updateTaxRegionsStep } from "../steps/update-tax-regions"
|
||||
|
||||
export const updateTaxRegionsWorkflowId = "update-tax-regions"
|
||||
/**
|
||||
* This workflow updates one or more tax regions.
|
||||
*/
|
||||
export const updateTaxRegionsWorkflow = createWorkflow(
|
||||
updateTaxRegionsWorkflowId,
|
||||
(
|
||||
input: WorkflowData<UpdateTaxRegionDTO[]>
|
||||
): WorkflowResponse<TaxRegionDTO[]> => {
|
||||
return new WorkflowResponse(updateTaxRegionsStep(input))
|
||||
}
|
||||
)
|
||||
@@ -206,6 +206,26 @@ export interface CreateTaxRegionDTO {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The tax region to be updated.
|
||||
*/
|
||||
export interface UpdateTaxRegionDTO {
|
||||
/**
|
||||
* The id of the tax region to update
|
||||
*/
|
||||
id: string
|
||||
|
||||
/**
|
||||
* The province code of the tax region.
|
||||
*/
|
||||
province_code?: string | null
|
||||
|
||||
/**
|
||||
* Holds custom data in key-value pairs.
|
||||
*/
|
||||
metadata?: MetadataType
|
||||
}
|
||||
|
||||
/**
|
||||
* The tax rate rule to be created.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
CreateTaxRateRuleDTO,
|
||||
CreateTaxRegionDTO,
|
||||
UpdateTaxRateDTO,
|
||||
UpdateTaxRegionDTO,
|
||||
UpsertTaxRateDTO,
|
||||
} from "./mutations"
|
||||
|
||||
@@ -407,6 +408,47 @@ export interface ITaxModuleService extends IModuleService {
|
||||
sharedContext?: Context
|
||||
): Promise<TaxRegionDTO[]>
|
||||
|
||||
/**
|
||||
* This method updates a tax region.
|
||||
*
|
||||
* @param {UpdateTaxRegionDTO} data - The tax region to be updated.
|
||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||
* @returns {Promise<TaxRegionDTO>} The updated tax region.
|
||||
*
|
||||
* @example
|
||||
* const taxRegion = await taxModule.updateTaxRegions({
|
||||
* province_code: "be",
|
||||
* })
|
||||
*/
|
||||
updateTaxRegions(
|
||||
data: UpdateTaxRegionDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<TaxRegionDTO>
|
||||
|
||||
/**
|
||||
* This method updates tax regions.
|
||||
*
|
||||
* @param {UpdateTaxRegionDTO[]} data - The tax regions to be updated.
|
||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||
* @returns {Promise<TaxRegionDTO[]>} The updated tax regions.
|
||||
*
|
||||
* @example
|
||||
* const taxRegions = await taxModule.updateTaxRegions([
|
||||
* {
|
||||
* id: "tx-1",
|
||||
* province_code: "be",
|
||||
* },
|
||||
* {
|
||||
* id: "tx-2",
|
||||
* province_code: "ca",
|
||||
* },
|
||||
* ])
|
||||
*/
|
||||
updateTaxRegions(
|
||||
data: UpdateTaxRegionDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<TaxRegionDTO[]>
|
||||
|
||||
/**
|
||||
* This method deletes tax regions by their IDs.
|
||||
*
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { deleteTaxRegionsWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/framework/utils"
|
||||
deleteTaxRegionsWorkflow,
|
||||
updateTaxRegionsWorkflow,
|
||||
} from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "@medusajs/framework/http"
|
||||
import { HttpTypes } from "@medusajs/framework/types"
|
||||
import { HttpTypes, RemoteQueryFunction } from "@medusajs/framework/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/framework/utils"
|
||||
import { AdminUpdateTaxRegionType } from "../validators"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
@@ -27,6 +31,38 @@ export const GET = async (
|
||||
res.status(200).json({ tax_region: taxRegion })
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminUpdateTaxRegionType>,
|
||||
res: MedusaResponse<HttpTypes.AdminTaxRegionResponse>
|
||||
) => {
|
||||
const { id } = req.params
|
||||
const query = req.scope.resolve<RemoteQueryFunction>(
|
||||
ContainerRegistrationKeys.QUERY
|
||||
)
|
||||
|
||||
await updateTaxRegionsWorkflow(req.scope).run({
|
||||
input: [
|
||||
{
|
||||
id,
|
||||
...req.validatedBody,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const {
|
||||
data: [tax_region],
|
||||
} = await query.graph(
|
||||
{
|
||||
entity: "tax_region",
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
filters: { id },
|
||||
},
|
||||
{ throwIfKeyNotFound: true }
|
||||
)
|
||||
|
||||
return res.json({ tax_region })
|
||||
}
|
||||
|
||||
export const DELETE = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse<HttpTypes.AdminTaxRegionDeleteResponse>
|
||||
|
||||
@@ -4,13 +4,14 @@ import {
|
||||
AdminCreateTaxRegion,
|
||||
AdminGetTaxRegionParams,
|
||||
AdminGetTaxRegionsParams,
|
||||
AdminUpdateTaxRegion,
|
||||
} from "./validators"
|
||||
|
||||
import { MiddlewareRoute } from "@medusajs/framework/http"
|
||||
import {
|
||||
validateAndTransformBody,
|
||||
validateAndTransformQuery,
|
||||
} from "@medusajs/framework"
|
||||
import { MiddlewareRoute } from "@medusajs/framework/http"
|
||||
|
||||
export const adminTaxRegionRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
{
|
||||
@@ -20,7 +21,18 @@ export const adminTaxRegionRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
validateAndTransformBody(AdminCreateTaxRegion),
|
||||
validateAndTransformQuery(
|
||||
AdminGetTaxRegionsParams,
|
||||
QueryConfig.listTransformQueryConfig
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: "POST",
|
||||
matcher: "/admin/tax-regions/:id",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminUpdateTaxRegion),
|
||||
validateAndTransformQuery(
|
||||
AdminGetTaxRegionsParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
|
||||
@@ -54,3 +54,9 @@ export const AdminCreateTaxRegion = z.object({
|
||||
.optional(),
|
||||
metadata: z.record(z.unknown()).nullish(),
|
||||
})
|
||||
|
||||
export type AdminUpdateTaxRegionType = z.infer<typeof AdminUpdateTaxRegion>
|
||||
export const AdminUpdateTaxRegion = z.object({
|
||||
province_code: z.string().nullish(),
|
||||
metadata: z.record(z.unknown()).nullish(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user