Skip to content

Commit

Permalink
feature #273 Refunding multiple shipments (GSadee)
Browse files Browse the repository at this point in the history
This PR was merged into the 1.0-dev branch.

Discussion
----------

Fixes #110

Commits
-------

33e16be [Behat] Add scenarios for refunding multiple shipments
a841673 [Taxation] Fix applying shipment taxes for multiple shipments
85b7959 Refunding multiple shipments
5092357 [Behat] Duplicate some steps from Sylius due to support for Sylius 1.8
a77277b [Taxation] Add spec for applying taxes when one of the multiple shipments has 0 tax amount
  • Loading branch information
lchrusciel authored Mar 24, 2021
2 parents 9be9a7e + a77277b commit 817ff65
Show file tree
Hide file tree
Showing 12 changed files with 430 additions and 31 deletions.
35 changes: 25 additions & 10 deletions features/refunding_order_shipping_cost.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,30 @@ Feature: Refunding an order shipping cost

Background:
Given the store operates on a single green channel in "United States"
And the store has "VAT" tax rate of 23% for "Pidgeons Services" within the "US" zone
And the store has "VAT" tax rate of 23% for "Shipping Services" within the "US" zone
And the store has a product "Mr. Meeseeks T-Shirt" priced at "$10.00"
And the store has "Galaxy Post" shipping method with "$20.00" fee
And the store has "Space Pidgeons Post" shipping method with "$10.00" fee within the "US" zone
And shipping method "Space Pidgeons Post" belongs to "Pidgeons Services" tax category
And shipping method "Space Pidgeons Post" belongs to "Shipping Services" tax category
And the store allows paying with "Space money"
And there is a customer "[email protected]" that placed an order "#00000022"
And the customer bought 2 "Mr. Meeseeks T-Shirt" products
And the customer chose "Galaxy Post" shipping method to "United States" with "Space money" payment
And the order "#00000022" is already paid
And there is a customer "[email protected]" that placed an order "#00000023"
And the customer bought a single "Mr. Meeseeks T-Shirt"
And the customer chose "Space Pidgeons Post" shipping method to "United States" with "Space money" payment
And the order "#00000023" is already paid
And I am logged in as an administrator

@ui @application
Scenario: Refunding an order shipment
Given the customer bought 2 "Mr. Meeseeks T-Shirt" products
And the customer chose "Galaxy Post" shipping method to "United States" with "Space money" payment
And the order "#00000022" is already paid
When I want to refund some units of order "#00000022"
And I decide to refund order shipment with "Space money" payment
Then this order refunded total should be "$20.00"
And I should not be able to refund order shipment

@ui @application
Scenario: Refunding an order shipment along with order unit
Given the customer bought 2 "Mr. Meeseeks T-Shirt" products
And the customer chose "Galaxy Post" shipping method to "United States" with "Space money" payment
And the order "#00000022" is already paid
When I want to refund some units of order "#00000022"
And I decide to refund order shipment and 1st "Mr. Meeseeks T-Shirt" product with "Space money" payment
Then I should be notified that selected order units have been successfully refunded
Expand All @@ -40,7 +39,23 @@ Feature: Refunding an order shipping cost

@ui @application
Scenario: Refunding an order shipment with its tax
When I want to refund some units of order "#00000023"
Given the customer bought a single "Mr. Meeseeks T-Shirt"
And the customer chose "Space Pidgeons Post" shipping method to "United States" with "Space money" payment
And the order "#00000022" is already paid
When I want to refund some units of order "#00000022"
And I decide to refund order shipment with "Space money" payment
Then this order refunded total should be "$12.30"
And I should not be able to refund order shipment

@ui @application
Scenario: Refunding multiple order shipments
Given the customer bought a single "Mr. Meeseeks T-Shirt"
And the customer chose "Galaxy Post" shipping method to "United States"
And the customer bought another "Mr. Meeseeks T-Shirt" with separate "Space Pidgeons Post" shipment
And the customer chose "Space money" payment
And the order "#00000022" is already paid
When I want to refund some units of order "#00000022"
And I decide to refund "Galaxy Post" order shipment with "Space money" payment
And I decide to refund "Space Pidgeons Post" order shipment with "Space money" payment
Then this order refunded total should be "$32.30"
And I should not be able to refund order shipment
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ Feature: Refunding an order shipping cost
Then this order refunded total should be "$6.15"
And I should not be able to refund order shipment

@ui @application
Scenario: Refunding multiple order shipments with taxes and a promotion applied
Given there is a promotion "50% shipping discount"
And it gives "50%" discount on shipping to every order
And there is a customer "[email protected]" that placed an order "#00000022"
And the customer bought a single "Mr. Meeseeks T-Shirt"
And the customer chose "Galaxy Post" shipping method to "United States"
And the customer bought another "Mr. Meeseeks T-Shirt" with separate "Space Pidgeons Post" shipment
And the customer chose "Space money" payment
And the order "#00000022" is already paid
When I want to refund some units of order "#00000022"
And I decide to refund "Galaxy Post" order shipment with "Space money" payment
And I decide to refund "Space Pidgeons Post" order shipment with "Space money" payment
Then this order refunded total should be "$16.15"
And I should not be able to refund order shipment

