From 2113e7a457d795da0257dd2fb174504ac3c50ca4 Mon Sep 17 00:00:00 2001 From: gmorel Date: Mon, 19 Aug 2013 20:02:53 +0200 Subject: [PATCH] WIP Coupon RemoveXPercent and RemoveXAmount implementation --- core/lib/Thelia/Coupon/CouponAbstract.php | 69 +++++++- .../Thelia/Coupon/CouponAdapterInterface.php | 22 +++ core/lib/Thelia/Coupon/CouponBaseAdapter.php | 20 +++ core/lib/Thelia/Coupon/Type/RemoveXAmount.php | 40 +++++ .../lib/Thelia/Coupon/Type/RemoveXPercent.php | 55 +++++++ .../Exception/MissingAdapterException.php | 50 ++++++ .../Tests/Coupon/Type/RemoveXAmountTest.php | 147 +++++++++++++++++- .../Tests/Coupon/Type/RemoveXPercentTest.php | 139 +++++++++++++++++ 8 files changed, 533 insertions(+), 9 deletions(-) create mode 100644 core/lib/Thelia/Exception/MissingAdapterException.php diff --git a/core/lib/Thelia/Coupon/CouponAbstract.php b/core/lib/Thelia/Coupon/CouponAbstract.php index 8c78dd924..b2d4f9268 100644 --- a/core/lib/Thelia/Coupon/CouponAbstract.php +++ b/core/lib/Thelia/Coupon/CouponAbstract.php @@ -23,6 +23,8 @@ namespace Thelia\Coupon; +use Symfony\Component\Intl\Exception\NotImplementedException; + /** * Created by JetBrains PhpStorm. * Date: 8/19/13 @@ -36,9 +38,57 @@ namespace Thelia\Coupon; */ abstract class CouponAbstract implements CouponInterface { + /** @var CouponAdapterInterface Provide necessary value from Thelia*/ + protected $adapter; + /** @var RuleOrganizerInterface */ protected $organizer = null; + /** @var string Coupon code (ex: XMAS) */ + protected $code = null; + + /** @var string Coupon title (ex: Coupon for XMAS) */ + protected $title = null; + + /** @var string Coupon short description */ + protected $shortDescription = null; + + /** @var string Coupon description */ + protected $description = null; + + /** @var bool if Coupon is cumulative */ + protected $isCumulative = false; + + /** @var bool if Coupon is removing postage */ + protected $isRemovingPostage = false; + + /** + * Set Adapter containing all relevant data + * + * @param CouponAdapterInterface $adapter Adapter + * + * @return $this + */ + public function setAdapter($adapter) + { + $this->adapter = $adapter; + + return $this; + } + + /** + * Set Rule Organizer + * + * @param RuleOrganizerInterface $organizer Manage Rule groups (&& and ||) + * + * @return $this + */ + public function setOrganizer($organizer) + { + $this->organizer = $organizer; + + return $this; + } /** * Return Coupon code (ex: XMAS) @@ -47,7 +97,7 @@ abstract class CouponAbstract implements CouponInterface */ public function getCode() { - // TODO: Implement getCode() method. + return $this->code; } /** @@ -57,7 +107,7 @@ abstract class CouponAbstract implements CouponInterface */ public function getTitle() { - // TODO: Implement getTitle() method. + return $this->title; } /** @@ -67,7 +117,7 @@ abstract class CouponAbstract implements CouponInterface */ public function getShortDescription() { - // TODO: Implement getShortDescription() method. + return $this->shortDescription; } /** @@ -77,7 +127,7 @@ abstract class CouponAbstract implements CouponInterface */ public function getDescription() { - // TODO: Implement getDescription() method. + return $this->description; } /** @@ -85,11 +135,11 @@ abstract class CouponAbstract implements CouponInterface * If is cumulative you can sum Coupon effects * If not cancel all other Coupon and take the last given * - * @return string + * @return bool */ public function isCumulative() { - // TODO: Implement isCumulative() method. + return $this->isCumulative; } /** @@ -99,17 +149,20 @@ abstract class CouponAbstract implements CouponInterface */ public function isRemovingPostage() { - // TODO: Implement isRemovingPostage() method. + return $this->isRemovingPostage; } /** * Return effects generated by the coupon * + * @throws \Symfony\Component\Intl\Exception\NotImplementedException * @return \Closure */ public function getEffect() { - // TODO: Implement getEffect() method. + throw new NotImplementedException( + 'Abstract method to implement (CouponAbstract->getEffect)' + ); } } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/CouponAdapterInterface.php b/core/lib/Thelia/Coupon/CouponAdapterInterface.php index ece82fe28..f36c13427 100644 --- a/core/lib/Thelia/Coupon/CouponAdapterInterface.php +++ b/core/lib/Thelia/Coupon/CouponAdapterInterface.php @@ -57,4 +57,26 @@ interface CouponAdapterInterface * @return \Thelia\Model\Customer */ public function getCustomer(); + + /** + * Return Checkout total price + * + * @return float + */ + public function getCheckoutTotalPrice(); + + /** + * Return Products total price + * + * @return float + */ + public function getCheckoutTotalPriceWithoutDiscountAndPostagePrice(); + + /** + * Return Checkout total postage (only) price + * + * @return float + */ + public function getCheckoutPostagePrice(); + } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/CouponBaseAdapter.php b/core/lib/Thelia/Coupon/CouponBaseAdapter.php index 35b15af41..bb24306e2 100644 --- a/core/lib/Thelia/Coupon/CouponBaseAdapter.php +++ b/core/lib/Thelia/Coupon/CouponBaseAdapter.php @@ -64,4 +64,24 @@ class CouponBaseAdapter implements CouponAdapterInterface // TODO: Implement getCustomer() method. } + /** + * Return Checkout total price + * + * @return float + */ + public function getCheckoutTotalPrice() + { + // TODO: Implement getCheckoutTotalPrice() method. + } + + /** + * Return Checkout total postage (only) price + * + * @return float + */ + public function getCheckoutPostagePrice() + { + // TODO: Implement getCheckoutPostagePrice() method. + } + } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php index 1119d4ac2..6c9a6e7ba 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php @@ -30,6 +30,8 @@ use Thelia\Coupon\CouponAbstract; * Date: 8/19/13 * Time: 3:24 PM * + * Allow to remove an amount from the checkout total + * * @package Coupon * @author Guillaume MOREL * @@ -37,4 +39,42 @@ use Thelia\Coupon\CouponAbstract; class RemoveXAmount extends CouponAbstract { + protected $amount = 0; + + /** + * Constructor + * + * @param string $code Coupon code (ex: XMAS) + * @param string $title Coupon title (ex: Coupon for XMAS) + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param float $amount Coupon amount to deduce + * @param bool $isCumulative if Coupon is cumulative + * @param bool $isRemovingPostage if Coupon is removing postage + */ + function __construct($code, $title, $shortDescription, $description, $amount, $isCumulative, $isRemovingPostage) + { + $this->code = $code; + $this->title = $title; + $this->shortDescription = $shortDescription; + $this->description = $description; + + $this->isCumulative = $isCumulative; + $this->isRemovingPostage = $isRemovingPostage; + + $this->amount = $amount; + } + + /** + * Return effects generated by the coupon + * A negative value + * + * @return float + */ + public function getEffect() + { + return -$this->amount; + } + + } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php index 638861e71..3f0fd43fc 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php @@ -23,6 +23,9 @@ namespace Thelia\Coupon\Type; +use Thelia\Coupon\CouponAbstract; +use Thelia\Exception\MissingAdapterException; + /** * Created by JetBrains PhpStorm. * Date: 8/19/13 @@ -34,5 +37,57 @@ namespace Thelia\Coupon\Type; */ class RemoveXPercent extends CouponAbstract { + protected $percent = 0; + + /** + * Constructor + * + * @param string $code Coupon code (ex: XMAS) + * @param string $title Coupon title (ex: Coupon for XMAS) + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param float $percent Coupon % to deduce (ex:3.14 for 3.14%) + * @param bool $isCumulative if Coupon is cumulative + * @param bool $isRemovingPostage if Coupon is removing postage + */ + function __construct($code, $title, $shortDescription, $description, $percent, $isCumulative, $isRemovingPostage) + { + $this->code = $code; + $this->title = $title; + $this->shortDescription = $shortDescription; + $this->description = $description; + + $this->isCumulative = $isCumulative; + $this->isRemovingPostage = $isRemovingPostage; + + $this->percent = $percent; + } + + /** + * Return effects generated by the coupon + * A negative value + * + * @throws \Thelia\Exception\MissingAdapterException + * @throws \InvalidArgumentException + * @return float + */ + public function getEffect() + { + if ($this->adapter === null) { + throw new MissingAdapterException( + 'Cant calculate effect : CouponAdapterInterface is missing.' + ); + } + + if ($this->percent >= 100) { + throw new \InvalidArgumentException( + 'Percentage must be inferior to 100' + ); + } + + $basePrice = $this->adapter + ->getCheckoutTotalPriceWithoutDiscountAndPostagePrice(); + return $basePrice * (( 100 - $this->percent ) / 100); + } } \ No newline at end of file diff --git a/core/lib/Thelia/Exception/MissingAdapterException.php b/core/lib/Thelia/Exception/MissingAdapterException.php new file mode 100644 index 000000000..645020cab --- /dev/null +++ b/core/lib/Thelia/Exception/MissingAdapterException.php @@ -0,0 +1,50 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Exception; + +use Thelia\Log\Tlog; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Thrown when the Adapter is not set + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class MissingAdapterException extends \RuntimeException +{ + /** + * {@inheritdoc} + */ + public function __construct($message, $code = null, $previous = null) { + + Tlog::getInstance()->addError($message); + + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php index 4b28a1d7b..27d0e9afb 100644 --- a/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php @@ -1,20 +1,165 @@ Loremipsum'; /** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. */ protected function setUp() { + } + + protected function generateValidCumulativeRemovingPostageCoupon() + { + $coupon = new RemoveXAmount( + self::VALID_COUPON_CODE, + self::VALID_COUPON_TITLE, + self::VALID_COUPON_SHORT_DESCRIPTION, + self::VALID_COUPON_DESCRIPTION, + 30.00, + true, + true + ); + + return $coupon; + } + + protected function generateValidNonCumulativeNonRemovingPostageCoupon() + { + $coupon = new RemoveXAmount( + self::VALID_COUPON_CODE, + self::VALID_COUPON_TITLE, + self::VALID_COUPON_SHORT_DESCRIPTION, + self::VALID_COUPON_DESCRIPTION, + 30.00, + false, + false + ); + + return $coupon; + } + + /** + * + * @covers Thelia\Coupon\type\RemoveXAmount::getCode + * @covers Thelia\Coupon\type\RemoveXAmount::getTitle + * @covers Thelia\Coupon\type\RemoveXAmount::getShortDescription + * @covers Thelia\Coupon\type\RemoveXAmount::getDescription + * + */ + public function testDisplay() + { + + $coupon = $this->generateValidCumulativeRemovingPostageCoupon(); + + $expected = self::VALID_COUPON_CODE; + $actual = $coupon->getCode(); + $this->assertEquals($expected, $actual); + + $expected = self::VALID_COUPON_TITLE; + $actual = $coupon->getTitle(); + $this->assertEquals($expected, $actual); + + $expected = self::VALID_COUPON_SHORT_DESCRIPTION; + $actual = $coupon->getShortDescription(); + $this->assertEquals($expected, $actual); + + $expected = self::VALID_COUPON_DESCRIPTION; + $actual = $coupon->getDescription(); + $this->assertEquals($expected, $actual); + + } + + + /** + * + * @covers Thelia\Coupon\type\RemoveXAmount::isCumulative + * + */ + public function testIsCumulative() + { + + $coupon = $this->generateValidCumulativeRemovingPostageCoupon(); + + $actual = $coupon->isCumulative(); + $this->assertTrue($actual); + } + + /** + * + * @covers Thelia\Coupon\type\RemoveXAmount::isCumulative + * + */ + public function testIsNotCumulative() + { + + $coupon = $this->generateValidNonCumulativeNonRemovingPostageCoupon(); + + $actual = $coupon->isCumulative(); + $this->assertFalse($actual); + } + + + /** + * + * @covers Thelia\Coupon\type\RemoveXAmount::isRemovingPostage + * + */ + public function testIsRemovingPostage() + { + + $coupon = $this->generateValidCumulativeRemovingPostageCoupon(); + + $actual = $coupon->isRemovingPostage(); + $this->assertTrue($actual); + } + + /** + * + * @covers Thelia\Coupon\type\RemoveXAmount::isRemovingPostage + * + */ + public function testIsNotRemovingPostage() + { + + $coupon = $this->generateValidNonCumulativeNonRemovingPostageCoupon(); + + $actual = $coupon->isRemovingPostage(); + $this->assertFalse($actual); + } + + + /** + * + * @covers Thelia\Coupon\type\RemoveXAmount::getEffect + * + */ + public function testGetEffect() + { + + $coupon = $this->generateValidNonCumulativeNonRemovingPostageCoupon(); + + $expected = -30.00; + $actual = $coupon->getEffect(); + $this->assertEquals($expected, $actual); + } + + /** * Tears down the fixture, for example, closes a network connection. * This method is called after a test is executed. diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php index a7aa2e65f..33372cdb2 100644 --- a/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php @@ -1,6 +1,9 @@ generateValidCumulativeRemovingPostageCoupon(); + + $expected = self::VALID_COUPON_CODE; + $actual = $coupon->getCode(); + $this->assertEquals($expected, $actual); + + $expected = self::VALID_COUPON_TITLE; + $actual = $coupon->getTitle(); + $this->assertEquals($expected, $actual); + + $expected = self::VALID_COUPON_SHORT_DESCRIPTION; + $actual = $coupon->getShortDescription(); + $this->assertEquals($expected, $actual); + + $expected = self::VALID_COUPON_DESCRIPTION; + $actual = $coupon->getDescription(); + $this->assertEquals($expected, $actual); + + } + + + /** + * + * @covers Thelia\Coupon\Type\RemoveXPercent::isCumulative + * + */ + public function testIsCumulative() + { + + $coupon = $this->generateValidCumulativeRemovingPostageCoupon(); + + $actual = $coupon->isCumulative(); + $this->assertTrue($actual); + } + + /** + * + * @covers Thelia\Coupon\Type\RemoveXPercent::isCumulative + * + */ + public function testIsNotCumulative() + { + + $coupon = $this->generateValidNonCumulativeNonRemovingPostageCoupon(); + + $actual = $coupon->isCumulative(); + $this->assertFalse($actual); + } + + + /** + * + * @covers Thelia\Coupon\Type\RemoveXPercent::isRemovingPostage + * + */ + public function testIsRemovingPostage() + { + + $coupon = $this->generateValidCumulativeRemovingPostageCoupon(); + + $actual = $coupon->isRemovingPostage(); + $this->assertTrue($actual); + } + + /** + * + * @covers Thelia\Coupon\Type\RemoveXPercent::isRemovingPostage + * + */ + public function testIsNotRemovingPostage() + { + + $coupon = $this->generateValidNonCumulativeNonRemovingPostageCoupon(); + + $actual = $coupon->isRemovingPostage(); + $this->assertFalse($actual); + } + + + /** + * + * @covers Thelia\Coupon\Type\RemoveXPercent::getEffect + * + */ + public function testGetEffect() + { + + $coupon = $this->generateValidNonCumulativeNonRemovingPostageCoupon(); + + $expected = -30.00; + $actual = $coupon->getEffect(); + $this->assertEquals($expected, $actual); + } + /** * Tears down the fixture, for example, closes a network connection. * This method is called after a test is executed.