Skip to content

Commit

Permalink
feat(core-flows,types,medusa): Add tax region update API (medusajs#9634)
Browse files Browse the repository at this point in the history
* feat(core-flows,types,medusa): Add tax region update API

* chore: added specs
  • Loading branch information
riqwan authored Oct 17, 2024
1 parent 2cba362 commit 3b50c6d
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 12 deletions.
106 changes: 106 additions & 0 deletions integration-tests/http/__tests__/tax-region/admin/tax-region.spec.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 58 additions & 0 deletions packages/core/core-flows/src/tax/steps/update-tax-regions.ts
Original file line number Diff line number Diff line change
@@ -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)
}
)
11 changes: 6 additions & 5 deletions packages/core/core-flows/src/tax/workflows/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export * from "./create-tax-regions"
export * from "./delete-tax-regions"
export * from "./create-tax-rate-rules"
export * from "./create-tax-rates"
export * from "./update-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 "./create-tax-rate-rules"
export * from "./delete-tax-rate-rules"
export * from "./update-tax-rates"
export * from "./update-tax-regions"
20 changes: 20 additions & 0 deletions packages/core/core-flows/src/tax/workflows/update-tax-regions.ts
Original file line number Diff line number Diff line change
@@ -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))
}
)
20 changes: 20 additions & 0 deletions packages/core/types/src/tax/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
42 changes: 42 additions & 0 deletions packages/core/types/src/tax/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
CreateTaxRateRuleDTO,
CreateTaxRegionDTO,
UpdateTaxRateDTO,
UpdateTaxRegionDTO,
UpsertTaxRateDTO,
} from "./mutations"

Expand Down Expand Up @@ -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.
*
Expand Down
46 changes: 41 additions & 5 deletions packages/medusa/src/api/admin/tax-regions/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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>
Expand Down
16 changes: 14 additions & 2 deletions packages/medusa/src/api/admin/tax-regions/middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [
{
Expand All @@ -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
),
],
},
Expand Down
6 changes: 6 additions & 0 deletions packages/medusa/src/api/admin/tax-regions/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
})

0 comments on commit 3b50c6d

Please sign in to comment.