@ui @application
Scenario: Being unable to refund an order shipping cost with 100% shipping discount applied
Given there is a promotion "100% shipping discount"
Expand Down
142 changes: 142 additions & 0 deletions spec/TaxesApplicator/OrderShipmentTaxesApplicatorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,148 @@ function it_applies_taxes_on_multiple_shipments_based_on_shipment_adjustments_pr
$this->apply($order, $zone);
}

function it_applies_taxes_on_multiple_shipments_when_there_is_no_tax_rate_for_one_of_them(
CalculatorInterface $calculator,
AdjustmentFactoryInterface $adjustmentsFactory,
TaxRateResolverInterface $taxRateResolver,
AdjustmentInterface $shippingTaxAdjustment,
OrderInterface $order,
ShipmentInterface $firstShipment,
ShipmentInterface $secondShipment,
ShippingMethodInterface $firstShippingMethod,
ShippingMethodInterface $secondShippingMethod,
TaxRateInterface $taxRate,
ZoneInterface $zone
): void {
$order->getShippingTotal()->willReturn(1000);
$order->hasShipments()->willReturn(true);
$order->getShipments()->willReturn(new ArrayCollection([
$firstShipment->getWrappedObject(),
$secondShipment->getWrappedObject(),
]));
$firstShipment->getAdjustmentsTotal()->willReturn(600);
$firstShipment->getMethod()->willReturn($firstShippingMethod);
$secondShipment->getAdjustmentsTotal()->willReturn(400);
$secondShipment->getMethod()->willReturn($secondShippingMethod);

$firstShippingMethod->getCode()->willReturn('dhl');
$firstShippingMethod->getName()->willReturn('DHL');

$secondShippingMethod->getCode()->willReturn('fedex');
$secondShippingMethod->getName()->willReturn('FedEx');

$taxRateResolver->resolve($firstShippingMethod, ['zone' => $zone])->willReturn(null);

$taxRateResolver->resolve($secondShippingMethod, ['zone' => $zone])->willReturn($taxRate);
$taxRate->getLabel()->willReturn('Simple tax (10%)');
$taxRate->getCode()->willReturn('simple_tax');
$taxRate->getName()->willReturn('Simple tax');
$taxRate->getAmount()->willReturn(0.1);
$taxRate->isIncludedInPrice()->willReturn(false);

$firstShipment->addAdjustment(Argument::any())->shouldNotBeCalled();

$calculator->calculate(400, $taxRate)->willReturn(40);
$adjustmentsFactory
->createWithData(
AdjustmentInterface::TAX_ADJUSTMENT,
'Simple tax (10%)',
40,
false,
)
->willReturn($shippingTaxAdjustment)
;
$shippingTaxAdjustment
->setDetails([
'shippingMethodCode' => 'fedex',
'shippingMethodName' => 'FedEx',
'taxRateCode' => 'simple_tax',
'taxRateName' => 'Simple tax',
'taxRateAmount' => 0.1,
])
->shouldBeCalled()
;
$secondShipment->addAdjustment($shippingTaxAdjustment)->shouldBeCalled();

$this->apply($order, $zone);
}

