Skip to content

Commit

Permalink
Solve 500 error on orders of 0.00 total (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubtobiasz authored Oct 29, 2024
2 parents efd905d + fc09278 commit 9d10b22
Show file tree
Hide file tree
Showing 15 changed files with 271 additions and 14 deletions.
10 changes: 10 additions & 0 deletions src/ContextProvider/BankListContextProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use CommerceWeavers\SyliusTpayPlugin\Tpay\Provider\TpayApiBankListProviderInterface;
use Sylius\Bundle\UiBundle\ContextProvider\ContextProviderInterface;
use Sylius\Bundle\UiBundle\Registry\TemplateBlock;
use Sylius\Component\Core\Model\OrderInterface;

final class BankListContextProvider implements ContextProviderInterface
{
Expand All @@ -17,6 +18,15 @@ public function __construct(

public function provide(array $templateContext, TemplateBlock $templateBlock): array
{
if (isset($templateContext['order'])) {
/** @var OrderInterface $order */
$order = $templateContext['order'];

if (null === $order->getLastPayment()) {
return $templateContext;
}
}

$templateContext['banks'] = $this->bankListProvider->provide();

return $templateContext;
Expand Down
8 changes: 8 additions & 0 deletions src/Form/Extension/CompleteTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@

use CommerceWeavers\SyliusTpayPlugin\Form\Type\TpayPaymentDetailsType;
use Sylius\Bundle\CoreBundle\Form\Type\Checkout\CompleteType;
use Sylius\Component\Core\Model\OrderInterface;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;

final class CompleteTypeExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
/** @var OrderInterface $order */
$order = $options['data'];

if (null === $order->getLastPayment()) {
return;
}

$builder
->add(
'tpay',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{% set payment = order.lastCartPayment() %}

{# >>> SyliusTpayPlugin customization #}
{% set payment_type = cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') %}
{% if payment is null %}
{% set payment_type = null %}
{% else %}
{% set payment_type = cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') %}
{% endif %}

{% if payment_type in ['apple_pay', 'google_pay'] %}
{{ sylius_template_event('cw.tpay.shop.checkout.complete.navigation', { form, order, payment }) }}
Expand All @@ -11,3 +15,4 @@
</button>
{% endif %}
{# SyliusTpayPlugin customization <<< #}

4 changes: 3 additions & 1 deletion templates/shop/cart/complete/_apple_pay.html.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% if cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == 'apple_pay' %}
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::APPLE_PAY')
%}
<input type="hidden" data-apple-pay-amount value="{{ order.total|cw_tpay_convert_minor_to_major_currency }}">
<input type="hidden" data-apple-pay-merchant-identifier value="{{ cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'apple_pay_merchant_id') }}">
<input type="hidden" data-apple-pay-currency value="{{ order.currencyCode }}">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{% set payment = order.lastCartPayment() %}

{% if cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') ==
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') ==
constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::APPLE_PAY')
%}
<div class="ui stackable grid">
Expand Down
4 changes: 3 additions & 1 deletion templates/shop/cart/complete/_blik.html.twig
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{% set payment = order.lastCartPayment() %}

{% if cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == 'blik' %}
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::BLIK')
%}
<div class="ui stackable grid">
{% include '@CommerceWeaversSyliusTpayPlugin/shop/payment/_blik.html.twig' %}
</div>
Expand Down
8 changes: 5 additions & 3 deletions templates/shop/cart/complete/_card.html.twig
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{% set method = order.lastCartPayment().method %}
{% set payment = order.lastCartPayment() %}

{% if cw_tpay_get_gateway_config_value(method.gatewayConfig, 'type') == 'card' %}
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::CARD')
%}
<div class="ui stackable grid">
{% include '@CommerceWeaversSyliusTpayPlugin/shop/payment/_card.html.twig' with {'method': method} %}
{% include '@CommerceWeaversSyliusTpayPlugin/shop/payment/_card.html.twig' with {'method': payment.method} %}
</div>
{% endif %}
4 changes: 3 additions & 1 deletion templates/shop/cart/complete/_google_pay.html.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% if cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == 'google_pay' %}
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::GOOGLE_PAY')
%}
{% set payment = order.lastCartPayment() %}
{% set gatewayConfig = payment.method.gatewayConfig %}
{% set productionMode = gatewayConfig.config['production_mode'] ?? true %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{% set payment = order.lastCartPayment() %}

{% if cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') ==
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') ==
constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::GOOGLE_PAY')
%}
<div class="ui stackable grid">
Expand Down
4 changes: 3 additions & 1 deletion templates/shop/cart/complete/_payByLink.html.twig
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{% set payment = order.lastCartPayment() %}

{% if cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == 'pay_by_link' %}
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::PAY_BY_LINK')
%}
<div class="bank-container">
{% for bank in banks %}
<div class="bank-tile" data-bank-id="{{ bank.id }}">
Expand Down
4 changes: 3 additions & 1 deletion templates/shop/cart/complete/_visaMobile.html.twig
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{% set payment = order.lastCartPayment() %}

{% if cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::VISA_MOBILE') %}
{% if payment is not null and
cw_tpay_get_gateway_config_value(payment.method.gatewayConfig, 'type') == constant('CommerceWeavers\\SyliusTpayPlugin\\Tpay\\PaymentType::VISA_MOBILE')
%}
<div class="ui stackable grid">
<div class="ui column eight wide">
<div class="ui small icon message">
Expand Down
39 changes: 39 additions & 0 deletions tests/E2E/Checkout/FreePaymentCheckoutTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace E2E\Checkout;

use Tests\CommerceWeavers\SyliusTpayPlugin\E2E\E2ETestCase;
use Tests\CommerceWeavers\SyliusTpayPlugin\E2E\Helper\Account\LoginShopUserTrait;
use Tests\CommerceWeavers\SyliusTpayPlugin\E2E\Helper\Order\CartTrait;
use Tests\CommerceWeavers\SyliusTpayPlugin\E2E\Helper\Order\TpayTrait;

final class FreePaymentCheckoutTest extends E2ETestCase
{
use CartTrait;
use TpayTrait;
use LoginShopUserTrait;

private const FORM_ID = 'sylius_checkout_complete';

protected function setUp(): void
{
parent::setUp();

$this->loadFixtures(['addressed_free_cart.yaml']);

$this->loginShopUser('[email protected]', 'sylius');
// the cart is already addressed, so we go straight to selecting a shipping method
$this->showSelectingShippingMethodStep();
$this->processWithDefaultShippingMethod();
}

public function test_it_completes_the_checkout_if_order_total_is_0(): void
{
// total is 0.00 so we do not choose payment method and go straight to complete
$this->placeOrder();

$this->assertPageTitleContains('Thank you!');
}
}
109 changes: 109 additions & 0 deletions tests/E2E/Resources/fixtures/addressed_free_cart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
include:
- common/channel.yaml
- common/country.yaml
- common/customer.yaml
- common/payment_method.yaml
- common/shipping_category.yaml
- free_shipping_method.yaml
- common/tax_category.yaml

Sylius\Component\Core\Model\Product:
product:
fallbackLocale: en_US
currentLocale: en
code: 'MUG_SW'
translations:
- '@product_translation'

Sylius\Component\Core\Model\ProductTranslation:
product_translation:
name: 'Mug'
slug: 'mug'
locale: 'en_US'
translatable: '@product'

Sylius\Component\Product\Model\ProductVariantTranslation:
product_variant_translation:
name: 'Mug'
locale: en_US
translatable: '@product_variant'

Sylius\Component\Core\Model\ProductVariant:
product_variant:
code: 'MUG'
version: 1
product: '@product'
fallbackLocale: en_US
currentLocale: en
position: 1
optionValues: ['@product_option_value_color_blue']
channelPricings:
channel_web: '@product_variant_channel_web_pricing'
translations:
- '@product_variant_translation'
enabled: true
tracked: true
onHold: 0
onHand: 10
weight: 100.50
width: 100.50
height: 100.50
depth: 100.50
taxCategory: '@tax_category_default'
shippingCategory: '@shipping_category_default'
shippingRequired: true

Sylius\Component\Core\Model\ChannelPricing:
product_variant_channel_web_pricing:
channelCode: 'WEB'
price: 00

Sylius\Component\Product\Model\ProductOption:
product_option_color:
code: 'COLOR'
currentLocale: 'en_US'
translations:
- '@product_option_translation_en_EN'

Sylius\Component\Product\Model\ProductOptionTranslation:
product_option_translation_en_EN:
locale: 'en_US'
name: 'Color'
translatable: '@product_option_color'

Sylius\Component\Product\Model\ProductOptionValue:
product_option_value_color_blue:
code: 'COLOR_BLUE'
currentLocale: 'en_US'
fallbackLocale: 'en_US'
option: '@product_option_color'
translations:
- '@product_option_value_translation_blue'

Sylius\Component\Product\Model\ProductOptionValueTranslation:
product_option_value_translation_blue:
locale: 'en_US'
value: 'Blue'
translatable: '@product_option_value_color_blue'

App\Entity\Order:
addressed_cart:
channel: '@channel_web'
currencyCode: 'USD'
localeCode: 'en_US'
customer: '@customer_tony'
state: 'cart'
checkoutState: 'addressed'
createdByGuest: false
shippingAddress: '@address_tony'
billingAddress: '@address_tony'
__calls:
- addItem: ["@order_item"]

Sylius\Component\Core\Model\OrderItem:
order_item:
variant: '@product_variant'

Sylius\Component\Core\Model\OrderItemUnit:
order_item_unit:
__construct: ['@order_item']
32 changes: 32 additions & 0 deletions tests/E2E/Resources/fixtures/free_shipping_method.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Sylius\Component\Core\Model\ShippingMethod:
shipping_method_free:
code: 'FREE'
enabled: true
calculator: 'flat_rate'
configuration:
WEB:
amount: 00
MOBILE:
amount: 00
zone: '@zone_world'
currentLocale: 'en_US'
translations: ["@shipping_method_translation_free"]
channels: ["@channel_web"]

Sylius\Component\Shipping\Model\ShippingMethodTranslation:
shipping_method_translation_free:
name: 'FREE'
locale: 'en_US'
description: '<paragraph(2)>'
translatable: '@shipping_method_free'

Sylius\Component\Addressing\Model\ZoneMember:
zone_member_{US, FR, DE}:
code: '<current()>'

Sylius\Component\Addressing\Model\Zone:
zone_world:
code: 'WORLD'
name: 'World'
type: 'country'
members: ['@zone_member_US', '@zone_member_FR', '@zone_member_DE']
46 changes: 43 additions & 3 deletions tests/Unit/ContextProvider/BankListContextProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Sylius\Bundle\UiBundle\Registry\TemplateBlock;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;

class BankListContextProviderTest extends TestCase
{
Expand Down Expand Up @@ -48,14 +50,53 @@ public function test_it_supports_select_payment_choice_item_form_template_event_
$this->assertTrue($supports);
}

public function test_it_provides_bank_list_as_context(): void
public function test_it_provides_banks_for_context_if_there_is_no_order_in_template_context(): void
{
$templateBlock = new TemplateBlock('pay_by_link', 'cw.tpay.shop.select_payment.choice_item_form', null, null, null, null);

$this->bankListProvider->provide()->shouldBeCalled();
$this->bankListProvider->provide()->willReturn(['1' => 'some bank']);

$context = $this->createTestObject()->provide([], $templateBlock);
$context = $this->createTestObject()->provide(
['i_am_not_an_order' => 'some_context'],
$templateBlock
);

$this->assertArrayHasKey('banks', $context);
$this->assertSame(['1' => 'some bank'], $context['banks']);
}

public function test_it_provides_nothing_new_for_context_if_order_has_no_payment(): void
{
$templateBlock = new TemplateBlock('pay_by_link', 'cw.tpay.shop.select_payment.choice_item_form', null, null, null, null);
$order = $this->prophesize(OrderInterface::class);
$order->getLastPayment()->willReturn(null);

$this->bankListProvider->provide()->shouldNotBeCalled();
$this->bankListProvider->provide()->willReturn(['1' => 'some bank']);

$context = $this->createTestObject()->provide(
['order' => $order->reveal()],
$templateBlock
);

$this->assertArrayNotHasKey('banks', $context);
}

public function test_it_provides_bank_list_as_context_if_order_has_payment(): void
{
$templateBlock = new TemplateBlock('pay_by_link', 'cw.tpay.shop.select_payment.choice_item_form', null, null, null, null);
$order = $this->prophesize(OrderInterface::class);
$payment = $this->prophesize(PaymentInterface::class);
$order->getLastPayment()->willReturn($payment);

$this->bankListProvider->provide()->shouldBeCalled();
$this->bankListProvider->provide()->willReturn(['1' => 'some bank']);

$context = $this->createTestObject()->provide(
['order' => $order->reveal()],
$templateBlock
);

$this->assertArrayHasKey('banks', $context);
$this->assertSame(['1' => 'some bank'], $context['banks']);
Expand All @@ -65,5 +106,4 @@ private function createTestObject(): BankListContextProvider
{
return new BankListContextProvider($this->bankListProvider->reveal());
}

}

0 comments on commit 9d10b22

Please sign in to comment.