商品SKU, 'quantity' => 10] * ] * @return array */ public function getAvailableCoupons(User $user, array $products): array { $coupons = $user->coupons()->onlyAvailable()->get(); $coupons->load(['ranges' => function ($query) { $query->isEnable(); }]); $availableCoupons = []; foreach ($coupons as $coupon) { // 是否满足券使用规则 $passes = false; // 可用优惠券的商品的总额 $amount = 0; foreach ($products as $product) { $sku = $product['sku']; if ($coupon->isSupport($sku)) { $passes = true; $amount += $sku->getRealPrice($user) * $product['quantity']; } } if ($passes && $amount >= $coupon->coupon_threshold) { $availableCoupons[] = $coupon; } } return $availableCoupons; } /** * 根据分区,领取优惠券 */ public function receivePartCoupon(ProductPart $part, User $user) { //如果分区不显示,直接退出; if (!$part->is_show) { return; } //如果用户已领取过该分区设置的券,直接退出; if (ReceivePartCouponLog::where(['user_id'=>$user->id, 'part_id'=>$part->id])->exists()) { return; } //取出需要发放的券 $coupons = Coupon::whereIn('id', $part->coupons->pluck('coupon_id')->toArray())->get(); $coupons = $coupons->keyBy('id'); $someCoupons = []; foreach ($part->coupons as $coupon) { $someCoupons[] = [ 'coupon'=>$coupons[$coupon->coupon_id], 'num'=>$coupon->num, ]; } $this->receiveSomeCoupons($user, $someCoupons); ReceivePartCouponLog::create(['user_id'=>$user->id, 'part_id'=>$part->id]); } /** * 根据活动领取优惠券 * * @return void */ public function receiveActivityCoupons(Activity $activity, User $user) { $someCoupons = []; foreach ($activity->coupons as $coupon) { $someCoupons[] = [ 'coupon'=>$coupon, 'num'=>$coupon->pivot->qty, ]; } $this->receiveSomeCoupons($user, $someCoupons, $activity->id); } /** * 领取一批券 * * @param User $user * @param array $coupons * @return void */ protected function receiveSomeCoupons(User $user, array $coupons, ?int $activityId = null) { $userCoupons = []; foreach ($coupons as $key=> $coupon) { //更新对应券发送量,余量; try { $canSent = true; if ($coupon['coupon']->limit > 0) {//限量才减少余量 $coupon['coupon']->decrement('stock', $coupon['num']); } } catch (QueryException $e) { if (strpos($e->getMessage(), 'Numeric value out of range') !== false) { $canSent = false; } else { throw new $e(); } } if ($canSent) { for ($i = 0; $i < $coupon['num']; $i++) { $userCoupons[] = self::createUserCouponData($user->id, $coupon['coupon'], $activityId ?? null); } $coupon['coupon']->increment('sent', $coupon['num']); } } UserCoupon::insert($userCoupons); } /** * todo-领取指定券 * * @param User $user * @param Coupon $coupon * @param int $num * @return void */ public function receiveCoupon(User $user, Coupon $coupon, int $num = 1) { return; } /** * 创建用户券数据 * * @return array */ public static function createUserCouponData(int $userId, Coupon $coupon, ?int $activityId = null) { //如果userId小于等于0,直接退出 if ($userId <= 0) { return []; } if ($coupon->use_start_at && $coupon->use_end_at) { $useStartAt = $coupon->use_start_at; $useEndAt = $coupon->use_end_at; } else { $useStartAt = now(); $useEndAt = now()->addDays($coupon->use_day); } return [ 'user_id' => $userId, 'coupon_id' => $coupon->id, 'coupon_name' => $coupon->name, 'coupon_type' => $coupon->type, 'coupon_amount' => (int) bcmul($coupon->amount, 100), 'coupon_threshold'=> (int) bcmul($coupon->threshold, 100), 'use_start_at' => $useStartAt, 'use_end_at' => $useEndAt, 'created_at' => now(), 'updated_at' => now(), 'activity_id' => $activityId ?? null, ]; } }