Skip to content

Commit

Permalink
Implement add cart rule handler
Browse files Browse the repository at this point in the history
  • Loading branch information
rokaszygmantas committed Sep 3, 2019
1 parent fc71c26 commit ea16323
Show file tree
Hide file tree
Showing 16 changed files with 411 additions and 34 deletions.
240 changes: 240 additions & 0 deletions src/Adapter/CartRule/CommandHandler/AddCartRuleHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
<?php
/**
* 2007-2019 PrestaShop and Contributors
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://www.prestashop.com for more information.
*
* @author PrestaShop SA <[email protected]>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/

namespace PrestaShop\PrestaShop\Adapter\CartRule\CommandHandler;

use CartRule;
use PrestaShop\PrestaShop\Core\Domain\CartRule\Command\AddCartRuleCommand;
use PrestaShop\PrestaShop\Core\Domain\CartRule\CommandHandler\AddCartRuleHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\CartRule\Exception\CartRuleConstraintException;
use PrestaShop\PrestaShop\Core\Domain\CartRule\Exception\CartRuleException;
use PrestaShop\PrestaShop\Core\Domain\CartRule\ValueObject\CartRuleAction\CartRuleActionInterface;
use PrestaShop\PrestaShop\Core\Domain\CartRule\ValueObject\CartRuleId;
use PrestaShop\PrestaShop\Core\Domain\CartRule\ValueObject\DiscountApplicationType;
use PrestaShopDatabaseException;
use PrestaShopException;

/**
* Handles adding new cart rule using legacy logic.
*/
final class AddCartRuleHandler implements AddCartRuleHandlerInterface
{
/**
* {@inheritdoc}
*/
public function handle(AddCartRuleCommand $command): CartRuleId
{
try {
$cartRule = $this->buildCartRuleFromCommandData($command);

if (false === $cartRule->validateFields(false) || false === $cartRule->validateFieldsLang(false)) {
throw new CartRuleConstraintException('Cart rule contains invalid field values');
}
if (false === $cartRule->add()) {
throw new CartRuleException('Failed to add new cart rule');
}
} catch (PrestaShopException $e) {
throw new CartRuleException('An error occurred when trying to add new cart rule');
}

return new CartRuleId((int) $cartRule->id);
}

/**
* @param AddCartRuleCommand $command
*
* @return CartRule
*
* @throws PrestaShopException
*/
private function buildCartRuleFromCommandData(AddCartRuleCommand $command): CartRule
{
$cartRule = new CartRule();

$cartRule->name = $command->getLocalizedNames();
$cartRule->description = $command->getDescription();
$cartRule->code = $command->getCode();
$cartRule->highlight = $command->isHighlightInCart();
$cartRule->partial_use = $command->isAllowPartialUse();
$cartRule->priority = $command->getPriority();
$cartRule->active = $command->isActive();

$this->fillCartRuleConditionsFromCommandData($cartRule, $command);
$this->fillCartRuleActionsFromCommandData($cartRule, $command);

return $cartRule;
}

/**
* Fills cart rule with conditions data from command.
*
* @param CartRule $cartRule
* @param AddCartRuleCommand $command
*/
private function fillCartRuleConditionsFromCommandData(CartRule $cartRule, AddCartRuleCommand $command): void
{
$cartRule->id_customer = null !== $command->getCustomerId() ? $command->getCustomerId()->getValue() : null;

$cartRule->date_from = $command->getValidFrom()->format('Y-m-d H:i:s');
$cartRule->date_to = $command->getValidTo()->format('Y-m-d H:i:s');

$minimumAmount = $command->getMinimumAmount();
$cartRule->minimum_amount = $minimumAmount->getMoneyAmount()->getAmount();
$cartRule->minimum_amount_currency = $minimumAmount->getMoneyAmount()->getCurrencyId()->getValue();
$cartRule->minimum_amount_shipping = $minimumAmount->isShippingExcluded();
$cartRule->minimum_amount_tax = $minimumAmount->isTaxExcluded();

$cartRule->quantity = $command->getTotalQuantity();
$cartRule->quantity_per_user = $command->getQuantityPerUser();

$cartRule->country_restriction = $command->hasCountryRestriction();
$cartRule->carrier_restriction = $command->hasCarrierRestriction();
$cartRule->group_restriction = $command->hasGroupRestriction();
$cartRule->cart_rule_restriction = $command->hasCartRuleRestriction();
$cartRule->product_restriction = $command->hasProductRestriction();
$cartRule->shop_restriction = $command->hasShopRestriction();
}

/**
* Fills cart rule with actions data from command.
*
* @param CartRule $cartRule
* @param AddCartRuleCommand $command
*/
private function fillCartRuleActionsFromCommandData(CartRule $cartRule, AddCartRuleCommand $command): void
{
$cartRuleAction = $command->getCartRuleAction();
$amountDiscount = $cartRuleAction->getAmountDiscount();
$percentageDiscount = $cartRuleAction->getPercentageDiscount();
$giftProduct = $cartRuleAction->getGiftProduct();
$cartRule->free_shipping = $cartRuleAction->isFreeShipping();

$cartRule->gift_product = null !== $giftProduct ? $giftProduct->getProductId()->getValue() : null;
$cartRule->gift_product_attribute = null !== $giftProduct ? $giftProduct->getProductAttributeId() : null;
$cartRule->reduction_amount = null !== $amountDiscount ?
$amountDiscount->getMoneyAmount()->getAmount() :
null;
$cartRule->reduction_currency = null !== $amountDiscount ?
$amountDiscount->getMoneyAmount()->getCurrencyId()->getValue() :
null;

// Legacy reduction_tax property is true when it's tax included, false when tax excluded.
$cartRule->reduction_tax = null !== $amountDiscount ? !$amountDiscount->isTaxExcluded() : null;

$cartRule->reduction_percent = null !== $percentageDiscount ? $percentageDiscount->getPercentage() : null;
$cartRule->reduction_exclude_special = null !== $percentageDiscount ?
!$percentageDiscount->appliesToDiscountedProducts() :
null;

$discountApplicationType = $command->getDiscountApplicationType();

if (null !== $discountApplicationType) {
$this->fillDiscountApplicationType(
$cartRule,
$command,
$cartRuleAction,
$discountApplicationType
);
}
}

/**
* @param CartRule $cartRule
* @param AddCartRuleCommand $command
* @param CartRuleActionInterface $cartRuleAction
* @param DiscountApplicationType $discountApplicationType
*
* @throws CartRuleConstraintException
*/
private function fillDiscountApplicationType(
CartRule $cartRule,
AddCartRuleCommand $command,
CartRuleActionInterface $cartRuleAction,
DiscountApplicationType $discountApplicationType
): void {
$hasAmountDiscount = null !== $cartRuleAction->getAmountDiscount();
$hasPercentageDiscount = null !== $cartRuleAction->getPercentageDiscount();

switch ($discountApplicationType->getValue()) {
case DiscountApplicationType::SELECTED_PRODUCTS:
if (!$hasPercentageDiscount) {
throw new CartRuleConstraintException(
'Cart rule, which is applied to selected products, must have percent discount type.',
CartRuleConstraintException::INCOMPATIBLE_CART_RULE_ACTIONS
);
}

$cartRule->reduction_product = -2;

break;

case DiscountApplicationType::CHEAPEST_PRODUCT:
if (!$hasPercentageDiscount) {
throw new CartRuleConstraintException(
'Cart rule, which is applied to cheapest product, must have percent discount type.',
CartRuleConstraintException::INCOMPATIBLE_CART_RULE_ACTIONS
);
}

$cartRule->reduction_product = -1;

break;

case DiscountApplicationType::SPECIFIC_PRODUCT:
if (!$hasPercentageDiscount && !$hasAmountDiscount) {
throw new CartRuleConstraintException(
'Cart rule, which is applied to a specific product, '.
'must have percentage or amount application type.',
CartRuleConstraintException::INCOMPATIBLE_CART_RULE_ACTIONS
);
}

if (null === $command->getDiscountProductId()) {
throw new CartRuleConstraintException(
'Cart rule, which is applied to a specific product, must have a product specified.',
CartRuleConstraintException::MISSING_DISCOUNT_APPLICATION_PRODUCT
);
}

$cartRule->reduction_product = $command->getDiscountProductId()->getValue();

break;

case DiscountApplicationType::ORDER_WITHOUT_SHIPPING:
if (!$hasAmountDiscount && !$hasPercentageDiscount) {
throw new CartRuleConstraintException(
'Cart rule, which is applied to whole order without shipping, '.
'must have percentage or amount application type.',
CartRuleConstraintException::INCOMPATIBLE_CART_RULE_ACTIONS
);
}

$cartRule->reduction_product = 0;

break;
}
}
}
65 changes: 62 additions & 3 deletions src/Core/Domain/CartRule/Command/AddCartRuleCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@
use DateTime;
use PrestaShop\PrestaShop\Core\Domain\CartRule\Exception\CartRuleConstraintException;
use PrestaShop\PrestaShop\Core\Domain\CartRule\ValueObject\CartRuleAction\CartRuleActionInterface;
use PrestaShop\PrestaShop\Core\Domain\CartRule\ValueObject\DiscountApplicationType;
use PrestaShop\PrestaShop\Core\Domain\CartRule\ValueObject\MoneyAmountCondition;
use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\CustomerId;
use PrestaShop\PrestaShop\Core\Domain\Language\ValueObject\LanguageId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;

