fix(pricing,dashboard): update min_quantity/max_quantity to decimal in price model (#14045)
This commit is contained in:
6
.changeset/swift-lizards-fetch.md
Normal file
6
.changeset/swift-lizards-fetch.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@medusajs/dashboard": patch
|
||||
"@medusajs/pricing": patch
|
||||
---
|
||||
|
||||
fix(pricing,dashboard): update min_quantity/max_quantity to decimal in price model
|
||||
@@ -487,6 +487,31 @@ medusaIntegrationTestRunner({
|
||||
}),
|
||||
])
|
||||
|
||||
// Update item with decimal quantity
|
||||
result = (
|
||||
await api.post(
|
||||
`/admin/order-edits/${orderId}/items/item/${item.id}`,
|
||||
{
|
||||
quantity: 2.5,
|
||||
unit_price: 30,
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
).data.order_preview
|
||||
|
||||
expect(result.summary.current_order_total).toEqual(111.4)
|
||||
expect(result.summary.original_order_total).toEqual(60)
|
||||
|
||||
const decimalUpdatedItem = result.items.find((i) => i.id === item.id)
|
||||
expect(decimalUpdatedItem.actions[3]).toEqual(
|
||||
expect.objectContaining({
|
||||
details: expect.objectContaining({
|
||||
quantity: 2.5,
|
||||
unit_price: 30,
|
||||
quantity_diff: 0.5,
|
||||
}),
|
||||
})
|
||||
)
|
||||
// Remove the item by setting the quantity to 0
|
||||
result = (
|
||||
await api.post(
|
||||
@@ -542,7 +567,7 @@ medusaIntegrationTestRunner({
|
||||
)
|
||||
).data.order_changes
|
||||
|
||||
expect(result[0].actions).toHaveLength(5)
|
||||
expect(result[0].actions).toHaveLength(6)
|
||||
expect(result[0].status).toEqual("confirmed")
|
||||
expect(result[0].confirmed_by).toEqual(expect.stringContaining("user_"))
|
||||
})
|
||||
|
||||
@@ -196,7 +196,7 @@ medusaIntegrationTestRunner({
|
||||
name: "Test shipping option",
|
||||
price_type: "flat",
|
||||
prices: expect.arrayContaining([
|
||||
{
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
amount: 1000,
|
||||
currency_code: "usd",
|
||||
@@ -215,8 +215,8 @@ medusaIntegrationTestRunner({
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
price_rules: [],
|
||||
},
|
||||
{
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
amount: 500,
|
||||
currency_code: "usd",
|
||||
@@ -246,7 +246,7 @@ medusaIntegrationTestRunner({
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
deleted_at: null,
|
||||
},
|
||||
}),
|
||||
]),
|
||||
provider_id: "manual_test-provider",
|
||||
provider: expect.objectContaining({
|
||||
|
||||
@@ -122,7 +122,7 @@ medusaIntegrationTestRunner({
|
||||
"customer.groups.id": [customerGroup.id],
|
||||
},
|
||||
prices: [
|
||||
{
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
@@ -143,7 +143,7 @@ medusaIntegrationTestRunner({
|
||||
value: "5000",
|
||||
precision: 20,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
])
|
||||
@@ -289,7 +289,7 @@ medusaIntegrationTestRunner({
|
||||
"customer.groups.id": [customerGroup.id],
|
||||
},
|
||||
prices: [
|
||||
{
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
currency_code: "usd",
|
||||
amount: 5000,
|
||||
@@ -310,7 +310,7 @@ medusaIntegrationTestRunner({
|
||||
rules: {
|
||||
region_id: region.id,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
)
|
||||
|
||||
@@ -180,6 +180,7 @@ function OrderEditItem({ item, currencyCode, orderId }: OrderEditItemProps) {
|
||||
<Input
|
||||
className="bg-ui-bg-base txt-small w-[67px] rounded-lg [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
|
||||
type="number"
|
||||
step="any"
|
||||
disabled={item.detail.fulfilled_quantity === item.quantity}
|
||||
min={item.detail.fulfilled_quantity}
|
||||
defaultValue={item.quantity}
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_deleted_at\" ON \"price_list\" (deleted_at) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_deleted_at\" ON \"price_list\" (\"deleted_at\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_list_id_status_starts_at_ends_at",
|
||||
@@ -143,7 +143,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_id_status_starts_at_ends_at\" ON \"price_list\" (id, status, starts_at, ends_at) WHERE deleted_at IS NULL AND status = 'active'"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_id_status_starts_at_ends_at\" ON \"price_list\" (\"id\", \"status\", \"starts_at\", \"ends_at\") WHERE deleted_at IS NULL AND status = 'active'"
|
||||
},
|
||||
{
|
||||
"keyName": "price_list_pkey",
|
||||
@@ -241,7 +241,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_price_list_id\" ON \"price_list_rule\" (price_list_id) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_price_list_id\" ON \"price_list_rule\" (\"price_list_id\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_list_rule_deleted_at",
|
||||
@@ -250,7 +250,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_deleted_at\" ON \"price_list_rule\" (deleted_at) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_deleted_at\" ON \"price_list_rule\" (\"deleted_at\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_list_rule_attribute",
|
||||
@@ -259,7 +259,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_attribute\" ON \"price_list_rule\" (attribute) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_attribute\" ON \"price_list_rule\" (\"attribute\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_list_rule_value",
|
||||
@@ -268,7 +268,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_value\" ON \"price_list_rule\" USING gin (value) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_list_rule_value\" ON \"price_list_rule\" USING gin (\"value\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "price_list_rule_pkey",
|
||||
@@ -381,7 +381,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_preference_deleted_at\" ON \"price_preference\" (deleted_at) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_preference_deleted_at\" ON \"price_preference\" (\"deleted_at\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_preference_attribute_value",
|
||||
@@ -390,7 +390,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_price_preference_attribute_value\" ON \"price_preference\" (attribute, value) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_price_preference_attribute_value\" ON \"price_preference\" (\"attribute\", \"value\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "price_preference_pkey",
|
||||
@@ -461,7 +461,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_set_deleted_at\" ON \"price_set\" (deleted_at) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_set_deleted_at\" ON \"price_set\" (\"deleted_at\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "price_set_pkey",
|
||||
@@ -518,21 +518,21 @@
|
||||
},
|
||||
"min_quantity": {
|
||||
"name": "min_quantity",
|
||||
"type": "integer",
|
||||
"type": "numeric",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "integer"
|
||||
"mappedType": "decimal"
|
||||
},
|
||||
"max_quantity": {
|
||||
"name": "max_quantity",
|
||||
"type": "integer",
|
||||
"type": "numeric",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "integer"
|
||||
"mappedType": "decimal"
|
||||
},
|
||||
"rules_count": {
|
||||
"name": "rules_count",
|
||||
@@ -571,6 +571,24 @@
|
||||
"nullable": false,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"raw_min_quantity": {
|
||||
"name": "raw_min_quantity",
|
||||
"type": "jsonb",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"raw_max_quantity": {
|
||||
"name": "raw_max_quantity",
|
||||
"type": "jsonb",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamptz",
|
||||
@@ -614,7 +632,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_price_set_id\" ON \"price\" (price_set_id) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_price_set_id\" ON \"price\" (\"price_set_id\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_price_list_id",
|
||||
@@ -623,7 +641,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_price_list_id\" ON \"price\" (price_list_id) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_price_list_id\" ON \"price\" (\"price_list_id\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_deleted_at",
|
||||
@@ -632,7 +650,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_deleted_at\" ON \"price\" (deleted_at) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_deleted_at\" ON \"price\" (\"deleted_at\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_currency_code",
|
||||
@@ -641,16 +659,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_currency_code\" ON \"price\" (currency_code) WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_currency_code_price_set_id_min_quantity",
|
||||
"columnNames": [],
|
||||
"composite": false,
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_currency_code_price_set_id_min_quantity\" ON \"price\" (currency_code, price_set_id, min_quantity) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_currency_code\" ON \"price\" (\"currency_code\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "price_pkey",
|
||||
@@ -802,7 +811,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_price_id\" ON \"price_rule\" (price_id) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_price_id\" ON \"price_rule\" (\"price_id\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_rule_deleted_at",
|
||||
@@ -811,7 +820,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_deleted_at\" ON \"price_rule\" (deleted_at) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_deleted_at\" ON \"price_rule\" (\"deleted_at\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_rule_price_id_attribute_operator_unique",
|
||||
@@ -820,7 +829,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_price_rule_price_id_attribute_operator_unique\" ON \"price_rule\" (price_id, attribute, operator) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_price_rule_price_id_attribute_operator_unique\" ON \"price_rule\" (\"price_id\", \"attribute\", \"operator\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_rule_attribute",
|
||||
@@ -829,7 +838,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_attribute\" ON \"price_rule\" (attribute) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_attribute\" ON \"price_rule\" (\"attribute\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_rule_attribute_value",
|
||||
@@ -838,7 +847,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_attribute_value\" ON \"price_rule\" (attribute, value) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_attribute_value\" ON \"price_rule\" (\"attribute\", \"value\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_rule_operator_value",
|
||||
@@ -847,7 +856,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_operator_value\" ON \"price_rule\" (operator, value) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_operator_value\" ON \"price_rule\" (\"operator\", \"value\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "IDX_price_rule_attribute_value_price_id",
|
||||
@@ -856,7 +865,7 @@
|
||||
"constraint": false,
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_attribute_value_price_id\" ON \"price_rule\" (attribute, value, price_id) WHERE deleted_at IS NULL"
|
||||
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_price_rule_attribute_value_price_id\" ON \"price_rule\" (\"attribute\", \"value\", \"price_id\") WHERE deleted_at IS NULL"
|
||||
},
|
||||
{
|
||||
"keyName": "price_rule_pkey",
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20251112192723 extends Migration {
|
||||
|
||||
override async up(): Promise<void> {
|
||||
this.addSql(`drop index if exists "IDX_price_currency_code_price_set_id_min_quantity";`);
|
||||
|
||||
this.addSql(`alter table if exists "price" add column if not exists "raw_min_quantity" jsonb null, add column if not exists "raw_max_quantity" jsonb null;`);
|
||||
this.addSql(`alter table if exists "price" alter column "min_quantity" type numeric using ("min_quantity"::numeric);`);
|
||||
this.addSql(`alter table if exists "price" alter column "max_quantity" type numeric using ("max_quantity"::numeric);`);
|
||||
}
|
||||
|
||||
override async down(): Promise<void> {
|
||||
this.addSql(`alter table if exists "price" drop column if exists "raw_min_quantity", drop column if exists "raw_max_quantity";`);
|
||||
|
||||
this.addSql(`alter table if exists "price" alter column "min_quantity" type integer using ("min_quantity"::integer);`);
|
||||
this.addSql(`alter table if exists "price" alter column "max_quantity" type integer using ("max_quantity"::integer);`);
|
||||
this.addSql(`CREATE INDEX IF NOT EXISTS "IDX_price_currency_code_price_set_id_min_quantity" ON "price" (currency_code, price_set_id, min_quantity) WHERE deleted_at IS NULL;`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,8 +9,8 @@ const Price = model
|
||||
title: model.text().nullable(),
|
||||
currency_code: model.text(),
|
||||
amount: model.bigNumber(),
|
||||
min_quantity: model.number().nullable(),
|
||||
max_quantity: model.number().nullable(),
|
||||
min_quantity: model.bigNumber().nullable(),
|
||||
max_quantity: model.bigNumber().nullable(),
|
||||
rules_count: model.number().default(0).nullable(),
|
||||
price_set: model.belongsTo(() => PriceSet, {
|
||||
mappedBy: "prices",
|
||||
|
||||
@@ -535,16 +535,16 @@ export default class PricingModuleService
|
||||
id: calculatedPrice?.id || null,
|
||||
price_list_id: calculatedPrice?.price_list_id || null,
|
||||
price_list_type: calculatedPrice?.price_list_type || null,
|
||||
min_quantity: parseInt(calculatedPrice?.min_quantity || "") || null,
|
||||
max_quantity: parseInt(calculatedPrice?.max_quantity || "") || null,
|
||||
min_quantity: parseFloat(calculatedPrice?.min_quantity || "") || null,
|
||||
max_quantity: parseFloat(calculatedPrice?.max_quantity || "") || null,
|
||||
},
|
||||
|
||||
original_price: {
|
||||
id: originalPrice?.id || null,
|
||||
price_list_id: originalPrice?.price_list_id || null,
|
||||
price_list_type: originalPrice?.price_list_type || null,
|
||||
min_quantity: parseInt(originalPrice?.min_quantity || "") || null,
|
||||
max_quantity: parseInt(originalPrice?.max_quantity || "") || null,
|
||||
min_quantity: parseFloat(originalPrice?.min_quantity || "") || null,
|
||||
max_quantity: parseFloat(originalPrice?.max_quantity || "") || null,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user