Added per-user coupon maximum usage count

This commit is contained in:
Franck Allimant
2014-05-17 10:20:26 +02:00
parent 9cdac6d50e
commit f8ccea1899
43 changed files with 4506 additions and 152 deletions

View File

@@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
use Thelia\Condition\ConditionFactory;
use Thelia\Coupon\Type\CouponInterface;
use Thelia\Exception\CouponExpiredException;
use Thelia\Exception\CouponNoUsageLeftException;
use Thelia\Exception\InvalidConditionException;
use Thelia\Model\Coupon;
@@ -62,12 +63,19 @@ class CouponFactory
return false;
}
// Check coupon expiration date
if ($couponModel->getExpirationDate() < new \DateTime()) {
throw new CouponExpiredException($couponCode);
}
// Check coupon usage count
if ($couponModel->getUsagesLeft($this->facade->getCustomer()->getId()) <= 0) {
throw new CouponNoUsageLeftException($couponCode);
}
/** @var CouponInterface $couponInterface */
$couponInterface = $this->buildCouponFromModel($couponModel);
if ($couponInterface && $couponInterface->getConditions()->count() == 0) {
throw new InvalidConditionException(
get_class($couponInterface)
@@ -109,7 +117,8 @@ class CouponFactory
$model->getMaxUsage(),
$model->getExpirationDate(),
$model->getFreeShippingForCountries(),
$model->getFreeShippingForModules()
$model->getFreeShippingForModules(),
$model->getPerCustomerUsageCount()
);
/** @var ConditionFactory $conditionFactory */

View File

@@ -20,6 +20,8 @@ use Thelia\Model\AddressQuery;
use Thelia\Model\Base\CouponModule;
use Thelia\Model\Coupon;
use Thelia\Model\CouponCountry;
use Thelia\Model\CouponCustomerCount;
use Thelia\Model\CouponCustomerCountQuery;
use Thelia\Model\Order;
use Thelia\Model\OrderAddress;
use Thelia\Model\OrderAddressQuery;
@@ -272,26 +274,64 @@ class CouponManager
* To call when a coupon is consumed
*
* @param \Thelia\Model\Coupon $coupon Coupon consumed
* @param int|null $customerId the ID of the ordering customer
*
* @return int Usage left after decremental
*/
public function decrementQuantity(Coupon $coupon)
public function decrementQuantity(Coupon $coupon, $customerId = null)
{
$ret = -1;
$ret = false;
try {
$usageLeft = $coupon->getMaxUsage();
$usageLeft = $coupon->getUsagesLeft($customerId);
if ($usageLeft > 0) {
$usageLeft--;
$coupon->setMaxUsage($usageLeft);
if ($usageLeft > 0) {
$coupon->save();
$ret = $usageLeft;
}
// If the coupon usage is per user, add an entry to coupon customer usage count table
if ($coupon->getPerCustomerUsageCount()) {
} catch (\Exception $e) {
$ret = false;
if (null == $customerId) {
throw new \LogicException("Customer should not be null at this time.");
}
$ccc = CouponCustomerCountQuery::create()
->filterByCouponId($coupon->getId())
->filterByCustomerId($customerId)
->findOne()
;
if ($ccc === null) {
$ccc = new CouponCustomerCount();
$ccc
->setCustomerId($customerId)
->setCouponId($coupon->getId())
->setCount(0);
}
$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()));
}
return $ret;

View File

@@ -96,6 +96,9 @@ abstract class CouponAbstract implements CouponInterface
/** @var CouponModule[] list of shipping module IDs for which shippiog is free. All if empty*/
protected $freeShippingForModules = [];
/** @var true if usage count is per customer only */
protected $perCustomerUsageCount;
/**
* Constructor
*
@@ -139,7 +142,8 @@ abstract class CouponAbstract implements CouponInterface
$maxUsage,
\DateTime $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
$freeShippingForModules,
$perCustomerUsageCount
)
{
$this->code = $code;
@@ -161,10 +165,29 @@ abstract class CouponAbstract implements CouponInterface
$this->freeShippingForCountries = $freeShippingForCountries;
$this->freeShippingForModules = $freeShippingForModules;
$this->perCustomerUsageCount = $perCustomerUsageCount;
return $this;
}
/**
* @param true $perCustomerUsageCount
*/
public function setPerCustomerUsageCount($perCustomerUsageCount)
{
$this->perCustomerUsageCount = $perCustomerUsageCount;
return $this;
}
/**
* @return true
*/
public function getPerCustomerUsageCount()
{
return $this->perCustomerUsageCount;
}
/**
* Return Coupon code (ex: XMAS)
*

View File

@@ -66,7 +66,7 @@ interface CouponInterface
* @param \Datetime $expirationDate When the Code is expiring
* @param ObjectCollection $freeShippingForCountries list of countries which shipping is free. All if empty
* @param ObjectCollection $freeShippingForModules list of modules for which shipping is free. All if empty
* @param bool $perCustomerUsageCount true if usage count is per customer only
*/
public function set(
FacadeInterface $facade,
@@ -82,7 +82,8 @@ interface CouponInterface
$maxUsage,
\DateTime $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
$freeShippingForModules,
$perCustomerUsageCount
);
/**
@@ -162,6 +163,14 @@ interface CouponInterface
*/
public function isAvailableOnSpecialOffers();
/**
* Check if the Coupon can be used against a
* product already with a special offer price
*
* @return boolean
*/
public function getPerCustomerUsageCount();
/**
* Check if Coupon has been disabled by admin
*

View File

@@ -51,14 +51,16 @@ class RemoveXPercent extends CouponAbstract
$maxUsage,
\DateTime $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
$freeShippingForModules,
$perCustomerUsageCount
)
{
parent::set(
$facade, $code, $title, $shortDescription, $description, $effects,
$isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate,
$freeShippingForCountries,
$freeShippingForModules
$freeShippingForModules,
$perCustomerUsageCount
);
$this->percentage = $effects[self::INPUT_PERCENTAGE_NAME];