/**
* Adds new cart rule
Expand All @@ -54,7 +56,7 @@ class AddCartRuleCommand
private $minimumAmount;

/**
* @var CustomerId
* @var CustomerId|null
*/
private $customerId;

Expand Down Expand Up @@ -138,6 +140,21 @@ class AddCartRuleCommand
*/
private $cartRuleAction;

/**
* Discount application type indicates what the discount should be applied to.
* E.g. to whole order, to a specific product, to cheapest product.
*
* @var DiscountApplicationType
*/
private $discountApplicationType;

/**
* This is the product to which discount is applied, when discount application type is "specific product".
*
* @var ProductId|null
*/
private $discountProductId;

/**
* @param array $localizedNames
* @param bool $highlightInCart
Expand Down Expand Up @@ -177,6 +194,48 @@ public function __construct(
$this->cartRuleAction = $cartRuleAction;
}

/**
* @return DiscountApplicationType
*/
public function getDiscountApplicationType(): DiscountApplicationType
{
return $this->discountApplicationType;
}

/**
* @param string $discountApplicationType
*
* @return AddCartRuleCommand
*
* @throws CartRuleConstraintException
*/
public function setDiscountApplicationType(string $discountApplicationType): AddCartRuleCommand
{
$this->discountApplicationType = new DiscountApplicationType($discountApplicationType);

return $this;
}

