Skip to content

[Bug]: Breaking change in handling item quantities in orderEditAddNewItemWorkflow in 2.11.1 #13906

@insigmagit

Description

@insigmagit

Package.json file

{
  "name": "medusa-starter-default",
  "version": "0.0.1",
  "description": "A starter for Medusa projects.",
  "author": "Medusa (https://medusajs.com)",
  "license": "MIT",
  "keywords": [
    "sqlite",
    "postgres",
    "typescript",
    "ecommerce",
    "headless",
    "medusa"
  ],
  "scripts": {
    "build": "medusa build",
    "seed": "medusa exec ./src/scripts/seed.ts",
    "start": "medusa start",
    "dev": "medusa develop",
    "test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --forceExit",
    "test:integration:modules": "TEST_TYPE=integration:modules NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --forceExit",
    "test:unit": "TEST_TYPE=unit NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
    "docker:up": "docker compose up --build -d",
    "docker:down": "docker compose down"
  },
  "dependencies": {
    "@medusajs/admin-sdk": "2.11.1",
    "@medusajs/cli": "2.11.1",
    "@medusajs/framework": "2.11.1",
    "@medusajs/medusa": "2.11.1"
  },
  "devDependencies": {
    "@medusajs/test-utils": "2.11.1",
    "@swc/core": "1.5.7",
    "@swc/jest": "^0.2.36",
    "@types/jest": "^29.5.13",
    "@types/node": "^20.0.0",
    "@types/react": "^18.3.2",
    "@types/react-dom": "^18.2.25",
    "jest": "^29.7.0",
    "prop-types": "^15.8.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "ts-node": "^10.9.2",
    "typescript": "^5.6.2",
    "vite": "^5.2.11",
    "yalc": "^1.0.0-pre.53"
  },
  "engines": {
    "node": ">=20"
  }
}

Node.js version

22.21.0

Database and its version

17.4

Operating system name and version

Linux 5.10.244-240.965.amzn2.x86_64

Browser name

No response

What happended?

I upgraded meduasjs from 2.7.1 to medusa 2.11.1 and there is a breaking change in handling order item quantities in orderEditAddNewItemWorkflow. In medusa 2.7.1 the item quantity was allowed to be a decimal number, but now the code isn't working anymore and produces this error with database query:

