Skip to content

[Bug]: [Dashboard] Refund form default amount incorrectly rounds sub-cent pending_difference using toFixed #15057

@damienNiji

Description

@damienNiji

Package.json file

{
  "name": "example",
  "version": "0.0.62",
  "description": "",
  "scripts": {
    "build": "medusa build",    
    "dev": "medusa develop",    
  },
  "dependencies": {
    "@aws-sdk/client-dynamodb": "^3.0.0",
    "@medusajs/admin-sdk": "2.13.1",
    "@medusajs/auth": "2.13.1",
    "@medusajs/auth-emailpass": "2.13.1",
    "@medusajs/auth-google": "2.13.1",
    "@medusajs/caching-redis": "^2.13.4",
    "@medusajs/cli": "2.13.1",
    "@medusajs/draft-order": "2.13.1",
    "@medusajs/framework": "2.13.1",
    "@medusajs/index": "2.13.1",
    "@medusajs/medusa": "2.13.1",
    "ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "algoliasearch": "5.39.0",
    "cronstrue": "^3.12.0",
    "dayjs": "^1.11.18",
    "fast-xml-parser": "^5.5.6",
    "json-rules-engine": "^7.3.1",
    "jsonwebtoken": "^9.0.2",
    "nodemailer": "^7.0.11"
  },
  "devDependencies": {
    "@biomejs/biome": "2.0.6",
    "@medusajs/test-utils": "2.13.1",
    "@swc/core": "1.5.7",
    "@swc/jest": "0.2.39",
    "@types/ajv": "^0.0.5",
    "@types/jest": "30.0.0",
    "@types/jsonwebtoken": "^9.0.10",
    "@types/node": "^22.0.0",
    "@types/nodemailer": "^7.0.4",
    "@types/react": "^18.3.2",
    "@types/react-dom": "^18.2.25",
    "jest": "30.2.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "ts-node": "^10.9.2",
    "typescript": "5.9.3",
    "vite": "^5.4.21",
    "yalc": "^1.0.0-pre.53"
  },  
  "engines": {
    "node": ">=24.1.0"
  },
  "volta": {
    "node": "24.1.0",
    "yarn": "4.12.0"
  },
  "overrides": {
    "axios": "1.13.5",
    "glob": "11.1.0",
    "immutable": "4.3.8",
    "jws": "4.0.1",
    "multer": "2.1.1",
    "qs": "6.14.1",
    "rollup": "4.59.0",
    "tar": "7.5.11",
    "@isaacs/brace-expansion": "5.0.1",
    "fast-xml-parser": "5.5.6",
    "minimatch@^10.1.1": "10.2.3"
  },
  "resolutions": {
    "tar": "7.5.11",
    "@isaacs/brace-expansion": "5.0.1",
    "fast-xml-parser": "5.5.6",
    "axios": "1.13.5",
    "immutable": "4.3.8",
    "multer": "2.1.1",
    "rollup": "4.59.0",
    "minimatch@^10.1.1": "10.2.3"
  },
  "packageManager": "[email protected]"
}

Node.js version

24.1.0

Database and its version

PostGres 16-alpine

Operating system name and version

MAC Docker

Browser name

Chrome

What happended?

Description

When an order has a pending_difference with sub-cent precision (e.g. -17.705),
the refund form dialog is pre-filled with a different value than the "Refund X€"
button label on the order page.

Steps to reproduce

  1. Create an order with a discount that produces sub-cent arithmetic
    (e.g. total = 36.425, pending_difference = -17.705)
  2. Request a return for some items
  3. On the order page, the "Refund" button shows 17.71€
  4. Click it → the refund dialog pre-fills with 17.70€

Root cause

In create-refund-form.tsx:

form.setValue("amount", {
  value: normalizedAmount.toFixed(currency.decimal_digits), // BUG
  float: normalizedAmount,
})

### Expected behavior


// Use (decimal-aware via the shortest string representation):
const str = normalizedAmount.toString()
const dot = str.indexOf('.')
const dec = dot === -1 ? 0 : str.length - dot - 1
const rounded = dec <= currency.decimal_digits
  ? normalizedAmount
  : Math.round(Math.round(normalizedAmount * 10**dec) / 10**(dec - currency.decimal_digits)) / 10**currency.decimal_digits
value: rounded.toFixed(currency.decimal_digits)

### Actual behavior

value: normalizedAmount.toFixed(currency.decimal_digits)

### Link to reproduction repo

norepo

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