Merge pull request #473 from roadster31/coupon-end
Major coupon types refactoring.
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
#2.0.3
|
||||
- New coupon type: Free product if selected products are in the cart.
|
||||
|
||||
#2.0.2
|
||||
- Coupon UI has been redesigned.
|
||||
- New coupon types:
|
||||
|
||||
@@ -109,6 +109,17 @@ class Coupon extends BaseAction implements EventSubscriberInterface
|
||||
$this->createOrUpdateCondition($modelCoupon, $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all coupons in session.
|
||||
*/
|
||||
public function clearAllCoupons()
|
||||
{
|
||||
// Tell coupons to clear any data they may have stored
|
||||
$this->couponManager->clear();
|
||||
|
||||
$this->request->getSession()->setConsumedCoupons(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurring when a Coupon condition is about to be consumed
|
||||
*
|
||||
@@ -139,21 +150,22 @@ class Coupon extends BaseAction implements EventSubscriberInterface
|
||||
$consumedCoupons[$event->getCode()] = $event->getCode();
|
||||
|
||||
$this->request->getSession()->setConsumedCoupons($consumedCoupons);
|
||||
|
||||
$totalDiscount = $this->couponManager->getDiscount();
|
||||
|
||||
$this->request
|
||||
->getSession()
|
||||
->getCart()
|
||||
->setDiscount($totalDiscount)
|
||||
->save();
|
||||
$this->request
|
||||
->getSession()
|
||||
->getOrder()
|
||||
->setDiscount($totalDiscount)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
$totalDiscount = $this->couponManager->getDiscount();
|
||||
|
||||
$this->request
|
||||
->getSession()
|
||||
->getCart()
|
||||
->setDiscount($totalDiscount)
|
||||
->save();
|
||||
|
||||
$this->request
|
||||
->getSession()
|
||||
->getOrder()
|
||||
->setDiscount($totalDiscount)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
$event->setIsValid($isValid);
|
||||
@@ -339,7 +351,8 @@ class Coupon extends BaseAction implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
$this->request->getSession()->setConsumedCoupons(array());
|
||||
// Clear all coupons.
|
||||
$event->getDispatcher()->dispatch(TheliaEvents::COUPON_CLEAR_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,6 +381,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface
|
||||
TheliaEvents::COUPON_CREATE => array("create", 128),
|
||||
TheliaEvents::COUPON_UPDATE => array("update", 128),
|
||||
TheliaEvents::COUPON_CONSUME => array("consume", 128),
|
||||
TheliaEvents::COUPON_CLEAR_ALL => array("clearAllCoupons", 128),
|
||||
TheliaEvents::COUPON_CONDITION_UPDATE => array("updateCondition", 128),
|
||||
TheliaEvents::ORDER_SET_POSTAGE => array("testFreePostage", 132),
|
||||
TheliaEvents::ORDER_BEFORE_PAYMENT => array("afterOrder", 128),
|
||||
|
||||
@@ -55,6 +55,8 @@ class StartDate extends ConditionAbstract
|
||||
*/
|
||||
public function setValidatorsFromForm(array $operators, array $values)
|
||||
{
|
||||
$this->checkComparisonOperatorValue($operators, self::START_DATE);
|
||||
|
||||
if (! isset($values[self::START_DATE])) {
|
||||
$values[self::START_DATE] = time();
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ return array(
|
||||
'Cart item count is' => 'Cart item count is',
|
||||
'Cart total amount' => 'Cart total amount',
|
||||
'Cart total amount is' => 'Cart total amount is',
|
||||
'Catalog' => 'Catalog',
|
||||
'Category title *' => 'Category title *',
|
||||
'Cellphone' => 'Cellphone',
|
||||
'Chapo' => 'Chapo',
|
||||
@@ -111,14 +112,18 @@ return array(
|
||||
'First Name' => 'First Name',
|
||||
'Firstname' => 'Firstname',
|
||||
'Fixed Amount Discount' => 'Fixed Amount Discount',
|
||||
'Fixed amount discount for selected attribute values' => 'Fixed amount discount for selected attribute values',
|
||||
'Fixed amount discount for selected categories' => 'Fixed amount discount for selected categories',
|
||||
'Fixed amount discount for selected products' => 'Fixed amount discount for selected products',
|
||||
'Folder' => 'Folder',
|
||||
'Folder title *' => 'Folder title *',
|
||||
'For one ore more customers' => 'For one ore more customers',
|
||||
'Free product when buying one or more selected products' => 'Free product when buying one or more selected products',
|
||||
'Full Name' => 'Full Name',
|
||||
'Greater than' => 'Greater than',
|
||||
'Greater than or equals' => 'Greater than or equals',
|
||||
'HTML Message' => 'HTML Message',
|
||||
'Home' => 'Home',
|
||||
'Host' => 'Host',
|
||||
'I would like to receive the newsletter or the latest news.' => 'I would like to receive the newsletter or the latest news.',
|
||||
'ISO 4217 code *' => 'ISO 4217 code *',
|
||||
@@ -190,6 +195,7 @@ return array(
|
||||
'Password *' => 'Password *',
|
||||
'Password confirmation' => 'Password confirmation',
|
||||
'Per customer' => 'Per customer',
|
||||
'Percentage discount for selected attribute values' => 'Percentage discount for selected attribute values',
|
||||
'Percentage discount for selected categories' => 'Percentage discount for selected categories',
|
||||
'Percentage discount for selected products' => 'Percentage discount for selected products',
|
||||
'Percentage of the product price' => 'Percentage of the product price',
|
||||
@@ -199,8 +205,12 @@ return array(
|
||||
'Please enter your email address' => 'Please enter your email address',
|
||||
'Please enter your password' => 'Please enter your password',
|
||||
'Please select a category' => 'Please select a category',
|
||||
'Please select an attribute' => 'Please select an attribute',
|
||||
'Please select at least one attribute value' => 'Please select at least one attribute value',
|
||||
'Please select at least one category' => 'Please select at least one category',
|
||||
'Please select at least one product' => 'Please select at least one product',
|
||||
'Please select the category of the offred product' => 'Please select the category of the offred product',
|
||||
'Please select the offered product' => 'Please select the offered product',
|
||||
'Please specify either \'path\' or \'file\' parameter in {url} function.' => 'Please specify either \'path\' or \'file\' parameter in {url} function.',
|
||||
'Port' => 'Port',
|
||||
'Post Scriptum' => 'Post Scriptum',
|
||||
@@ -288,10 +298,13 @@ return array(
|
||||
'This category is online.' => 'This category is online.',
|
||||
'This condition is always true' => 'This condition is always true',
|
||||
'This content is online.' => 'This content is online.',
|
||||
'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'This coupon adds a free product to the cart if one of the selected products is in the cart.',
|
||||
'This coupon does not exists' => 'This coupon does not exists',
|
||||
'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
@@ -324,7 +337,6 @@ return array(
|
||||
'Valid only from %date% to the coupon expiration date' => 'Valide à partir du %date% jusqu\'à la date d\'expiration',
|
||||
'Value' => 'Value',
|
||||
'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Value %val for Discount Amount is invalid. Please enter a positive value.',
|
||||
'Value %val for Disount Amount is invalid. Please enter a positive value.' => 'Value %val for Disount Amount is invalid. Please enter a positive value.',
|
||||
'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.',
|
||||
'Value *' => 'Value *',
|
||||
'Warnings' => 'Warnings',
|
||||
|
||||
@@ -50,6 +50,7 @@ return array(
|
||||
'Cart item count is' => 'Le nombre d\'articles dans le panier est',
|
||||
'Cart total amount' => 'Montant total du panier',
|
||||
'Cart total amount is' => 'Le total du panier est',
|
||||
'Catalog' => 'Catalogue',
|
||||
'Category title *' => 'Titre de la catégorie *',
|
||||
'Cellphone' => 'Numéro de portable',
|
||||
'Chapo' => 'Chapeau',
|
||||
@@ -111,14 +112,18 @@ return array(
|
||||
'First Name' => 'Prénom',
|
||||
'Firstname' => 'Prénom',
|
||||
'Fixed Amount Discount' => 'Remise d\'un montant fixe',
|
||||
'Fixed amount discount for selected attribute values' => 'Remise constante pour certaines valeurs de déclinaison',
|
||||
'Fixed amount discount for selected categories' => 'Remise fixe pour certaines catégories',
|
||||
'Fixed amount discount for selected products' => 'Remise fixe pour certains produits',
|
||||
'Folder' => 'Dossier',
|
||||
'Folder title *' => 'Titre du dossier *',
|
||||
'For one ore more customers' => 'Valable pour un ou plusieurs clients',
|
||||
'Free product when buying one or more selected products' => 'Un produit offert pour l\'achat d\'un ou plusieurs produits',
|
||||
'Full Name' => 'Nom complet',
|
||||
'Greater than' => 'Supérieur à',
|
||||
'Greater than or equals' => 'Supérieur ou égal à',
|
||||
'HTML Message' => 'Message au format HTML',
|
||||
'Home' => 'Accueil',
|
||||
'Host' => 'Nom de l\'hôte',
|
||||
'I would like to receive the newsletter or the latest news.' => 'Je souhaite recevoir la lettre d\'information ou les dernières actualités.',
|
||||
'ISO 4217 code *' => 'Code ISO 4217 *',
|
||||
@@ -190,6 +195,7 @@ return array(
|
||||
'Password *' => 'Mot de passe *',
|
||||
'Password confirmation' => 'Confirmation du mot de passe.',
|
||||
'Per customer' => 'Par client',
|
||||
'Percentage discount for selected attribute values' => 'Remise en pourcentage pour certaines valeurs de déclinaison',
|
||||
'Percentage discount for selected categories' => 'Remise en pourcentage pour certaines catégories',
|
||||
'Percentage discount for selected products' => 'Remise en pourcentage pour certains produits',
|
||||
'Percentage of the product price' => 'Pourcentage du prix du produit',
|
||||
@@ -199,8 +205,12 @@ return array(
|
||||
'Please enter your email address' => 'Renseignez votre adresse mail',
|
||||
'Please enter your password' => 'Entrez votre mot de passe.',
|
||||
'Please select a category' => 'Merci de choisir une catégorie',
|
||||
'Please select an attribute' => 'Merci de choisir une déclinaison',
|
||||
'Please select at least one attribute value' => 'Merci de choisir au moins une valeur de déclinaison',
|
||||
'Please select at least one category' => 'Merci de choisir au moins une catégorie.',
|
||||
'Please select at least one product' => 'Merci de choisir au moins un produit',
|
||||
'Please select the category of the offred product' => 'Merci de choisir la catégorie du produit offert',
|
||||
'Please select the offered product' => 'Merci de choisir le produit offert',
|
||||
'Please specify either \'path\' or \'file\' parameter in {url} function.' => 'Veuillez spécifier soit le paramètre \'chemin\' ou \'fichier\' dans la fonction {url}',
|
||||
'Port' => 'Port',
|
||||
'Post Scriptum' => 'Post-scriptum',
|
||||
@@ -288,10 +298,13 @@ return array(
|
||||
'This category is online.' => 'Cette catégorie est en ligne.',
|
||||
'This condition is always true' => 'Cette condition est troujours vérifiée',
|
||||
'This content is online.' => 'Ce contenu est en ligne.',
|
||||
'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Ce coupon ajoute un produit gratuit (sous forme de remise) au panier, si un des produits indiqués est présent dans le panier.',
|
||||
'This coupon does not exists' => 'Ce code promo n\'existe pas',
|
||||
'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits appartenant aux catégories sélectionnées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.',
|
||||
'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits ayant au moins une des valeurs de déclinaisons indiquées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.',
|
||||
'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits sélectionnés. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.',
|
||||
'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits appartenant aux catégories sélectionnées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.',
|
||||
'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits ayant au moins une des valeurs de déclinaisons indiquées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.',
|
||||
'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits sélectionnés. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.',
|
||||
'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le pourcentage indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.',
|
||||
'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.',
|
||||
@@ -324,7 +337,6 @@ return array(
|
||||
'Valid only from %date% to the coupon expiration date' => 'Valide à partir de %date% jusqu\'à la date d\'expoiration',
|
||||
'Value' => 'Valeur',
|
||||
'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'La valeur %val pour le montant de la remise est invalide. Merci d\'indiquer une valeur positive.',
|
||||
'Value %val for Disount Amount is invalid. Please enter a positive value.' => 'La valeur %val pour le montant de la remise est invalide. Merci d\'indiquer une valeur positive.',
|
||||
'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'La valeur %val pour le pourcentage de remise est invalide. Merci d\'indiquer un nombre entre 1 et 100',
|
||||
'Value *' => 'Valeur *',
|
||||
'Warnings' => 'Avertissements',
|
||||
|
||||
@@ -51,6 +51,25 @@
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.coupon.type.remove_percentage_on_products" class="Thelia\Coupon\Type\RemovePercentageOnProducts">
|
||||
<argument type="service" id="thelia.facade" />
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.coupon.type.remove_amount_on_attribute_av" class="Thelia\Coupon\Type\RemoveAmountOnAttributeValues">
|
||||
<argument type="service" id="thelia.facade" />
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.coupon.type.remove_percentage_on_attribute_av" class="Thelia\Coupon\Type\RemovePercentageOnAttributeValues">
|
||||
<argument type="service" id="thelia.facade" />
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<service id="thelia.coupon.type.free_product" class="Thelia\Coupon\Type\FreeProduct">
|
||||
<argument type="service" id="thelia.facade" />
|
||||
<tag name="thelia.coupon.addCoupon"/>
|
||||
</service>
|
||||
|
||||
<!-- Condition module -->
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Thelia\Core\Event\Cart;
|
||||
|
||||
use Thelia\Core\Event\ActionEvent;
|
||||
use Thelia\Model\Cart;
|
||||
use Thelia\Model\CartItem;
|
||||
|
||||
class CartEvent extends ActionEvent
|
||||
{
|
||||
@@ -31,7 +32,8 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $append
|
||||
* @param bool $append
|
||||
* @return CartEvent
|
||||
*/
|
||||
public function setAppend($append)
|
||||
{
|
||||
@@ -41,7 +43,7 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return bool
|
||||
*/
|
||||
public function getAppend()
|
||||
{
|
||||
@@ -49,7 +51,8 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $cartItem
|
||||
* @param CartItem $cartItem
|
||||
* @return CartEvent
|
||||
*/
|
||||
public function setCartItem($cartItem)
|
||||
{
|
||||
@@ -59,7 +62,7 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return CartItem
|
||||
*/
|
||||
public function getCartItem()
|
||||
{
|
||||
@@ -67,7 +70,8 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $newness
|
||||
* @param bool $newness
|
||||
* @return CartEvent
|
||||
*/
|
||||
public function setNewness($newness)
|
||||
{
|
||||
@@ -77,7 +81,7 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return bool
|
||||
*/
|
||||
public function getNewness()
|
||||
{
|
||||
@@ -85,7 +89,8 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $product
|
||||
* @param int $product the product ID
|
||||
* @return CartEvent
|
||||
*/
|
||||
public function setProduct($product)
|
||||
{
|
||||
@@ -95,7 +100,7 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return int the product ID
|
||||
*/
|
||||
public function getProduct()
|
||||
{
|
||||
@@ -103,7 +108,8 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $productSaleElementsId
|
||||
* @param int $productSaleElementsId
|
||||
* @return CartEvent
|
||||
*/
|
||||
public function setProductSaleElementsId($productSaleElementsId)
|
||||
{
|
||||
@@ -113,7 +119,7 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return int
|
||||
*/
|
||||
public function getProductSaleElementsId()
|
||||
{
|
||||
@@ -121,7 +127,8 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $quantity
|
||||
* @param int $quantity
|
||||
* @return CartEvent
|
||||
*/
|
||||
public function setQuantity($quantity)
|
||||
{
|
||||
@@ -131,7 +138,7 @@ class CartEvent extends ActionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return int
|
||||
*/
|
||||
public function getQuantity()
|
||||
{
|
||||
|
||||
@@ -464,6 +464,11 @@ final class TheliaEvents
|
||||
*/
|
||||
const COUPON_CONSUME = "action.consume_coupon";
|
||||
|
||||
/**
|
||||
* Sent when all coupons in the current session should be cleared
|
||||
*/
|
||||
const COUPON_CLEAR_ALL = "action.clear_all_coupon";
|
||||
|
||||
/**
|
||||
* Sent just before an attempt to use a Coupon
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@ use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Core\Template\ParserInterface;
|
||||
use Thelia\Core\Template\TemplateHelper;
|
||||
use Thelia\Model\AddressQuery;
|
||||
use Thelia\Model\Country;
|
||||
use Thelia\Model\Coupon;
|
||||
use Thelia\Model\CouponQuery;
|
||||
use Thelia\Cart\CartTrait;
|
||||
@@ -149,6 +150,14 @@ class BaseFacade implements FacadeInterface
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Country the delivery country
|
||||
*/
|
||||
public function getDeliveryCountry()
|
||||
{
|
||||
return $this->getContainer()->get('thelia.taxEngine')->getDeliveryCountry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Checkout currency EUR|USD
|
||||
*
|
||||
|
||||
@@ -69,7 +69,7 @@ class CouponFactory
|
||||
}
|
||||
|
||||
// Check coupon usage count
|
||||
if ($couponModel->getUsagesLeft($this->facade->getCustomer()->getId()) <= 0) {
|
||||
if (! $couponModel->isUsageUnlimited() && $couponModel->getUsagesLeft($this->facade->getCustomer()->getId()) <= 0) {
|
||||
throw new CouponNoUsageLeftException($couponCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,14 +58,15 @@ class CouponManager
|
||||
|
||||
/**
|
||||
* Get Discount for the given Coupons
|
||||
*
|
||||
* @api
|
||||
* @return float checkout discount
|
||||
*/
|
||||
public function getDiscount()
|
||||
{
|
||||
$discount = 0.00;
|
||||
|
||||
$coupons = $this->facade->getCurrentCoupons();
|
||||
|
||||
if (count($coupons) > 0) {
|
||||
$couponsKept = $this->sortCoupons($coupons);
|
||||
|
||||
@@ -73,6 +74,7 @@ class CouponManager
|
||||
|
||||
// Just In Case test
|
||||
$checkoutTotalPrice = $this->facade->getCartTotalTaxPrice();
|
||||
|
||||
if ($discount >= $checkoutTotalPrice) {
|
||||
$discount = $checkoutTotalPrice;
|
||||
}
|
||||
@@ -83,6 +85,9 @@ class CouponManager
|
||||
|
||||
/**
|
||||
* Check if there is a Coupon removing Postage
|
||||
*
|
||||
* @param Order $order the order for which we have to check if postage is free
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCouponRemovingPostage(Order $order)
|
||||
@@ -266,6 +271,19 @@ class CouponManager
|
||||
return $this->availableConditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all data kept by coupons
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$coupons = $this->facade->getCurrentCoupons();
|
||||
|
||||
/** @var CouponInterface $coupon */
|
||||
foreach ($coupons as $coupon) {
|
||||
$coupon->clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement this coupon quantity
|
||||
*
|
||||
@@ -278,57 +296,61 @@ class CouponManager
|
||||
*/
|
||||
public function decrementQuantity(Coupon $coupon, $customerId = null)
|
||||
{
|
||||
$ret = false;
|
||||
if ($coupon->isUsageUnlimited()) {
|
||||
$ret = true;
|
||||
} else {
|
||||
$ret = false;
|
||||
|
||||
try {
|
||||
try {
|
||||
|
||||
$usageLeft = $coupon->getUsagesLeft($customerId);
|
||||
$usageLeft = $coupon->getUsagesLeft($customerId);
|
||||
|
||||
if ($usageLeft > 0) {
|
||||
if ($usageLeft > 0) {
|
||||
|
||||
// If the coupon usage is per user, add an entry to coupon customer usage count table
|
||||
if ($coupon->getPerCustomerUsageCount()) {
|
||||
// If the coupon usage is per user, add an entry to coupon customer usage count table
|
||||
if ($coupon->getPerCustomerUsageCount()) {
|
||||
|
||||
if (null == $customerId) {
|
||||
throw new \LogicException("Customer should not be null at this time.");
|
||||
}
|
||||
if (null == $customerId) {
|
||||
throw new \LogicException("Customer should not be null at this time.");
|
||||
}
|
||||
|
||||
$ccc = CouponCustomerCountQuery::create()
|
||||
->filterByCouponId($coupon->getId())
|
||||
->filterByCustomerId($customerId)
|
||||
->findOne()
|
||||
;
|
||||
$ccc = CouponCustomerCountQuery::create()
|
||||
->filterByCouponId($coupon->getId())
|
||||
->filterByCustomerId($customerId)
|
||||
->findOne()
|
||||
;
|
||||
|
||||
if ($ccc === null) {
|
||||
$ccc = new CouponCustomerCount();
|
||||
if ($ccc === null) {
|
||||
$ccc = new CouponCustomerCount();
|
||||
|
||||
$ccc
|
||||
->setCustomerId($customerId)
|
||||
->setCouponId($coupon->getId())
|
||||
->setCount(0);
|
||||
}
|
||||
|
||||
$newCount = 1 + $ccc->getCount();
|
||||
|
||||
$ccc
|
||||
->setCustomerId($customerId)
|
||||
->setCouponId($coupon->getId())
|
||||
->setCount(0);
|
||||
->setCount($newCount)
|
||||
->save()
|
||||
;
|
||||
|
||||
$ret = $usageLeft - $newCount;
|
||||
} else {
|
||||
$usageLeft--;
|
||||
|
||||
$coupon->setMaxUsage($usageLeft);
|
||||
|
||||
$coupon->save();
|
||||
|
||||
$ret = $usageLeft;
|
||||
}
|
||||
|
||||
$newCount = 1 + $ccc->getCount();
|
||||
|
||||
$ccc
|
||||
->setCount($newCount)
|
||||
->save()
|
||||
;
|
||||
|
||||
$ret = $usageLeft - $newCount;
|
||||
} else {
|
||||
$usageLeft--;
|
||||
|
||||
$coupon->setMaxUsage($usageLeft);
|
||||
|
||||
$coupon->save();
|
||||
|
||||
$ret = $usageLeft;
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
// Just log the problem.
|
||||
Tlog::getInstance()->addError(sprintf("Failed to decrement coupon %s: %s", $coupon->getCode(), $ex->getMessage()));
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
// Just log the problem.
|
||||
Tlog::getInstance()->addError(sprintf("Failed to decrement coupon %s: %s", $coupon->getCode(), $ex->getMessage()));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
@@ -18,6 +18,7 @@ use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Core\Template\ParserInterface;
|
||||
use Thelia\Model\Country;
|
||||
use Thelia\Model\Coupon;
|
||||
|
||||
/**
|
||||
@@ -51,6 +52,11 @@ interface FacadeInterface
|
||||
*/
|
||||
public function getDeliveryAddress();
|
||||
|
||||
/**
|
||||
* @return Country the delivery country
|
||||
*/
|
||||
public function getDeliveryCountry();
|
||||
|
||||
/**
|
||||
* Return an Customer a CouponManager can process
|
||||
*
|
||||
|
||||
128
core/lib/Thelia/Coupon/Type/AbstractRemove.php
Normal file
128
core/lib/Thelia/Coupon/Type/AbstractRemove.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
abstract class AbstractRemove extends CouponAbstract implements AmountAndPercentageCouponInterface
|
||||
{
|
||||
/**
|
||||
* Set the value of specific coupon fields.
|
||||
*
|
||||
* @param Array $effects the Coupon effects params
|
||||
*/
|
||||
abstract public function setFieldsValue($effects);
|
||||
|
||||
/**
|
||||
* Get the discount for a specific cart item.
|
||||
*
|
||||
* @param CartItem $cartItem the cart item
|
||||
* @return float the discount value
|
||||
*/
|
||||
abstract public function getCartItemDiscount($cartItem);
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->setFieldsValue($effects);
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product of the selected categories.
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$categories = $cartItem->getProduct()->getCategories();
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
|
||||
if (in_array($category->getId(), $this->category_list)) {
|
||||
$discount += $this->getCartItemDiscount($cartItem);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBaseBackOfficeInputs($templateName, $otherFields)
|
||||
{
|
||||
return $this->facade->getParser()->render($templateName, $otherFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseFieldList($otherFields)
|
||||
{
|
||||
return array_merge($otherFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function checkBaseCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
return $fieldValue;
|
||||
}
|
||||
}
|
||||
180
core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php
Normal file
180
core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\AttributeCombination;
|
||||
use Thelia\Model\CartItem;
|
||||
|
||||
/**
|
||||
* The base class to process a discount related to Attribute values.
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
abstract class AbstractRemoveOnAttributeValues extends CouponAbstract implements AmountAndPercentageCouponInterface
|
||||
{
|
||||
const ATTRIBUTES_AV_LIST = 'attribute_avs';
|
||||
const ATTRIBUTE = 'attribute_id';
|
||||
|
||||
public $attributeAvList = array();
|
||||
public $attribute = 0;
|
||||
|
||||
/**
|
||||
* Set the value of specific coupon fields.
|
||||
* @param Array $effects the Coupon effects params
|
||||
*/
|
||||
abstract public function setFieldsValue($effects);
|
||||
|
||||
/**
|
||||
* Get the discount for a specific cart item.
|
||||
*
|
||||
* @param CartItem $cartItem the cart item
|
||||
* @return float the discount value
|
||||
*/
|
||||
abstract public function getCartItemDiscount($cartItem);
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->attributeAvList = isset($effects[self::ATTRIBUTES_AV_LIST]) ? $effects[self::ATTRIBUTES_AV_LIST] : array();
|
||||
|
||||
if (! is_array($this->attributeAvList)) $this->attributeAvList = array($this->attributeAvList);
|
||||
|
||||
$this->attribute = isset($effects[self::ATTRIBUTE]) ? $effects[self::ATTRIBUTE] : 0;
|
||||
|
||||
$this->setFieldsValue($effects);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product which uses the selected attributes
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$productSaleElements = $cartItem->getProductSaleElements();
|
||||
|
||||
$combinations = $productSaleElements->getAttributeCombinations();
|
||||
|
||||
/** @var AttributeCombination $combination */
|
||||
foreach ($combinations as $combination) {
|
||||
|
||||
$attrValue = $combination->getAttributeAvId();
|
||||
|
||||
if (in_array($attrValue, $this->attributeAvList)) {
|
||||
$discount += $this->getCartItemDiscount($cartItem);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the template which implements coupon specific user-input,
|
||||
* using the provided template file, and a list of specific input fields.
|
||||
*
|
||||
* @param string $templateName the path to the template
|
||||
* @param array $otherFields the list of additional fields fields
|
||||
*
|
||||
* @return string the rendered template.
|
||||
*/
|
||||
public function drawBaseBackOfficeInputs($templateName, $otherFields)
|
||||
{
|
||||
return $this->facade->getParser()->render($templateName, array_merge($otherFields, [
|
||||
|
||||
// The attributes list field
|
||||
'attribute_field_name' => $this->makeCouponFieldName(self::ATTRIBUTE),
|
||||
'attribute_value' => $this->attribute,
|
||||
|
||||
// The attributes list field
|
||||
'attribute_av_field_name' => $this->makeCouponFieldName(self::ATTRIBUTES_AV_LIST),
|
||||
'attribute_av_values' => $this->attributeAvList
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseFieldList($otherFields)
|
||||
{
|
||||
return array_merge($otherFields, [self::ATTRIBUTE, self::ATTRIBUTES_AV_LIST]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function checkBaseCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::ATTRIBUTE) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select an attribute'
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::ATTRIBUTES_AV_LIST) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select at least one attribute value'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
}
|
||||
152
core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php
Normal file
152
core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
abstract class AbstractRemoveOnCategories extends CouponAbstract implements AmountAndPercentageCouponInterface
|
||||
{
|
||||
const CATEGORIES_LIST = 'categories';
|
||||
|
||||
protected $category_list = array();
|
||||
|
||||
/**
|
||||
* Set the value of specific coupon fields.
|
||||
*
|
||||
* @param Array $effects the Coupon effects params
|
||||
*/
|
||||
abstract public function setFieldsValue($effects);
|
||||
|
||||
/**
|
||||
* Get the discount for a specific cart item.
|
||||
*
|
||||
* @param CartItem $cartItem the cart item
|
||||
* @return float the discount value
|
||||
*/
|
||||
abstract public function getCartItemDiscount($cartItem);
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array();
|
||||
|
||||
if (! is_array($this->category_list)) $this->category_list = array($this->category_list);
|
||||
|
||||
$this->setFieldsValue($effects);
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product of the selected categories.
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$categories = $cartItem->getProduct()->getCategories();
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
|
||||
if (in_array($category->getId(), $this->category_list)) {
|
||||
$discount += $this->getCartItemDiscount($cartItem);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBaseBackOfficeInputs($templateName, $otherFields)
|
||||
{
|
||||
return $this->facade->getParser()->render($templateName, array_merge($otherFields, [
|
||||
|
||||
// The categories list field
|
||||
'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST),
|
||||
'categories_values' => $this->category_list
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseFieldList($otherFields)
|
||||
{
|
||||
return array_merge($otherFields, [self::CATEGORIES_LIST]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function checkBaseCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::CATEGORIES_LIST) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select at least one category'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
}
|
||||
162
core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php
Normal file
162
core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
abstract class AbstractRemoveOnProducts extends CouponAbstract implements AmountAndPercentageCouponInterface
|
||||
{
|
||||
const CATEGORY_ID = 'category_id';
|
||||
const PRODUCTS_LIST = 'products';
|
||||
|
||||
public $category_id = 0;
|
||||
public $product_list = array();
|
||||
|
||||
/**
|
||||
* Set the value of specific coupon fields.
|
||||
*
|
||||
* @param Array $effects the Coupon effects params
|
||||
*/
|
||||
abstract public function setFieldsValue($effects);
|
||||
|
||||
/**
|
||||
* Get the discount for a specific cart item.
|
||||
*
|
||||
* @param CartItem $cartItem the cart item
|
||||
* @return float the discount value
|
||||
*/
|
||||
abstract public function getCartItemDiscount($cartItem);
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->product_list = isset($effects[self::PRODUCTS_LIST]) ? $effects[self::PRODUCTS_LIST] : array();
|
||||
|
||||
if (! is_array($this->product_list)) $this->product_list = array($this->product_list);
|
||||
|
||||
$this->category_id = isset($effects[self::CATEGORY_ID]) ? $effects[self::CATEGORY_ID] : 0;
|
||||
|
||||
$this->setFieldsValue($effects);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product of the selected products.
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
if (in_array($cartItem->getProduct()->getId(), $this->product_list)) {
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$discount += $this->getCartItemDiscount($cartItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBaseBackOfficeInputs($templateName, $otherFields)
|
||||
{
|
||||
return $this->facade->getParser()->render($templateName, array_merge($otherFields, [
|
||||
|
||||
// The category ID field
|
||||
'category_id_field_name' => $this->makeCouponFieldName(self::CATEGORY_ID),
|
||||
'category_id_value' => $this->category_id,
|
||||
|
||||
// The products list field
|
||||
'products_field_name' => $this->makeCouponFieldName(self::PRODUCTS_LIST),
|
||||
'products_values' => $this->product_list,
|
||||
'products_values_csv' => implode(', ', $this->product_list)
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseFieldList($otherFields)
|
||||
{
|
||||
return array_merge($otherFields, [self::CATEGORY_ID, self::PRODUCTS_LIST]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function checkBaseCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::CATEGORY_ID) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select a category'
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::PRODUCTS_LIST) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select at least one product'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
/**
|
||||
* Represents a Coupon ready to be processed in a Checkout process
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
*
|
||||
*/
|
||||
interface AmountAndPercentageCouponInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Set the value of specific coupon fields.
|
||||
* @param Array $effects the Coupon effects params
|
||||
*/
|
||||
public function setFieldsValue($effects);
|
||||
|
||||
/**
|
||||
* Get the discount for a specific cart item.
|
||||
*
|
||||
* @param CartItem $cartItem the cart item
|
||||
* @return float the discount value
|
||||
*/
|
||||
public function getCartItemDiscount($cartItem);
|
||||
|
||||
/**
|
||||
* Renders the template which implements coupon specific user-input,
|
||||
* using the provided template file, and a list of specific input fields.
|
||||
*
|
||||
* @param string $templateName the path to the template
|
||||
* @param array $otherFields the list of additional fields fields
|
||||
*
|
||||
* @return string the rendered template.
|
||||
*/
|
||||
public function drawBaseBackOfficeInputs($templateName, $otherFields);
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseFieldList($otherFields);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function checkBaseCouponFieldValue($fieldName, $fieldValue);
|
||||
}
|
||||
93
core/lib/Thelia/Coupon/Type/AmountCouponTrait.php
Normal file
93
core/lib/Thelia/Coupon/Type/AmountCouponTrait.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
|
||||
/**
|
||||
* A trait to manage a coupon which removes a constant amount from the order total.
|
||||
* Should be used on coupons classes which implements AmountAndPercentageCouponInterface
|
||||
*
|
||||
* Class AmountCouponTrait
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
* @package Thelia\Coupon\Type
|
||||
*/
|
||||
Trait AmountCouponTrait {
|
||||
|
||||
// The amount is already defined in CouponAbstract, and should not be redefined here.
|
||||
// protected $amount = 0;
|
||||
|
||||
/**
|
||||
* Should return the amount field name, defined in the parent class.
|
||||
*
|
||||
* @return string the percentage field name
|
||||
*/
|
||||
abstract protected function getAmountFieldName();
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function setFieldsValue($effects)
|
||||
{
|
||||
$this->amount = $effects[$this->getAmountFieldName()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getCartItemDiscount($cartItem)
|
||||
{
|
||||
return $cartItem->getQuantity() * $this->amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function callDrawBackOfficeInputs($templateName)
|
||||
{
|
||||
return $this->drawBaseBackOfficeInputs($templateName, [
|
||||
'amount_field_name' => $this->makeCouponFieldName($this->getAmountFieldName()),
|
||||
'amount_value' => $this->amount
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return $this->getBaseFieldList([$this->getAmountFieldName()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
$this->checkBaseCouponFieldValue($fieldName, $fieldValue);
|
||||
|
||||
if ($fieldName === $this->getAmountFieldName()) {
|
||||
|
||||
if (floatval($fieldValue) < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Discount Amount is invalid. Please enter a positive value.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
}
|
||||
@@ -499,4 +499,12 @@ abstract class CouponAbstract implements CouponInterface
|
||||
|
||||
return $effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
// Does nothing. Override this function as needed.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,4 +239,9 @@ interface CouponInterface
|
||||
*/
|
||||
public function getEffects($data);
|
||||
|
||||
/**
|
||||
* Clear all the data the coupon may have stored, called after an order is completed.
|
||||
*/
|
||||
public function clear();
|
||||
|
||||
}
|
||||
|
||||
345
core/lib/Thelia/Coupon/Type/FreeProduct.php
Normal file
345
core/lib/Thelia/Coupon/Type/FreeProduct.php
Normal file
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Event\Cart\CartEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Model\CartItem;
|
||||
use Thelia\Model\CartItemQuery;
|
||||
use Thelia\Model\Product;
|
||||
use Thelia\Model\ProductQuery;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class FreeProduct extends AbstractRemoveOnProducts
|
||||
{
|
||||
const OFFERED_PRODUCT_ID = 'offered_product_id';
|
||||
const OFFERED_CATEGORY_ID = 'offered_category_id';
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.free_product';
|
||||
|
||||
protected $offeredProductId;
|
||||
protected $offeredCategoryId;
|
||||
|
||||
/**
|
||||
* This constant is user to mark a free product as in the process of being added to the cart,
|
||||
* but the CartItem ID is not yet been defined.
|
||||
*/
|
||||
const ADD_TO_CART_IN_PROCESS = -1;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setFieldsValue($effects)
|
||||
{
|
||||
$this->offeredProductId = $effects[self::OFFERED_PRODUCT_ID];
|
||||
$this->offeredCategoryId = $effects[self::OFFERED_CATEGORY_ID];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getCartItemDiscount($cartItem)
|
||||
{
|
||||
// This method is not used, we use our own implementation of exec();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The session variable where the cart item IDs for the free products are stored
|
||||
*/
|
||||
protected function getSessionVarName()
|
||||
{
|
||||
return "coupon.free_product.cart_items." . $this->getCode();
|
||||
}
|
||||
/**
|
||||
* Return the cart item id which contains the free product related to a given product
|
||||
*
|
||||
* @param Product $product the product in the cart which triggered the discount
|
||||
*
|
||||
* @return bool|int|CartItem the cart item which contains the free product, or false if the product is no longer in the cart, or ADD_TO_CART_IN_PROCESS if the adding process is not finished
|
||||
*/
|
||||
protected function getRelatedCartItem($product)
|
||||
{
|
||||
$cartItemIdList = $this->facade->getRequest()->getSession()->get(
|
||||
$this->getSessionVarName(),
|
||||
array()
|
||||
);
|
||||
|
||||
if (isset($cartItemIdList[$product->getId()])) {
|
||||
|
||||
$cartItemId = $cartItemIdList[$product->getId()];
|
||||
|
||||
if ($cartItemId == self::ADD_TO_CART_IN_PROCESS) {
|
||||
return self::ADD_TO_CART_IN_PROCESS;
|
||||
} elseif (null !== $cartItem = CartItemQuery::create()->findPk($cartItemId)) {
|
||||
return $cartItem;
|
||||
}
|
||||
} else {
|
||||
// Maybe the product we're offering is already in the cart ? Search it.
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
if ($cartItem->getProduct()->getId() == $this->offeredProductId) {
|
||||
|
||||
// We found the product. Store its cart item as the free product container.
|
||||
$this->setRelatedCartItem($product, $cartItem->getId());
|
||||
|
||||
return $cartItem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cart item id which contains the free product related to a given product
|
||||
*
|
||||
* @param Product $product the product in the cart which triggered the discount
|
||||
* @param bool|int $cartItemId the cart item ID which contains the free product, or just true if the free product is not yet added.
|
||||
*/
|
||||
protected function setRelatedCartItem($product, $cartItemId)
|
||||
{
|
||||
$cartItemIdList = $this->facade->getRequest()->getSession()->get(
|
||||
$this->getSessionVarName(),
|
||||
array()
|
||||
);
|
||||
|
||||
if (! is_array($cartItemIdList)) $cartItemIdList = array();
|
||||
|
||||
$cartItemIdList[$product->getId()] = $cartItemId;
|
||||
|
||||
$this->facade->getRequest()->getSession()->set(
|
||||
$this->getSessionVarName(),
|
||||
$cartItemIdList
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the product id / cart item id list.
|
||||
*
|
||||
* @return array an array where the free product ID is the key, and the related cart item id the value.
|
||||
*/
|
||||
protected function getFreeProductsCartItemIds()
|
||||
{
|
||||
return $this->facade->getRequest()->getSession()->get(
|
||||
$this->getSessionVarName(),
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the session variable.
|
||||
*/
|
||||
protected function clearFreeProductsCartItemIds()
|
||||
{
|
||||
return $this->facade->getRequest()->getSession()->remove($this->getSessionVarName());
|
||||
}
|
||||
|
||||
/**
|
||||
* We overload this method here to remove the free products when the
|
||||
* coupons conditions are no longer met.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function isMatching()
|
||||
{
|
||||
$match = parent::isMatching();
|
||||
|
||||
if (! $match) {
|
||||
// Cancel coupon effect (but no not remove the product)
|
||||
$this->clearFreeProductsCartItemIds();
|
||||
}
|
||||
|
||||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var Product $eligibleProduct */
|
||||
$eligibleProduct = null;
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
if (in_array($cartItem->getProduct()->getId(), $this->product_list)) {
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$eligibleProduct = $cartItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($eligibleProduct !== null) {
|
||||
|
||||
// Get the cart item for the eligible product
|
||||
$freeProductCartItem = $this->getRelatedCartItem($eligibleProduct);
|
||||
|
||||
// We add the free product it only if it not yet in the cart.
|
||||
if ($freeProductCartItem === false) {
|
||||
|
||||
if (null !== $freeProduct = ProductQuery::create()->findPk($this->offeredProductId)) {
|
||||
|
||||
// Store in the session that the free product is added to the cart,
|
||||
// so that we don't enter the following infinite loop :
|
||||
//
|
||||
// 1) exec() adds a product by firing a CART_ADDITEM event,
|
||||
// 2) the event is processed by Action\Coupon::updateOrderDiscount(),
|
||||
// 3) Action\Coupon::updateOrderDiscount() calls CouponManager::getDiscount()
|
||||
// 4) CouponManager::getDiscount() calls exec() -> Infinite loop !!
|
||||
|
||||
// Store a marker first, we do not have the cart item id yet.
|
||||
$this->setRelatedCartItem($eligibleProduct, self::ADD_TO_CART_IN_PROCESS);
|
||||
|
||||
$cartEvent = new CartEvent($this->facade->getCart());
|
||||
|
||||
$cartEvent->setNewness(true);
|
||||
$cartEvent->setAppend(false);
|
||||
$cartEvent->setQuantity(1);
|
||||
$cartEvent->setProductSaleElementsId($freeProduct->getDefaultSaleElements()->getId());
|
||||
$cartEvent->setProduct($this->offeredProductId);
|
||||
|
||||
$this->facade->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent);
|
||||
|
||||
// Store the final cart item ID.
|
||||
$this->setRelatedCartItem($eligibleProduct, $cartEvent->getCartItem()->getId());
|
||||
|
||||
$freeProductCartItem = $cartEvent->getCartItem();
|
||||
|
||||
// Setting product price is dangerous, as the customer could change the ordered quantity of this product.
|
||||
// We will instead add the product price to the order discount.
|
||||
// $cartEvent->getCartItem()->setPrice(0)->save();
|
||||
}
|
||||
}
|
||||
|
||||
if ($freeProductCartItem instanceof CartItem) {
|
||||
|
||||
$taxCountry = $this->facade->getDeliveryCountry();
|
||||
|
||||
// The discount is the product price.
|
||||
$discount = $freeProductCartItem->getPromo() ?
|
||||
$freeProductCartItem->getPromoPrice() : $freeProductCartItem->getPrice();
|
||||
}
|
||||
}
|
||||
// No eligible product was found !
|
||||
else {
|
||||
// Remove all free products for this coupon, but no not remove the product from the cart.
|
||||
$this->clearFreeProductsCartItemIds();
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return $this->getBaseFieldList([self::OFFERED_CATEGORY_ID, self::OFFERED_PRODUCT_ID]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
$this->checkBaseCouponFieldValue($fieldName, $fieldValue);
|
||||
|
||||
if ($fieldName === self::OFFERED_PRODUCT_ID) {
|
||||
|
||||
if (floatval($fieldValue) < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select the offered product'
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::OFFERED_CATEGORY_ID) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select the category of the offred product'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get I18n name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->facade
|
||||
->getTranslator()
|
||||
->trans('Free product when buying one or more selected products', array(), 'coupon');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getToolTip()
|
||||
{
|
||||
$toolTip = $this->facade
|
||||
->getTranslator()
|
||||
->trans(
|
||||
'This coupon adds a free product to the cart if one of the selected products is in the cart.',
|
||||
array(),
|
||||
'coupon'
|
||||
);
|
||||
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->drawBaseBackOfficeInputs("coupon/type-fragments/free-product.html", [
|
||||
'offered_category_field_name' => $this->makeCouponFieldName(self::OFFERED_CATEGORY_ID),
|
||||
'offered_category_value' => $this->offeredCategoryId,
|
||||
|
||||
'offered_product_field_name' => $this->makeCouponFieldName(self::OFFERED_PRODUCT_ID),
|
||||
'offered_product_value' => $this->offeredProductId
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
// Clear the session variable when the coupon is cleared.
|
||||
$this->clearFreeProductsCartItemIds();
|
||||
}
|
||||
}
|
||||
92
core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php
Normal file
92
core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
/**
|
||||
* A trait to manage a coupon which removes a percentage of cart items from the order total.
|
||||
* Should be used on coupons classes which implements AmountAndPercentageCouponInterface
|
||||
*
|
||||
* Class PercentageCouponTrait
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
* @package Thelia\Coupon\Type
|
||||
*/
|
||||
Trait PercentageCouponTrait {
|
||||
|
||||
public $percentage = 0;
|
||||
|
||||
/**
|
||||
* Should return the percentage field name, defined in the parent class.
|
||||
*
|
||||
* @return string the percentage field name
|
||||
*/
|
||||
abstract protected function getPercentageFieldName();
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function setFieldsValue($effects)
|
||||
{
|
||||
$this->percentage = $effects[$this->getPercentageFieldName()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getCartItemDiscount($cartItem)
|
||||
{
|
||||
return $cartItem->getQuantity() * $cartItem->getPrice() * ($this->percentage / 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function callDrawBackOfficeInputs($templateName)
|
||||
{
|
||||
return $this->drawBaseBackOfficeInputs($templateName, [
|
||||
'percentage_field_name' => $this->makeCouponFieldName($this->getPercentageFieldName()),
|
||||
'percentage_value' => $this->percentage,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return $this->getBaseFieldList([$this->getPercentageFieldName()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
$this->checkBaseCouponFieldValue($fieldName, $fieldValue);
|
||||
|
||||
if ($fieldName === $this->getPercentageFieldName()) {
|
||||
|
||||
$pcent = floatval($fieldValue);
|
||||
|
||||
if ($pcent <= 0 || $pcent > 100) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemoveAmountOnAttributeValues extends AbstractRemoveOnAttributeValues
|
||||
{
|
||||
use AmountCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_amount_on_attribute_av';
|
||||
|
||||
protected function getAmountFieldName()
|
||||
{
|
||||
return self::AMOUNT_FIELD_NAME;
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->facade
|
||||
->getTranslator()
|
||||
->trans('Fixed amount discount for selected attribute values', array(), 'coupon');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getToolTip()
|
||||
{
|
||||
$toolTip = $this->facade
|
||||
->getTranslator()
|
||||
->trans(
|
||||
'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
array(),
|
||||
'coupon'
|
||||
);
|
||||
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-attributes.html');
|
||||
}
|
||||
}
|
||||
@@ -12,63 +12,25 @@
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
use Thelia\Model\Category;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
*
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemoveAmountOnCategories extends CouponAbstract
|
||||
class RemoveAmountOnCategories extends AbstractRemoveOnCategories
|
||||
{
|
||||
const CATEGORIES_LIST = 'categories';
|
||||
use AmountCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_amount_on_categories';
|
||||
|
||||
public $category_list = array();
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
protected function getAmountFieldName()
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array();
|
||||
|
||||
if (! is_array($this->category_list)) $this->category_list = array($this->category_list);
|
||||
return $this;
|
||||
return self::AMOUNT_FIELD_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getName()
|
||||
@@ -94,89 +56,11 @@ class RemoveAmountOnCategories extends CouponAbstract
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product of the selected categories.
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$categories = $cartItem->getProduct()->getCategories();
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
|
||||
if (in_array($category->getId(), $this->category_list)) {
|
||||
$discount += $cartItem->getQuantity() * $this->amount;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->facade->getParser()->render('coupon/type-fragments/remove-amount-on-categories.html', [
|
||||
|
||||
// The standard "Amount" field
|
||||
'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME),
|
||||
'amount_value' => $this->amount,
|
||||
|
||||
// The categories list field
|
||||
'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST),
|
||||
'categories_values' => $this->category_list
|
||||
]);
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-categories.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return [self::AMOUNT_FIELD_NAME, self::CATEGORIES_LIST];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::AMOUNT_FIELD_NAME) {
|
||||
|
||||
if (floatval($fieldValue) < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Discount Amount is invalid. Please enter a positive value.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::CATEGORIES_LIST) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select at least one category'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,65 +12,24 @@
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
*
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemoveAmountOnProducts extends CouponAbstract
|
||||
class RemoveAmountOnProducts extends AbstractRemoveOnProducts
|
||||
{
|
||||
const CATEGORY_ID = 'category_id';
|
||||
const PRODUCTS_LIST = 'products';
|
||||
use AmountCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_amount_on_products';
|
||||
|
||||
public $category_id = 0;
|
||||
public $product_list = array();
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
protected function getAmountFieldName()
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->product_list = isset($effects[self::PRODUCTS_LIST]) ? $effects[self::PRODUCTS_LIST] : array();
|
||||
|
||||
if (! is_array($this->product_list)) $this->product_list = array($this->product_list);
|
||||
|
||||
$this->category_id = isset($effects[self::CATEGORY_ID]) ? $effects[self::CATEGORY_ID] : 0;
|
||||
|
||||
return $this;
|
||||
return self::AMOUNT_FIELD_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,93 +60,11 @@ class RemoveAmountOnProducts extends CouponAbstract
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product of the selected products.
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
|
||||
if (in_array($cartItem->getProduct()->getId(), $this->product_list)) {
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$discount += $cartItem->getQuantity() * $this->amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->facade->getParser()->render('coupon/type-fragments/remove-amount-on-products.html', [
|
||||
|
||||
// The standard "Amount" field
|
||||
'amount_field_name' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME),
|
||||
'amount_value' => $this->amount,
|
||||
|
||||
// The category ID field
|
||||
'category_id_field_name' => $this->makeCouponFieldName(self::CATEGORY_ID),
|
||||
'category_id_value' => $this->category_id,
|
||||
|
||||
// The products list field
|
||||
'products_field_name' => $this->makeCouponFieldName(self::PRODUCTS_LIST),
|
||||
'products_values' => $this->product_list,
|
||||
'products_values_csv' => implode(', ', $this->product_list)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return [self::AMOUNT_FIELD_NAME, self::CATEGORY_ID, self::PRODUCTS_LIST];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::AMOUNT_FIELD_NAME) {
|
||||
|
||||
if (floatval($fieldValue) < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Discount Amount is invalid. Please enter a positive value.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::CATEGORY_ID) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select a category'
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::PRODUCTS_LIST) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select at least one product'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-products.html');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemovePercentageOnAttributeValues extends AbstractRemoveOnAttributeValues
|
||||
{
|
||||
const PERCENTAGE = 'percentage';
|
||||
|
||||
use PercentageCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_percentage_on_attribute_av';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getPercentageFieldName()
|
||||
{
|
||||
return self::PERCENTAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->facade
|
||||
->getTranslator()
|
||||
->trans('Percentage discount for selected attribute values', array(), 'coupon');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getToolTip()
|
||||
{
|
||||
$toolTip = $this->facade
|
||||
->getTranslator()
|
||||
->trans(
|
||||
'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.',
|
||||
array(),
|
||||
'coupon'
|
||||
);
|
||||
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-attributes.html');
|
||||
}
|
||||
}
|
||||
@@ -12,61 +12,24 @@
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
use Thelia\Model\Category;
|
||||
|
||||
/**
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*
|
||||
*/
|
||||
class RemovePercentageOnCategories extends CouponAbstract
|
||||
class RemovePercentageOnCategories extends AbstractRemoveOnCategories
|
||||
{
|
||||
const CATEGORIES_LIST = 'categories';
|
||||
const PERCENTAGE = 'percentage';
|
||||
const PERCENTAGE = 'percentage';
|
||||
|
||||
use PercentageCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_percentage_on_categories';
|
||||
|
||||
protected $category_list = array();
|
||||
|
||||
protected $percentage = 0;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
protected function getPercentageFieldName()
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array();
|
||||
$this->percentage = isset($effects[self::PERCENTAGE]) ? $effects[self::PERCENTAGE] : 0;
|
||||
|
||||
if (! is_array($this->category_list)) $this->category_list = array($this->category_list);
|
||||
return $this;
|
||||
return self::PERCENTAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,90 +58,11 @@ class RemovePercentageOnCategories extends CouponAbstract
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product of the selected categories.
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$categories = $cartItem->getProduct()->getCategories();
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
|
||||
if (in_array($category->getId(), $this->category_list)) {
|
||||
$discount += $cartItem->getPrice() * $this->percentage;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->facade->getParser()->render('coupon/type-fragments/remove-percentage-on-categories.html', [
|
||||
|
||||
// The standard "Amount" field
|
||||
'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE),
|
||||
'percentage_value' => $this->percentage,
|
||||
|
||||
// The categories list field
|
||||
'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST),
|
||||
'categories_values' => $this->category_list
|
||||
]);
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-categories.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return [self::PERCENTAGE, self::CATEGORIES_LIST];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::PERCENTAGE) {
|
||||
|
||||
$pcent = floatval($fieldValue);
|
||||
|
||||
if ($pcent <= 0 || $pcent > 100) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::CATEGORIES_LIST) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select at least one category'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,69 +12,29 @@
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
*
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemovePercentageOnProducts extends CouponAbstract
|
||||
class RemovePercentageOnProducts extends AbstractRemoveOnProducts
|
||||
{
|
||||
const CATEGORY_ID = 'category_id';
|
||||
const PRODUCTS_LIST = 'products';
|
||||
const PERCENTAGE = 'percentage';
|
||||
const PERCENTAGE = 'percentage';
|
||||
|
||||
use PercentageCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_percentage_on_products';
|
||||
|
||||
public $category_id = 0;
|
||||
public $product_list = array();
|
||||
public $percentage = 0;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
protected function getPercentageFieldName()
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->product_list = isset($effects[self::PRODUCTS_LIST]) ? $effects[self::PRODUCTS_LIST] : array();
|
||||
|
||||
if (! is_array($this->product_list)) $this->product_list = array($this->product_list);
|
||||
|
||||
$this->category_id = isset($effects[self::CATEGORY_ID]) ? $effects[self::CATEGORY_ID] : 0;
|
||||
|
||||
$this->percentage = $effects[self::PERCENTAGE];
|
||||
|
||||
return $this;
|
||||
return self::PERCENTAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,94 +65,11 @@ class RemovePercentageOnProducts extends CouponAbstract
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
// This coupon subtracts the specified amount from the order total
|
||||
// for each product of the selected products.
|
||||
$discount = 0;
|
||||
|
||||
$cartItems = $this->facade->getCart()->getCartItems();
|
||||
|
||||
/** @var CartItem $cartItem */
|
||||
foreach ($cartItems as $cartItem) {
|
||||
if (in_array($cartItem->getProduct()->getId(), $this->product_list)) {
|
||||
if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) {
|
||||
$discount += $cartItem->getQuantity() * $cartItem->getPrice() * $this->percentage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->facade->getParser()->render('coupon/type-fragments/remove-percentage-on-products.html', [
|
||||
|
||||
// The standard "Amount" field
|
||||
'percentage_field_name' => $this->makeCouponFieldName(self::PERCENTAGE),
|
||||
'percentage_value' => $this->percentage,
|
||||
|
||||
// The category ID field
|
||||
'category_id_field_name' => $this->makeCouponFieldName(self::CATEGORY_ID),
|
||||
'category_id_value' => $this->category_id,
|
||||
|
||||
// The products list field
|
||||
'products_field_name' => $this->makeCouponFieldName(self::PRODUCTS_LIST),
|
||||
'products_values' => $this->product_list,
|
||||
'products_values_csv' => implode(', ', $this->product_list)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return [self::PERCENTAGE, self::CATEGORY_ID, self::PRODUCTS_LIST];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::PERCENTAGE) {
|
||||
|
||||
$pcent = floatval($fieldValue);
|
||||
|
||||
if ($pcent <= 0 || $pcent > 100) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::CATEGORY_ID) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select a category'
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($fieldName === self::PRODUCTS_LIST) {
|
||||
if (empty($fieldValue)) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Please select at least one product'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-products.html');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,20 +12,25 @@
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
|
||||
/**
|
||||
* Allow to remove an amount from the checkout total
|
||||
*
|
||||
* @package Coupon
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>, Franck Allimant <franck@cqfdev.fr>
|
||||
*
|
||||
*/
|
||||
class RemoveXAmount extends CouponAbstract
|
||||
class RemoveXAmount extends AbstractRemove
|
||||
{
|
||||
use AmountCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_x_amount';
|
||||
|
||||
protected function getAmountFieldName()
|
||||
{
|
||||
return self::AMOUNT_FIELD_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@@ -52,43 +57,19 @@ class RemoveXAmount extends CouponAbstract
|
||||
return $toolTip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return $this->facade->getParser()->render('coupon/type-fragments/remove-x-amount.html', [
|
||||
'fieldName' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME),
|
||||
'value' => $this->amount
|
||||
]);
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-x-amount.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
{
|
||||
return [self::AMOUNT_FIELD_NAME];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::AMOUNT_FIELD_NAME) {
|
||||
|
||||
if (floatval($fieldValue) < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Disount Amount is invalid. Please enter a positive value.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,86 +12,26 @@
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>
|
||||
* @author Guillaume MOREL <gmorel@openstudio.fr>, Franck Allimant <franck@cqfdev.fr>
|
||||
*
|
||||
*/
|
||||
class RemoveXPercent extends CouponAbstract
|
||||
class RemoveXPercent extends AbstractRemove
|
||||
{
|
||||
const INPUT_PERCENTAGE_NAME = 'percentage';
|
||||
|
||||
use PercentageCouponTrait;
|
||||
|
||||
/** @var string Service Id */
|
||||
protected $serviceId = 'thelia.coupon.type.remove_x_percent';
|
||||
|
||||
/** @var float Percentage removed from the Cart */
|
||||
protected $percentage = 0;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set(
|
||||
FacadeInterface $facade,
|
||||
$code,
|
||||
$title,
|
||||
$shortDescription,
|
||||
$description,
|
||||
array $effects,
|
||||
$isCumulative,
|
||||
$isRemovingPostage,
|
||||
$isAvailableOnSpecialOffers,
|
||||
$isEnabled,
|
||||
$maxUsage,
|
||||
\DateTime $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
)
|
||||
protected function getPercentageFieldName()
|
||||
{
|
||||
parent::set(
|
||||
$facade, $code, $title, $shortDescription, $description, $effects,
|
||||
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
|
||||
$freeShippingForCountries,
|
||||
$freeShippingForModules,
|
||||
$perCustomerUsageCount
|
||||
);
|
||||
|
||||
$this->percentage = $effects[self::INPUT_PERCENTAGE_NAME];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
return round($this->facade->getCartTotalTaxPrice($this->isAvailableOnSpecialOffers()) * $this->percentage/100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkCouponFieldValue($fieldName, $fieldValue)
|
||||
{
|
||||
if ($fieldName === self::INPUT_PERCENTAGE_NAME) {
|
||||
|
||||
$pcent = floatval($fieldValue);
|
||||
|
||||
if ($pcent <= 0 || $pcent > 100) {
|
||||
throw new \InvalidArgumentException(
|
||||
Translator::getInstance()->trans(
|
||||
'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.',
|
||||
[ '%val' => $fieldValue]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $fieldValue;
|
||||
return self::INPUT_PERCENTAGE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,19 +63,16 @@ class RemoveXPercent extends CouponAbstract
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function drawBackOfficeInputs()
|
||||
public function exec()
|
||||
{
|
||||
return $this->facade->getParser()->render('coupon/type-fragments/remove-x-percent.html', [
|
||||
'fieldName' => $this->makeCouponFieldName(self::INPUT_PERCENTAGE_NAME),
|
||||
'value' => $this->percentage
|
||||
]);
|
||||
return round($this->facade->getCartTotalTaxPrice($this->isAvailableOnSpecialOffers()) * $this->percentage/100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getFieldList()
|
||||
public function drawBackOfficeInputs()
|
||||
{
|
||||
return [self::INPUT_PERCENTAGE_NAME];
|
||||
return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-x-percent.html');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ use Thelia\Model\Tools\ModelEventDispatcherTrait;
|
||||
class Coupon extends BaseCoupon
|
||||
{
|
||||
|
||||
// Define the value of an unlimited coupon usage.
|
||||
const UNLIMITED_COUPON_USE = -1;
|
||||
|
||||
use ModelEventDispatcherTrait;
|
||||
|
||||
/**
|
||||
@@ -265,6 +268,10 @@ class Coupon extends BaseCoupon
|
||||
return CouponModuleQuery::create()->filterByCouponId($this->getId())->find();
|
||||
}
|
||||
|
||||
public function isUsageUnlimited()
|
||||
{
|
||||
return $this->getMaxUsage() == self::UNLIMITED_COUPON_USE;
|
||||
}
|
||||
/**
|
||||
* Get coupon usage left, either overall, or per customer.
|
||||
*
|
||||
|
||||
@@ -61,7 +61,7 @@ class Product extends BaseProduct
|
||||
*/
|
||||
public function getDefaultSaleElements()
|
||||
{
|
||||
return ProductSaleElementsQuery::create()->filterByProductId($this->id)->filterByIsDefault(true)->find();
|
||||
return ProductSaleElementsQuery::create()->filterByProductId($this->id)->filterByIsDefault(true)->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Condition\SerializableCondition;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Category;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class CartContainsCategoriesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
$category1 = new Category();
|
||||
$category1->setId(10);
|
||||
|
||||
$category2 = new Category();
|
||||
$category2->setId(20);
|
||||
|
||||
$category3 = new Category();
|
||||
$category3->setId(30);
|
||||
|
||||
$product1 = new Product();
|
||||
$product1->addCategory($category1)->addCategory($category2);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->addCategory($category3);
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product1))
|
||||
;
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem1Stub, $cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsCategories::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionOperatorException
|
||||
*/
|
||||
public function testInValidBackOfficeInputOperator()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
$operators = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => Operators::INFERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => array()
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsCategories::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionValueException
|
||||
*/
|
||||
public function testInValidBackOfficeInputValue()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
$operators = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => array()
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsCategories::isMatching
|
||||
*
|
||||
*/
|
||||
public function testMatchingRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
$operators = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => array(10, 20)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsCategories::isMatching
|
||||
*
|
||||
*/
|
||||
public function testNotMatching()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = false;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetSerializableRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$serializableRule = $condition1->getSerializableCondition();
|
||||
|
||||
$expected = new SerializableCondition();
|
||||
$expected->conditionServiceId = $condition1->getServiceId();
|
||||
$expected->operators = $operators;
|
||||
$expected->values = $values;
|
||||
|
||||
$actual = $serializableRule;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check getName i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsCategories::getName
|
||||
*
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
|
||||
$actual = $condition1->getName();
|
||||
$expected = 'Number of articles in cart';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check tooltip i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsCategories::getToolTip
|
||||
*
|
||||
*/
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
|
||||
$actual = $condition1->getToolTip();
|
||||
$expected = 'Sample coupon condition';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validator
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsCategories::generateInputs
|
||||
*
|
||||
*/
|
||||
public function testGetValidator()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new CartContainsCategories($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsCategories::CATEGORIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$actual = $condition1->getValidators();
|
||||
|
||||
$validators = array(
|
||||
'inputs' => array(
|
||||
CartContainsCategories::CATEGORIES_LIST => array(
|
||||
'availableOperators' => array(
|
||||
'in' => 'Price',
|
||||
'out' => 'Price',
|
||||
),
|
||||
'value' => '',
|
||||
'selectedOperator' => 'in'
|
||||
)
|
||||
),
|
||||
'setOperators' => array(
|
||||
'categories' => 'in'
|
||||
),
|
||||
'setValues' => array(
|
||||
'categories' => array(50, 60)
|
||||
)
|
||||
);
|
||||
$expected = $validators;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Condition\SerializableCondition;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Category;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class CartContainsProductsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
$category1 = new Category();
|
||||
$category1->setId(10);
|
||||
|
||||
$category2 = new Category();
|
||||
$category2->setId(20);
|
||||
|
||||
$category3 = new Category();
|
||||
$category3->setId(30);
|
||||
|
||||
$product1 = new Product();
|
||||
$product1->setId(10)->addCategory($category1)->addCategory($category2);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->setId(20)->addCategory($category3);
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product1))
|
||||
;
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem1Stub, $cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsProducts::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionOperatorException
|
||||
*/
|
||||
public function testInValidBackOfficeInputOperator()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
$operators = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => Operators::INFERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => array()
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsProducts::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionValueException
|
||||
*/
|
||||
public function testInValidBackOfficeInputValue()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
$operators = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => array()
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsProducts::isMatching
|
||||
*
|
||||
*/
|
||||
public function testMatchingRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
$operators = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => array(10, 20)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsProducts::isMatching
|
||||
*
|
||||
*/
|
||||
public function testNotMatching()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = false;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetSerializableRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$serializableRule = $condition1->getSerializableCondition();
|
||||
|
||||
$expected = new SerializableCondition();
|
||||
$expected->conditionServiceId = $condition1->getServiceId();
|
||||
$expected->operators = $operators;
|
||||
$expected->values = $values;
|
||||
|
||||
$actual = $serializableRule;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check getName i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsProducts::getName
|
||||
*
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
|
||||
$actual = $condition1->getName();
|
||||
$expected = 'Number of articles in cart';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check tooltip i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsProducts::getToolTip
|
||||
*
|
||||
*/
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
|
||||
$actual = $condition1->getToolTip();
|
||||
$expected = 'Sample coupon condition';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validator
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\CartContainsProducts::generateInputs
|
||||
*
|
||||
*/
|
||||
public function testGetValidator()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new CartContainsProducts($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
CartContainsProducts::PRODUCTS_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$actual = $condition1->getValidators();
|
||||
|
||||
$validators = array(
|
||||
'inputs' => array(
|
||||
CartContainsProducts::PRODUCTS_LIST => array(
|
||||
'availableOperators' => array(
|
||||
'in' => 'Price',
|
||||
'out' => 'Price',
|
||||
),
|
||||
'value' => '',
|
||||
'selectedOperator' => 'in'
|
||||
)
|
||||
),
|
||||
'setOperators' => array(
|
||||
'products' => 'in'
|
||||
),
|
||||
'setValues' => array(
|
||||
'products' => array(50, 60)
|
||||
)
|
||||
);
|
||||
$expected = $validators;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Condition\SerializableCondition;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Customer;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class ForSomeCustomersTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$customer = new Customer();
|
||||
$customer->setId(10);
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCustomer')
|
||||
->will($this->returnValue($customer));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\ForSomeCustomers::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionOperatorException
|
||||
*/
|
||||
public function testInValidBackOfficeInputOperator()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
$operators = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => Operators::INFERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => array()
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\ForSomeCustomers::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionValueException
|
||||
*/
|
||||
public function testInValidBackOfficeInputValue()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
$operators = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => array()
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\ForSomeCustomers::isMatching
|
||||
*
|
||||
*/
|
||||
public function testMatchingRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
$operators = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => array(10, 20)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\ForSomeCustomers::isMatching
|
||||
*
|
||||
*/
|
||||
public function testNotMatching()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = false;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetSerializableRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$serializableRule = $condition1->getSerializableCondition();
|
||||
|
||||
$expected = new SerializableCondition();
|
||||
$expected->conditionServiceId = $condition1->getServiceId();
|
||||
$expected->operators = $operators;
|
||||
$expected->values = $values;
|
||||
|
||||
$actual = $serializableRule;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check getName i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\ForSomeCustomers::getName
|
||||
*
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
|
||||
$actual = $condition1->getName();
|
||||
$expected = 'Number of articles in cart';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check tooltip i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\ForSomeCustomers::getToolTip
|
||||
*
|
||||
*/
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
|
||||
$actual = $condition1->getToolTip();
|
||||
$expected = 'Sample coupon condition';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validator
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\ForSomeCustomers::generateInputs
|
||||
*
|
||||
*/
|
||||
public function testGetValidator()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new ForSomeCustomers($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$actual = $condition1->getValidators();
|
||||
|
||||
$validators = array(
|
||||
'inputs' => array(
|
||||
ForSomeCustomers::CUSTOMERS_LIST => array(
|
||||
'availableOperators' => array(
|
||||
'in' => 'Price',
|
||||
'out' => 'Price',
|
||||
),
|
||||
'value' => '',
|
||||
'selectedOperator' => 'in'
|
||||
)
|
||||
),
|
||||
'setOperators' => array(
|
||||
'customers' => 'in'
|
||||
),
|
||||
'setValues' => array(
|
||||
'customers' => array(50, 60)
|
||||
)
|
||||
);
|
||||
$expected = $validators;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Condition\SerializableCondition;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Address;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class MatchBillingCountriesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$address = new Address();
|
||||
$address->setCountryId(10);
|
||||
|
||||
$stubCustomer = $this->getMockBuilder('\Thelia\Model\Customer')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubCustomer->expects($this->any())
|
||||
->method('getDefaultAddress')
|
||||
->will($this->returnValue($address));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCustomer')
|
||||
->will($this->returnValue($stubCustomer));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchBillingCountries::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionOperatorException
|
||||
*/
|
||||
public function testInValidBackOfficeInputOperator()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
$operators = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => Operators::INFERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => array()
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchBillingCountries::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionValueException
|
||||
*/
|
||||
public function testInValidBackOfficeInputValue()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
$operators = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => array()
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchBillingCountries::isMatching
|
||||
*
|
||||
*/
|
||||
public function testMatchingRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
$operators = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => array(10, 20)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchBillingCountries::isMatching
|
||||
*
|
||||
*/
|
||||
public function testNotMatching()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = false;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetSerializableRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$serializableRule = $condition1->getSerializableCondition();
|
||||
|
||||
$expected = new SerializableCondition();
|
||||
$expected->conditionServiceId = $condition1->getServiceId();
|
||||
$expected->operators = $operators;
|
||||
$expected->values = $values;
|
||||
|
||||
$actual = $serializableRule;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check getName i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchBillingCountries::getName
|
||||
*
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
|
||||
$actual = $condition1->getName();
|
||||
$expected = 'Number of articles in cart';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check tooltip i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchBillingCountries::getToolTip
|
||||
*
|
||||
*/
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
|
||||
$actual = $condition1->getToolTip();
|
||||
$expected = 'Sample coupon condition';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validator
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchBillingCountries::generateInputs
|
||||
*
|
||||
*/
|
||||
public function testGetValidator()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new MatchBillingCountries($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$actual = $condition1->getValidators();
|
||||
|
||||
$validators = array(
|
||||
'inputs' => array(
|
||||
MatchBillingCountries::COUNTRIES_LIST => array(
|
||||
'availableOperators' => array(
|
||||
'in' => 'Price',
|
||||
'out' => 'Price',
|
||||
),
|
||||
'value' => '',
|
||||
'selectedOperator' => 'in'
|
||||
)
|
||||
),
|
||||
'setOperators' => array(
|
||||
'countries' => 'in'
|
||||
),
|
||||
'setValues' => array(
|
||||
'countries' => array(50, 60)
|
||||
)
|
||||
);
|
||||
$expected = $validators;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Condition\SerializableCondition;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Address;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class MatchDeliveryCountriesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$address = new Address();
|
||||
$address->setCountryId(10);
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getDeliveryAddress')
|
||||
->will($this->returnValue($address));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchDeliveryCountries::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionOperatorException
|
||||
*/
|
||||
public function testInValidBackOfficeInputOperator()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
$operators = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => Operators::INFERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => array()
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchDeliveryCountries::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionValueException
|
||||
*/
|
||||
public function testInValidBackOfficeInputValue()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
$operators = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => array()
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchDeliveryCountries::isMatching
|
||||
*
|
||||
*/
|
||||
public function testMatchingRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
$operators = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => array(10, 20)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchDeliveryCountries::isMatching
|
||||
*
|
||||
*/
|
||||
public function testNotMatching()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = false;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetSerializableRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$serializableRule = $condition1->getSerializableCondition();
|
||||
|
||||
$expected = new SerializableCondition();
|
||||
$expected->conditionServiceId = $condition1->getServiceId();
|
||||
$expected->operators = $operators;
|
||||
$expected->values = $values;
|
||||
|
||||
$actual = $serializableRule;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check getName i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchDeliveryCountries::getName
|
||||
*
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
|
||||
$actual = $condition1->getName();
|
||||
$expected = 'Number of articles in cart';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check tooltip i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchDeliveryCountries::getToolTip
|
||||
*
|
||||
*/
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
|
||||
$actual = $condition1->getToolTip();
|
||||
$expected = 'Sample coupon condition';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validator
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\MatchDeliveryCountries::generateInputs
|
||||
*
|
||||
*/
|
||||
public function testGetValidator()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new MatchDeliveryCountries($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => Operators::IN
|
||||
);
|
||||
$values = array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => array(50, 60)
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$actual = $condition1->getValidators();
|
||||
|
||||
$validators = array(
|
||||
'inputs' => array(
|
||||
MatchDeliveryCountries::COUNTRIES_LIST => array(
|
||||
'availableOperators' => array(
|
||||
'in' => 'Price',
|
||||
'out' => 'Price',
|
||||
),
|
||||
'value' => '',
|
||||
'selectedOperator' => 'in'
|
||||
)
|
||||
),
|
||||
'setOperators' => array(
|
||||
'countries' => 'in'
|
||||
),
|
||||
'setValues' => array(
|
||||
'countries' => array(50, 60)
|
||||
)
|
||||
);
|
||||
$expected = $validators;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,6 @@
|
||||
namespace Thelia\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Currency;
|
||||
|
||||
|
||||
@@ -12,13 +12,12 @@
|
||||
|
||||
namespace Thelia\Tests\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\ConditionFactory;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
|
||||
use Thelia\Model\Currency;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
|
||||
|
||||
329
core/lib/Thelia/Tests/Condition/Implementation/StartDateTest.php
Normal file
329
core/lib/Thelia/Tests/Condition/Implementation/StartDateTest.php
Normal file
@@ -0,0 +1,329 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Condition\Implementation;
|
||||
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Condition\SerializableCondition;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Address;
|
||||
use Thelia\Model\Lang;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class StartDateTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
var $startDate;
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$this->startDate = time() - 2000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$address = new Address();
|
||||
$address->setCountryId(10);
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getDeliveryAddress')
|
||||
->will($this->returnValue($address));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
$lang = new Lang();
|
||||
$lang->setDateFormat("d/m/Y");
|
||||
|
||||
$stubSession = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Session\Session')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubSession->expects($this->any())
|
||||
->method('getLang')
|
||||
->will($this->returnValue($lang));
|
||||
|
||||
$stubRequest = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Request')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubRequest->expects($this->any())
|
||||
->method('getSession')
|
||||
->will($this->returnValue($stubSession));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getRequest')
|
||||
->will($this->returnValue($stubRequest));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\StartDate::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionOperatorException
|
||||
*/
|
||||
public function testInValidBackOfficeInputOperator()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
StartDate::START_DATE => 'petite licorne'
|
||||
);
|
||||
$values = array(
|
||||
StartDate::START_DATE => $this->startDate
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if validity test on BackOffice inputs are working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\StartDate::setValidators
|
||||
* @expectedException \Thelia\Exception\InvalidConditionValueException
|
||||
*/
|
||||
public function testInValidBackOfficeInputValue()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
$operators = array(
|
||||
StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
StartDate::START_DATE => 'petit poney'
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\StartDate::isMatching
|
||||
*
|
||||
*/
|
||||
public function testMatchingRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
$operators = array(
|
||||
StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
StartDate::START_DATE => $this->startDate
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = true;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if test inferior operator is working
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\StartDate::isMatching
|
||||
*
|
||||
*/
|
||||
public function testNotMatching()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
StartDate::START_DATE => time() + 2000
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$isValid = $condition1->isMatching();
|
||||
|
||||
$expected = false;
|
||||
$actual =$isValid;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetSerializableRule()
|
||||
{
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
StartDate::START_DATE => $this->startDate
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$serializableRule = $condition1->getSerializableCondition();
|
||||
|
||||
$expected = new SerializableCondition();
|
||||
$expected->conditionServiceId = $condition1->getServiceId();
|
||||
$expected->operators = $operators;
|
||||
$expected->values = $values;
|
||||
|
||||
$actual = $serializableRule;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check getName i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\StartDate::getName
|
||||
*
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Number of articles in cart');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
|
||||
$actual = $condition1->getName();
|
||||
$expected = 'Number of articles in cart';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check tooltip i18n
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\StartDate::getToolTip
|
||||
*
|
||||
*/
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Sample coupon condition');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
|
||||
$actual = $condition1->getToolTip();
|
||||
$expected = 'Sample coupon condition';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validator
|
||||
*
|
||||
* @covers Thelia\Condition\Implementation\StartDate::generateInputs
|
||||
*
|
||||
*/
|
||||
public function testGetValidator()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Price');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$condition1 = new StartDate($stubFacade);
|
||||
|
||||
$operators = array(
|
||||
StartDate::START_DATE => Operators::SUPERIOR_OR_EQUAL
|
||||
);
|
||||
$values = array(
|
||||
StartDate::START_DATE => $this->startDate
|
||||
);
|
||||
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$actual = $condition1->getValidators();
|
||||
|
||||
$validators = array(
|
||||
'inputs' => array(
|
||||
StartDate::START_DATE => array(
|
||||
'availableOperators' => array(
|
||||
'>=' => 'Price',
|
||||
),
|
||||
'value' => '',
|
||||
'selectedOperator' => '>='
|
||||
)
|
||||
),
|
||||
'setOperators' => array(
|
||||
'start_date' => '>='
|
||||
),
|
||||
'setValues' => array(
|
||||
'start_date' => $this->startDate
|
||||
)
|
||||
);
|
||||
$expected = $validators;
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
412
core/lib/Thelia/Tests/Coupon/Type/FreeProductTest.php
Normal file
412
core/lib/Thelia/Tests/Coupon/Type/FreeProductTest.php
Normal file
@@ -0,0 +1,412 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CartItem;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
use Thelia\Model\Product;
|
||||
use Thelia\Model\ProductQuery;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class FreeProductTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/** @var Product $freeProduct */
|
||||
var $freeProduct;
|
||||
var $originalPrice;
|
||||
var $originalPromo;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$currency = CurrencyQuery::create()->filterByCode('EUR')->findOne();
|
||||
|
||||
// Find a product
|
||||
$this->freeProduct = ProductQuery::create()->findOne();
|
||||
|
||||
$this->originalPrice = $this->freeProduct->getDefaultSaleElements()->getPricesByCurrency($currency)->getPrice();
|
||||
$this->originalPromo = $this->freeProduct->getDefaultSaleElements()->getPromo();
|
||||
|
||||
$this->freeProduct->getDefaultSaleElements()->setPromo(false)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$currencies = CurrencyQuery::create();
|
||||
$currencies = $currencies->find();
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getAvailableCurrencies')
|
||||
->will($this->returnValue($currencies));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
$stubDispatcher = $this->getMockBuilder('\Symfony\Component\EventDispatcher\EventDispatcher')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubDispatcher->expects($this->any())
|
||||
->method('dispatch')
|
||||
->will($this->returnCallback(function($dummy, $cartEvent) {
|
||||
$ci = new CartItem();
|
||||
$ci->setId(3)->setPrice(123)->setPromo(0);
|
||||
|
||||
$cartEvent->setCartItem($ci);
|
||||
}));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getDispatcher')
|
||||
->will($this->returnValue($stubDispatcher));
|
||||
|
||||
$stubSession = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Session\Session')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubSession->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->onConsecutiveCalls(-1, 3));
|
||||
|
||||
$stubRequest = $this->getMockBuilder('\Thelia\Core\HttpFoundation\Request')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$stubRequest->expects($this->any())
|
||||
->method('getSession')
|
||||
->will($this->returnValue($stubSession));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getRequest')
|
||||
->will($this->returnValue($stubRequest));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) {
|
||||
|
||||
$product1 = new Product();
|
||||
$product1->setId(10);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->setId(20);
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(100))
|
||||
;
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(150))
|
||||
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
if ($count == 1)
|
||||
$ret = [$cartItem1Stub];
|
||||
else
|
||||
$ret = [$cartItem1Stub, $cartItem2Stub];
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue($ret));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->setId(30);
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2))
|
||||
;
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(11000))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new FreeProduct($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$condition1 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 40.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$condition2 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 400.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition2->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$conditions = new ConditionCollection();
|
||||
$conditions[] = $condition1;
|
||||
$conditions[] = $condition2;
|
||||
$coupon->setConditions($conditions);
|
||||
|
||||
$this->assertEquals('TEST', $coupon->getCode());
|
||||
$this->assertEquals('TEST Coupon', $coupon->getTitle());
|
||||
$this->assertEquals('This is a test coupon title', $coupon->getShortDescription());
|
||||
$this->assertEquals('This is a test coupon description', $coupon->getDescription());
|
||||
|
||||
$this->assertEquals(true, $coupon->isCumulative());
|
||||
$this->assertEquals(true, $coupon->isRemovingPostage());
|
||||
$this->assertEquals(true, $coupon->isAvailableOnSpecialOffers());
|
||||
$this->assertEquals(true, $coupon->isEnabled());
|
||||
|
||||
$this->assertEquals(254, $coupon->getMaxUsage());
|
||||
$this->assertEquals($date, $coupon->getExpirationDate());
|
||||
}
|
||||
|
||||
public function testMatchOne()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new FreeProduct($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 1);
|
||||
|
||||
$this->assertEquals(123.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testMatchSeveral()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new FreeProduct($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 2);
|
||||
|
||||
$this->assertEquals(123.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testNoMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new FreeProduct($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20], 'offered_product_id' => $this->freeProduct->getId(), 'offered_category_id' => 1),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateNoMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(0.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new FreeProduct($stubFacade);
|
||||
|
||||
$actual = $coupon->getName();
|
||||
$expected = 'Coupon test name';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$tooltip = 'Coupon test tooltip';
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip);
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new FreeProduct($stubFacade);
|
||||
|
||||
$actual = $coupon->getToolTip();
|
||||
$expected = $tooltip;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->freeProduct->getDefaultSaleElements()->setPromo($this->originalPromo)->save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,398 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemoveAmountOnAttributeValuesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$currencies = CurrencyQuery::create();
|
||||
$currencies = $currencies->find();
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getAvailableCurrencies')
|
||||
->will($this->returnValue($currencies));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) {
|
||||
|
||||
$attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$attrCombination1
|
||||
->expects($this->any())
|
||||
->method('getAttributeAvId')
|
||||
->will($this->returnValue(10))
|
||||
;
|
||||
|
||||
$attrCombination2 = $this->getMockBuilder('\Thelia\Model\AttributeCombination')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$attrCombination2
|
||||
->expects($this->any())
|
||||
->method('getAttributeAvId')
|
||||
->will($this->returnValue(20))
|
||||
;
|
||||
|
||||
$pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$pse1
|
||||
->expects($this->any())
|
||||
->method('getAttributeCombinations')
|
||||
->will($this->returnValue([$attrCombination1]))
|
||||
;
|
||||
|
||||
$pse2 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
;
|
||||
$pse2
|
||||
->expects($this->any())
|
||||
->method('getAttributeCombinations')
|
||||
->will($this->returnValue([$attrCombination1, $attrCombination2]))
|
||||
;
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProductSaleElements')
|
||||
->will($this->returnValue($pse1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProductSaleElements')
|
||||
->will($this->returnValue($pse2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
if ($count == 1)
|
||||
$ret = [$cartItem1Stub];
|
||||
else
|
||||
$ret = [$cartItem1Stub, $cartItem2Stub];
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue($ret));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$attrCombination1
|
||||
->expects($this->any())
|
||||
->method('getAttributeAvId')
|
||||
->will($this->returnValue(30))
|
||||
;
|
||||
|
||||
$pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$pse1
|
||||
->expects($this->any())
|
||||
->method('getAttributeCombinations')
|
||||
->will($this->returnValue([$attrCombination1]))
|
||||
;
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProductSaleElements')
|
||||
->will($this->returnValue($pse1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem1Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$condition1 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 40.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$condition2 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 400.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition2->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$conditions = new ConditionCollection();
|
||||
$conditions[] = $condition1;
|
||||
$conditions[] = $condition2;
|
||||
$coupon->setConditions($conditions);
|
||||
|
||||
$this->assertEquals('TEST', $coupon->getCode());
|
||||
$this->assertEquals('TEST Coupon', $coupon->getTitle());
|
||||
$this->assertEquals('This is a test coupon title', $coupon->getShortDescription());
|
||||
$this->assertEquals('This is a test coupon description', $coupon->getDescription());
|
||||
|
||||
$this->assertEquals(true, $coupon->isCumulative());
|
||||
$this->assertEquals(true, $coupon->isRemovingPostage());
|
||||
$this->assertEquals(true, $coupon->isAvailableOnSpecialOffers());
|
||||
$this->assertEquals(true, $coupon->isEnabled());
|
||||
|
||||
$this->assertEquals(254, $coupon->getMaxUsage());
|
||||
$this->assertEquals($date, $coupon->getExpirationDate());
|
||||
}
|
||||
|
||||
public function testMatchOne()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 1);
|
||||
|
||||
$this->assertEquals(10.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testMatchSeveral()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 2);
|
||||
|
||||
$this->assertEquals(30.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testNoMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateNoMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(0.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemoveAmountOnAttributeValues($stubFacade);
|
||||
|
||||
$actual = $coupon->getName();
|
||||
$expected = 'Coupon test name';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$tooltip = 'Coupon test tooltip';
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip);
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemoveAmountOnAttributeValues($stubFacade);
|
||||
|
||||
$actual = $coupon->getToolTip();
|
||||
$expected = $tooltip;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Category;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemoveAmountOnCategoriesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$currencies = CurrencyQuery::create();
|
||||
$currencies = $currencies->find();
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getAvailableCurrencies')
|
||||
->will($this->returnValue($currencies));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$category1 = new Category();
|
||||
$category1->setId(10);
|
||||
|
||||
$category2 = new Category();
|
||||
$category2->setId(20);
|
||||
|
||||
$category3 = new Category();
|
||||
$category3->setId(30);
|
||||
|
||||
$product1 = new Product();
|
||||
$product1->addCategory($category1)->addCategory($category2);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->addCategory($category3);
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product1))
|
||||
;
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem1Stub, $cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$category3 = new Category();
|
||||
$category3->setId(30);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->addCategory($category3);
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2));
|
||||
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnCategories($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'categories' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$condition1 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 40.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$condition2 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 400.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition2->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$conditions = new ConditionCollection();
|
||||
$conditions[] = $condition1;
|
||||
$conditions[] = $condition2;
|
||||
$coupon->setConditions($conditions);
|
||||
|
||||
$this->assertEquals('TEST', $coupon->getCode());
|
||||
$this->assertEquals('TEST Coupon', $coupon->getTitle());
|
||||
$this->assertEquals('This is a test coupon title', $coupon->getShortDescription());
|
||||
$this->assertEquals('This is a test coupon description', $coupon->getDescription());
|
||||
|
||||
$this->assertEquals(true, $coupon->isCumulative());
|
||||
$this->assertEquals(true, $coupon->isRemovingPostage());
|
||||
$this->assertEquals(true, $coupon->isAvailableOnSpecialOffers());
|
||||
$this->assertEquals(true, $coupon->isEnabled());
|
||||
|
||||
$this->assertEquals(254, $coupon->getMaxUsage());
|
||||
$this->assertEquals($date, $coupon->getExpirationDate());
|
||||
|
||||
$this->generateMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(10.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnCategories($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'categories' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(10.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testNoMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnCategories($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'categories' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateNoMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(0.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemoveAmountOnCategories($stubFacade);
|
||||
|
||||
$actual = $coupon->getName();
|
||||
$expected = 'Coupon test name';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$tooltip = 'Coupon test tooltip';
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip);
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemoveAmountOnCategories($stubFacade);
|
||||
|
||||
$actual = $coupon->getToolTip();
|
||||
$expected = $tooltip;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
}
|
||||
343
core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnProductsTest.php
Normal file
343
core/lib/Thelia/Tests/Coupon/Type/RemoveAmountOnProductsTest.php
Normal file
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemoveAmountOnProductsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$currencies = CurrencyQuery::create();
|
||||
$currencies = $currencies->find();
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getAvailableCurrencies')
|
||||
->will($this->returnValue($currencies));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) {
|
||||
|
||||
$product1 = new Product();
|
||||
$product1->setId(10);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->setId(20);
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product1))
|
||||
;
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
if ($count == 1)
|
||||
$ret = [$cartItem1Stub];
|
||||
else
|
||||
$ret = [$cartItem1Stub, $cartItem2Stub];
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue($ret));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->setId(30);
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2));
|
||||
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$condition1 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 40.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$condition2 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 400.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition2->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$conditions = new ConditionCollection();
|
||||
$conditions[] = $condition1;
|
||||
$conditions[] = $condition2;
|
||||
$coupon->setConditions($conditions);
|
||||
|
||||
$this->assertEquals('TEST', $coupon->getCode());
|
||||
$this->assertEquals('TEST Coupon', $coupon->getTitle());
|
||||
$this->assertEquals('This is a test coupon title', $coupon->getShortDescription());
|
||||
$this->assertEquals('This is a test coupon description', $coupon->getDescription());
|
||||
|
||||
$this->assertEquals(true, $coupon->isCumulative());
|
||||
$this->assertEquals(true, $coupon->isRemovingPostage());
|
||||
$this->assertEquals(true, $coupon->isAvailableOnSpecialOffers());
|
||||
$this->assertEquals(true, $coupon->isEnabled());
|
||||
|
||||
$this->assertEquals(254, $coupon->getMaxUsage());
|
||||
$this->assertEquals($date, $coupon->getExpirationDate());
|
||||
}
|
||||
|
||||
public function testMatchOne()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 1);
|
||||
|
||||
$this->assertEquals(10.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testMatchSeveral()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 2);
|
||||
|
||||
$this->assertEquals(30.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testNoMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemoveAmountOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('amount' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateNoMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(0.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemoveAmountOnProducts($stubFacade);
|
||||
|
||||
$actual = $coupon->getName();
|
||||
$expected = 'Coupon test name';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$tooltip = 'Coupon test tooltip';
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip);
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemoveAmountOnProducts($stubFacade);
|
||||
|
||||
$actual = $coupon->getToolTip();
|
||||
$expected = $tooltip;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemovePercentageOnAttributeValuesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$currencies = CurrencyQuery::create();
|
||||
$currencies = $currencies->find();
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getAvailableCurrencies')
|
||||
->will($this->returnValue($currencies));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) {
|
||||
|
||||
$attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$attrCombination1
|
||||
->expects($this->any())
|
||||
->method('getAttributeAvId')
|
||||
->will($this->returnValue(10))
|
||||
;
|
||||
|
||||
$attrCombination2 = $this->getMockBuilder('\Thelia\Model\AttributeCombination')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$attrCombination2
|
||||
->expects($this->any())
|
||||
->method('getAttributeAvId')
|
||||
->will($this->returnValue(20))
|
||||
;
|
||||
|
||||
$pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$pse1
|
||||
->expects($this->any())
|
||||
->method('getAttributeCombinations')
|
||||
->will($this->returnValue([$attrCombination1]))
|
||||
;
|
||||
|
||||
$pse2 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
;
|
||||
$pse2
|
||||
->expects($this->any())
|
||||
->method('getAttributeCombinations')
|
||||
->will($this->returnValue([$attrCombination1, $attrCombination2]))
|
||||
;
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProductSaleElements')
|
||||
->will($this->returnValue($pse1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(100))
|
||||
;
|
||||
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProductSaleElements')
|
||||
->will($this->returnValue($pse2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(150))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
if ($count == 1)
|
||||
$ret = [$cartItem1Stub];
|
||||
else
|
||||
$ret = [$cartItem1Stub, $cartItem2Stub];
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue($ret));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$attrCombination1 = $this->getMockBuilder('\Thelia\Model\AttributeCombination')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$attrCombination1
|
||||
->expects($this->any())
|
||||
->method('getAttributeAvId')
|
||||
->will($this->returnValue(30))
|
||||
;
|
||||
|
||||
$pse1 = $this->getMockBuilder('\Thelia\Model\ProductSaleElements')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$pse1
|
||||
->expects($this->any())
|
||||
->method('getAttributeCombinations')
|
||||
->will($this->returnValue([$attrCombination1]))
|
||||
;
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProductSaleElements')
|
||||
->will($this->returnValue($pse1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(100))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem1Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$condition1 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 40.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$condition2 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 400.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition2->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$conditions = new ConditionCollection();
|
||||
$conditions[] = $condition1;
|
||||
$conditions[] = $condition2;
|
||||
$coupon->setConditions($conditions);
|
||||
|
||||
$this->assertEquals('TEST', $coupon->getCode());
|
||||
$this->assertEquals('TEST Coupon', $coupon->getTitle());
|
||||
$this->assertEquals('This is a test coupon title', $coupon->getShortDescription());
|
||||
$this->assertEquals('This is a test coupon description', $coupon->getDescription());
|
||||
|
||||
$this->assertEquals(true, $coupon->isCumulative());
|
||||
$this->assertEquals(true, $coupon->isRemovingPostage());
|
||||
$this->assertEquals(true, $coupon->isAvailableOnSpecialOffers());
|
||||
$this->assertEquals(true, $coupon->isEnabled());
|
||||
|
||||
$this->assertEquals(254, $coupon->getMaxUsage());
|
||||
$this->assertEquals($date, $coupon->getExpirationDate());
|
||||
}
|
||||
|
||||
public function testMatchOne()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 1);
|
||||
|
||||
$this->assertEquals(10.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testMatchSeveral()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 2);
|
||||
|
||||
$this->assertEquals(40.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testNoMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnAttributeValues($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'attribute_avs' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateNoMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(0.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemovePercentageOnAttributeValues($stubFacade);
|
||||
|
||||
$actual = $coupon->getName();
|
||||
$expected = 'Coupon test name';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$tooltip = 'Coupon test tooltip';
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip);
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemovePercentageOnAttributeValues($stubFacade);
|
||||
|
||||
$actual = $coupon->getToolTip();
|
||||
$expected = $tooltip;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\Category;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemovePercentageOnCategoriesTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$currencies = CurrencyQuery::create();
|
||||
$currencies = $currencies->find();
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getAvailableCurrencies')
|
||||
->will($this->returnValue($currencies));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$category1 = new Category();
|
||||
$category1->setId(10);
|
||||
|
||||
$category2 = new Category();
|
||||
$category2->setId(20);
|
||||
|
||||
$category3 = new Category();
|
||||
$category3->setId(30);
|
||||
|
||||
$product1 = new Product();
|
||||
$product1->addCategory($category1)->addCategory($category2);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->addCategory($category3);
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(100))
|
||||
;
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(200))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem1Stub, $cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$category3 = new Category();
|
||||
$category3->setId(30);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->addCategory($category3);
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2));
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(200000))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnCategories($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10, 'categories' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$condition1 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 40.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$condition2 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 400.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition2->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$conditions = new ConditionCollection();
|
||||
$conditions[] = $condition1;
|
||||
$conditions[] = $condition2;
|
||||
$coupon->setConditions($conditions);
|
||||
|
||||
$this->assertEquals('TEST', $coupon->getCode());
|
||||
$this->assertEquals('TEST Coupon', $coupon->getTitle());
|
||||
$this->assertEquals('This is a test coupon title', $coupon->getShortDescription());
|
||||
$this->assertEquals('This is a test coupon description', $coupon->getDescription());
|
||||
|
||||
$this->assertEquals(true, $coupon->isCumulative());
|
||||
$this->assertEquals(true, $coupon->isRemovingPostage());
|
||||
$this->assertEquals(true, $coupon->isAvailableOnSpecialOffers());
|
||||
$this->assertEquals(true, $coupon->isEnabled());
|
||||
|
||||
$this->assertEquals(254, $coupon->getMaxUsage());
|
||||
$this->assertEquals($date, $coupon->getExpirationDate());
|
||||
}
|
||||
|
||||
public function testMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnCategories($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10, 'categories' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(10.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testNoMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnCategories($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10, 'categories' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateNoMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(0.00, $coupon->exec());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Thelia\Coupon\Type\RemoveXAmount::getName
|
||||
*/
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemovePercentageOnCategories($stubFacade);
|
||||
|
||||
$actual = $coupon->getName();
|
||||
$expected = 'Coupon test name';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Thelia\Coupon\Type\RemoveXAmount::getToolTip
|
||||
*/
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$tooltip = 'Coupon test tooltip';
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip);
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemovePercentageOnCategories($stubFacade);
|
||||
|
||||
$actual = $coupon->getToolTip();
|
||||
$expected = $tooltip;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Coupon\Type;
|
||||
use Propel\Runtime\Collection\ObjectCollection;
|
||||
use Thelia\Condition\ConditionCollection;
|
||||
use Thelia\Condition\ConditionEvaluator;
|
||||
use Thelia\Condition\Implementation\MatchForTotalAmount;
|
||||
use Thelia\Condition\Operators;
|
||||
use Thelia\Coupon\FacadeInterface;
|
||||
use Thelia\Model\CurrencyQuery;
|
||||
use Thelia\Model\Product;
|
||||
|
||||
/**
|
||||
* @package Coupon
|
||||
* @author Franck Allimant <franck@cqfdev.fr>
|
||||
*/
|
||||
class RemovePercentageOnProductsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate adapter stub
|
||||
*
|
||||
* @param int $cartTotalPrice Cart total price
|
||||
* @param string $checkoutCurrency Checkout currency
|
||||
* @param string $i18nOutput Output from each translation
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function generateFacadeStub($cartTotalPrice = 400, $checkoutCurrency = 'EUR', $i18nOutput = '')
|
||||
{
|
||||
$stubFacade = $this->getMockBuilder('\Thelia\Coupon\BaseFacade')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$currencies = CurrencyQuery::create();
|
||||
$currencies = $currencies->find();
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getAvailableCurrencies')
|
||||
->will($this->returnValue($currencies));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCartTotalPrice')
|
||||
->will($this->returnValue($cartTotalPrice));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCheckoutCurrency')
|
||||
->will($this->returnValue($checkoutCurrency));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getConditionEvaluator')
|
||||
->will($this->returnValue(new ConditionEvaluator()));
|
||||
|
||||
$stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$stubTranslator->expects($this->any())
|
||||
->method('trans')
|
||||
->will($this->returnValue($i18nOutput));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getTranslator')
|
||||
->will($this->returnValue($stubTranslator));
|
||||
|
||||
return $stubFacade;
|
||||
}
|
||||
|
||||
public function generateMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade, $count) {
|
||||
|
||||
$product1 = new Product();
|
||||
$product1->setId(10);
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->setId(20);
|
||||
|
||||
$cartItem1Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product1))
|
||||
;
|
||||
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(1))
|
||||
;
|
||||
$cartItem1Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(100))
|
||||
|
||||
;
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2));
|
||||
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(150))
|
||||
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
if ($count == 1)
|
||||
$ret = [$cartItem1Stub];
|
||||
else
|
||||
$ret = [$cartItem1Stub, $cartItem2Stub];
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue($ret));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function generateNoMatchingCart(\PHPUnit_Framework_MockObject_MockObject $stubFacade) {
|
||||
|
||||
$product2 = new Product();
|
||||
$product2->setId(30);
|
||||
|
||||
$cartItem2Stub = $this->getMockBuilder('\Thelia\Model\CartItem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getProduct')
|
||||
->will($this->returnValue($product2))
|
||||
;
|
||||
$cartItem2Stub->expects($this->any())
|
||||
->method('getQuantity')
|
||||
->will($this->returnValue(2))
|
||||
;
|
||||
$cartItem2Stub
|
||||
->expects($this->any())
|
||||
->method('getPrice')
|
||||
->will($this->returnValue(11000))
|
||||
;
|
||||
|
||||
$cartStub = $this->getMockBuilder('\Thelia\Model\Cart')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$cartStub
|
||||
->expects($this->any())
|
||||
->method('getCartItems')
|
||||
->will($this->returnValue([$cartItem2Stub]));
|
||||
|
||||
$stubFacade->expects($this->any())
|
||||
->method('getCart')
|
||||
->will($this->returnValue($cartStub));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$condition1 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 40.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition1->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$condition2 = new MatchForTotalAmount($stubFacade);
|
||||
$operators = array(
|
||||
MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR,
|
||||
MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL
|
||||
);
|
||||
$values = array(
|
||||
MatchForTotalAmount::CART_TOTAL => 400.00,
|
||||
MatchForTotalAmount::CART_CURRENCY => 'EUR'
|
||||
);
|
||||
$condition2->setValidatorsFromForm($operators, $values);
|
||||
|
||||
$conditions = new ConditionCollection();
|
||||
$conditions[] = $condition1;
|
||||
$conditions[] = $condition2;
|
||||
$coupon->setConditions($conditions);
|
||||
|
||||
$this->assertEquals('TEST', $coupon->getCode());
|
||||
$this->assertEquals('TEST Coupon', $coupon->getTitle());
|
||||
$this->assertEquals('This is a test coupon title', $coupon->getShortDescription());
|
||||
$this->assertEquals('This is a test coupon description', $coupon->getDescription());
|
||||
|
||||
$this->assertEquals(true, $coupon->isCumulative());
|
||||
$this->assertEquals(true, $coupon->isRemovingPostage());
|
||||
$this->assertEquals(true, $coupon->isAvailableOnSpecialOffers());
|
||||
$this->assertEquals(true, $coupon->isEnabled());
|
||||
|
||||
$this->assertEquals(254, $coupon->getMaxUsage());
|
||||
$this->assertEquals($date, $coupon->getExpirationDate());
|
||||
}
|
||||
|
||||
public function testMatchOne()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 1);
|
||||
|
||||
$this->assertEquals(10.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testMatchSeveral()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateMatchingCart($stubFacade, 2);
|
||||
|
||||
$this->assertEquals(40.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testNoMatch()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub();
|
||||
|
||||
$coupon = new RemovePercentageOnProducts($stubFacade);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$coupon->set(
|
||||
$stubFacade,
|
||||
'TEST', 'TEST Coupon', 'This is a test coupon title', 'This is a test coupon description',
|
||||
array('percentage' => 10.00, 'products' => [10, 20]),
|
||||
true, true, true, true,
|
||||
254,
|
||||
$date->setTimestamp(strtotime("today + 3 months")),
|
||||
new ObjectCollection(),
|
||||
new ObjectCollection(),
|
||||
false
|
||||
);
|
||||
|
||||
$this->generateNoMatchingCart($stubFacade);
|
||||
|
||||
$this->assertEquals(0.00, $coupon->exec());
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', 'Coupon test name');
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemovePercentageOnProducts($stubFacade);
|
||||
|
||||
$actual = $coupon->getName();
|
||||
$expected = 'Coupon test name';
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testGetToolTip()
|
||||
{
|
||||
$tooltip = 'Coupon test tooltip';
|
||||
$stubFacade = $this->generateFacadeStub(399, 'EUR', $tooltip);
|
||||
|
||||
/** @var FacadeInterface $stubFacade */
|
||||
$coupon = new RemovePercentageOnProducts($stubFacade);
|
||||
|
||||
$actual = $coupon->getToolTip();
|
||||
$expected = $tooltip;
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -160,6 +160,11 @@
|
||||
<default key="_view">order-invoice</default>
|
||||
</route>
|
||||
|
||||
<route id="order.coupon.clear" path="/order/clear-coupons">
|
||||
<default key="_controller">Front\Controller\CouponController::clearAllCouponsAction</default>
|
||||
<default key="_view">order-invoice</default>
|
||||
</route>
|
||||
|
||||
<route id="order.payment.process" path="/order/pay">
|
||||
<default key="_controller">Front\Controller\OrderController::pay</default>
|
||||
</route>
|
||||
|
||||
@@ -40,9 +40,16 @@ use Thelia\Module\Exception\DeliveryException;
|
||||
*/
|
||||
class CouponController extends BaseFrontController
|
||||
{
|
||||
/**
|
||||
* Clear all coupons.
|
||||
*/
|
||||
public function clearAllCouponsAction() {
|
||||
// Dispatch Event to the Action
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::COUPON_CLEAR_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Coupon consuming
|
||||
* Coupon consuming
|
||||
*/
|
||||
public function consumeAction()
|
||||
{
|
||||
|
||||
@@ -62,6 +62,7 @@ return array(
|
||||
'Amount, e.g. 12.50' => 'Amount, e.g. 12.50',
|
||||
'An error occured' => 'An error occured',
|
||||
'And' => 'And',
|
||||
'Applies to attribute values :' => 'Applies to attribute values :',
|
||||
'Applies to products :' => 'Applies to products :',
|
||||
'Applies to products in categories :' => 'Applies to products in categories :',
|
||||
'Apply' => 'Apply',
|
||||
@@ -97,6 +98,7 @@ return array(
|
||||
'Catalog' => 'Catalog',
|
||||
'Categories' => 'Categories',
|
||||
'Categories in %cat' => 'Categories in %cat',
|
||||
'Category' => 'Category',
|
||||
'Category created on %date_create. Last modification: %date_change' => 'Category created on %date_create. Last modification: %date_change',
|
||||
'Category title' => 'Category title',
|
||||
'Cellular phone' => 'Cellular phone',
|
||||
@@ -143,6 +145,7 @@ return array(
|
||||
'Confirm' => 'Confirm',
|
||||
'Confirm changes' => 'Confirm changes',
|
||||
'Confirmation' => 'Confirmation',
|
||||
'Content' => 'Content',
|
||||
'Content title' => 'Content title',
|
||||
'Contents in %fold' => 'Contents in %fold',
|
||||
'Copy source text in input field' => 'Copy source text in input field',
|
||||
@@ -331,7 +334,6 @@ return array(
|
||||
'Do you really want to remove this zone ?' => 'Do you really want to remove this zone ?',
|
||||
'Do you really want to set this coupon available to everyone ?' => 'Do you really want to set this coupon available to everyone ?',
|
||||
'Do you really want to use this address by default ?' => 'Do you really want to use this address by default ?',
|
||||
'Document' => 'Document',
|
||||
'Document informations' => 'Document information',
|
||||
'Documents' => 'Documents',
|
||||
'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.',
|
||||
@@ -493,6 +495,7 @@ return array(
|
||||
'Flush the Thelia internal cache' => 'Flush the Thelia internal cache',
|
||||
'Flush the assets cache directory' => 'Flush the assets cache directory',
|
||||
'Flush the images and documents cache' => 'Flush the images and documents cache',
|
||||
'Folder' => 'Folder',
|
||||
'Folder created on %date_create. Last modification: %date_change' => 'Folder created on %date_create. Last modification: %date_change',
|
||||
'Folder title' => 'Folder title',
|
||||
'Folders' => 'Folders',
|
||||
@@ -529,7 +532,6 @@ return array(
|
||||
'If a translation is missing or incomplete :' => 'If a translation is missing or incomplete :',
|
||||
'If yes, redirections through Redirect::exec() will be displayed as links' => 'If yes, redirections through Redirect::exec() will be displayed as links',
|
||||
'Il seems that this string contains a Smarty variable ($). If \'s the case, it cannot be transleted properly.' => 'Il seems that this string contains a Smarty variable ($). If \'s the case, it cannot be transleted properly.',
|
||||
'Image' => 'Image',
|
||||
'Image information' => 'Image information',
|
||||
'Images' => 'Images',
|
||||
'Impossible to change default country. Please contact your administrator or try later' => 'Impossible to change default country. Please contact your administrator or try later',
|
||||
@@ -766,8 +768,11 @@ return array(
|
||||
'Select an attribute and click (+) to view available values' => 'Select an attribute and click (+) to view available values',
|
||||
'Select an attribute value...' => 'Select an attribute value...',
|
||||
'Select an attribute...' => 'Select an attribute...',
|
||||
'Select attribute :' => 'Select attribute :',
|
||||
'Select attribute values to combine. You may enter a default value for some of the fields of the generated combinations.' => 'Select attribute values to combine. You may enter a default value for some of the fields of the generated combinations.',
|
||||
'Select here the tax applicable to this product' => 'Select here the tax applicable to this product',
|
||||
'Select offered product :' => 'Select offered product :',
|
||||
'Select offrered product category :' => 'Select offrered product category :',
|
||||
'Select product category :' => 'Select product category :',
|
||||
'Send a mail to this customer' => 'Send a mail to this customer',
|
||||
'Send files' => 'Send files',
|
||||
@@ -939,6 +944,7 @@ return array(
|
||||
'Update this image' => 'Update this image',
|
||||
'Usage count' => 'Usages left',
|
||||
'Usages left' => 'Usages left',
|
||||
'Use Ctrl+click to select (or deselect) more that one attribute value' => 'Use Ctrl+click to select (or deselect) more that one attribute value',
|
||||
'Use Ctrl+click to select (or deselect) more that one category' => 'Use Ctrl+click to select (or deselect) more that one category',
|
||||
'Use Ctrl+click to select (or deselect) more that one country' => 'Utiliser Ctrl+clic pour sélectionner (ou dé-sélectionner) plusieurs pays.',
|
||||
'Use Ctrl+click to select (or deselect) more that one product' => 'Use Ctrl+click to select (or deselect) more that one product',
|
||||
|
||||
@@ -59,8 +59,12 @@ return array(
|
||||
'Alpha code 2' => 'Code alpha 2',
|
||||
'Alpha code 3' => 'Code alpha 3',
|
||||
'Amount' => 'Montant',
|
||||
'Amount, e.g. 12.50' => 'Montant, par ex. 12.50',
|
||||
'An error occured' => 'Une erreur est survenue',
|
||||
'And' => 'Et',
|
||||
'Applies to attribute values :' => 'Pour les valeurs de déclinaison :',
|
||||
'Applies to products :' => 'Pour les produits',
|
||||
'Applies to products in categories :' => 'Pour les produits des catégories :',
|
||||
'Apply' => 'Appliquer',
|
||||
'Associated countries' => 'Pays dans la zone',
|
||||
'Associations' => 'Associations',
|
||||
@@ -286,6 +290,7 @@ return array(
|
||||
'Disabled' => 'Désactivé',
|
||||
'Discount' => 'Remise',
|
||||
'Discount amount' => 'Montant de réduction',
|
||||
'Discount percentage' => 'Pourcentage de remise',
|
||||
'Do not use a product template' => 'Ne pas utiliser de gabarit',
|
||||
'Do you really want to add this attribute to all product templates ?' => 'Voulez-vous vraiment ajouter cette déclinaison de tous les gabarits de produit ?',
|
||||
'Do you really want to add this feature to all product templates ?' => 'Voulez-vous vraiment ajouter cette caractéristique à tous les gabarits de produit ?',
|
||||
@@ -329,7 +334,6 @@ return array(
|
||||
'Do you really want to remove this zone ?' => 'Voulez-vous vraiment supprimer cette zone ?',
|
||||
'Do you really want to set this coupon available to everyone ?' => 'êtes-vous sur de vouloir rendre ce code promo disponible à tout le monde ?',
|
||||
'Do you really want to use this address by default ?' => 'Voulez-vous vraiment utiliser cette adresse comme adresse par défaut ?',
|
||||
'Document' => 'Document',
|
||||
'Document informations' => 'Informations du document',
|
||||
'Documents' => 'Documents',
|
||||
'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Ne répétez pas sans cesse les même mots-clés dans une ligne. Préférez utiliser des expressions de mots-clés',
|
||||
@@ -528,7 +532,6 @@ return array(
|
||||
'If a translation is missing or incomplete :' => 'Si une traduction est manquante ou incomplète :',
|
||||
'If yes, redirections through Redirect::exec() will be displayed as links' => 'Si oui, les redirections générés pas Redirect::exec seront affichés par des liens',
|
||||
'Il seems that this string contains a Smarty variable ($). If \'s the case, it cannot be transleted properly.' => 'La chaîne semble contient une variable smarty ($). Si c\'est le cas elle ne peut pas être traduite correctement',
|
||||
'Image' => 'Image',
|
||||
'Image information' => 'Information de l\'image',
|
||||
'Images' => 'Images',
|
||||
'Impossible to change default country. Please contact your administrator or try later' => 'Impossible de modifier le pays par défaut. Veuillez contacter votre administrateur ou réessayer plus tard',
|
||||
@@ -639,6 +642,7 @@ return array(
|
||||
'Payment information' => 'Informations de paiement',
|
||||
'Payment module' => 'Module de paiement',
|
||||
'Payment modules' => 'Modules de payment',
|
||||
'Percent Discount' => 'Pourcentage de remise',
|
||||
'Period' => 'Période',
|
||||
'Phone' => 'Téléphone',
|
||||
'Phone number' => 'Numéro de téléphone',
|
||||
@@ -655,6 +659,7 @@ return array(
|
||||
'Please select the PDF template to translate' => 'Sélectionnez le template PDF à traduire',
|
||||
'Please select the module component' => 'Choisissez un composant du module',
|
||||
'Please select the module to translate' => 'Sélectionnez le module à traduire',
|
||||
'Please select...' => 'Merci de choisir...',
|
||||
'Please wait, loading' => 'Chargement, veuillez patienter',
|
||||
'Port' => 'Port',
|
||||
'Port :' => 'Port : ',
|
||||
@@ -763,8 +768,12 @@ return array(
|
||||
'Select an attribute and click (+) to view available values' => 'Sélectionnez une déclinaison et cliquez sur (+) pour voir les valeurs disponibles',
|
||||
'Select an attribute value...' => 'Sélectionnez une valeur de déclinaison...',
|
||||
'Select an attribute...' => 'Sélectionnez une déclinaison...',
|
||||
'Select attribute :' => 'Choisissez une déclinaison',
|
||||
'Select attribute values to combine. You may enter a default value for some of the fields of the generated combinations.' => 'Sélectionnez les valeurs de déclinaison à combiner. Vous pouvez entrer une valeur par défaut pour certains champs des combinaisons générées.',
|
||||
'Select here the tax applicable to this product' => 'Sélectionnez ici la taxe applicable sur ce produit',
|
||||
'Select offered product :' => 'Produit offert :',
|
||||
'Select offrered product category :' => 'Catégorie du produit offert :',
|
||||
'Select product category :' => 'Catégorie des propduits :',
|
||||
'Send a mail to this customer' => 'Contacter ce client par mail',
|
||||
'Send files' => 'Envoyer des fichiers',
|
||||
'Sequential number of log line' => 'Sequential number of log line',
|
||||
@@ -935,6 +944,7 @@ return array(
|
||||
'Update this image' => 'Modifier cette image',
|
||||
'Usage count' => 'Nombre d\'utilisations',
|
||||
'Usages left' => 'Utulisations restantes',
|
||||
'Use Ctrl+click to select (or deselect) more that one attribute value' => 'Ctrl+clic permet de séléctionner (ou dé-selectionner) plusieurs valeurs de déclinaison.',
|
||||
'Use Ctrl+click to select (or deselect) more that one category' => 'Ctrl+Clic permet de sélectionner ou dé-sélectionner plus d\'une catégorie',
|
||||
'Use Ctrl+click to select (or deselect) more that one country' => 'Ctrl+Clic permet de sélectionner ou dé-sélectionner plus d\'un pays',
|
||||
'Use Ctrl+click to select (or deselect) more that one product' => 'Ctrl+Clic permet de sélectionner ou dé-sélectionner plus d\'un produit',
|
||||
|
||||
@@ -214,10 +214,10 @@ $(function($){
|
||||
// ***********************************************
|
||||
|
||||
$.couponManager.displayEfffect = function(optionSelected) {
|
||||
var mainDiv = $('#coupon-type');
|
||||
mainDiv.find('.typeToolTip').html(optionSelected.data('description'));
|
||||
var typeDiv = $('#coupon-type');
|
||||
typeDiv.find('.typeToolTip').html(optionSelected.data('description'));
|
||||
|
||||
var inputsDiv = mainDiv.find('.inputs');
|
||||
var inputsDiv = $('.inputs', $('#coupon-inputs'));
|
||||
inputsDiv.html('<div class="loading" ></div>');
|
||||
var url = $.couponManager.urlAjaxAdminCouponDrawInputs;
|
||||
url = url.replace('couponServiceId', optionSelected.val());
|
||||
@@ -248,11 +248,11 @@ $(function($){
|
||||
|
||||
// Reload effect inputs when changing effect
|
||||
$.couponManager.onEffectChange = function() {
|
||||
var mainDiv = $('#coupon-type');
|
||||
var optionSelected = mainDiv.find('#type option:selected');
|
||||
mainDiv.find('.typeToolTip').html(optionSelected.data('description'));
|
||||
var typeDiv = $('#coupon-type');
|
||||
var optionSelected = typeDiv.find('#type option:selected');
|
||||
typeDiv.find('.typeToolTip').html(optionSelected.data('description'));
|
||||
|
||||
mainDiv.find('#type').on('change', function () {
|
||||
typeDiv.find('#type').on('change', function () {
|
||||
var optionSelected = $('option:selected', this);
|
||||
$.couponManager.displayEfffect(optionSelected);
|
||||
|
||||
|
||||
@@ -54,7 +54,31 @@
|
||||
{if $error}{$message}{/if}
|
||||
</div>
|
||||
{/form_field}
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
<div id="coupon-type">
|
||||
{form_field form=$form field='type'}
|
||||
<div class="form-group {if $error}has-error{/if}">
|
||||
<label for="type" class="control-label">{intl l='Coupon type * :'}</label>
|
||||
<select required name="{$name}" id="type" class="col-md-12 form-control">
|
||||
<option value="" data-description="" data-inputName="">{intl l='Please select a coupon type'}</option>
|
||||
{foreach from=$availableCoupons item=availableCoupon}
|
||||
<option value="{$availableCoupon.serviceId}" data-description="{$availableCoupon.toolTip}" data-inputName="{$availableCoupon.inputName}" {if $value == $availableCoupon.serviceId}selected{/if}>
|
||||
{$availableCoupon.name}
|
||||
</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
{if $error}{$message}{/if}
|
||||
<span class="help-block typeToolTip">{$availableCoupons.0.toolTip}</span>
|
||||
</div>
|
||||
{/form_field}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{form_field form=$form field='isEnabled'}
|
||||
<div class="form-group {if $error}has-error{/if}">
|
||||
<label for="is-enabled" class="checkbox control-label">
|
||||
@@ -163,23 +187,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div id="coupon-type">
|
||||
{form_field form=$form field='type'}
|
||||
<div class="form-group {if $error}has-error{/if}">
|
||||
<label for="type" class="control-label">{intl l='Coupon type * :'}</label>
|
||||
<select required name="{$name}" id="type" class="col-md-12 form-control">
|
||||
<option value="" data-description="" data-inputName="">{intl l='Please select a coupon type'}</option>
|
||||
{foreach from=$availableCoupons item=availableCoupon}
|
||||
<option value="{$availableCoupon.serviceId}" data-description="{$availableCoupon.toolTip}" data-inputName="{$availableCoupon.inputName}" {if $value == $availableCoupon.serviceId}selected{/if}>
|
||||
{$availableCoupon.name}
|
||||
</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
{if $error}{$message}{/if}
|
||||
<span class="help-block typeToolTip">{$availableCoupons.0.toolTip}</span>
|
||||
</div>
|
||||
{/form_field}
|
||||
|
||||
<div id="coupon-inputs">
|
||||
<div class="inputs">
|
||||
{$couponInputsHtml nofilter}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{loop type="attribute_availability" attribute={$smarty.post.attribute_id} name="list-of-attribute_avs" backend_context="1"}
|
||||
<option value="{$ID}">{$TITLE}</option>
|
||||
{/loop}
|
||||
@@ -0,0 +1,65 @@
|
||||
{block name="discount-field"}{/block}
|
||||
|
||||
<div class="form-group input-coupon-attribute-id">
|
||||
|
||||
<label for="coupon-category-id">{intl l="Select attribute :"}</label>
|
||||
|
||||
<select required class="form-control" id="coupon-attribute-id" name="{$attribute_field_name}">
|
||||
<option value="0">{intl l="Please select..."}</option>
|
||||
{loop type="attribute" name="list-of-attributes" order="alpha" backend_context="1"}
|
||||
<option value="{$ID}" {if $ID == $attribute_value}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="input-coupon-attributeAvs-id-loading" style="display: none"></div>
|
||||
|
||||
<div class="form-group" id="input-coupon-attributeAvs-id" {if $attribute_value == 0}style="display: none"{/if}>
|
||||
|
||||
<label for="coupon-products-id">{intl l="Applies to attribute values :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-attributeAvs-id" name="{$attribute_av_field_name}[]">
|
||||
{loop type="attribute_availability" attribute=$attribute_value|default:0 name="list-of-attribute_avs" backend_context="1"}
|
||||
<option value="{$ID}" {if in_array($ID, $attribute_av_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one attribute value'}</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function couponInputFormSetup() {
|
||||
|
||||
var $catSelect = $('#coupon-attribute-id');
|
||||
|
||||
$catSelect.change(function(ev) {
|
||||
|
||||
var $attribute_id = $(this).val();
|
||||
|
||||
$('#input-coupon-attributeAvs-id').hide();
|
||||
$('#coupon-attributeAvs-id').html('');
|
||||
|
||||
if ($attribute_id != 0) {
|
||||
|
||||
$('#input-coupon-attributeAvs-id-loading').show();
|
||||
|
||||
$.ajax({
|
||||
url: "{url path='/admin/coupon/type-fragments/ajax-attribute-avs-list'}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
attribute_id: $attribute_id
|
||||
},
|
||||
success: function(options) {
|
||||
$('#coupon-attributeAvs-id').html(options);
|
||||
$('#input-coupon-attributeAvs-id').show();
|
||||
},
|
||||
complete: function() {
|
||||
$('#input-coupon-attributeAvs-id-loading').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
{block name="javascript-init"}{/block}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,20 @@
|
||||
{block name="discount-field"}{/block}
|
||||
|
||||
<div class="form-group input-coupon-categories-id">
|
||||
|
||||
<label for="coupon-categories-id">{intl l="Applies to products in categories :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-categories-id" name="{$categories_field_name}[]">
|
||||
{loop type="category-tree" category=0 name="list-of-categories" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if in_array($ID, $categories_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one category'}</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function couponInputFormSetup() {
|
||||
{block name="javascript-init"}{/block}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,65 @@
|
||||
{block name="discount-field"}{/block}
|
||||
|
||||
<div class="form-group input-coupon-category-id">
|
||||
|
||||
<label for="coupon-category-id">{intl l="Select product category :"}</label>
|
||||
|
||||
<select required class="form-control" id="coupon-category-id" name="{$category_id_field_name}">
|
||||
<option value="0">{intl l="Please select..."}</option>
|
||||
{loop type="category-tree" category=0 name="list-of-category" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if $ID == $category_id_value}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="input-coupon-products-id-loading" style="display: none"></div>
|
||||
|
||||
<div class="form-group" id="input-coupon-products-id" {if $category_id_value == 0}style="display: none"{/if}>
|
||||
|
||||
<label for="coupon-products-id">{intl l="Applies to products :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-products-id" name="{$products_field_name}[]">
|
||||
{loop type="product" category=$category_id_value|default:0 name="list-of-products" backend_context="1"}
|
||||
<option value="{$ID}" {if in_array($ID, $products_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one product'}</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function couponInputFormSetup() {
|
||||
|
||||
var $catSelect = $('#coupon-category-id');
|
||||
|
||||
$catSelect.change(function(ev) {
|
||||
|
||||
var $category_id = $(this).val();
|
||||
|
||||
$('#input-coupon-products-id').hide();
|
||||
$('#coupon-products-id').html('');
|
||||
|
||||
if ($category_id != 0) {
|
||||
|
||||
$('#input-coupon-products-id-loading').show();
|
||||
|
||||
$.ajax({
|
||||
url: "{url path='/admin/coupon/type-fragments/ajax-products-list'}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
category_id: $category_id
|
||||
},
|
||||
success: function(options) {
|
||||
$('#coupon-products-id').html(options);
|
||||
$('#input-coupon-products-id').show();
|
||||
},
|
||||
complete: function() {
|
||||
$('#input-coupon-products-id-loading').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
{block name="javascript-init"}{/block}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,69 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-products.html"}
|
||||
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-free-product-category-id">
|
||||
|
||||
<label for="free-product-category-id">{intl l="Select offrered product category :"}</label>
|
||||
|
||||
<select required class="form-control" id="free-product-category-id" name="{$offered_category_field_name}">
|
||||
<option value="0">{intl l="Please select..."}</option>
|
||||
{loop type="category-tree" category=0 name="list-of-category" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if $ID == $offered_category_value}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="input-free-products-id-loading" style="display: none"></div>
|
||||
|
||||
<div class="form-group" id="input-free-products-id" {if $offered_category_value == 0}style="display: none"{/if}>
|
||||
|
||||
<label for="free-products-id">{intl l="Select offered product :"}</label>
|
||||
|
||||
<select required class="form-control" id="free-products-id" name="{$offered_product_field_name}">
|
||||
{loop type="product" category=$offered_category_value|default:0 name="list-of-products" backend_context="1"}
|
||||
<option value="{$ID}" {if $ID == $offered_product_value}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name="javascript-init"}
|
||||
|
||||
// Hide selected products category selection if the
|
||||
// offered product is not yet selected.
|
||||
if ({$offered_category_value|default:0} == 0) {
|
||||
$('.input-coupon-category-id').hide();
|
||||
}
|
||||
|
||||
var $freeCatSelect = $('#free-product-category-id');
|
||||
|
||||
$freeCatSelect.change(function(ev) {
|
||||
|
||||
var $category_id = $(this).val();
|
||||
|
||||
$('.input-coupon-category-id').hide();
|
||||
$('#input-free-products-id').hide();
|
||||
$('#free-products-id').html('');
|
||||
|
||||
if ($category_id != 0) {
|
||||
|
||||
$('#input-free-products-id-loading').show();
|
||||
|
||||
$.ajax({
|
||||
url: "{url path='/admin/coupon/type-fragments/ajax-products-list'}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
category_id: $category_id
|
||||
},
|
||||
success: function(options) {
|
||||
$('.input-coupon-category-id').show();
|
||||
$('#free-products-id').html(options);
|
||||
$('#input-free-products-id').show();
|
||||
},
|
||||
complete: function() {
|
||||
$('#input-free-products-id-loading').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
{/block}
|
||||
@@ -0,0 +1,16 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-attributes.html"}
|
||||
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-amount">
|
||||
|
||||
<label for="coupon-amount" class="control-label">{intl l="Discount amount"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$amount_field_name}" value="{$amount_value}" placeholder="14.50">
|
||||
|
||||
{loop type="currency" name="get-symbol" default_only="true"}
|
||||
<div class="input-group-addon">{$SYMBOL}</div>
|
||||
{/loop}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -1,26 +1,16 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-categories.html"}
|
||||
|
||||
<div class="form-group input-coupon-amount">
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-amount">
|
||||
|
||||
<label for="coupon-amount" class="control-label">{intl l="Discount amount"}</label>
|
||||
<label for="coupon-amount" class="control-label">{intl l="Discount amount"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$amount_field_name}" value="{$amount_value}" placeholder="14.50">
|
||||
<div class="input-group">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$amount_field_name}" value="{$amount_value}" placeholder="14.50">
|
||||
|
||||
{loop type="currency" name="get-symbol" default_only="true"}
|
||||
<div class="input-group-addon">{$SYMBOL}</div>
|
||||
{/loop}
|
||||
{loop type="currency" name="get-symbol" default_only="true"}
|
||||
<div class="input-group-addon">{$SYMBOL}</div>
|
||||
{/loop}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group input-coupon-categories-id">
|
||||
|
||||
<label for="coupon-categories-id">{intl l="Applies to products in categories :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-categories-id" name="{$categories_field_name}[]">
|
||||
{loop type="category-tree" category=0 name="list-of-categories" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if in_array($ID, $categories_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one category'}</span>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -1,77 +1,16 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-products.html"}
|
||||
|
||||
<div class="form-group input-coupon-amount">
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-amount">
|
||||
|
||||
<label for="coupon-amount" class="control-label">{intl l="Discount amount"}</label>
|
||||
<label for="coupon-amount" class="control-label">{intl l="Discount amount"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$amount_field_name}" value="{$amount_value}" placeholder="14.50">
|
||||
<div class="input-group">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$amount_field_name}" value="{$amount_value}" placeholder="14.50">
|
||||
|
||||
{loop type="currency" name="get-symbol" default_only="true"}
|
||||
<div class="input-group-addon">{$SYMBOL}</div>
|
||||
{/loop}
|
||||
{loop type="currency" name="get-symbol" default_only="true"}
|
||||
<div class="input-group-addon">{$SYMBOL}</div>
|
||||
{/loop}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group input-coupon-category-id">
|
||||
|
||||
<label for="coupon-category-id">{intl l="Select product category :"}</label>
|
||||
|
||||
<select required class="form-control" id="coupon-category-id" name="{$category_id_field_name}">
|
||||
<option value="0">{intl l="Please select..."}</option>
|
||||
{loop type="category-tree" category=0 name="list-of-category" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if $ID == $category_id_value}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one category'}</span>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="input-coupon-products-id-loading" style="display: none"></div>
|
||||
|
||||
<div class="form-group" id="input-coupon-products-id" {if $category_id_value == 0}style="display: none"{/if}>
|
||||
|
||||
<label for="coupon-products-id">{intl l="Applies to products :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-products-id" name="{$products_field_name}[]">
|
||||
{loop type="product" category=$category_id_value name="list-of-products" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if in_array($ID, $products_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one category'}</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function couponInputFormSetup() {
|
||||
|
||||
var $catSelect = $('#coupon-category-id');
|
||||
|
||||
$catSelect.change(function(ev) {
|
||||
|
||||
var $category_id = $(this).val();
|
||||
|
||||
$('#input-coupon-products-id').hide();
|
||||
$('#coupon-products-id').html('');
|
||||
|
||||
if ($category_id != 0) {
|
||||
|
||||
$('#input-coupon-products-id-loading').show();
|
||||
|
||||
$.ajax({
|
||||
url: "{url path='/admin/coupon/type-fragments/ajax-products-list'}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
category_id: $category_id
|
||||
},
|
||||
success: function(options) {
|
||||
$('#coupon-products-id').html(options);
|
||||
$('#input-coupon-products-id').show();
|
||||
},
|
||||
complete: function() {
|
||||
$('#input-coupon-products-id-loading').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
{/block}
|
||||
@@ -0,0 +1,14 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-attributes.html"}
|
||||
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-percentage">
|
||||
|
||||
<label for="coupon-percentage" class="control-label">{intl l="Discount percentage"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-percentage" type="number" class="form-control" name="{$percentage_field_name}" value="{$percentage_value}" placeholder="5">
|
||||
|
||||
<div class="input-group-addon">%</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -1,24 +1,14 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-categories.html"}
|
||||
|
||||
<div class="form-group input-coupon-percentage">
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-percentage">
|
||||
|
||||
<label for="coupon-percentage" class="control-label">{intl l="Discount percentage"}</label>
|
||||
<label for="coupon-percentage" class="control-label">{intl l="Discount percentage"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-percentage" type="number" class="form-control" name="{$percentage_field_name}" value="{$percentage_value}" placeholder="5">
|
||||
<div class="input-group">
|
||||
<input id="coupon-percentage" type="number" class="form-control" name="{$percentage_field_name}" value="{$percentage_value}" placeholder="5">
|
||||
|
||||
<div class="input-group-addon">%</div>
|
||||
<div class="input-group-addon">%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group input-coupon-categories-id">
|
||||
|
||||
<label for="coupon-categories-id">{intl l="Applies to products in categories :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-categories-id" name="{$categories_field_name}[]">
|
||||
{loop type="category-tree" category=0 name="list-of-categories" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if in_array($ID, $categories_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one category'}</span>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -1,75 +1,14 @@
|
||||
{extends file="coupon/type-fragments/base-remove-on-products.html"}
|
||||
|
||||
<div class="form-group input-coupon-percentage">
|
||||
{block name="discount-field"}
|
||||
<div class="form-group input-coupon-percentage">
|
||||
|
||||
<label for="coupon-percentage" class="control-label">{intl l="Discount percentage"}</label>
|
||||
<label for="coupon-percentage" class="control-label">{intl l="Discount percentage"}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-percentage" type="number" class="form-control" name="{$percentage_field_name}" value="{$percentage_value}" placeholder="5">
|
||||
<div class="input-group">
|
||||
<input id="coupon-percentage" type="number" class="form-control" name="{$percentage_field_name}" value="{$percentage_value}" placeholder="5">
|
||||
|
||||
<div class="input-group-addon">%</div>
|
||||
<div class="input-group-addon">%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group input-coupon-category-id">
|
||||
|
||||
<label for="coupon-category-id">{intl l="Select product category :"}</label>
|
||||
|
||||
<select required class="form-control" id="coupon-category-id" name="{$category_id_field_name}">
|
||||
<option value="0">{intl l="Please select..."}</option>
|
||||
{loop type="category-tree" category=0 name="list-of-category" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if $ID == $category_id_value}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one category'}</span>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="input-coupon-products-id-loading" style="display: none"></div>
|
||||
|
||||
<div class="form-group" id="input-coupon-products-id" {if $category_id_value == 0}style="display: none"{/if}>
|
||||
|
||||
<label for="coupon-products-id">{intl l="Applies to products :"}</label>
|
||||
|
||||
<select required multiple size="10" class="form-control" id="coupon-products-id" name="{$products_field_name}[]">
|
||||
{loop type="product" category=$category_id_value name="list-of-products" backend_context="1"}
|
||||
<option style="padding-left: {$LEVEL * 10}px" value="{$ID}" {if in_array($ID, $products_values)}selected="selected"{/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
|
||||
<span class="label-help-block">{intl l='Use Ctrl+click to select (or deselect) more that one category'}</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function couponInputFormSetup() {
|
||||
|
||||
var $catSelect = $('#coupon-category-id');
|
||||
|
||||
$catSelect.change(function(ev) {
|
||||
|
||||
var $category_id = $(this).val();
|
||||
|
||||
$('#input-coupon-products-id').hide();
|
||||
$('#coupon-products-id').html('');
|
||||
|
||||
if ($category_id != 0) {
|
||||
|
||||
$('#input-coupon-products-id-loading').show();
|
||||
|
||||
$.ajax({
|
||||
url: "{url path='/admin/coupon/type-fragments/ajax-products-list'}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
category_id: $category_id
|
||||
},
|
||||
success: function(options) {
|
||||
$('#coupon-products-id').html(options);
|
||||
$('#input-coupon-products-id').show();
|
||||
},
|
||||
complete: function() {
|
||||
$('#input-coupon-products-id-loading').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
{/block}
|
||||
@@ -2,7 +2,7 @@
|
||||
<label for="coupon-amount" class="control-label">{intl l='Discount amount'}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$fieldName}" value="{$value}" placeholder="{intl l="Amount, e.g. 12.50"}">
|
||||
<input id="coupon-amount" type="money" class="form-control" name="{$amount_field_name}" value="{$amount_value}" placeholder="{intl l="Amount, e.g. 12.50"}">
|
||||
|
||||
{loop type="currency" name="get-symbol" default_only="true"}
|
||||
<div class="input-group-addon">{$SYMBOL}</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<label for="coupon-percent" class="control-label">{intl l='Percent Discount'}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="coupon-percent" class="form-control" name="{$fieldName}" type="text" value="{$value}"/>
|
||||
<input id="coupon-percent" class="form-control" name="{$percentage_field_name}" type="text" value="{$percentage_value}"/>
|
||||
<div class="input-group-addon">%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user