LuckPrizeServices.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\services\activity\lottery;
  13. use app\services\BaseServices;
  14. use app\dao\activity\lottery\LuckPrizeDao;
  15. use app\services\activity\coupon\StoreCouponIssueServices;
  16. use crmeb\services\CacheService;
  17. use think\exception\ValidateException;
  18. /**
  19. *
  20. * Class LuckPrizeServices
  21. * @package app\services\activity\lottery
  22. * @mixin LuckPrizeDao
  23. */
  24. class LuckPrizeServices extends BaseServices
  25. {
  26. /**
  27. * @var array 1:未中奖2:积分3:余额4:红包5:优惠券6:站内商品7:等级经验8:用户等级 9:svip天数
  28. */
  29. public $prize_type = [
  30. '1' => '未中奖',
  31. '2' => '积分',
  32. '3' => '余额',
  33. '4' => '红包',
  34. '5' => '优惠券',
  35. '6' => '站内商品',
  36. '7' => '等级经验',
  37. '8' => '用户等级',
  38. '9' => 'svip天数'
  39. ];
  40. /**
  41. * 奖品数据字段
  42. * @var array
  43. */
  44. public $prize = [
  45. 'id' => 0,
  46. 'type' => 1,
  47. 'lottery_id' => 0,
  48. 'name' => '',
  49. 'prompt' => '',
  50. 'image' => '',
  51. 'chance' => 0,
  52. 'total' => 0,
  53. 'coupon_id' => 0,
  54. 'product_id' => 0,
  55. 'unique' => '',
  56. 'num' => 1,
  57. 'sort' => 0,
  58. 'status' => 1,
  59. 'is_del' => 0,
  60. 'add_time' => 0,
  61. ];
  62. /**
  63. * LuckPrizeServices constructor.
  64. * @param LuckPrizeDao $dao
  65. */
  66. public function __construct(LuckPrizeDao $dao)
  67. {
  68. $this->dao = $dao;
  69. }
  70. /**
  71. * 奖品数据验证
  72. * @param array $data
  73. * @return array
  74. */
  75. public function checkPrizeData(array $data)
  76. {
  77. $data = array_merge($this->prize, array_intersect_key($data, $this->prize));
  78. if (!isset($data['name']) || !$data['name']) {
  79. throw new ValidateException('请填写奖品名称');
  80. }
  81. if (!isset($data['image']) || !$data['image']) {
  82. throw new ValidateException('请选择奖品图片');
  83. }
  84. if (!isset($data['chance'])) {
  85. throw new ValidateException('请填写奖品中奖权重');
  86. }
  87. if (!isset($data['type']) || !isset($this->prize_type[$data['type']])) {
  88. throw new ValidateException('请选择奖品类型');
  89. }
  90. if (in_array($data['type'], [2, 3, 4]) && (!isset($data['num']) || !$data['num'])) {
  91. $msg = '';
  92. switch ($data['type']) {
  93. case 2:
  94. $msg = '积分';
  95. break;
  96. case 3:
  97. $msg = '余额';
  98. break;
  99. case 4:
  100. $msg = '红包';
  101. break;
  102. }
  103. throw new ValidateException('请填写奖品赠送' . $msg . '数');
  104. }
  105. if ($data['type'] == 2) {
  106. $data['num'] = (int)$data['num'];
  107. }
  108. if ($data['type'] == 5 && (!isset($data['coupon_id']) || !$data['coupon_id'])) {
  109. throw new ValidateException('请选择优惠券');
  110. }
  111. if ($data['type'] == 6 && (!isset($data['product_id']) || !$data['product_id'])) {
  112. throw new ValidateException('请选择商品');
  113. }
  114. return $data;
  115. }
  116. /**
  117. * 修改奖品
  118. * @param int $id
  119. * @param array $data
  120. * @return bool
  121. * @throws \think\db\exception\DataNotFoundException
  122. * @throws \think\db\exception\DbException
  123. * @throws \think\db\exception\ModelNotFoundException
  124. */
  125. public function edit(int $id, array $data)
  126. {
  127. $this->checkPrizeData($data);
  128. $prize = $this->dao->get($id);
  129. if (!$prize) {
  130. throw new ValidateException('奖品不存在');
  131. }
  132. if (!$this->dao->update($id, $data, 'id')) {
  133. throw new ValidateException('修改失败');
  134. }
  135. return true;
  136. }
  137. /**
  138. * 获取某个抽奖活动的所有奖品
  139. * @param int $lottery_id
  140. * @param string $field
  141. * @return array
  142. * @throws \think\db\exception\DataNotFoundException
  143. * @throws \think\db\exception\DbException
  144. * @throws \think\db\exception\ModelNotFoundException
  145. */
  146. public function getLotteryPrizeList(int $lottery_id, string $field = '*')
  147. {
  148. return $this->dao->getPrizeList($lottery_id, $field);
  149. }
  150. /**
  151. * 随机奖品
  152. * @param array $data
  153. * @return array|mixed
  154. */
  155. public function getLuckPrize(array $data)
  156. {
  157. $prize = [];
  158. if (!$data) return $prize;
  159. $coupon = [];
  160. $coupon_ids = array_unique(array_column($data, 'coupon_id'));
  161. if ($coupon_ids) {
  162. /** @var StoreCouponIssueServices $couponServices */
  163. $couponServices = app()->make(StoreCouponIssueServices::class);
  164. $coupon = $couponServices->getGiveCoupon([['id', 'IN', $coupon_ids]]);
  165. if ($coupon) $coupon = array_combine(array_column($coupon, 'id'), $coupon);
  166. }
  167. $totalChance = (int)array_sum(array_column($data, 'chance'));
  168. if (!$totalChance) return $prize;
  169. $startChance = 0;
  170. mt_srand();
  171. $prizeChance = rand(0, $totalChance - 1);
  172. $newPrize = array_combine(array_column($data, 'type'), $data);
  173. foreach ($data as $item) {
  174. $newStartChance = (int)bcadd((string)$item['chance'], (string)$startChance);
  175. //随机数在这个基数端内 且该商品数量大于0 中奖
  176. if ($prizeChance >= $startChance && $prizeChance < $newStartChance) {
  177. //奖品权重<=0 || 随机到不是未中奖奖品-》设置了奖品数量-》数量不足时 返回未中奖奖品 || 抽到优惠券 数量不足
  178. if ((int)$item['chance'] <= 0 ||
  179. (
  180. $item['type'] != 1 &&
  181. $item['total'] != -1 &&
  182. $item['total'] <= 0 &&
  183. CacheService::popStock((string)$item['id'], 1, 6)
  184. )
  185. ||
  186. (
  187. $item['coupon_id'] &&
  188. $coupon &&
  189. !isset($coupon[$item['coupon_id']])
  190. )
  191. ) {
  192. $prize = $newPrize[1] ?? [];
  193. } else {
  194. $prize = $item;
  195. }
  196. break;
  197. }
  198. $startChance = $newStartChance;
  199. }
  200. return $prize;
  201. }
  202. /**
  203. * 中奖后减少奖品数量
  204. * @param int $id
  205. * @param array $prize
  206. * @return bool
  207. * @throws \think\db\exception\DataNotFoundException
  208. * @throws \think\db\exception\DbException
  209. * @throws \think\db\exception\ModelNotFoundException
  210. */
  211. public function decPrizeNum(int $id, array $prize = [])
  212. {
  213. if (!$id) return false;
  214. if (!$prize) {
  215. $prize = $this->dao->get($id);
  216. }
  217. if (!$prize) {
  218. throw new ValidateException('该奖品不存在');
  219. }
  220. //不是未中奖奖品 减少奖品数量
  221. if ($prize['type'] != 1 && $prize['total'] >= 1) {
  222. $total = $prize['total'] - 1;
  223. if (!$this->dao->update($id, ['total' => $total], 'id')) {
  224. throw new ValidateException('抽奖减少奖品总数失败');
  225. }
  226. }
  227. return true;
  228. }
  229. }