CustomCoupon.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php namespace App\Models;
  2. use App\Facades\Servers\Redis\RedisLock;
  3. use Illuminate\Database\Eloquent\Factories\HasFactory;
  4. use Illuminate\Database\Eloquent\Model;
  5. /**
  6. * 客户优惠券模型
  7. *
  8. */
  9. class CustomCoupon extends Model
  10. {
  11. use HasFactory;
  12. // 与模型关联的表名
  13. protected $table = 'custom_coupon';
  14. // 是否主动维护时间戳
  15. public $timestamps = false;
  16. // 定义时间戳字段名
  17. // const CREATED_AT = 'insert_time';
  18. // const UPDATED_AT = 'update_time';
  19. /**
  20. * 添加数据
  21. *
  22. */
  23. public function add($data)
  24. {
  25. // 时间
  26. $data['insert_time'] = time();
  27. $data['update_time'] = time();
  28. // 写入数据表
  29. $id = $this->query()->insertGetId($data);
  30. // 返回结果
  31. return $id;
  32. }
  33. /**
  34. * 添加数据
  35. *
  36. */
  37. public function edit($id,$data)
  38. {
  39. // 更新时间
  40. $data['update_time'] = time();
  41. // 写入数据表
  42. $result = $this->query()->where(['id'=>$id])->update($data);
  43. // 返回结果
  44. return $result;
  45. }
  46. /**
  47. * 获取优惠券
  48. *
  49. * @param int $id 客户优惠券ID(注意:不是优惠券的id)
  50. * @param int $uid 客户ID
  51. *
  52. */
  53. public function getCouponById($id,$uid)
  54. {
  55. // 返回结果
  56. if( !$id ) return [];
  57. // 查询条件
  58. $map = [['custom_coupon.id','=',$id],['custom_coupon.custom_uid','=',$uid],['custom_coupon.status','=',0]];
  59. // 查询优惠券
  60. $coupon = $this->query()->join('coupon','custom_coupon.coupon_id','=','coupon.id')->where($map)->first(['custom_coupon.id','coupon.id as coupon_id','coupon.name','coupon.type_id','coupon.rebate_type','coupon.std_pay','coupon.rebate','custom_coupon.status','custom_coupon.exp_time']);
  61. // 如果不存在优惠券
  62. if( !$coupon ) return [];
  63. // 转数组方便操作
  64. $coupon = $coupon->toArray();
  65. // 查询优惠券的商品范围
  66. $coupon['product_scope'] = $coupon['type_id'] == 1 ? (new CouponProduct())->getProducts($coupon['coupon_id']) : [];
  67. // 获取赠品信息
  68. $coupon['rebate_scope'] = $coupon['rebate_type'] == 3 ? (new CouponRebate())->getProductByCouponId($coupon['coupon_id']) : [];
  69. // 返回结果
  70. return $coupon;
  71. }
  72. /**
  73. * 是否已有优惠券
  74. *
  75. * @param array $couponIds 多个优惠券ID
  76. *
  77. */
  78. public function isHaveCoupon($couponIds,$uid)
  79. {
  80. // 查询优惠券
  81. $haveList = $this->query()->where([['custom_uid','=',$uid]])->whereIn('coupon_id',$couponIds)->pluck('id','coupon_id')->toArray();
  82. // 如果不存在优惠券
  83. if( !$haveList ) return [];
  84. // 返回结果
  85. return $haveList;
  86. }
  87. /**
  88. * 过期状态设置
  89. *
  90. */
  91. public function setStatusByExpire()
  92. {
  93. // 上锁
  94. if(RedisLock::lock('customcoupon::set::status::by::expire',1,30)){
  95. // 修改
  96. $result = $this->query()->where([['status','=',0],['exp_time','<=',time()]])->update(['status'=>3,'update_time'=>time()]);
  97. // 不管成功失败,都解锁
  98. RedisLock::unlock('customcoupon::set::status::by::expire',1);
  99. // 返回结果
  100. return $result;
  101. }
  102. }
  103. /**
  104. * 过期状态设置
  105. *
  106. */
  107. public function setStatusByCouponId($couponId,$status)
  108. {
  109. // 修改未使用以及暂停的为对应的状态,其他状态的保持不变
  110. return $this->query()->where([['coupon_id','=',$couponId]])->whereIn('status',[0,2])->update(['status'=>$status,'update_time'=>time()]);
  111. }
  112. /**
  113. * 获取优惠券扣减金额
  114. *
  115. */
  116. public function getRebatePrice($customCouponId,$uid,$productPrice){
  117. // 如果有优惠券
  118. if( !$customCouponId ) return ['is_used'=>0,'product_price'=>$productPrice,'rebate_product'=>[]];
  119. // 查询用户的指定优惠券
  120. $coupon = $this->getCouponById($customCouponId,$uid);
  121. // 如果有优惠券
  122. if( !$coupon ) return ['is_used'=>0,'product_price'=>$productPrice,'rebate_product'=>[]];
  123. // 总价格
  124. $totalPrice = 0;
  125. // 判断是否指定商品范围
  126. if( $coupon['product_scope'] ) {
  127. // 去重,避免重复计算
  128. $coupon['product_scope'] = array_values(array_unique($coupon['product_scope']));
  129. // 循环商品范围
  130. foreach ( $coupon['product_scope'] as $productId ) {
  131. // 如果在商品范围
  132. if( isset($productPrice[$productId]['price_total']) ) $totalPrice = $totalPrice + $productPrice[$productId]['price_total'];
  133. }
  134. }else{
  135. $totalPrice = array_sum(array_column($productPrice,'price_total'));
  136. }
  137. // 如果没有达标
  138. if( $coupon['std_pay'] > $totalPrice ) return ['is_used'=>0,'product_price'=>$productPrice,'rebate_product'=>[]];
  139. // 达标结果
  140. $rebatePrice = 0;
  141. // 满减 扣减金额
  142. if( $coupon['rebate_type'] == 1 ) $rebatePrice = (float) $coupon['rebate'];
  143. // 折扣 扣减金额
  144. if( $coupon['rebate_type'] == 2 ) $rebatePrice = (float) $totalPrice - ( $totalPrice * $coupon['rebate'] * 0.1);
  145. // 赠品 赠送产品
  146. if( $coupon['rebate_type'] == 3 ) {
  147. // 如果没有赠品范围
  148. if( !$coupon['rebate_scope'] ) return ['is_used'=>1,'product_price'=>$productPrice,'rebate_product'=>[]];
  149. // 返回结果
  150. $productList = (new Product())->getListByIds(array_column($coupon['rebate_scope'],'product_id'));
  151. // 返回赠品数据
  152. $rebateProduct = [];
  153. // 循环处理
  154. foreach ($coupon['rebate_scope'] as $scope) {
  155. foreach ($productList as $product) {
  156. // 如果商品ID相等
  157. if( $scope['product_id'] == $product['id'] ){
  158. // 产品ID
  159. $product['product_id'] = $product['id'];
  160. $product['buy_num'] = $scope['rebate_num'];
  161. $product['price_total'] = $scope['rebate_num'] * $product['price'];
  162. $product['pay_total'] = 0;
  163. $product['coupon_total']= $product['price_total'];
  164. // 写入到赠品中
  165. $rebateProduct[$product['business_id']][$product['product_id']] = $product;
  166. }
  167. }
  168. }
  169. // 返回扣减结果
  170. return ['is_used'=>$customCouponId,'product_price'=>$productPrice,'rebate_product'=>$rebateProduct];
  171. }
  172. // 判断每个产品扣减多少钱
  173. // 循环产品
  174. foreach ($productPrice as $productId => $value) {
  175. // 如果有商品范围,且产品id不在商品范围的
  176. if( !empty($coupon['product_scope']) && !in_array($productId,$coupon['product_scope']) ) {
  177. // 跳过,不做计算
  178. continue;
  179. }
  180. // 优惠价格 = 价格占总价的比例 * 优惠的总价
  181. $value['rebate_price'] = number_format( $rebatePrice * ($value['price_total'] / $totalPrice) , 2 , '.' ,'');
  182. // 重组
  183. $productPrice[$productId] = $value;
  184. }
  185. // 返回扣减结果
  186. return ['is_used'=>$customCouponId,'product_price'=>$productPrice,'rebate_product'=>[]];
  187. }
  188. /**
  189. * 发放优惠券
  190. *
  191. * @param int $couponId 优惠券ID
  192. * @param int $customUid 客户ID
  193. *
  194. */
  195. public function giveCoupon($couponId,$customUid){
  196. // 达标的是否已经发送过优惠券
  197. $havaCoupon = $this->query()->where([['custom_uid','=',$customUid],['coupon_id','=',$couponId]])->first(['status']);
  198. // 已经发过优惠券的,不发
  199. if( $havaCoupon ) return 0;
  200. // 优惠券
  201. $Coupon = new \App\Models\Coupon();
  202. // 获取优惠券的可用时间
  203. $couponData = $Coupon->query()->where([['id','=',$couponId],['status','=','0']])->first(['issue_total','status','exp_time']);
  204. // 如果不存在数据,发送失败
  205. if( !$couponData || $couponData['status'] ) return 0;
  206. // 查询总共发放数量
  207. $total = $this->query()->where([['coupon_id','=',$couponId]])->count();
  208. // 数量超过的话。不发
  209. if( $total >= $couponData['issue_total'] ) return 0;
  210. // 时间转时间
  211. $expTime = $Coupon->getExpTime($couponData['exp_time']);
  212. // 发送优惠券
  213. return $this->add(['coupon_id'=>$couponId,'custom_uid'=>$customUid,'exp_time'=>$expTime]);
  214. }
  215. }