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

Refund shipping cost with promotion applied #255

Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@refunds
Feature: Refunding an order shipping cost
In order to give back money spent by Customer for order shipment
As an Administrator
I want to be able to refund 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 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 the store allows paying with "Space money"
And I am logged in as an administrator

@ui @application
Scenario: Refunding an order shipping cost with 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 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 "$10.00"
And I should not be able to refund order shipment

@ui @application
Scenario: Refunding an order shipping cost 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 "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 "$6.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"
And it gives "100%" discount on shipping to every order over "$25.00"
And there is a customer "[email protected]" that placed an order "#00000022"
And the customer bought 3 "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"
Then I should not be able to refund order shipment
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace spec\Sylius\RefundPlugin\PromotionAction;

use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Promotion\Action\PromotionActionCommandInterface;
use Sylius\Component\Promotion\Model\PromotionInterface;
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\RefundPlugin\Entity\ShipmentInterface;

final class ShippingPercentageDiscountPromotionActionCommandSpec extends ObjectBehavior
{
function let(FactoryInterface $adjustmentFactory): void
{
$this->beConstructedWith($adjustmentFactory);
}

function it_implements_a_promotion_action_interface(): void
{
$this->shouldImplement(PromotionActionCommandInterface::class);
}

function it_applies_percentage_discount_on_every_shipment(
FactoryInterface $adjustmentFactory,
OrderInterface $order,
PromotionInterface $promotion,
ShipmentInterface $firstShipment,
ShipmentInterface $secondShipment,
AdjustmentInterface $firstAdjustment,
AdjustmentInterface $secondAdjustment
): void {
$promotion->getName()->willReturn('Promotion');
$promotion->getCode()->willReturn('PROMOTION');

$order->hasShipments()->willReturn(true);
$order->getShipments()->willReturn(new ArrayCollection([
$firstShipment->getWrappedObject(),
$secondShipment->getWrappedObject(),
]));

$firstShipment->getAdjustmentsTotal(AdjustmentInterface::SHIPPING_ADJUSTMENT)->willReturn(400);
$firstShipment->getAdjustmentsTotal(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$adjustmentFactory->createNew()->willReturn($firstAdjustment, $secondAdjustment);
$firstAdjustment->setType(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->shouldBeCalled();
$firstAdjustment->setLabel('Promotion')->shouldBeCalled();
$firstAdjustment->setOriginCode('PROMOTION')->shouldBeCalled();
$firstAdjustment->setAmount(-200);
$firstShipment->addAdjustment($firstAdjustment);

$secondShipment->getAdjustmentsTotal(AdjustmentInterface::SHIPPING_ADJUSTMENT)->willReturn(600);
$secondShipment->getAdjustmentsTotal(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$secondAdjustment->setType(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->shouldBeCalled();
$secondAdjustment->setLabel('Promotion')->shouldBeCalled();
$secondAdjustment->setOriginCode('PROMOTION')->shouldBeCalled();
$secondAdjustment->setAmount(-300)->shouldBeCalled();
$secondShipment->addAdjustment($secondAdjustment)->shouldBeCalled();

$this->execute($order, ['percentage' => 0.5], $promotion)->shouldReturn(true);
}

function it_does_not_apply_discount_if_order_has_no_shipment(
FactoryInterface $adjustmentFactory,
OrderInterface $order,
PromotionInterface $promotion
): void {
$order->hasShipments()->willReturn(false);
$order->getShipments()->shouldNotBeCalled();
$adjustmentFactory->createNew()->shouldNotBeCalled();

$this->execute($order, ['percentage' => 0.1], $promotion)->shouldReturn(false);
}

function it_does_not_apply_discount_if_adjustment_amount_would_be_0(
FactoryInterface $adjustmentFactory,
OrderInterface $order,
PromotionInterface $promotion,
ShipmentInterface $shipment
): void {
$order->hasShipments()->willReturn(true);
$order->getShipments()->willReturn(new ArrayCollection([$shipment->getWrappedObject()]));

$shipment->getAdjustmentsTotal(AdjustmentInterface::SHIPPING_ADJUSTMENT)->willReturn(0);
$shipment->getAdjustmentsTotal(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$adjustmentFactory->createNew()->shouldNotBeCalled();

$this->execute($order, ['percentage' => 0.5], $promotion)->shouldReturn(false);
}

function it_throws_exception_if_subject_is_not_an_order(
PromotionInterface $promotion,
PromotionSubjectInterface $subject
): void {
$this
->shouldThrow(\InvalidArgumentException::class)
->during('execute', [$subject, [], $promotion])
;
}

function it_reverts_adjustments(
OrderInterface $order,
AdjustmentInterface $firstAdjustment,
AdjustmentInterface $secondAdjustment,
ShipmentInterface $firstShipment,
ShipmentInterface $secondShipment,
PromotionInterface $promotion
): void {
$promotion->getCode()->willReturn('PROMOTION');

$firstAdjustment->getOriginCode()->willReturn('PROMOTION');
$secondAdjustment->getOriginCode()->willReturn('OTHER_PROMOTION');

$order->hasShipments()->willReturn(true);
$order->getShipments()->willReturn(new ArrayCollection([
$firstShipment->getWrappedObject(),
$secondShipment->getWrappedObject(),
]));
$order
->getAdjustments(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)
->willReturn(new ArrayCollection([$firstAdjustment->getWrappedObject(), $secondAdjustment->getWrappedObject()]))
;

$order->removeAdjustment($firstAdjustment)->shouldBeCalled();
$order->removeAdjustment($secondAdjustment)->shouldNotBeCalled();

$firstShipment
->getAdjustments(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)
->willReturn(new ArrayCollection([$firstAdjustment->getWrappedObject()]))
;
$firstShipment->removeAdjustment($firstAdjustment)->shouldBeCalled();

$secondShipment
->getAdjustments(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)
->willReturn(new ArrayCollection([$secondAdjustment->getWrappedObject()]))
;
$secondShipment->removeAdjustment($secondAdjustment)->shouldNotBeCalled();

$this->revert($order, [], $promotion);
}

function it_does_not_revert_adjustments_if_order_has_no_shipment(OrderInterface $order, PromotionInterface $promotion): void
{
$order->hasShipments()->willReturn(false);
$order->getShipments()->shouldNotBeCalled();

$this->revert($order, [], $promotion);
}

function it_throws_an_exception_while_reverting_subject_is_not_an_order(
PromotionInterface $promotion,
PromotionSubjectInterface $subject
): void {
$this
->shouldThrow(\InvalidArgumentException::class)
->during('revert', [$subject, [], $promotion])
;
}
}
Loading