From c8a55581a053ffb636341d7ed1d7d1fb4959ef2a Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 14 Feb 2022 13:54:13 +0200 Subject: [PATCH] Render fees --- modules/ppcp-wc-gateway/services.php | 4 + .../src/Admin/FeesRenderer.php | 82 +++++++++++++++++ .../ppcp-wc-gateway/src/WCGatewayModule.php | 17 ++++ .../WcGateway/Admin/FeesRendererTest.php | 92 +++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 modules/ppcp-wc-gateway/src/Admin/FeesRenderer.php create mode 100644 tests/PHPUnit/WcGateway/Admin/FeesRendererTest.php diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 532ada86c..494bb7e9e 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -19,6 +19,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\MessagesDisclaimers; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer; use WooCommerce\PayPalCommerce\Onboarding\State; +use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer; use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn; use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail; use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderAuthorizeAction; @@ -251,6 +252,9 @@ return array( $settings = $container->get( 'wcgateway.settings' ); return new OrderTablePaymentStatusColumn( $settings ); }, + 'wcgateway.admin.fees-renderer' => static function ( ContainerInterface $container ): FeesRenderer { + return new FeesRenderer(); + }, 'wcgateway.settings.fields' => static function ( ContainerInterface $container ): array { diff --git a/modules/ppcp-wc-gateway/src/Admin/FeesRenderer.php b/modules/ppcp-wc-gateway/src/Admin/FeesRenderer.php new file mode 100644 index 000000000..e1b047971 --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Admin/FeesRenderer.php @@ -0,0 +1,82 @@ +get_meta( PayPalGateway::FEES_META_KEY ); + if ( ! is_array( $breakdown ) ) { + return ''; + } + + $html = ''; + + $fee = $breakdown['paypal_fee'] ?? null; + if ( is_array( $fee ) ) { + $html .= $this->render_money_row( + __( 'PayPal Fee:', 'woocommerce-paypal-payments' ), + __( 'The fee PayPal collects for the transaction.', 'woocommerce-paypal-payments' ), + $fee['value'], + $fee['currency_code'] + ); + } + + $net = $breakdown['net_amount'] ?? null; + if ( is_array( $net ) ) { + $html .= $this->render_money_row( + __( 'PayPal Payout:', 'woocommerce-paypal-payments' ), + __( 'The net total that will be credited to your PayPal account.', 'woocommerce-paypal-payments' ), + $net['value'], + $net['currency_code'] + ); + } + + return $html; + } + + /** + * Renders a row in the order price breakdown table. + * + * @param string $title The row title. + * @param string $tooltip The title tooltip. + * @param string|float $value The money value. + * @param string $currency The currency code. + * @return string + */ + private function render_money_row( string $title, string $tooltip, $value, string $currency ): string { + /** + * Bad type hint in WC phpdoc. + * + * @psalm-suppress InvalidScalarArgument + */ + return ' + + ' . wc_help_tip( $tooltip ) . ' ' . esc_html( $title ) . ' + + + + - ' . wc_price( $value, array( 'currency' => $currency ) ) . ' + + '; + } +} diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 718e26c50..a2e38a3ad 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository; use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture; use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository; +use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer; use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn; use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail; use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderAuthorizeAction; @@ -86,6 +87,22 @@ class WCGatewayModule implements ModuleInterface { 2 ); + $fees_renderer = $c->get( 'wcgateway.admin.fees-renderer' ); + assert( $fees_renderer instanceof FeesRenderer ); + + add_action( + 'woocommerce_admin_order_totals_after_total', + function ( int $order_id ) use ( $fees_renderer ) { + $wc_order = wc_get_order( $order_id ); + if ( ! $wc_order instanceof WC_Order ) { + return; + } + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo $fees_renderer->render( $wc_order ); + } + ); + if ( $c->has( 'wcgateway.url' ) ) { $assets = new SettingsPageAssets( $c->get( 'wcgateway.url' ), diff --git a/tests/PHPUnit/WcGateway/Admin/FeesRendererTest.php b/tests/PHPUnit/WcGateway/Admin/FeesRendererTest.php new file mode 100644 index 000000000..0f7ccedfb --- /dev/null +++ b/tests/PHPUnit/WcGateway/Admin/FeesRendererTest.php @@ -0,0 +1,92 @@ +renderer = new FeesRenderer(); + + when('wc_help_tip')->returnArg(); + when('wc_price')->returnArg(); + } + + public function testRender() { + $wcOrder = Mockery::mock(WC_Order::class); + + $wcOrder->expects('get_meta') + ->with(PayPalGateway::FEES_META_KEY) + ->andReturn([ + 'gross_amount' => [ + 'currency_code' => 'USD', + 'value' => '10.42', + ], + 'paypal_fee' => [ + 'currency_code' => 'USD', + 'value' => '0.41', + ], + 'net_amount' => [ + 'currency_code' => 'USD', + 'value' => '10.01', + ], + ]); + + $result = $this->renderer->render($wcOrder); + $this->assertStringContainsString('Fee', $result); + $this->assertStringContainsString('0.41', $result); + $this->assertStringContainsString('Payout', $result); + $this->assertStringContainsString('10.01', $result); + } + + public function testRenderWithoutNet() { + $wcOrder = Mockery::mock(WC_Order::class); + + $wcOrder->expects('get_meta') + ->with(PayPalGateway::FEES_META_KEY) + ->andReturn([ + 'paypal_fee' => [ + 'currency_code' => 'USD', + 'value' => '0.41', + ], + ]); + + $result = $this->renderer->render($wcOrder); + $this->assertStringContainsString('Fee', $result); + $this->assertStringContainsString('0.41', $result); + $this->assertStringNotContainsString('Payout', $result); + } + + /** + * @dataProvider noFeesDataProvider + */ + public function testNoFees($meta) { + $wcOrder = Mockery::mock(WC_Order::class); + + $wcOrder->expects('get_meta') + ->with(PayPalGateway::FEES_META_KEY) + ->andReturn($meta); + + $this->assertSame('', $this->renderer->render($wcOrder)); + } + + function noFeesDataProvider(): array + { + return [ + ['hello'], + [[]], + [['paypal_fee' => 'hello']], + ]; + } +}