'select "price"."id" as "id", "price"."price_set_id" as "price_set_id", "price"."amount" as "amount", "price"."raw_amount" as "raw_amount", "price"."min_quantity" as "min_quantity", "price"."max_quantity" as "max_quantity", "price"."currency_code" as "currency_code", "price"."price_list_id" as "price_list_id", "pl"."type" as "price_list_type", "price"."rules_count" as "rules_count", "pl"."rules_count" as "price_list_rules_count" from "price" left join "price_list" as "pl" on "pl"."id" = "price"."price_list_id" and "pl"."status" = $1 and ("pl"."deleted_at" is null) and ("pl"."starts_at" is null or "pl"."starts_at" <= CURRENT_TIMESTAMP) and ("pl"."ends_at" is null or "pl"."ends_at" >= CURRENT_TIMESTAMP) left join LATERAL (\n' +
    '            SELECT\n' +
    '              COUNT(*) FILTER (WHERE (pr.attribute = $2 AND pr.value IN ($3)) OR (pr.attribute = $4 AND pr.value IN ($5)) OR (pr.attribute = $6 AND pr.value IN ($7)) OR (pr.attribute = $8 AND pr.value IN ($9)) OR (pr.attribute = $10 AND pr.value IN ($11))) as matched_count,\n' +
    '              COUNT(*) as total_count\n' +
    '            FROM price_rule pr\n' +
    '            WHERE pr.price_id = price.id\n' +
    '              AND pr.deleted_at IS NULL\n' +
    '          ) pr_stats on true left join LATERAL (\n' +
    '            SELECT\n' +
    '              COUNT(*) FILTER (WHERE (plr.attribute = $12 AND plr.value @> $13) OR (plr.attribute = $14 AND plr.value @> $15) OR (plr.attribute = $16 AND plr.value @> $17) OR (plr.attribute = $18 AND plr.value @> $19) OR (plr.attribute = $20 AND plr.value @> $21)) as matched_count,\n' +
    '              COUNT(*) as total_count\n' +
    '            FROM price_list_rule plr\n' +
    '            WHERE plr.price_list_id = pl.id\n' +
    '              AND plr.deleted_at IS NULL\n' +
    '          ) plr_stats on true where "price"."price_set_id" in ($22) and "price"."currency_code" = $23 and "price"."deleted_at" is null and (("price"."min_quantity" <= $24 and "price"."max_quantity" >= $25 or "price"."min_quantity" <= $26 and "price"."max_quantity" is null or "price"."min_quantity" is null and "price"."max_quantity" is null or "price"."min_quantity" is null and "price"."max_quantity" >= $27)) and (("price"."price_list_id" is null and ("price"."rules_count" = $28 or pr_stats.matched_count = price.rules_count)) or ("price"."price_list_id" is not null and ("price"."rules_count" = $29 or pr_stats.matched_count = price.rules_count) and ("pl"."rules_count" = $30 or plr_stats.matched_count = pl.rules_count))) order by price.price_list_id IS NOT NULL DESC, price.rules_count + COALESCE(pl.rules_count, 0) DESC, "price"."amount" asc - invalid input syntax for type integer: "123.4"',
  name: 'error',
  stack: 'error: select "price"."id" as "id", "price"."price_set_id" as "price_set_id", "price"."amount" as "amount", "price"."raw_amount" as "raw_amount", "price"."min_quantity" as "min_quantity", "price"."max_quantity" as "max_quantity", "price"."currency_code" as "currency_code", "price"."price_list_id" as "price_list_id", "pl"."type" as "price_list_type", "price"."rules_count" as "rules_count", "pl"."rules_count" as "price_list_rules_count" from "price" left join "price_list" as "pl" on "pl"."id" = "price"."price_list_id" and "pl"."status" = $1 and ("pl"."deleted_at" is null) and ("pl"."starts_at" is null or "pl"."starts_at" <= CURRENT_TIMESTAMP) and ("pl"."ends_at" is null or "pl"."ends_at" >= CURRENT_TIMESTAMP) left join LATERAL (\n' +
    '            SELECT\n' +
    '              COUNT(*) FILTER (WHERE (pr.attribute = $2 AND pr.value IN ($3)) OR (pr.attribute = $4 AND pr.value IN ($5)) OR (pr.attribute = $6 AND pr.value IN ($7)) OR (pr.attribute = $8 AND pr.value IN ($9)) OR (pr.attribute = $10 AND pr.value IN ($11))) as matched_count,\n' +
    '              COUNT(*) as total_count\n' +
    '            FROM price_rule pr\n' +
    '            WHERE pr.price_id = price.id\n' +
    '              AND pr.deleted_at IS NULL\n' +
    '          ) pr_stats on true left join LATERAL (\n' +
    '            SELECT\n' +
    '              COUNT(*) FILTER (WHERE (plr.attribute = $12 AND plr.value @> $13) OR (plr.attribute = $14 AND plr.value @> $15) OR (plr.attribute = $16 AND plr.value @> $17) OR (plr.attribute = $18 AND plr.value @> $19) OR (plr.attribute = $20 AND plr.value @> $21)) as matched_count,\n' +
    '              COUNT(*) as total_count\n' +
    '            FROM price_list_rule plr\n' +
    '            WHERE plr.price_list_id = pl.id\n' +
    '              AND plr.deleted_at IS NULL\n' +
    '          ) plr_stats on true where "price"."price_set_id" in ($22) and "price"."currency_code" = $23 and "price"."deleted_at" is null and (("price"."min_quantity" <= $24 and "price"."max_quantity" >= $25 or "price"."min_quantity" <= $26 and "price"."max_quantity" is null or "price"."min_quantity" is null and "price"."max_quantity" is null or "price"."min_quantity" is null and "price"."max_quantity" >= $27)) and (("price"."price_list_id" is null and ("price"."rules_count" = $28 or pr_stats.matched_count = price.rules_count)) or ("price"."price_list_id" is not null and ("price"."rules_count" = $29 or pr_stats.matched_count = price.rules_count) and ("pl"."rules_count" = $30 or plr_stats.matched_count = pl.rules_count))) order by price.price_list_id IS NOT NULL DESC, price.rules_count + COALESCE(pl.rules_count, 0) DESC, "price"."amount" asc - invalid input syntax for type integer: "123.4"\n' +
    '    at Parser.parseErrorMessage (~/Projects/p1/node_modules/pg-protocol/src/parser.ts:369:69)\n' +
    '    at Parser.handlePacket (~/Projects/p1/node_modules/pg-protocol/src/parser.ts:187:21)\n' +
    '    at Parser.parse (~/Projects/p1/node_modules/pg-protocol/src/parser.ts:102:30)\n' +
    '    at Socket.<anonymous> (~/Projects/p1/node_modules/pg-protocol/src/index.ts:7:48)\n' +
    '    at Socket.emit (node:events:518:28)\n' +
    '    at Socket.emit (node:domain:489:12)\n' +
    '    at addChunk (node:internal/streams/readable:561:12)\n' +
    '    at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)\n' +
    '    at Socket.Readable.push (node:internal/streams/readable:392:5)\n' +
    '    at TCP.onStreamRead (node:internal/stream_base_commons:189:23)\n' +
    '    at TCP.callbackTrampoline (node:internal/async_hooks:130:17)\n' +
    '⮑ sat ~/Projects/p1/node_modules/@medusajs/core-flows/dist/cart/workflows/get-variants-and-items-with-prices.js: [get-variant-items-with-prices-workflow -> get-variant-price-sets (invoke)]\n' +
    '⮑ sat ~/Projects/p1/node_modules/@medusajs/core-flows/dist/order/workflows/add-line-items.js: [order-add-line-items -> get-variant-items-with-prices-workflow-as-step (invoke)]\n' +
    '⮑ sat ~/Projects/p1/node_modules/@medusajs/core-flows/dist/order/workflows/order-edit/order-edit-add-new-item.js: [order-edit-add-new-item -> order-add-line-items-as-step (invoke)]',
  length: 144,
  severity: 'ERROR',
  code: '22P02',
  detail: undefined,
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: "unnamed portal parameter $24 = '...'",
  schema: undefined,
  table: undefined,
  column: undefined,
  dataType: undefined,
  constraint: undefined,
  file: 'numutils.c',
  line: '232',
  routine: 'pg_strtoint32'

