From c4760dfd5fb97f0d1b4216a304f4577a3814dbc7 Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Thu, 29 Feb 2024 13:06:11 +0100 Subject: [PATCH] feat(tax): v2 api tax rates and regions deletes (#6541) --- .../plugins/__tests__/tax/admin/tax.spec.ts | 78 +++++++++++++++++++ .../src/tax/steps/delete-tax-rates.ts | 28 +++++++ .../src/tax/steps/delete-tax-regions.ts | 28 +++++++ packages/core-flows/src/tax/steps/index.ts | 2 + .../src/tax/workflows/delete-tax-rates.ts | 12 +++ .../src/tax/workflows/delete-tax-regions.ts | 12 +++ .../core-flows/src/tax/workflows/index.ts | 2 + .../src/api-v2/admin/tax-rates/[id]/route.ts | 27 ++++++- .../api-v2/admin/tax-regions/[id]/route.ts | 27 +++++++ packages/types/src/tax/common.ts | 1 + packages/types/src/tax/service.ts | 14 +++- 11 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 packages/core-flows/src/tax/steps/delete-tax-rates.ts create mode 100644 packages/core-flows/src/tax/steps/delete-tax-regions.ts create mode 100644 packages/core-flows/src/tax/workflows/delete-tax-rates.ts create mode 100644 packages/core-flows/src/tax/workflows/delete-tax-regions.ts create mode 100644 packages/medusa/src/api-v2/admin/tax-regions/[id]/route.ts diff --git a/integration-tests/plugins/__tests__/tax/admin/tax.spec.ts b/integration-tests/plugins/__tests__/tax/admin/tax.spec.ts index 703cce2a22ae4..23c675cbadda5 100644 --- a/integration-tests/plugins/__tests__/tax/admin/tax.spec.ts +++ b/integration-tests/plugins/__tests__/tax/admin/tax.spec.ts @@ -295,4 +295,82 @@ describe("Taxes - Admin", () => { }, }) }) + + it("can create a tax rate and delete it", async () => { + const api = useApi() as any + const regionRes = await api.post( + `/admin/tax-regions`, + { + country_code: "us", + default_tax_rate: { code: "default", rate: 2, name: "default rate" }, + }, + adminHeaders + ) + + const usRegionId = regionRes.data.tax_region.id + + const rateRes = await api.post( + `/admin/tax-rates`, + { + tax_region_id: usRegionId, + code: "RATE2", + name: "another rate", + rate: 10, + rules: [{ reference: "product", reference_id: "prod_1234" }], + }, + adminHeaders + ) + + const deleteRes = await api.delete( + `/admin/tax-rates/${rateRes.data.tax_rate.id}`, + adminHeaders + ) + + expect(deleteRes.status).toEqual(200) + expect(deleteRes.data).toEqual({ + id: rateRes.data.tax_rate.id, + object: "tax_rate", + deleted: true, + }) + + const rates = await service.list( + { id: rateRes.data.tax_rate.id }, + { withDeleted: true } + ) + expect(rates.length).toEqual(1) + expect(rates[0].deleted_at).not.toBeNull() + }) + + it("can create a tax region and delete it", async () => { + const api = useApi() as any + const regionRes = await api.post( + `/admin/tax-regions`, + { + country_code: "us", + default_tax_rate: { code: "default", rate: 2, name: "default rate" }, + }, + adminHeaders + ) + + const usRegionId = regionRes.data.tax_region.id + + const deleteRes = await api.delete( + `/admin/tax-regions/${usRegionId}`, + adminHeaders + ) + + expect(deleteRes.status).toEqual(200) + expect(deleteRes.data).toEqual({ + id: usRegionId, + object: "tax_region", + deleted: true, + }) + + const rates = await service.listTaxRegions( + { id: usRegionId }, + { withDeleted: true } + ) + expect(rates.length).toEqual(1) + expect(rates[0].deleted_at).not.toBeNull() + }) }) diff --git a/packages/core-flows/src/tax/steps/delete-tax-rates.ts b/packages/core-flows/src/tax/steps/delete-tax-rates.ts new file mode 100644 index 0000000000000..b574bf0a24651 --- /dev/null +++ b/packages/core-flows/src/tax/steps/delete-tax-rates.ts @@ -0,0 +1,28 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { ITaxModuleService } from "@medusajs/types" +import { StepResponse, createStep } from "@medusajs/workflows-sdk" + +export const deleteTaxRatesStepId = "delete-tax-rates" +export const deleteTaxRatesStep = createStep( + deleteTaxRatesStepId, + async (ids: string[], { container }) => { + const service = container.resolve( + ModuleRegistrationName.TAX + ) + + await service.softDelete(ids) + + return new StepResponse(void 0, ids) + }, + async (prevIds, { container }) => { + if (!prevIds?.length) { + return + } + + const service = container.resolve( + ModuleRegistrationName.TAX + ) + + await service.restore(prevIds) + } +) diff --git a/packages/core-flows/src/tax/steps/delete-tax-regions.ts b/packages/core-flows/src/tax/steps/delete-tax-regions.ts new file mode 100644 index 0000000000000..8e5ea406bb34e --- /dev/null +++ b/packages/core-flows/src/tax/steps/delete-tax-regions.ts @@ -0,0 +1,28 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { ITaxModuleService } from "@medusajs/types" +import { StepResponse, createStep } from "@medusajs/workflows-sdk" + +export const deleteTaxRegionsStepId = "delete-tax-regions" +export const deleteTaxRegionsStep = createStep( + deleteTaxRegionsStepId, + async (ids: string[], { container }) => { + const service = container.resolve( + ModuleRegistrationName.TAX + ) + + await service.softDeleteTaxRegions(ids) + + return new StepResponse(void 0, ids) + }, + async (prevIds, { container }) => { + if (!prevIds?.length) { + return + } + + const service = container.resolve( + ModuleRegistrationName.TAX + ) + + await service.restoreTaxRegions(prevIds) + } +) diff --git a/packages/core-flows/src/tax/steps/index.ts b/packages/core-flows/src/tax/steps/index.ts index 934a5c97c70a1..5bb861dab387d 100644 --- a/packages/core-flows/src/tax/steps/index.ts +++ b/packages/core-flows/src/tax/steps/index.ts @@ -1,3 +1,5 @@ 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" diff --git a/packages/core-flows/src/tax/workflows/delete-tax-rates.ts b/packages/core-flows/src/tax/workflows/delete-tax-rates.ts new file mode 100644 index 0000000000000..aad20cd28a97f --- /dev/null +++ b/packages/core-flows/src/tax/workflows/delete-tax-rates.ts @@ -0,0 +1,12 @@ +import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk" +import { deleteTaxRatesStep } from "../steps" + +type WorkflowInput = { ids: string[] } + +export const deleteTaxRatesWorkflowId = "delete-tax-rates" +export const deleteTaxRatesWorkflow = createWorkflow( + deleteTaxRatesWorkflowId, + (input: WorkflowData): WorkflowData => { + return deleteTaxRatesStep(input.ids) + } +) diff --git a/packages/core-flows/src/tax/workflows/delete-tax-regions.ts b/packages/core-flows/src/tax/workflows/delete-tax-regions.ts new file mode 100644 index 0000000000000..e144799446b20 --- /dev/null +++ b/packages/core-flows/src/tax/workflows/delete-tax-regions.ts @@ -0,0 +1,12 @@ +import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk" +import { deleteTaxRegionsStep } from "../steps" + +type WorkflowInput = { ids: string[] } + +export const deleteTaxRegionsWorkflowId = "delete-tax-regions" +export const deleteTaxRegionsWorkflow = createWorkflow( + deleteTaxRegionsWorkflowId, + (input: WorkflowData): WorkflowData => { + return deleteTaxRegionsStep(input.ids) + } +) diff --git a/packages/core-flows/src/tax/workflows/index.ts b/packages/core-flows/src/tax/workflows/index.ts index 934a5c97c70a1..5bb861dab387d 100644 --- a/packages/core-flows/src/tax/workflows/index.ts +++ b/packages/core-flows/src/tax/workflows/index.ts @@ -1,3 +1,5 @@ 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" diff --git a/packages/medusa/src/api-v2/admin/tax-rates/[id]/route.ts b/packages/medusa/src/api-v2/admin/tax-rates/[id]/route.ts index 1f5e24a27fef2..6f8fdf6b3151a 100644 --- a/packages/medusa/src/api-v2/admin/tax-rates/[id]/route.ts +++ b/packages/medusa/src/api-v2/admin/tax-rates/[id]/route.ts @@ -6,7 +6,10 @@ import { import { defaultAdminTaxRateFields } from "../query-config" import { remoteQueryObjectFromString } from "@medusajs/utils" import { AdminPostTaxRatesTaxRateReq } from "../../../../api/routes/admin/tax-rates" -import { updateTaxRatesWorkflow } from "@medusajs/core-flows" +import { + deleteTaxRatesWorkflow, + updateTaxRatesWorkflow, +} from "@medusajs/core-flows" export const POST = async ( req: AuthenticatedMedusaRequest, @@ -55,3 +58,25 @@ export const GET = async ( res.status(200).json({ tax_rate: taxRate }) } + +export const DELETE = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const id = req.params.id + + const { errors } = await deleteTaxRatesWorkflow(req.scope).run({ + input: { ids: [id] }, + throwOnError: false, + }) + + if (Array.isArray(errors) && errors[0]) { + throw errors[0].error + } + + res.status(200).json({ + id, + object: "tax_rate", + deleted: true, + }) +} diff --git a/packages/medusa/src/api-v2/admin/tax-regions/[id]/route.ts b/packages/medusa/src/api-v2/admin/tax-regions/[id]/route.ts new file mode 100644 index 0000000000000..d23d7f9eec52f --- /dev/null +++ b/packages/medusa/src/api-v2/admin/tax-regions/[id]/route.ts @@ -0,0 +1,27 @@ +import { deleteTaxRegionsWorkflow } from "@medusajs/core-flows" +import { + AuthenticatedMedusaRequest, + MedusaResponse, +} from "../../../../types/routing" + +export const DELETE = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const id = req.params.id + + const { errors } = await deleteTaxRegionsWorkflow(req.scope).run({ + input: { ids: [id] }, + throwOnError: false, + }) + + if (Array.isArray(errors) && errors[0]) { + throw errors[0].error + } + + res.status(200).json({ + id, + object: "tax_region", + deleted: true, + }) +} diff --git a/packages/types/src/tax/common.ts b/packages/types/src/tax/common.ts index ad12557536870..45e4b97e93571 100644 --- a/packages/types/src/tax/common.ts +++ b/packages/types/src/tax/common.ts @@ -78,6 +78,7 @@ export interface TaxRegionDTO { created_at: string | Date updated_at: string | Date created_by: string | null + deleted_at: string | Date | null } export interface FilterableTaxRegionProps diff --git a/packages/types/src/tax/service.ts b/packages/types/src/tax/service.ts index b56477f1e8da5..34f719b30f9c3 100644 --- a/packages/types/src/tax/service.ts +++ b/packages/types/src/tax/service.ts @@ -1,5 +1,5 @@ import { FindConfig } from "../common" -import { SoftDeleteReturn } from "../dal" +import { RestoreReturn, SoftDeleteReturn } from "../dal" import { IModuleService } from "../modules-sdk" import { Context } from "../shared-context" import { @@ -73,6 +73,12 @@ export interface ITaxModuleService extends IModuleService { delete(taxRateIds: string[], sharedContext?: Context): Promise delete(taxRateId: string, sharedContext?: Context): Promise + restore( + taxRateIds: string[], + config?: RestoreReturn, + sharedContext?: Context + ): Promise | void> + createTaxRegions( data: CreateTaxRegionDTO, sharedContext?: Context @@ -136,6 +142,12 @@ export interface ITaxModuleService extends IModuleService { sharedContext?: Context ): Promise | void> + restoreTaxRegions( + taxRegionIds: string[], + config?: RestoreReturn, + sharedContext?: Context + ): Promise | void> + softDeleteTaxRateRules( taxRateRulePairs: { tax_rate_id: string; reference_id: string }[], config?: SoftDeleteReturn,