LotteryRecordService.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. <?php
  2. namespace app\common\Service\Lottery;
  3. use app\common\model\lottery\LotteryDrawRecord;
  4. use app\common\model\lottery\LotteryWinRecord;
  5. use app\common\model\lottery\LotteryPrize;
  6. use app\common\Enum\LotteryEnum;
  7. use think\Exception;
  8. use app\common\model\lottery\LotteryActivity;
  9. /**
  10. * 抽奖记录服务类
  11. * 专门处理抽奖记录和中奖记录的业务逻辑
  12. */
  13. class LotteryRecordService
  14. {
  15. // ============ 抽奖记录相关方法 ============
  16. /**
  17. * 创建抽奖记录
  18. */
  19. public static function createDrawRecord($activityId, $userId, $prizeId, $isWin, $triggerType, $triggerOrderId = null, $triggerAmount = null, $winInfo = [])
  20. {
  21. $data = [
  22. 'activity_id' => $activityId,
  23. 'user_id' => $userId,
  24. 'prize_id' => $prizeId,
  25. 'is_win' => $isWin ? 1 : 0,
  26. 'trigger_type' => $triggerType,
  27. 'trigger_order_id' => $triggerOrderId,
  28. 'trigger_amount' => $triggerAmount,
  29. 'win_info' => $winInfo ? json_encode($winInfo) : '',
  30. 'draw_ip' => request()->ip(),
  31. 'draw_time' => time(),
  32. 'device_info' => request()->header('user-agent', '')
  33. ];
  34. return LotteryDrawRecord::create($data);
  35. }
  36. /**
  37. * 获取用户抽奖次数
  38. */
  39. public static function getUserDrawCount($activityId, $userId, $timeRange = null)
  40. {
  41. $query = LotteryDrawRecord::where('activity_id', $activityId)
  42. ->where('user_id', $userId);
  43. if ($timeRange) {
  44. if (isset($timeRange['start'])) {
  45. $query->where('draw_time', '>=', $timeRange['start']);
  46. }
  47. if (isset($timeRange['end'])) {
  48. $query->where('draw_time', '<=', $timeRange['end']);
  49. }
  50. }
  51. return $query->count();
  52. }
  53. /**
  54. * 获取用户中奖次数
  55. */
  56. public static function getUserWinCount($activityId, $userId, $timeRange = null)
  57. {
  58. $query = LotteryDrawRecord::where('activity_id', $activityId)
  59. ->where('user_id', $userId)
  60. ->where('is_win', 1);
  61. if ($timeRange) {
  62. if (isset($timeRange['start'])) {
  63. $query->where('draw_time', '>=', $timeRange['start']);
  64. }
  65. if (isset($timeRange['end'])) {
  66. $query->where('draw_time', '<=', $timeRange['end']);
  67. }
  68. }
  69. return $query->count();
  70. }
  71. /**
  72. * 获取活动抽奖统计
  73. */
  74. public static function getActivityDrawStats($activityId, $timeRange = null)
  75. {
  76. $query = LotteryDrawRecord::where('activity_id', $activityId);
  77. if ($timeRange) {
  78. if (isset($timeRange['start'])) {
  79. $query->where('draw_time', '>=', $timeRange['start']);
  80. }
  81. if (isset($timeRange['end'])) {
  82. $query->where('draw_time', '<=', $timeRange['end']);
  83. }
  84. }
  85. return [
  86. 'total_draw' => $query->count(),
  87. 'total_win' => $query->where('is_win', 1)->count(),
  88. 'total_people' => $query->distinct('user_id')->count()
  89. ];
  90. }
  91. /**
  92. * 获取用户抽奖记录列表
  93. */
  94. public static function getUserDrawRecords($userId = 0, $activityId = null,$status = 0, $page = 1, $pageSize = 20)
  95. {
  96. $query = LotteryDrawRecord::where('user_id', $userId);
  97. if ($activityId) {
  98. $query->where('activity_id', $activityId);
  99. }
  100. if ($status) {
  101. $query->where('status', $status);
  102. }
  103. // 1. 先分页查询抽奖记录
  104. $records = $query->field('id,activity_id,user_id,prize_id,is_win,trigger_type,trigger_order_id,trigger_amount,
  105. draw_time,status')
  106. ->order('draw_time', 'desc')
  107. ->paginate($pageSize, false, ['page' => $page]);
  108. if (empty($records) || $records->isEmpty()) {
  109. return $records;
  110. }
  111. // 2. 收集关联ID
  112. $activityIds = [];
  113. $prizeIds = [];
  114. $drawRecordIds = [];
  115. foreach ($records as $record) {
  116. $activityIds[] = $record->activity_id;
  117. $prizeIds[] = $record->prize_id;
  118. if ($record->is_win) {
  119. $drawRecordIds[] = $record->id;
  120. }
  121. }
  122. // 去重
  123. $activityIds = array_unique($activityIds);
  124. $prizeIds = array_unique($prizeIds);
  125. $drawRecordIds = array_unique($drawRecordIds);
  126. // 3. 批量查询关联数据
  127. $activities = [];
  128. if (!empty($activityIds)) {
  129. $activityList = LotteryActivity::whereIn('id', $activityIds)
  130. ->field('id,name,status,lottery_type,lottery_time')
  131. ->select();
  132. foreach ($activityList as $activity) {
  133. $activities[$activity->id] = $activity;
  134. }
  135. }
  136. $prizes = [];
  137. if (!empty($prizeIds)) {
  138. $prizeList = LotteryPrize::whereIn('id', $prizeIds)
  139. ->field('id,name,image,activity_id,type')
  140. ->select();
  141. foreach ($prizeList as $prize) {
  142. $prizes[$prize->id] = $prize;
  143. }
  144. }
  145. $winRecords = [];
  146. if (!empty($drawRecordIds)) {
  147. $winRecordList = LotteryWinRecord::whereIn('draw_record_id', $drawRecordIds)
  148. ->field('id,draw_record_id,deliver_status,deliver_time,exchange_code,receiver_name,receiver_mobile,receiver_address,express_company,express_number,exchange_code')
  149. ->select();
  150. foreach ($winRecordList as $winRecord) {
  151. $winRecords[$winRecord->draw_record_id] = $winRecord;
  152. }
  153. }
  154. // 4. 将关联数据作为字段附加到记录中
  155. foreach ($records as $record) {
  156. // 附加活动信息字段
  157. $activity = $activities[$record->activity_id] ?? null;
  158. $record->activity_name = $activity ? $activity->name : '';
  159. $record->activity_status = $activity ? $activity->status : 0;
  160. $record->activity_lottery_type = $activity ? $activity->lottery_type : 0;
  161. $record->activity_lottery_time = $activity ? $activity->lottery_time : 0;
  162. // 附加奖品信息字段
  163. $prize = $prizes[$record->prize_id] ?? null;
  164. $record->prize_name = $prize ? $prize->name : '';
  165. $record->prize_image = $prize ? cdnurl($prize->image) : '';
  166. $record->prize_type = $prize ? $prize->type : 0;
  167. // 附加中奖记录信息字段(仅限中奖记录)
  168. if ($record->is_win) {
  169. $winRecord = $winRecords[$record->id] ?? null;
  170. $record->win_record_id = $winRecord ? $winRecord->id : 0;
  171. $record->deliver_status = $winRecord ? $winRecord->deliver_status : 0;
  172. $record->deliver_time = $winRecord ? $winRecord->deliver_time : 0;
  173. $record->exchange_code = $winRecord ? $winRecord->exchange_code : '';
  174. $record->receiver_name = $winRecord ? $winRecord->receiver_name : '';
  175. $record->receiver_mobile = $winRecord ? $winRecord->receiver_mobile : '';
  176. $record->receiver_address = $winRecord ? $winRecord->receiver_address : '';
  177. $record->express_company = $winRecord ? $winRecord->express_company : '';
  178. $record->express_number = $winRecord ? $winRecord->express_number : '';
  179. } else {
  180. $record->win_record_id = 0;
  181. $record->deliver_status = 0;
  182. $record->deliver_time = 0;
  183. $record->exchange_code = '';
  184. $record->receiver_name = '';
  185. $record->receiver_mobile = '';
  186. $record->receiver_address = '';
  187. $record->express_company = '';
  188. $record->express_number = '';
  189. }
  190. // 添加触发类型文本
  191. $record->trigger_type_text = LotteryEnum::getTriggerTypeMap($record->trigger_type);
  192. }
  193. return $records;
  194. }
  195. /**
  196. * 获取活动抽奖记录列表
  197. */
  198. public static function getActivityDrawRecords($activityId, $page = 1, $limit = 20, $filters = [])
  199. {
  200. $query = LotteryDrawRecord::where('activity_id', $activityId);
  201. // 应用过滤器
  202. if (isset($filters['is_win'])) {
  203. $query->where('is_win', $filters['is_win']);
  204. }
  205. if (isset($filters['trigger_type'])) {
  206. $query->where('trigger_type', $filters['trigger_type']);
  207. }
  208. if (isset($filters['start_time'])) {
  209. $query->where('draw_time', '>=', $filters['start_time']);
  210. }
  211. if (isset($filters['end_time'])) {
  212. $query->where('draw_time', '<=', $filters['end_time']);
  213. }
  214. return $query->with(['user', 'prize', 'winRecord'])
  215. ->order('draw_time', 'desc')
  216. ->page($page, $limit)
  217. ->select();
  218. }
  219. /**
  220. * 获取抽奖记录详情
  221. *
  222. * @param int $drawRecordId 抽奖记录ID
  223. * @param int $userId 用户ID(可选,用于验证权限)
  224. * @return LotteryDrawRecord|null 抽奖记录详情,包含关联信息
  225. */
  226. public static function getDrawRecordDetail($drawRecordId, $userId = 0)
  227. {
  228. // 1. 查询抽奖记录基础信息
  229. $query = LotteryDrawRecord::where('id', $drawRecordId);
  230. // 如果指定了用户ID,则验证权限
  231. if ($userId) {
  232. $query->where('user_id', $userId);
  233. }
  234. $record = $query->field('id,activity_id,user_id,prize_id,is_win,trigger_type,trigger_order_id,
  235. trigger_amount,draw_time,remark,status,createtime')
  236. ->find();
  237. if (!$record) {
  238. return null;
  239. }
  240. // 2. 查询关联的活动信息
  241. $activity = LotteryActivity::where('id', $record->activity_id)
  242. ->field('id,name,type,status,lottery_type,lottery_time')
  243. ->find();
  244. // 3. 查询关联的奖品信息
  245. $prize = null;
  246. if ($record->prize_id > 0) {
  247. $prize = LotteryPrize::where('id', $record->prize_id)
  248. ->field('id,name,image,type')
  249. ->find();
  250. }
  251. // 4. 查询关联的中奖记录信息(仅限中奖记录)
  252. $winRecord = null;
  253. if ($record->is_win) {
  254. $winRecord = LotteryWinRecord::where('draw_record_id', $record->id)
  255. ->field('id,draw_record_id,prize_name,prize_type,deliver_status,
  256. deliver_time,receiver_name,receiver_mobile,receiver_address,
  257. express_company,express_number,exchange_code,code_used_time')
  258. ->find();
  259. }
  260. // 5. 将关联数据作为字段附加到记录中
  261. // 附加活动信息字段
  262. $record->activity_name = $activity ? $activity->name : '';
  263. $record->activity_type = $activity ? $activity->type : 0;
  264. $record->activity_status = $activity ? $activity->status : 0;
  265. $record->activity_lottery_type = $activity ? $activity->lottery_type : 0;
  266. $record->activity_lottery_time = $activity ? $activity->lottery_time : 0;
  267. // 附加奖品信息字段
  268. $record->prize_name = $prize ? $prize->name : '';
  269. $record->prize_image = $prize ? cdnurl($prize->image) : '';
  270. $record->prize_type = $prize ? $prize->type : 0;
  271. // 附加中奖记录信息字段
  272. if ($winRecord) {
  273. $record->win_record_id = $winRecord->id;
  274. $record->win_prize_name = $winRecord->prize_name;
  275. $record->win_prize_type = $winRecord->prize_type;
  276. $record->deliver_status = $winRecord->deliver_status;
  277. $record->deliver_time = $winRecord->deliver_time;
  278. $record->receiver_name = $winRecord->receiver_name;
  279. $record->receiver_mobile = $winRecord->receiver_mobile;
  280. $record->receiver_address = $winRecord->receiver_address;
  281. $record->express_company = $winRecord->express_company;
  282. $record->express_number = $winRecord->express_number;
  283. $record->exchange_code = $winRecord->exchange_code;
  284. $record->code_used_time = $winRecord->code_used_time;
  285. } else {
  286. $record->win_record_id = 0;
  287. $record->win_prize_name = '';
  288. $record->win_prize_type = 0;
  289. $record->deliver_status = 0;
  290. $record->deliver_time = 0;
  291. $record->receiver_name = '';
  292. $record->receiver_mobile = '';
  293. $record->receiver_address = '';
  294. $record->express_company = '';
  295. $record->express_number = '';
  296. $record->exchange_code = '';
  297. $record->code_used_time = 0;
  298. }
  299. return $record;
  300. }
  301. /**
  302. * 检查用户是否已为指定订单抽奖
  303. */
  304. public static function hasUserDrawnForOrder($activityId, $userId, $orderId)
  305. {
  306. return LotteryDrawRecord::where('activity_id', $activityId)
  307. ->where('user_id', $userId)
  308. ->where('trigger_order_id', $orderId)
  309. ->count() > 0;
  310. }
  311. /**
  312. * 获取用户抽奖历史统计
  313. */
  314. public static function getUserDrawHistoryStats($userId)
  315. {
  316. $stats = LotteryDrawRecord::where('user_id', $userId)
  317. ->field([
  318. 'COUNT(*) as total_draws',
  319. 'SUM(is_win) as total_wins',
  320. 'COUNT(DISTINCT activity_id) as total_activities'
  321. ])
  322. ->find();
  323. return [
  324. 'total_draws' => $stats['total_draws'] ?? 0,
  325. 'total_wins' => $stats['total_wins'] ?? 0,
  326. 'total_activities' => $stats['total_activities'] ?? 0,
  327. 'win_rate' => $stats['total_draws'] > 0 ?
  328. round(($stats['total_wins'] / $stats['total_draws']) * 100, 2) : 0
  329. ];
  330. }
  331. /**
  332. * 获取活动抽奖排行榜
  333. */
  334. public static function getActivityDrawRanking($activityId, $limit = 50)
  335. {
  336. return LotteryDrawRecord::where('activity_id', $activityId)
  337. ->field('user_id, COUNT(*) as draw_count, SUM(is_win) as win_count')
  338. ->with('user')
  339. ->group('user_id')
  340. ->order('draw_count desc, win_count desc')
  341. ->limit($limit)
  342. ->select();
  343. }
  344. /**
  345. * 获取活动抽奖时间分布统计
  346. */
  347. public static function getActivityDrawTimeDistribution($activityId, $dateRange = null)
  348. {
  349. $query = LotteryDrawRecord::where('activity_id', $activityId);
  350. if ($dateRange) {
  351. if (isset($dateRange['start'])) {
  352. $query->where('draw_time', '>=', $dateRange['start']);
  353. }
  354. if (isset($dateRange['end'])) {
  355. $query->where('draw_time', '<=', $dateRange['end']);
  356. }
  357. }
  358. return $query->field('DATE(FROM_UNIXTIME(draw_time)) as date, COUNT(*) as draw_count, SUM(is_win) as win_count')
  359. ->group('date')
  360. ->order('date asc')
  361. ->select();
  362. }
  363. // ============ 中奖记录相关方法 ============
  364. /**
  365. * 创建中奖记录
  366. */
  367. public static function createWinRecord($drawRecordId, $activityId, $userId, $prizeId, $prizeName, $prizeType, $prizeValue = [])
  368. {
  369. $data = [
  370. 'draw_record_id' => $drawRecordId,
  371. 'activity_id' => $activityId,
  372. 'user_id' => $userId,
  373. 'prize_id' => $prizeId,
  374. 'prize_name' => $prizeName,
  375. 'prize_type' => $prizeType,
  376. 'prize_value' => is_array($prizeValue) ? json_encode($prizeValue) : $prizeValue,
  377. 'deliver_status' => LotteryEnum::DELIVER_STATUS_PENDING
  378. ];
  379. return LotteryWinRecord::create($data);
  380. }
  381. /**
  382. * 标记中奖记录为发放成功
  383. */
  384. public static function markWinRecordAsDelivered(LotteryWinRecord $winRecord, $deliverInfo = [])
  385. {
  386. $winRecord->deliver_status = LotteryEnum::DELIVER_STATUS_SUCCESS;
  387. $winRecord->deliver_time = time();
  388. if ($deliverInfo) {
  389. $winRecord->deliver_info = json_encode($deliverInfo);
  390. }
  391. return $winRecord->save();
  392. }
  393. /**
  394. * 标记中奖记录为发放失败
  395. */
  396. public static function markWinRecordAsFailed(LotteryWinRecord $winRecord, $reason = '')
  397. {
  398. $winRecord->deliver_status = LotteryEnum::DELIVER_STATUS_FAILED;
  399. $winRecord->fail_reason = $reason;
  400. return $winRecord->save();
  401. }
  402. /**
  403. * 设置中奖记录收货地址
  404. */
  405. public static function setWinRecordDeliveryAddress(LotteryWinRecord $winRecord, $name, $mobile, $address)
  406. {
  407. $winRecord->receiver_name = $name;
  408. $winRecord->receiver_mobile = $mobile;
  409. $winRecord->receiver_address = $address;
  410. return $winRecord->save();
  411. }
  412. /**
  413. * 设置中奖记录快递信息
  414. */
  415. public static function setWinRecordExpressInfo(LotteryWinRecord $winRecord, $company, $number)
  416. {
  417. $winRecord->express_company = $company;
  418. $winRecord->express_number = $number;
  419. return $winRecord->save();
  420. }
  421. /**
  422. * 设置中奖记录兑换码
  423. */
  424. public static function setWinRecordExchangeCode(LotteryWinRecord $winRecord, $code)
  425. {
  426. $winRecord->exchange_code = $code;
  427. return $winRecord->save();
  428. }
  429. /**
  430. * 标记中奖记录兑换码已使用
  431. */
  432. public static function markWinRecordCodeUsed(LotteryWinRecord $winRecord)
  433. {
  434. $winRecord->code_used_time = time();
  435. return $winRecord->save();
  436. }
  437. /**
  438. * 获取待发放的中奖记录
  439. */
  440. public static function getPendingWinRecords($limit = 100)
  441. {
  442. return LotteryWinRecord::where('deliver_status', LotteryEnum::DELIVER_STATUS_PENDING)
  443. ->order('createtime', 'asc')
  444. ->limit($limit)
  445. ->select();
  446. }
  447. /**
  448. * 获取用户中奖记录
  449. */
  450. public static function getUserWinRecords($userId, $page = 1, $limit = 20)
  451. {
  452. return LotteryWinRecord::where('user_id', $userId)
  453. ->with(['activity', 'prize'])
  454. ->order('createtime', 'desc')
  455. ->page($page, $limit)
  456. ->select();
  457. }
  458. /**
  459. * 获取活动中奖统计
  460. */
  461. public static function getActivityWinStats($activityId)
  462. {
  463. return [
  464. 'total_win' => LotteryWinRecord::where('activity_id', $activityId)->count(),
  465. 'delivered' => LotteryWinRecord::where('activity_id', $activityId)
  466. ->where('deliver_status', LotteryEnum::DELIVER_STATUS_SUCCESS)
  467. ->count(),
  468. 'pending' => LotteryWinRecord::where('activity_id', $activityId)
  469. ->where('deliver_status', LotteryEnum::DELIVER_STATUS_PENDING)
  470. ->count(),
  471. 'failed' => LotteryWinRecord::where('activity_id', $activityId)
  472. ->where('deliver_status', LotteryEnum::DELIVER_STATUS_FAILED)
  473. ->count()
  474. ];
  475. }
  476. /**
  477. * 批量处理待发放的中奖记录
  478. */
  479. public static function batchProcessPendingWinRecords($limit = 50)
  480. {
  481. $pendingRecords = static::getPendingWinRecords($limit);
  482. $processedCount = 0;
  483. foreach ($pendingRecords as $winRecord) {
  484. try {
  485. $prize = LotteryPrize::find($winRecord->prize_id);
  486. if ($prize && $prize->deliver_type == LotteryEnum::DELIVER_TYPE_AUTO) {
  487. static::autoDeliverPrize($winRecord, $prize);
  488. $processedCount++;
  489. }
  490. } catch (Exception $e) {
  491. static::markWinRecordAsFailed($winRecord, $e->getMessage());
  492. trace('自动发放奖品失败: ' . $e->getMessage(), 'error');
  493. }
  494. }
  495. return $processedCount;
  496. }
  497. /**
  498. * 手动发放奖品(管理员操作)
  499. */
  500. public static function manualDeliverPrize($winRecordId, $deliverInfo = [], $adminId = 0)
  501. {
  502. $winRecord = LotteryWinRecord::find($winRecordId);
  503. if (!$winRecord) {
  504. throw new Exception('中奖记录不存在');
  505. }
  506. if ($winRecord->deliver_status != LotteryEnum::DELIVER_STATUS_PENDING) {
  507. throw new Exception('该记录已处理,无法重复发放');
  508. }
  509. $deliverInfo['admin_id'] = $adminId;
  510. $deliverInfo['manual_deliver_time'] = time();
  511. return static::markWinRecordAsDelivered($winRecord, $deliverInfo);
  512. }
  513. /**
  514. * 取消中奖记录
  515. */
  516. public static function cancelWinRecord($winRecordId, $reason = '', $adminId = 0)
  517. {
  518. $winRecord = LotteryWinRecord::find($winRecordId);
  519. if (!$winRecord) {
  520. throw new Exception('中奖记录不存在');
  521. }
  522. $winRecord->deliver_status = LotteryEnum::DELIVER_STATUS_CANCELLED;
  523. $winRecord->fail_reason = $reason;
  524. $winRecord->cancel_time = time();
  525. $winRecord->cancel_admin_id = $adminId;
  526. return $winRecord->save();
  527. }
  528. /**
  529. * 自动发放奖品
  530. */
  531. public static function autoDeliverPrize($winRecord, $prize)
  532. {
  533. try {
  534. switch ($prize->type) {
  535. case LotteryEnum::PRIZE_TYPE_COUPON:
  536. static::deliverCoupon($winRecord, $prize);
  537. break;
  538. case LotteryEnum::PRIZE_TYPE_REDPACK:
  539. static::deliverRedPacket($winRecord, $prize);
  540. break;
  541. case LotteryEnum::PRIZE_TYPE_CODE:
  542. static::deliverExchangeCode($winRecord, $prize);
  543. break;
  544. case LotteryEnum::PRIZE_TYPE_SHOP_GOODS:
  545. static::deliverGoods($winRecord, $prize);
  546. break;
  547. }
  548. } catch (Exception $e) {
  549. static::markWinRecordAsFailed($winRecord, $e->getMessage());
  550. }
  551. }
  552. /**
  553. * 发放优惠券
  554. */
  555. private static function deliverCoupon($winRecord, $prize)
  556. {
  557. // 这里调用优惠券发放接口
  558. // 示例代码,需要根据实际优惠券系统实现
  559. static::markWinRecordAsDelivered($winRecord, ['coupon_id' => $prize->coupon_id]);
  560. }
  561. /**
  562. * 发放红包
  563. */
  564. private static function deliverRedPacket($winRecord, $prize)
  565. {
  566. // 这里调用红包发放接口
  567. // 示例代码,需要根据实际红包系统实现
  568. static::markWinRecordAsDelivered($winRecord, ['amount' => $prize->amount]);
  569. }
  570. /**
  571. * 发放兑换码
  572. */
  573. private static function deliverExchangeCode($winRecord, $prize)
  574. {
  575. $code = LotteryService::getAvailableExchangeCode($prize);
  576. if ($code) {
  577. static::setWinRecordExchangeCode($winRecord, $code);
  578. LotteryService::markExchangeCodeUsed($prize, $code);
  579. static::markWinRecordAsDelivered($winRecord, ['exchange_code' => $code]);
  580. } else {
  581. throw new Exception('兑换码已用完');
  582. }
  583. }
  584. /**
  585. * 发放商城商品
  586. */
  587. private static function deliverGoods($winRecord, $prize)
  588. {
  589. // 这里可以自动加入购物车或创建订单
  590. // 示例代码,需要根据实际商城系统实现
  591. static::markWinRecordAsDelivered($winRecord, [
  592. 'goods_id' => $prize->goods_id,
  593. 'goods_sku_id' => $prize->goods_sku_id
  594. ]);
  595. }
  596. }