Skip to content

Normalise decimal WC quantities to integers before sending to Mollie#1240

Open
mmaymo wants to merge 1 commit into
dev/developfrom
PIWOO-887-decimal-quantities-cause-mollie-api-422-error-quantity-must-be-whole-number
Open

Normalise decimal WC quantities to integers before sending to Mollie#1240
mmaymo wants to merge 1 commit into
dev/developfrom
PIWOO-887-decimal-quantities-cause-mollie-api-422-error-quantity-must-be-whole-number

Conversation

@mmaymo

@mmaymo mmaymo commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

What and why

WooCommerce supports fractional product quantities (e.g. 1.5 metres of fabric) via third-party plugins. When a
cart contained such a quantity, both OrderLines and PaymentLines passed the raw float directly to the Mollie API
as the quantity field. Mollie requires quantity to be a whole number of at least 1, so any order with a
fractional quantity was rejected with a 422 Unprocessable Entity response — making payment completely impossible
for those customers.

How it works now

Both OrderLines and PaymentLines now include a private toIntegerQuantity() helper that converts a fractional
WooCommerce quantity to the smallest equivalent whole number by finding the minimal decimal scale factor (e.g.
1.5 → ×10 → 15, 0.4 → ×10 → 4). get_item_quantity() returns this scaled integer to Mollie, and get_item_price()
divides the line subtotal by the same scaled value — preserving Mollie's required invariant unitPrice × quantity
− discountAmount == totalAmount exactly. For repeating decimals that cannot be scaled exactly within four
decimal places, the helper falls back to rounding and clamps to a minimum of 1.

What to verify in review

Covered by unit tests

  • ✓ A fractional quantity of 1.5 is sent to Mollie as integer 15 (scale factor ×10)
  • ✓ The unit price for quantity 1.5 is lineSubtotal / 15, keeping unitPrice × 15 − discountAmount == totalAmount
  • ✓ A fractional quantity of 0.4 is sent to Mollie as integer 4 (scale factor ×10)
  • ✓ A quantity below 0.5 that cannot be scaled exactly (e.g. 1/3) is clamped to 1 rather than 0, preventing
    division by zero
  • ✓ An integer quantity such as 3 passes through unchanged
  • ✓ OrderLines and PaymentLines produce identical quantity and price values for the same input

Not covered by unit tests

None — all acceptance criteria are covered by the unit test suite.

@mmaymo mmaymo requested a review from danielhuesken June 29, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants