fix(utils): bignumber util considers nullable options when setting value (#6499)
what: - when setting null for nullable columns, big number utils should not throw error - remove circular soft delete depenedencies for cart module - trims zeros on big number values
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(utils): bignumber util considers nullable options when setting value
|
||||||
@@ -24,7 +24,7 @@ import LineItem from "./line-item"
|
|||||||
export default class LineItemAdjustment extends AdjustmentLine {
|
export default class LineItemAdjustment extends AdjustmentLine {
|
||||||
@ManyToOne({
|
@ManyToOne({
|
||||||
entity: () => LineItem,
|
entity: () => LineItem,
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST, "soft-remove"] as any,
|
cascade: [Cascade.REMOVE, Cascade.PERSIST],
|
||||||
})
|
})
|
||||||
item: LineItem
|
item: LineItem
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import ShippingMethod from "./shipping-method"
|
|||||||
export default class ShippingMethodAdjustment extends AdjustmentLine {
|
export default class ShippingMethodAdjustment extends AdjustmentLine {
|
||||||
@ManyToOne({
|
@ManyToOne({
|
||||||
entity: () => ShippingMethod,
|
entity: () => ShippingMethod,
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST, "soft-remove"] as any,
|
cascade: [Cascade.REMOVE, Cascade.PERSIST],
|
||||||
})
|
})
|
||||||
shipping_method: ShippingMethod
|
shipping_method: ShippingMethod
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { IPaymentModuleService } from "@medusajs/types"
|
|
||||||
import { Modules } from "@medusajs/modules-sdk"
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
|
import { IPaymentModuleService } from "@medusajs/types"
|
||||||
|
|
||||||
|
import {
|
||||||
|
moduleIntegrationTestRunner,
|
||||||
|
SuiteOptions,
|
||||||
|
} from "medusa-test-utils/dist"
|
||||||
import {
|
import {
|
||||||
createPaymentCollections,
|
createPaymentCollections,
|
||||||
createPayments,
|
createPayments,
|
||||||
createPaymentSessions,
|
createPaymentSessions,
|
||||||
} from "../../../__fixtures__"
|
} from "../../../__fixtures__"
|
||||||
import {
|
|
||||||
moduleIntegrationTestRunner,
|
|
||||||
SuiteOptions,
|
|
||||||
} from "medusa-test-utils/dist"
|
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
@@ -466,7 +466,7 @@ moduleIntegrationTestRunner({
|
|||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
amount: 100,
|
amount: 100,
|
||||||
raw_amount: { value: "100.00000000000000000", precision: 20 },
|
raw_amount: { value: "100", precision: 20 },
|
||||||
provider_id: "system",
|
provider_id: "system",
|
||||||
data: {},
|
data: {},
|
||||||
status: "authorized",
|
status: "authorized",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
export * from "./alter-columns-helper"
|
export * from "./alter-columns-helper"
|
||||||
export * from "./array-difference"
|
export * from "./array-difference"
|
||||||
export * from "./get-set-difference"
|
|
||||||
export * from "./build-query"
|
export * from "./build-query"
|
||||||
export * from "./camel-to-snake-case"
|
export * from "./camel-to-snake-case"
|
||||||
export * from "./container"
|
export * from "./container"
|
||||||
@@ -12,8 +11,10 @@ export * from "./errors"
|
|||||||
export * from "./generate-entity-id"
|
export * from "./generate-entity-id"
|
||||||
export * from "./generate-linkable-keys-map"
|
export * from "./generate-linkable-keys-map"
|
||||||
export * from "./get-config-file"
|
export * from "./get-config-file"
|
||||||
|
export * from "./get-duplicates"
|
||||||
export * from "./get-iso-string-from-date"
|
export * from "./get-iso-string-from-date"
|
||||||
export * from "./get-selects-and-relations-from-object-array"
|
export * from "./get-selects-and-relations-from-object-array"
|
||||||
|
export * from "./get-set-difference"
|
||||||
export * from "./group-by"
|
export * from "./group-by"
|
||||||
export * from "./handle-postgres-database-error"
|
export * from "./handle-postgres-database-error"
|
||||||
export * from "./is-big-number"
|
export * from "./is-big-number"
|
||||||
@@ -35,6 +36,7 @@ export * from "./promise-all"
|
|||||||
export * from "./remote-query-object-from-string"
|
export * from "./remote-query-object-from-string"
|
||||||
export * from "./remote-query-object-to-string"
|
export * from "./remote-query-object-to-string"
|
||||||
export * from "./remove-nullisih"
|
export * from "./remove-nullisih"
|
||||||
|
export * from "./remove-undefined"
|
||||||
export * from "./selector-constraints-to-string"
|
export * from "./selector-constraints-to-string"
|
||||||
export * from "./set-metadata"
|
export * from "./set-metadata"
|
||||||
export * from "./simple-hash"
|
export * from "./simple-hash"
|
||||||
@@ -45,7 +47,6 @@ export * from "./to-camel-case"
|
|||||||
export * from "./to-kebab-case"
|
export * from "./to-kebab-case"
|
||||||
export * from "./to-pascal-case"
|
export * from "./to-pascal-case"
|
||||||
export * from "./transaction"
|
export * from "./transaction"
|
||||||
|
export * from "./trim-zeros"
|
||||||
export * from "./upper-case-first"
|
export * from "./upper-case-first"
|
||||||
export * from "./wrap-handler"
|
export * from "./wrap-handler"
|
||||||
export * from "./remove-undefined"
|
|
||||||
export * from "./get-duplicates"
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export function trimZeros(value: string) {
|
||||||
|
const [whole, fraction] = value.split(".")
|
||||||
|
|
||||||
|
if (fraction) {
|
||||||
|
const decimal = fraction.replace(/0+$/, "")
|
||||||
|
|
||||||
|
if (!decimal) {
|
||||||
|
return whole
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${whole}.${decimal}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return whole
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { MikroOrmBigNumberProperty } from "../big-number-field"
|
|
||||||
import { BigNumberRawValue } from "@medusajs/types"
|
import { BigNumberRawValue } from "@medusajs/types"
|
||||||
import { BigNumber } from "../../../totals/big-number"
|
import { BigNumber } from "../../../totals/big-number"
|
||||||
|
import { MikroOrmBigNumberProperty } from "../big-number-field"
|
||||||
|
|
||||||
describe("@MikroOrmBigNumberProperty", () => {
|
describe("@MikroOrmBigNumberProperty", () => {
|
||||||
it("should correctly assign and update BigNumber values", () => {
|
it("should correctly assign and update BigNumber values", () => {
|
||||||
@@ -9,6 +9,11 @@ describe("@MikroOrmBigNumberProperty", () => {
|
|||||||
amount: BigNumber | number
|
amount: BigNumber | number
|
||||||
|
|
||||||
raw_amount: BigNumberRawValue
|
raw_amount: BigNumberRawValue
|
||||||
|
|
||||||
|
@MikroOrmBigNumberProperty({ nullable: true })
|
||||||
|
nullable_amount: BigNumber | number | null = null
|
||||||
|
|
||||||
|
raw_nullable_amount: BigNumberRawValue | null = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAmount = new TestAmount()
|
const testAmount = new TestAmount()
|
||||||
@@ -21,10 +26,20 @@ describe("@MikroOrmBigNumberProperty", () => {
|
|||||||
expect(testAmount.amount).toEqual(100)
|
expect(testAmount.amount).toEqual(100)
|
||||||
expect((testAmount as any).amount_).toEqual(100)
|
expect((testAmount as any).amount_).toEqual(100)
|
||||||
expect(testAmount.raw_amount).toEqual({
|
expect(testAmount.raw_amount).toEqual({
|
||||||
value: "100.00000000000000000",
|
value: "100",
|
||||||
precision: 20,
|
precision: 20,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
;(testAmount as any).amount = null
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toEqual(
|
||||||
|
"Invalid BigNumber value: null. Should be one of: string, number, BigNumber (bignumber.js), BigNumberRawValue"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
testAmount.nullable_amount = null
|
||||||
|
expect(testAmount.nullable_amount).toEqual(null)
|
||||||
// Update the amount
|
// Update the amount
|
||||||
|
|
||||||
testAmount.amount = 200
|
testAmount.amount = 200
|
||||||
@@ -32,7 +47,7 @@ describe("@MikroOrmBigNumberProperty", () => {
|
|||||||
expect(testAmount.amount).toEqual(200)
|
expect(testAmount.amount).toEqual(200)
|
||||||
expect((testAmount as any).amount_).toEqual(200)
|
expect((testAmount as any).amount_).toEqual(200)
|
||||||
expect(testAmount.raw_amount).toEqual({
|
expect(testAmount.raw_amount).toEqual({
|
||||||
value: "200.00000000000000000",
|
value: "200",
|
||||||
precision: 20,
|
precision: 20,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -42,6 +57,6 @@ describe("@MikroOrmBigNumberProperty", () => {
|
|||||||
|
|
||||||
expect(testAmount.amount).toEqual(300)
|
expect(testAmount.amount).toEqual(300)
|
||||||
expect((testAmount as any).amount_).toEqual(300)
|
expect((testAmount as any).amount_).toEqual(300)
|
||||||
expect(testAmount.raw_amount).toEqual({ value: "300.00", precision: 5 })
|
expect(testAmount.raw_amount).toEqual({ value: "300", precision: 5 })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { BigNumber } from "../../totals/big-number"
|
|
||||||
import { Property } from "@mikro-orm/core"
|
|
||||||
import { BigNumberInput } from "@medusajs/types"
|
import { BigNumberInput } from "@medusajs/types"
|
||||||
|
import { Property } from "@mikro-orm/core"
|
||||||
|
import { isPresent, trimZeros } from "../../common"
|
||||||
|
import { BigNumber } from "../../totals/big-number"
|
||||||
|
|
||||||
export function MikroOrmBigNumberProperty(
|
export function MikroOrmBigNumberProperty(
|
||||||
options: Parameters<typeof Property>[0] & {
|
options: Parameters<typeof Property>[0] & {
|
||||||
@@ -16,21 +17,37 @@ export function MikroOrmBigNumberProperty(
|
|||||||
return this[targetColumn]
|
return this[targetColumn]
|
||||||
},
|
},
|
||||||
set(value: BigNumberInput) {
|
set(value: BigNumberInput) {
|
||||||
|
if (options?.nullable && !isPresent(value)) {
|
||||||
|
this[targetColumn] = null
|
||||||
|
this[rawColumnName] = null
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let bigNumber: BigNumber
|
let bigNumber: BigNumber
|
||||||
|
|
||||||
if (value instanceof BigNumber) {
|
if (value instanceof BigNumber) {
|
||||||
bigNumber = value
|
bigNumber = value
|
||||||
} else if (this[rawColumnName]) {
|
} else if (this[rawColumnName]) {
|
||||||
const precision = this[rawColumnName].precision
|
const precision = this[rawColumnName].precision
|
||||||
this[rawColumnName].value = new BigNumber(value, {
|
|
||||||
precision,
|
this[rawColumnName].value = trimZeros(
|
||||||
}).raw!.value
|
new BigNumber(value, {
|
||||||
|
precision,
|
||||||
|
}).raw!.value as string
|
||||||
|
)
|
||||||
|
|
||||||
bigNumber = new BigNumber(this[rawColumnName])
|
bigNumber = new BigNumber(this[rawColumnName])
|
||||||
} else {
|
} else {
|
||||||
bigNumber = new BigNumber(value)
|
bigNumber = new BigNumber(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
this[targetColumn] = bigNumber.numeric
|
this[targetColumn] = bigNumber.numeric
|
||||||
this[rawColumnName] = bigNumber.raw
|
|
||||||
|
const raw = bigNumber.raw!
|
||||||
|
raw.value = trimZeros(raw.value as string)
|
||||||
|
|
||||||
|
this[rawColumnName] = raw
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,15 @@ describe("BigNumber", function () {
|
|||||||
it("should throw if not correct type", function () {
|
it("should throw if not correct type", function () {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
expect(() => new BigNumber([])).toThrow(
|
expect(() => new BigNumber([])).toThrow(
|
||||||
"Invalid BigNumber value. Should be one of: string, number, BigNumber (bignumber.js), BigNumberRawValue"
|
"Invalid BigNumber value: . Should be one of: string, number, BigNumber (bignumber.js), BigNumberRawValue"
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(() => new BigNumber(null as any)).toThrow(
|
||||||
|
"Invalid BigNumber value: null. Should be one of: string, number, BigNumber (bignumber.js), BigNumberRawValue"
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(() => new BigNumber(undefined as any)).toThrow(
|
||||||
|
"Invalid BigNumber value: undefined. Should be one of: string, number, BigNumber (bignumber.js), BigNumberRawValue"
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,61 +8,61 @@ export class BigNumber {
|
|||||||
private numeric_: number
|
private numeric_: number
|
||||||
private raw_?: BigNumberRawValue
|
private raw_?: BigNumberRawValue
|
||||||
|
|
||||||
constructor(rawPrice: BigNumberInput, options?: { precision?: number }) {
|
constructor(rawValue: BigNumberInput, options?: { precision?: number }) {
|
||||||
this.setRawPriceOrThrow(rawPrice, options)
|
this.setRawValueOrThrow(rawValue, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
setRawPriceOrThrow(
|
setRawValueOrThrow(
|
||||||
rawPrice: BigNumberInput,
|
rawValue: BigNumberInput,
|
||||||
{ precision }: { precision?: number } = {}
|
{ precision }: { precision?: number } = {}
|
||||||
) {
|
) {
|
||||||
precision ??= BigNumber.DEFAULT_PRECISION
|
precision ??= BigNumber.DEFAULT_PRECISION
|
||||||
|
|
||||||
if (BigNumberJS.isBigNumber(rawPrice)) {
|
if (BigNumberJS.isBigNumber(rawValue)) {
|
||||||
/**
|
/**
|
||||||
* Example:
|
* Example:
|
||||||
* const bnUnitPrice = new BigNumberJS("10.99")
|
* const bnUnitValue = new BigNumberJS("10.99")
|
||||||
* const unitPrice = new BigNumber(bnUnitPrice)
|
* const unitValue = new BigNumber(bnUnitValue)
|
||||||
*/
|
*/
|
||||||
this.numeric_ = rawPrice.toNumber()
|
this.numeric_ = rawValue.toNumber()
|
||||||
this.raw_ = {
|
this.raw_ = {
|
||||||
value: rawPrice.toPrecision(precision),
|
value: rawValue.toPrecision(precision),
|
||||||
precision,
|
precision,
|
||||||
}
|
}
|
||||||
} else if (isString(rawPrice)) {
|
} else if (isString(rawValue)) {
|
||||||
/**
|
/**
|
||||||
* Example: const unitPrice = "1234.1234"
|
* Example: const unitValue = "1234.1234"
|
||||||
*/
|
*/
|
||||||
const bigNum = new BigNumberJS(rawPrice)
|
const bigNum = new BigNumberJS(rawValue)
|
||||||
|
|
||||||
this.numeric_ = bigNum.toNumber()
|
this.numeric_ = bigNum.toNumber()
|
||||||
this.raw_ = this.raw_ = {
|
this.raw_ = this.raw_ = {
|
||||||
value: bigNum.toPrecision(precision),
|
value: bigNum.toPrecision(precision),
|
||||||
precision,
|
precision,
|
||||||
}
|
}
|
||||||
} else if (isBigNumber(rawPrice)) {
|
} else if (isBigNumber(rawValue)) {
|
||||||
/**
|
/**
|
||||||
* Example: const unitPrice = { value: "1234.1234" }
|
* Example: const unitValue = { value: "1234.1234" }
|
||||||
*/
|
*/
|
||||||
this.numeric_ = BigNumberJS(rawPrice.value).toNumber()
|
const definedPrecision = rawValue.precision ?? precision
|
||||||
|
this.numeric_ = BigNumberJS(rawValue.value).toNumber()
|
||||||
this.raw_ = {
|
this.raw_ = {
|
||||||
...rawPrice,
|
...rawValue,
|
||||||
precision,
|
precision: definedPrecision,
|
||||||
}
|
}
|
||||||
} else if (typeof rawPrice === `number` && !Number.isNaN(rawPrice)) {
|
} else if (typeof rawValue === `number` && !Number.isNaN(rawValue)) {
|
||||||
/**
|
/**
|
||||||
* Example: const unitPrice = 1234
|
* Example: const unitValue = 1234
|
||||||
*/
|
*/
|
||||||
this.numeric_ = rawPrice as number
|
this.numeric_ = rawValue as number
|
||||||
|
|
||||||
this.raw_ = {
|
this.raw_ = {
|
||||||
value: BigNumberJS(rawPrice as number).toPrecision(precision),
|
value: BigNumberJS(rawValue as number).toPrecision(precision),
|
||||||
precision,
|
precision,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Invalid BigNumber value. Should be one of: string, number, BigNumber (bignumber.js), BigNumberRawValue"
|
`Invalid BigNumber value: ${rawValue}. Should be one of: string, number, BigNumber (bignumber.js), BigNumberRawValue`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user