Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refunding multiple shipments #273

Merged
merged 5 commits into from
Mar 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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