/**
* @return ProductId|null
*/
public function getDiscountProductId(): ?ProductId
{
return $this->discountProductId;
}

/**
* @param ProductId|null $discountProductId
*
* @return AddCartRuleCommand
*/
public function setDiscountProductId(?ProductId $discountProductId): AddCartRuleCommand
{
$this->discountProductId = $discountProductId;

return $this;
}

/**
* @return string
*/
Expand All @@ -202,9 +261,9 @@ public function getMinimumAmount(): MoneyAmountCondition
}

/**
* @return CustomerId
* @return CustomerId|null
*/
public function getCustomerId(): CustomerId
public function getCustomerId(): ?CustomerId
{
return $this->customerId;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
/**
* 2007-2019 PrestaShop and Contributors
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://www.prestashop.com for more information.
*
* @author PrestaShop SA <[email protected]>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/

namespace PrestaShop\PrestaShop\Core\Domain\CartRule\CommandHandler;

use PrestaShop\PrestaShop\Core\Domain\CartRule\Command\AddCartRuleCommand;
use PrestaShop\PrestaShop\Core\Domain\CartRule\ValueObject\CartRuleId;

/**
* Interface for service that handles adding new cart rule.
*/
interface AddCartRuleHandlerInterface
{
/**
* @param AddCartRuleCommand $command
*
* @return CartRuleId
*/
public function handle(AddCartRuleCommand $command): CartRuleId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,9 @@ class CartRuleConstraintException extends CartRuleException
* Used when cart rule is missing an action.
*/
const MISSING_ACTION = 11;

/**
* Used when discount is applied to specific product, but that product is not set.
*/
const MISSING_DISCOUNT_APPLICATION_PRODUCT = 12;
}
Loading

0 comments on commit ea16323

Please sign in to comment.