The quantity is still allowed to be a decimal number in postgres database table and works as decimal number in many other places

Expected behavior

Ordering with decimal quantity is working.

Also orderEditUpdateItemQuantityWorkflow is working with decimal quantities

await orderEditUpdateItemQuantityWorkflow(container).run({
    input: {
      order_id: order.id,
      items: order.items?.map((item) => ({
        id: item.id,
        quantity: 123.5,
      })) || [],
    },
  });

Also orderEditAddNewItemWorkflow should work, but it doesn't. It worked in version 2.7.1

await orderEditAddNewItemWorkflow(container).run({
    input: {
      order_id: order.id,
      items: variants?.map((variant) => ({
        variant_id: variant.id,
        quantity: 123.5 // changing this to an integer value like 124 makes it work
      })),
    },
  })

Actual behavior

Produces error with DB query.

error:   select "price"."id" as "id", "price"."price_set_id" as "price_set_id", "price"."amount" as "amount", "price"."raw_amount" as "raw_amount", "price"."min_quantity" as "min_quantity", "price"."max_quantity" as "max_quantity", "price"."currency_code" as "currency_code", "price"."price_list_id" as "price_list_id", "pl"."type" as "price_list_type", "price"."rules_count" as "rules_count", "pl"."rules_count" as "price_list_rules_count" from "price" left join "price_list" as "pl" on "pl"."id" = "price"."price_list_id" and "pl"."status" = $1 and ("pl"."deleted_at" is null) and ("pl"."starts_at" is null or "pl"."starts_at" <= CURRENT_TIMESTAMP) and ("pl"."ends_at" is null or "pl"."ends_at" >= CURRENT_TIMESTAMP) left join LATERAL (
            SELECT
              COUNT(*) FILTER (WHERE (pr.attribute = $2 AND pr.value IN ($3)) OR (pr.attribute = $4 AND pr.value IN ($5)) OR (pr.attribute = $6 AND pr.value IN ($7))) as matched_count,
              COUNT(*) as total_count
            FROM price_rule pr
            WHERE pr.price_id = price.id
              AND pr.deleted_at IS NULL
          ) pr_stats on true left join LATERAL (
            SELECT
              COUNT(*) FILTER (WHERE (plr.attribute = $8 AND plr.value @> $9) OR (plr.attribute = $10 AND plr.value @> $11) OR (plr.attribute = $12 AND plr.value @> $13)) as matched_count,
              COUNT(*) as total_count
            FROM price_list_rule plr
            WHERE plr.price_list_id = pl.id
              AND plr.deleted_at IS NULL
          ) plr_stats on true where "price"."price_set_id" in ($14) and "price"."currency_code" = $15 and "price"."deleted_at" is null and (("price"."min_quantity" <= $16 and "price"."max_quantity" >= $17 or "price"."min_quantity" <= $18 and "price"."max_quantity" is null or "price"."min_quantity" is null and "price"."max_quantity" is null or "price"."min_quantity" is null and "price"."max_quantity" >= $19)) and (("price"."price_list_id" is null and ("price"."rules_count" = $20 or pr_stats.matched_count = price.rules_count)) or ("price"."price_list_id" is not null and ("price"."rules_count" = $21 or pr_stats.matched_count = price.rules_count) and ("pl"."rules_count" = $22 or plr_stats.matched_count = pl.rules_count))) order by price.price_list_id IS NOT NULL DESC, price.rules_count + COALESCE(pl.rules_count, 0) DESC, "price"."amount" asc - invalid input syntax for type integer: "123.5"

Link to reproduction repo

https://github.com/Infuel-Oy/medusa-quantity-demo

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions