diff --git a/.changeset/orange-bikes-sparkle.md b/.changeset/orange-bikes-sparkle.md new file mode 100644 index 0000000000..8e20d236ee --- /dev/null +++ b/.changeset/orange-bikes-sparkle.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +fix(medusa): Upserting tax rates diff --git a/integration-tests/api/__tests__/taxes/__snapshots__/admin-tax-rates.js.snap b/integration-tests/api/__tests__/taxes/__snapshots__/admin-tax-rates.js.snap index 196fc06eed..c877e3534b 100644 --- a/integration-tests/api/__tests__/taxes/__snapshots__/admin-tax-rates.js.snap +++ b/integration-tests/api/__tests__/taxes/__snapshots__/admin-tax-rates.js.snap @@ -1,17 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`/admin/tax-rates creates a tax rate 1`] = ` -Object { - "code": "tricks", - "created_at": Any, - "id": StringMatching /\\^txr_\\*/, - "name": "special", - "rate": null, - "region_id": "test-region", - "updated_at": Any, -} -`; - exports[`/admin/tax-rates deletes a tax rate 1`] = ` Object { "deleted": true, @@ -38,15 +26,3 @@ Object { "region_id": Any, } `; - -exports[`/admin/tax-rates updates a tax rate 1`] = ` -Object { - "code": "something new", - "created_at": Any, - "id": StringMatching /\\^txr_\\*/, - "name": "special", - "rate": 10, - "region_id": "test-region", - "updated_at": Any, -} -`; diff --git a/integration-tests/api/__tests__/taxes/admin-tax-rates.js b/integration-tests/api/__tests__/taxes/admin-tax-rates.js index 49f98e82c7..618ddbb934 100644 --- a/integration-tests/api/__tests__/taxes/admin-tax-rates.js +++ b/integration-tests/api/__tests__/taxes/admin-tax-rates.js @@ -397,11 +397,84 @@ describe("/admin/tax-rates", () => { ) expect(response.status).toEqual(200) - expect(response.data.tax_rate).toMatchSnapshot({ - id: expect.stringMatching(/^txr_*/), - created_at: expect.any(String), - updated_at: expect.any(String), + expect(response.data.tax_rate).toEqual( + expect.objectContaining({ + id: expect.stringMatching(/^txr_*/), + name: "special", + code: "tricks", + rate: null, + }) + ) + }) + + test("creates a tax rate with a rate", async () => { + await adminSeeder(dbConnection) + + const api = useApi() + await simpleRegionFactory(dbConnection, { + id: "test-region", }) + + const response = await api.post( + `/admin/tax-rates`, + { + name: "special", + code: "tricks", + region_id: "test-region", + rate: 2, + }, + { + headers: { + authorization: "Bearer test_token", + }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.tax_rate).toEqual( + expect.objectContaining({ + id: expect.stringMatching(/^txr_*/), + name: "special", + code: "tricks", + region_id: "test-region", + rate: 2, + }) + ) + }) + + test("creates a tax rate with a null rate", async () => { + await adminSeeder(dbConnection) + + const api = useApi() + await simpleRegionFactory(dbConnection, { + id: "test-region", + }) + + const response = await api.post( + `/admin/tax-rates`, + { + name: "special", + code: "tricks", + region_id: "test-region", + rate: null, + }, + { + headers: { + authorization: "Bearer test_token", + }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.tax_rate).toEqual( + expect.objectContaining({ + id: expect.stringMatching(/^txr_*/), + name: "special", + code: "tricks", + region_id: "test-region", + rate: null, + }) + ) }) test("creates a tax rate and assigns products", async () => { @@ -453,6 +526,7 @@ describe("/admin/tax-rates", () => { { name: "special", code: "something new", + rate: 5, }, { headers: { @@ -462,13 +536,48 @@ describe("/admin/tax-rates", () => { ) expect(response.status).toEqual(200) - expect(response.data.tax_rate).toMatchSnapshot({ - id: expect.stringMatching(/^txr_*/), - code: "special", - code: "something new", - created_at: expect.any(String), - updated_at: expect.any(String), + expect(response.data.tax_rate).toEqual( + expect.objectContaining({ + id: expect.stringMatching(/^txr_*/), + name: "special", + code: "something new", + rate: 5, + }) + ) + }) + + test("updates a tax rate with null rate", async () => { + await adminSeeder(dbConnection) + + await simpleRegionFactory(dbConnection, { id: "test-region" }) + + const rate = await simpleTaxRateFactory(dbConnection, { + name: "test", + code: "something", + rate: 10, + region_id: "test-region", }) + + const api = useApi() + const response = await api.post( + `/admin/tax-rates/${rate.id}`, + { + rate: null, + }, + { + headers: { + authorization: "Bearer test_token", + }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.tax_rate).toEqual( + expect.objectContaining({ + id: expect.stringMatching(/^txr_*/), + rate: null, + }) + ) }) test("deletes a tax rate", async () => { diff --git a/packages/medusa/src/api/routes/admin/tax-rates/create-tax-rate.ts b/packages/medusa/src/api/routes/admin/tax-rates/create-tax-rate.ts index 70e7ea34f9..9a24565bc3 100644 --- a/packages/medusa/src/api/routes/admin/tax-rates/create-tax-rate.ts +++ b/packages/medusa/src/api/routes/admin/tax-rates/create-tax-rate.ts @@ -1,12 +1,11 @@ -import { IsArray, IsOptional, IsString } from "class-validator" +import { IsArray, IsNumber, IsOptional, IsString } from "class-validator" import { getRetrieveConfig, pickByConfig } from "./utils/get-query-config" -import { EntityManager } from "typeorm" -import { IsType } from "../../../../utils/validators/is-type" +import { omit } from "lodash" import { isDefined, MedusaError } from "medusa-core-utils" +import { EntityManager } from "typeorm" import { TaxRate } from "../../../.." import { TaxRateService } from "../../../../services" -import { omit } from "lodash" import { validator } from "../../../../utils/validator" /** @@ -187,7 +186,7 @@ export class AdminPostTaxRatesReq { region_id: string @IsOptional() - @IsType([Number, null]) + @IsNumber() rate?: number | null @IsOptional() diff --git a/packages/medusa/src/api/routes/admin/tax-rates/update-tax-rate.ts b/packages/medusa/src/api/routes/admin/tax-rates/update-tax-rate.ts index 9b01a42856..0966b8c10c 100644 --- a/packages/medusa/src/api/routes/admin/tax-rates/update-tax-rate.ts +++ b/packages/medusa/src/api/routes/admin/tax-rates/update-tax-rate.ts @@ -1,13 +1,12 @@ -import { IsArray, IsOptional, IsString } from "class-validator" +import { IsArray, IsNumber, IsOptional, IsString } from "class-validator" import { getRetrieveConfig, pickByConfig } from "./utils/get-query-config" +import { omit } from "lodash" +import { isDefined } from "medusa-core-utils" import { EntityManager } from "typeorm" -import { IsType } from "../../../../utils/validators/is-type" import { TaxRate } from "../../../.." import { TaxRateService } from "../../../../services" -import { omit } from "lodash" import { validator } from "../../../../utils/validator" -import { isDefined } from "medusa-core-utils" /** * @oas [post] /admin/tax-rates/{id} @@ -183,7 +182,7 @@ export class AdminPostTaxRatesTaxRateReq { region_id?: string @IsOptional() - @IsType([Number, null]) + @IsNumber() rate?: number | null @IsOptional()