'CUDT' . date("ymdHi") . random_string(4, 'up'), 'join_detail_coupon_id' => $params['coupon_id'], 'join_coupon_detail_member_id' => $params['member_id'], 'coupon_detail_status' => 'ACTIVED', 'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'], 'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'], 'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0, 'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']), 'coupon_detail_addtimes' => time(), ]); } catch (\Exception $e) { throw new BusinessException('写入优惠券失败'); } } public static function customSendCouponHave($params) { $gettype = 'SEND'; if (!empty($params['gettype'])) { $gettype = $params['gettype']; } try { CouponDetail::where('join_detail_coupon_id', $params['coupon_id']) ->whereIn('coupon_detail_status', ['INIT', 'PENDING']) ->limit($params['chooseCouponNbr']) ->update([ 'join_coupon_detail_member_id' => $params['member_id'], 'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'], 'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'], 'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']), 'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0, 'coupon_detail_status' => 'ACTIVED', 'coupon_detail_addtimes' => time() ]); } catch (\Exception $e) { throw new BusinessException('写入优惠券失败'); } } /** * @Desc 发周期优惠券 - 没有发行数量 * @Author Gorden * @Date 2024/9/27 13:44 * * @param $params * @return void */ public static function sendPeriodCoupon($params) { Db::beginTransaction(); try { $coupon = Coupon::where('coupon_id', $params['coupon_id'])->first(); if ($coupon->coupon_is_period != 'Y') { return; } $detailCount = -1; if ($coupon->coupon_number > 0) { $detailCount = CouponDetail::where('join_detail_coupon_id', $params['coupon_id'])->whereIn('coupon_detail_status', ['INIT', 'PENDING'])->count(); } $periodJson = json_decode($coupon->coupon_period_json, true); if ($detailCount != -1 && $detailCount - $periodJson['nbr'] < 0) { throw new BusinessException("优惠券余量不足"); } $periodJson['now_nbr'] = 1; // 手动发券会传来时间 $periodJson['gain_datetime'] = $params['coupon_detail_gain_datetime'] ?? date('Y-m-d H:i:s'); if (!empty($periodJson['nbr'])) { for ($i = 0; $i < $periodJson['nbr']; $i++) { $periodParams = self::generatePeriod($periodJson); $periodParams['gettype'] = $params['gettype'] ?? ''; $periodParams['order_id'] = $params['order_id'] ?? ''; $periodParams['coupon_id'] = $params['coupon_id']; $periodParams['member_id'] = $params['member_id']; $periodParams['coupon_detail_period_num'] = $periodJson['now_nbr']; if ($detailCount > 0) { $periodParams['chooseCouponNbr'] = 1; self::sendPeriodCouponHave($periodParams); } else { self::sendPeriodCouponNoLimit($periodParams); } $periodJson['now_nbr'] += 1; } } Db::commit(); } catch (BusinessException $e) { Db::rollBack(); Log::error("发券失败:" . $e->getMessage()); throw new BusinessException($e->getMessage()); } catch (\Exception $e) { Db::rollBack(); Log::error("发券失败:" . $e->getMessage()); throw new BusinessException("优惠券发放失败"); } } /** * @Desc 有发行数量 * @Author Gorden * @Date 2024/9/27 13:45 * * @param $params * @return void */ public static function sendPeriodCouponHave($params) { $gettype = 'SEND'; if (!empty($params['gettype'])) { $gettype = $params['gettype']; } try { CouponDetail::where('join_detail_coupon_id', $params['coupon_id']) ->whereIn('coupon_detail_status', ['INIT', 'PENDING']) ->limit($params['chooseCouponNbr']) ->update([ 'join_coupon_detail_member_id' => $params['member_id'], 'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'], 'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'], 'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']), 'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0, 'coupon_detail_status' => 'ACTIVED', 'coupon_detail_addtimes' => time() ]); } catch (\Exception $e) { dump($e->getMessage()); throw new BusinessException('写入优惠券失败'); } } /** * @Desc 发行量不限 * @Author Gorden * @Date 2024/9/27 16:19 * * @param $params * @return void * @throws BusinessException */ public static function sendPeriodCouponNoLimit($params) { $gettype = 'SEND'; if (!empty($params['gettype'])) { $gettype = $params['gettype']; } try { CouponDetail::insert([ 'coupon_detail_id' => 'CUDT' . date("ymdHi") . random_string(4, 'up'), 'join_detail_coupon_id' => $params['coupon_id'], 'join_coupon_detail_member_id' => $params['member_id'], 'coupon_detail_status' => 'ACTIVED', 'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'], 'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'], 'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0, 'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']), 'coupon_detail_addtimes' => time(), ]); } catch (\Exception $e) { throw new BusinessException('写入优惠券失败'); } } /** * @Desc * @Author Gorden * @Date 2024/9/27 13:54 * * @param $periodJson * @return array */ public static function generatePeriod($periodJson) { // 当前第几期 $now_nbr = $periodJson['now_nbr']; $params = []; if ($periodJson['unit'] == 'day') { $val = $periodJson['val'] - 1; if ($val < 1) { if ($now_nbr == 1) { $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime'])); $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime'])); } else { $now_nbr -= 1; $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime'] . "+" . $now_nbr . ' day')); $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime'] . "+" . $now_nbr . ' day')); } } else { if ($now_nbr == 1) { $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime'])); $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime'] . "+" . $val . ' day')); } else { $now_nbr -= 1; $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime'] . "+" . ((($val + 1) * $now_nbr)) . " day")); $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime'] . "+" . ((($val + 1) * $now_nbr) + $val) . " day")); } } } elseif ($periodJson['unit'] == 'week') { $val = $periodJson['val'] - 1; // 选的日期的周一距离今周周一是几个周 $timestamp = strtotime($periodJson['gain_datetime']); $gainWeekDay = date("w", $timestamp); $gainWeekAdd = date("w", $gainWeekDay) == 1 ? 0 : 1 - $gainWeekDay; $gainMonday = date("Y-m-d 00:00:00", strtotime("$gainWeekAdd days", $timestamp)); $nowMonday = date('Y-m-d 00:00:00', strtotime('this week Monday')); $interval = (new \DateTime(date($gainMonday)))->diff(new \DateTime($nowMonday)); $weekCut = $interval->days / 7; if (strtotime($periodJson['gain_datetime']) < time() && $weekCut > 0) { $weekCut = -$weekCut; } if ($val < 1) { if ($now_nbr == 1) { $params['coupon_detail_gain_datetime'] = $gainMonday; $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($gainMonday . "+6 days")); } else { $now_nbr -= 1; $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d 00:00:00', strtotime('this week Monday')) . "+" . ($now_nbr + $weekCut) . ' week')); $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d 23:59:59', strtotime('this week Sunday')) . "+" . ($now_nbr + $weekCut) . ' week')); } } else { if ($now_nbr == 1) { $params['coupon_detail_gain_datetime'] = $gainMonday; $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d 23:59:59', strtotime('this week Sunday')) . "+" . ($val + $weekCut) . ' week')); } else { $now_nbr -= 1; $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d 00:00:00', strtotime('this week Monday')) . "+" . ((($val + 1) * $now_nbr) + $weekCut) . ' week')); $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d 23:59:59', strtotime('this week Sunday')) . "+" . ((($val + 1) * $now_nbr) + $val + $weekCut) . ' week')); } } } elseif ($periodJson['unit'] == 'month') { $val = $periodJson['val'] - 1; // 选的日期的1号距离今月1号是几个月 $interval = (new \DateTime(date('Y-m-02 00:00:00', strtotime($periodJson['gain_datetime']))))->diff(new \DateTime(date('Y-m-02 00:00:00'))); $monthCut = $interval->m + ($interval->y * 12); if (strtotime($periodJson['gain_datetime']) < time() && $monthCut > 0) { $monthCut = -$monthCut; } if ($val < 1) { if ($now_nbr == 1) { $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime($periodJson['gain_datetime'])); $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime($periodJson['gain_datetime'])); } else { $now_nbr -= 1; $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime(date('Y-m-01 00:00:00') . "+" . ($now_nbr + $monthCut) . ' month')); $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime(date('Y-m-01 00:00:00') . "+" . ($now_nbr + $monthCut) . ' month')); } } else { if ($now_nbr == 1) { $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime($periodJson['gain_datetime'])); $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime(date('Y-m-01 00:00:00') . "+" . ($val + $monthCut) . ' month')); } else { $now_nbr -= 1; $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime(date('Y-m-01 00:00:00') . "+" . ((($val + 1) * $now_nbr) + $monthCut) . ' month')); $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime(date('Y-m-01 00:00:00') . "+" . ((($val + 1) * $now_nbr) + $val + $monthCut) . ' month')); } } } return $params; } public static function customSendService($chooseCoupons, $couponUseMember, $memberList, $condition) { if ($couponUseMember == 'condition') { if ($condition == 'is_employ') { $memberList = Member::where('member_classify', 'EMPLOY')->pluck('member_id')->toArray(); } elseif ($condition == 'is_member') { $memberList = Member::where('member_classify', 'MEMBER')->pluck('member_id')->toArray(); } elseif ($condition == 'is_vip') { $memberList = Member::where('member_is_vip', 'Y')->pluck('member_id')->toArray(); } } $couponNbr = []; Db::beginTransaction(); try { $couponIds = array_column($chooseCoupons, 'id'); $coupons = Coupon::whereIn('coupon_id', $couponIds)->get()->toArray(); foreach ($coupons as $coupon) { foreach ($chooseCoupons as $chooseCoupon) { if ($chooseCoupon['id'] == $coupon['coupon_id']) { if (empty($chooseCoupon['gain_datetime'])) { $chooseCoupon['gain_datetime'] = date('Y-m-d H:i:s'); } $params['coupon_id'] = $coupon['coupon_id']; $params['coupon_detail_gain_datetime'] = date('Y-m-d H:i:s', strtotime($chooseCoupon['gain_datetime'])); if (($coupon['coupon_validdate_day'] == 0 || $coupon['coupon_validdate_day'] == '') && !empty($coupon['coupon_validdate_end'])) { $params['coupon_detail_deadline_datetime'] = $coupon['coupon_validdate_end']; } elseif ($coupon['coupon_validdate_day'] > 0) { $endUnix = strtotime($chooseCoupon['gain_datetime']); $params['coupon_detail_deadline_datetime'] = date('Y-m-d H:i:s', $endUnix + ($coupon['coupon_validdate_day'] * 24 * 3600) - 1); } foreach ($memberList as $item) { $params['member_id'] = $item; if ($coupon['coupon_is_period'] == 'Y') { // if (CouponDetail::where('join_coupon_detail_member_id', $item)->where('join_detail_coupon_id', $coupon['coupon_id'])->exists()) { // throw new BusinessException("请勿重复发放周期券"); // } $params['coupon_detail_period_num'] = 1; $periodJson = json_decode($coupon['coupon_period_json'], true); // for ($i=0;$i<$periodJson['nbr'];$i++){ CouponDetailService::sendPeriodCoupon($params); // } continue; } if ($chooseCoupon['nbr'] > 0) { // 有发行数量 if ($coupon['coupon_number'] != 0) { // 查询还有多少张没领的 $count = CouponDetail::where('join_detail_coupon_id', $coupon['coupon_id']) ->whereIn('coupon_detail_status', ['INIT', 'PENDING']) ->count(); if (!isset($couponNbr[$coupon['coupon_id']])) { $couponNbr[$coupon['coupon_id']] = $count; } if ($couponNbr[$coupon['coupon_id']] - $chooseCoupon['nbr'] < 0) { throw new BusinessException($coupon['coupon_name'] . "超出发行数量"); } $couponNbr[$coupon['coupon_id']] = $couponNbr[$coupon['coupon_id']] - $chooseCoupon['nbr']; $params['chooseCouponNbr'] = $chooseCoupon['nbr']; // 匹配已发行的优惠券 CouponDetailService::customSendCouponHave($params); } else { for ($i = 0; $i < $chooseCoupon['nbr']; $i++) { CouponDetailService::customSendCoupon($params); } } } } } } } Db::commit(); } catch (BusinessException $e) { Db::rollBack(); Log::error('优惠券发放失败', ['msg' => $e->getMessage()]); throw new BusinessException($e->getMessage()); } catch (\Exception $e) { Db::rollBack(); Log::error('优惠券发放失败', ['msg' => $e->getMessage()]); throw new BusinessException('优惠券发放失败'); } } /** * @Desc 把指定账户的优惠券加到另一个账户 * @Author Gorden * @Date 2024/11/7 16:33 * * @param $originMemberId * @param $memberId * @return void */ public static function transCoupon($originMemberId, $memberId) { $details = CouponDetail::where('join_coupon_detail_member_id', $originMemberId) ->where('coupon_detail_status', 'ACTIVED') ->get() ->toArray(); foreach ($details as $detail) { $detailModel = new CouponDetail(); $detailModel->coupon_detail_id = 'CUDT' . date('ymdHi').random_string(4,'up'); $detailModel->join_detail_coupon_id = $detail['join_detail_coupon_id']; $detailModel->join_coupon_detail_member_id = $memberId; $detailModel->coupon_detail_status = $detail['coupon_detail_status']; $detailModel->coupon_detail_deadline_datetime = $detail['coupon_detail_deadline_datetime']; $detailModel->coupon_detail_gain_datetime = date('Y-m-d H:i:s'); $detailModel->coupon_detail_extend_json = $detail['coupon_detail_extend_json']; $detailModel->coupon_detail_addtimes = time(); $detailModel->save(); } } }