function it_applies_taxes_on_multiple_shipments_when_one_of_them_has_0_tax_amount(
CalculatorInterface $calculator,
AdjustmentFactoryInterface $adjustmentsFactory,
TaxRateResolverInterface $taxRateResolver,
AdjustmentInterface $shippingTaxAdjustment,
OrderInterface $order,
ShipmentInterface $firstShipment,
ShipmentInterface $secondShipment,
ShippingMethodInterface $firstShippingMethod,
ShippingMethodInterface $secondShippingMethod,
TaxRateInterface $taxRate,
ZoneInterface $zone
): void {
$order->getShippingTotal()->willReturn(1000);
$order->hasShipments()->willReturn(true);
$order->getShipments()->willReturn(new ArrayCollection([
$firstShipment->getWrappedObject(),
$secondShipment->getWrappedObject(),
]));
$firstShipment->getAdjustmentsTotal()->willReturn(600);
$firstShipment->getMethod()->willReturn($firstShippingMethod);
$secondShipment->getAdjustmentsTotal()->willReturn(400);
$secondShipment->getMethod()->willReturn($secondShippingMethod);

$firstShippingMethod->getCode()->willReturn('dhl');
$firstShippingMethod->getName()->willReturn('DHL');

$secondShippingMethod->getCode()->willReturn('fedex');
$secondShippingMethod->getName()->willReturn('FedEx');

$taxRateResolver->resolve($firstShippingMethod, ['zone' => $zone])->willReturn($taxRate);
$taxRateResolver->resolve($secondShippingMethod, ['zone' => $zone])->willReturn($taxRate);
$taxRate->getLabel()->willReturn('Simple tax (10%)');
$taxRate->getCode()->willReturn('simple_tax');
$taxRate->getName()->willReturn('Simple tax');
$taxRate->getAmount()->willReturn(0.1);
$taxRate->isIncludedInPrice()->willReturn(false);

$firstShipment->addAdjustment(Argument::any())->shouldNotBeCalled();

$calculator->calculate(600, $taxRate)->willReturn(0);
$adjustmentsFactory
->createWithData(
AdjustmentInterface::TAX_ADJUSTMENT,
'Simple tax (10%)',
0,
false,
)
->shouldNotBeCalled()
;

$calculator->calculate(400, $taxRate)->willReturn(40);
$adjustmentsFactory
->createWithData(
AdjustmentInterface::TAX_ADJUSTMENT,
'Simple tax (10%)',
40,
false,
)
->willReturn($shippingTaxAdjustment)
;
$shippingTaxAdjustment
->setDetails([
'shippingMethodCode' => 'fedex',
'shippingMethodName' => 'FedEx',
'taxRateCode' => 'simple_tax',
'taxRateName' => 'Simple tax',
'taxRateAmount' => 0.1,
])
->shouldBeCalled()
;
$secondShipment->addAdjustment($shippingTaxAdjustment)->shouldBeCalled();

$this->apply($order, $zone);
}

function it_does_nothing_if_the_tax_amount_is_0(
CalculatorInterface $calculator,
AdjustmentFactoryInterface $adjustmentsFactory,
Expand Down
5 changes: 2 additions & 3 deletions src/Resources/views/_shipping.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

{% set shipmentRefundType = constant('Sylius\\RefundPlugin\\Model\\RefundType::SHIPMENT') %}

{% if order.getAdjustments('shipping')|length > 0 %}
{% set shippingAdjustment = order.getAdjustments('shipping').first() %}
{% for shippingAdjustment in order.getAdjustments('shipping') %}
{% set shipment = shippingAdjustment.shipment %}

<tr class="shipment">
Expand Down Expand Up @@ -31,4 +30,4 @@
</button>
</td>
</tr>
{% endif %}
{% endfor %}
4 changes: 2 additions & 2 deletions src/TaxesApplicator/OrderShipmentTaxesApplicator.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ public function apply(OrderInterface $order, ZoneInterface $zone): void
/** @var TaxRateInterface|null $taxRate */
$taxRate = $this->taxRateResolver->resolve($shippingMethod, ['zone' => $zone]);
if (null === $taxRate) {
return;
continue;
}

$taxAmount = $this->calculator->calculate($shipment->getAdjustmentsTotal(), $taxRate);
if (0.00 === $taxAmount) {
return;
continue;
}

$this->addAdjustment($shipment, (int) $taxAmount, $taxRate, $shippingMethod);
Expand Down
28 changes: 28 additions & 0 deletions tests/Behat/Context/Application/RefundingContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ public function decideToRefundOrderShipment(PaymentMethodInterface $paymentMetho
));
}

/**
* @When I decide to refund :shippingMethodName order shipment with :paymentMethod payment
*/
public function iDecideToRefundOrderShipmentWithPayment(
string $shippingMethodName,
PaymentMethodInterface $paymentMethod
): void {
$shippingAdjustment = $this->getShippingAdjustment($shippingMethodName);
$remainingTotal = $this->remainingTotalProvider->getTotalLeftToRefund($shippingAdjustment->getId(), RefundType::shipment());

$this->commandBus->dispatch(new RefundUnits(
$this->order->getNumber(), [], [new ShipmentRefund($shippingAdjustment->getId(), $remainingTotal)], $paymentMethod->getId(), ''
));
}

/**
* @When /^I decide to refund ("[^"]+") from order shipment with ("[^"]+" payment)$/
*/
Expand Down Expand Up @@ -316,4 +331,17 @@ private function getOrderUnit(int $unitNumber, string $productName): OrderItemUn

return $unitsWithProduct->get($unitNumber-1);
}

private function getShippingAdjustment(string $shippingMethodName): AdjustmentInterface
{
$this->order->getAdjustments(AdjustmentInterface::SHIPPING_ADJUSTMENT);

$shippingAdjustments = $this->order
->getAdjustments(AdjustmentInterface::SHIPPING_ADJUSTMENT)
->filter(function(AdjustmentInterface $adjustment) use ($shippingMethodName): bool {
return $adjustment->getLabel() === $shippingMethodName;
});

return $shippingAdjustments->first();
}
}
Loading

0 comments on commit 817ff65

Please sign in to comment.