Added per-user coupon maximum usage count
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
*
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user