Skip to content

Commit 0b3faa5

Browse files
layoutdclaude
andcommitted
Fix refund amount calculations to prevent rounding errors and ensure partial refunds stay under 50%
For full refunds, use the order's actual total instead of summing line items to avoid rounding discrepancies that created tiny 0.01 refunds. For partial refunds, ensure the total stays below 50% of the order total by removing items if needed, preventing two partial refunds from fully refunding an order. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ac5f820 commit 0b3faa5

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

includes/Generator/Order.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,9 +521,46 @@ protected static function create_refund( $order, $force_partial = false ) {
521521
}
522522
}
523523

524+
// For full refunds, use the order's actual remaining total to avoid rounding discrepancies
525+
if ( $is_full_refund ) {
526+
$refund_amount = $order->get_total() - $order->get_total_refunded();
527+
}
528+
524529
// Round refund amount to 2 decimal places for currency precision
525530
$refund_amount = round( $refund_amount, 2 );
526531

532+
// For partial refunds, ensure refund is < 50% of order total by removing items if needed
533+
if ( ! $is_full_refund ) {
534+
$max_partial_refund = $order->get_total() * 0.5;
535+
536+
// If refund exceeds 50%, remove items until it's under 50%
537+
while ( $refund_amount >= $max_partial_refund && count( $line_items ) > 1 ) {
538+
// Remove a random item from the refund
539+
$item_id_to_remove = array_rand( $line_items );
540+
$removed_item = $line_items[ $item_id_to_remove ];
541+
unset( $line_items[ $item_id_to_remove ] );
542+
543+
// Recalculate refund amount and counts
544+
$refund_amount = 0;
545+
$total_items = 0;
546+
$total_qty = 0;
547+
548+
foreach ( $line_items as $item_id => $item_data ) {
549+
$refund_amount += abs( $item_data['refund_total'] );
550+
$total_items++;
551+
$total_qty += $item_data['qty'];
552+
553+
if ( ! empty( $item_data['refund_tax'] ) ) {
554+
foreach ( $item_data['refund_tax'] as $tax_amount ) {
555+
$refund_amount += abs( $tax_amount );
556+
}
557+
}
558+
}
559+
560+
$refund_amount = round( $refund_amount, 2 );
561+
}
562+
}
563+
527564
// Calculate maximum refundable amount (order total minus already refunded)
528565
$max_refund = $order->get_total() - $order->get_total_refunded();
529566
$max_refund = round( $max_refund, 2 );

0 commit comments

Comments
 (0)