I have a project where I have implemented coupon system. Problem is, one user can use a coupon multiple times until the coupon expires. I would lke: Limiting coupon usage based on max usage defined in coupon table;
I have also looked for various sites in google. Which includes stackoverflow along with others.
id
code
type
value
cart_value
expiry_date
timestamps
max
Max- maximum time a coupon can be used.
Pivot table: user_coupons
id
coupon_id
user_id
code
The code column here stores how many times a specific coupon has been used.
Apply Coupon Method.
public function applyCouponCode()
{
$promo = Coupon::where('code', $this->couponCode)
->where('expiry_date', '>=', Carbon::today())
->where('cart_value', '<=', Cart::instance('cart')->subtotal())
->first();
$coupon = Coupon::with('userCoupon')
->where('expiry_date', '>=', Carbon::today())
->where('code', '!=', 'user_coupons.code')
->where('cart_value', '<=', Cart::instance('cart')->subtotal())
->first();
if ($coupon->userCoupon()->code === $this->couponCode) {
$this->alert('error', 'Code already used!');
return;
// dd($coupon->code);
} else if (!$promo) {
$this->alert('error', 'Invalid code!');
return;
} else if ($coupon) {
$this->alert('success', 'Code ok!');
return;
}
//this part never appears. Even though coupon is valid
$this->alert('success', 'Coupon is applied');
}
Issues:
1.codes previously used are recognised.
- invalid codes are recognised. But valid codes also says Invalid code.
What am I missing?
I am using Laravel 8 with livewire. I have tried many methods. Nothing seems to work.
I have tried query builder. At some point I was able to get the codes used by the user by joining coupons using inner join with the user_coupons
table. I have also tried using model relationship however it says collection does not exist.
CodePudding user response:
I do implementing coupon system on my project. And I think we have the same term for this. You might try my way:
- This is my vouchers table attributes. I declared it as fillable attributes in Voucher model.
protected $fillable = [
'service_id',
'code',
'name',
'description',
'percentage', // percentage of discount
'maximum_value', // maximum value of discount
'maximum_usage', // maximum usage per user. If it's 1, it means user only can use it once.
'user_terms', // additional terms
'amount', // amount of voucher. If it's 1, it means the voucher is only can be redeemed once.
'expired_at',
'is_active', // for exception if we want to deactivate the voucher (although voucher is valid)
];
- This is my voucher_redemptions table, this table is used when the user redeem the voucher. I declared it in VoucherRedemption model.
protected $fillable = [
'redeemer_id', // user id who redeems the voucher
'voucher_id', // voucher
'item_id', // product item
];
- This is my function to redeem voucher
/**
* Apply voucher to an item
* @param int $redeemerId user id
* @param string $voucherCode voucher code
* @param int $itemId project batch package id
* @return VoucherRedemption $redemption
*/
public static function apply($redeemerId, $voucherCode, $itemId)
{
$voucher = Voucher::where('code', $voucherCode)->first();
// Make sure item is exist and the batch has not been checked out
$item = ProjectBatchPackage::where('id', $itemId)->first();
if (!$item) {
return;
} else if ($item->batch->status != null) {
return;
}
// Make sure voucher exist
if (!$voucher) {
return;
}
// Make sure is voucher active, not expired and available.
if ($voucher->is_active == false || $voucher->isExpired() || !$voucher->isAvailable()) {
return;
}
// Make sure voucher usage for user
if ($voucher->maximum_usage != null) {
$user_usages = VoucherRedemption::where('redeemer_id', $redeemerId)
->where('voucher_id', $voucher->id)
->get()
->count();
if ($user_usages >= $voucher->maximum_usage) {
return;
}
}
// Apply voucher to project batch package (item)
$redemption = VoucherRedemption::create([
'redeemer_id' => $redeemerId,
'voucher_id' => $voucher->id,
'item_id' => $itemId
]);
return $redemption;
}
Thank you.