Browse Source

修改领取优惠卷可能会超发的情况

master
Mike 5 years ago
parent
commit
cf5603b94c
  1. 72
      app/Controller/CouponController.php

72
app/Controller/CouponController.php

@ -100,46 +100,54 @@ class CouponController extends BaseController
$test = $this->request->input("test", 0);
$ids = explode(',', $ids);
$cps = Coupon::whereIn('id', $ids)->get();
$now = time();
$success = [];
$fail = [];
foreach ($cps as $key => $cp) {
$crt = CouponUserRecType::where(
[
'system_coupon_user_id' => $cp->id,
'receive_type' => $receiveType
]
)->first();
$cr = new CouponRec;
$cr->user_id = $userId;
$cr->system_coupon_user_id = $cp->id;
$cr->order_main_id = 0;
$cr->receive_time = $now;
$cr->number = $crt->one_receive_number;
$cr->number_remain = $crt->one_receive_number;
$cr->status = 0;
$cr->update_time = $now;
$cr->receive_type = $receiveType;
if ($test && ($cp->id % 2)) {
$fail[] = $cp;
} else {
//TODO 会有超发情况
//如果优惠卷库存小于等于已领取的数量, 则返回领取失败的优惠券
if ($cp->inventory<=$cp->inventory_use||$cp->inventory<($cp->inventory_use+$cr->number)){
Db::transaction(function () use ($ids,$receiveType,$userId,&$success,&$fail,$test) {
//读写锁,完全控制,性能底
$cps = Coupon::whereIn('id', $ids)->lockForUpdate()->get();
//写锁,可能在高并发下,读取到脏数据,写入可能有超发情况
//$cps = Coupon::whereIn('id', $ids)->sharedLock()->get();
foreach ($cps as $key => $cp) {
$crt = CouponUserRecType::where(
[
'system_coupon_user_id' => $cp->id,
'receive_type' => $receiveType
]
)->first();
$cr = new CouponRec;
$cr->user_id = $userId;
$cr->system_coupon_user_id = $cp->id;
$cr->order_main_id = 0;
$cr->receive_time = $now;
$cr->number = $crt->one_receive_number;
$cr->number_remain = $crt->one_receive_number;
$cr->status = 0;
$cr->update_time = $now;
$cr->receive_type = $receiveType;
if ($test && ($cp->id % 2)) {
$fail[] = $cp;
}else{
$cp->inventory_use += $cr->number;//记录已领取的数量
if ($cr->save()&&$cp->save()) {
$success[] = $cp;
} else {
} else {
//TODO 会有超发情况
//如果优惠卷库存小于等于已领取的数量, 则返回领取失败的优惠券
if ($cp->inventory<=$cp->inventory_use||$cp->inventory<($cp->inventory_use+$cr->number)){
$fail[] = $cp;
}else{
$cp->inventory_use += $cr->number;//记录已领取的数量
if ($cr->save()&&$cp->save()) {
$success[] = $cp;
} else {
$fail[] = $cp;
}
}
}
}
}
}
});
return $this->success([
'success' => $success,

Loading…
Cancel
Save