diff --git a/includes/class-tmdo-wc-orders-interceptor.php b/includes/class-tmdo-wc-orders-interceptor.php index 155c638..068e066 100644 --- a/includes/class-tmdo-wc-orders-interceptor.php +++ b/includes/class-tmdo-wc-orders-interceptor.php @@ -149,6 +149,10 @@ class TMDO_WC_Orders_Interceptor extends TMDO_Interceptor_Base { if ( ! get_option( 'hp_vendor_include_taxes' ) ) { $subtotal -= (float) $order->get_total_tax(); } + // Marketplace subtracts the full tax even after a refund; a fully + // refunded taxed order would otherwise record a negative amount. + $subtotal = max( 0.0, $subtotal ); + $vendor_payout = max( 0.0, $subtotal * $vendor_share - $fee ); $commission = $subtotal - $vendor_payout; $commission_rate = round( ( 1 - $vendor_share ) * 100, 2 ); // Platform percentage, as set in Marketplace. diff --git a/tests/integration/WCOrdersInterceptorTest.php b/tests/integration/WCOrdersInterceptorTest.php index e624a47..0366e34 100644 --- a/tests/integration/WCOrdersInterceptorTest.php +++ b/tests/integration/WCOrdersInterceptorTest.php @@ -204,6 +204,23 @@ class WCOrdersInterceptorTest extends TestCase { $this->assertEqualsWithDelta( 0.0, (float) $row['vendor_payout'], 0.0001 ); } + /** + * Amounts follow Marketplace::get_order_profit() (what the vendor is paid, + * which subtracts the full tax after refunds), but a fully refunded taxed + * order must not record a negative subtotal or commission. + */ + public function test_a_fully_refunded_taxed_order_records_no_negative_amounts(): void { + $this->place_order( $this->marketplace_meta(), 110.0, 10.0 ); + $this->refund( 110.0, 'refunded' ); + + ( new TMDO_WC_Orders_Interceptor() )->action_order_refunded( self::ORDER_ID, 1 ); + + $row = $this->commission_row(); + $this->assertEqualsWithDelta( 0.0, (float) $row['subtotal'], 0.0001 ); + $this->assertEqualsWithDelta( 0.0, (float) $row['commission'], 0.0001 ); + $this->assertEqualsWithDelta( 0.0, (float) $row['vendor_payout'], 0.0001 ); + } + public function test_a_refund_of_an_untracked_order_records_nothing(): void { $this->refund( 50.0, 'pending' );