PreMemberCoupon.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: shenyang
  5. * Date: 2018/12/27
  6. * Time: 10:57 PM
  7. */
  8. namespace app\common\modules\coupon\models;
  9. use app\common\exceptions\AppException;
  10. use app\common\models\Coupon;
  11. use app\common\models\Member;
  12. use app\common\models\MemberCoupon;
  13. use app\common\models\MemberShopInfo;
  14. use app\common\modules\coupon\events\AfterMemberReceivedCoupon;
  15. use Illuminate\Support\Facades\DB;
  16. use Yunshop\BindCoupon\models\BindCouponLog;
  17. class PreMemberCoupon extends MemberCoupon
  18. {
  19. /**
  20. * @var Member $member
  21. */
  22. private $member;
  23. /**
  24. * @var Coupon $coupon
  25. */
  26. private $coupon;
  27. private $exchange_total;
  28. private $integralCanExchange;
  29. /**
  30. * @param Member $member
  31. * @param Coupon $coupon
  32. * @param int $exchange_total
  33. */
  34. public function init(Member $member, Coupon $coupon, $exchange_total = 1)
  35. {
  36. $this->member = $member;
  37. $this->coupon = $coupon;
  38. $this->exchange_total = $exchange_total;
  39. $this->initAttributes();
  40. }
  41. private function initAttributes()
  42. {
  43. $data = [
  44. 'uniacid' => $this->member->uniacid,
  45. 'uid' => $this->member->uid,
  46. 'coupon_id' => $this->coupon->id,
  47. 'get_type' => 1,
  48. 'get_time' => time(),
  49. ];
  50. $this->fill($data);
  51. }
  52. /**
  53. * @throws AppException
  54. */
  55. public function generate()
  56. {
  57. $this->verify($this->member->yzMember, $this->coupon, $this->exchange_total);
  58. $validator = $this->validator();
  59. if ($validator->fails()) {
  60. throw new AppException('领取失败', $validator->messages());
  61. }
  62. if ($this->exchange_total == 1) {
  63. if (request()->is_bind_coupon) {
  64. DB::transaction(function (){
  65. if (request()->bind_coupon_share_uid){
  66. if (!$share_member_coupon = MemberCoupon::uniacid()
  67. ->where('used', 0)
  68. ->where('is_member_deleted', 0)
  69. ->where('is_expired', 0)
  70. ->where('uid', request()->bind_coupon_share_uid)
  71. ->where('coupon_id', $this->coupon->id)
  72. ->lockForUpdate()
  73. ->first()){
  74. throw new AppException('分享人无可用优惠券');
  75. }
  76. $share_member_coupon->used = 1;
  77. $share_member_coupon->use_time = time();
  78. $share_member_coupon->save();
  79. $share_member_coupon_id = $share_member_coupon->id;
  80. }else{
  81. $share_member_coupon_id = 0;
  82. }
  83. if (!BindCouponLog::uniacid()
  84. ->where('status', 0)
  85. ->where('coupon_sn', request()->bind_coupon_sn)
  86. ->update([
  87. 'status' => 1,
  88. 'finish_time' => time(),
  89. 'uid' => $this->member->uid,
  90. 'share_coupon_id' => $share_member_coupon_id,
  91. ])) {
  92. throw new AppException('绑定优惠券修改失败');
  93. }
  94. });
  95. }
  96. $this->save();
  97. } else {
  98. for ($i = 1; $i <= $this->exchange_total; $i++) {
  99. $insertData[] = [
  100. 'uniacid' => $this->member->uniacid,
  101. 'uid' => $this->member->uid,
  102. 'coupon_id' => $this->coupon->id,
  103. 'get_type' => 1,
  104. 'get_time' => time(),
  105. ];
  106. }
  107. if (empty($insertData)) {
  108. throw new AppException('领取优惠券失败');
  109. }
  110. static::insert($insertData);
  111. }
  112. if (!empty($this->integralCanExchange)) {
  113. //扣除兑换优惠券需要的消费积分
  114. $this->deductIntegral();
  115. }
  116. event(new AfterMemberReceivedCoupon($this,$this->exchange_total));
  117. }
  118. /**
  119. * @param MemberShopInfo $yzMember
  120. * @param Coupon $coupon
  121. * @param $exchange_total
  122. * @throws AppException
  123. */
  124. public function verify(MemberShopInfo $yzMember, Coupon $coupon, $exchange_total = 1)
  125. {
  126. $special_type = 0;
  127. if (app('plugins')->isEnabled('bind-coupon')
  128. && request()->bind_coupon_sn
  129. && ($this->exchange_total == 1)
  130. ) {
  131. if ($bind_coupon = BindCouponLog::uniacid()
  132. ->where('status', 0)
  133. ->where('coupon_sn', request()->bind_coupon_sn)
  134. ->where('coupon_id', $coupon->id)
  135. ->first()) {
  136. $special_type = 1;
  137. request()->offsetSet('is_bind_coupon', 1);
  138. request()->offsetSet('bind_coupon_share_uid', $bind_coupon->share_uid ?: 0);
  139. }
  140. }
  141. if (!$coupon->available($special_type)) {
  142. throw new AppException('没有该优惠券或者优惠券不可用');
  143. }
  144. if (!empty($coupon->level_limit) && ($coupon->level_limit != -1)) { //优惠券有会员等级要求
  145. // 通过会员记录的level_id找到会员等级
  146. $memberLevel = \app\common\models\MemberLevel::find($yzMember->level_id)->level;
  147. // 通过优惠券记录的level_id找到会员等级,level_limit实际就是level_id
  148. $couponMemberLevel = \app\common\models\MemberLevel::find($coupon->level_limit)->level;
  149. if (empty($yzMember->level_id)) {
  150. throw new AppException('该优惠券有会员等级要求,但该用户没有会员等级');
  151. } elseif ((!empty($memberLevel) ? $memberLevel : 0) < $couponMemberLevel) {
  152. throw new AppException('没有达到领取该优惠券的会员等级要求');
  153. }
  154. }
  155. //判断优惠券是否过期
  156. $timeLimit = $coupon->time_limit;
  157. if ($timeLimit == 1 && (time() > $coupon->time_end->timestamp)) {
  158. throw new AppException('优惠券已过期');
  159. }
  160. //是否达到个人领取上限
  161. $counts = self::where('uid', $yzMember->member_id)->where('coupon_id', $coupon->id)->where('get_type',1);
  162. $count = $counts->count();
  163. if ($exchange_total > 1) {
  164. $count += ($exchange_total-1);//领取多张需要增加当前数量进行判断
  165. }
  166. if ($count >= $coupon->get_max && ($coupon->get_max != -1)) {
  167. throw new AppException('已经达到个人领取上限',['reason' => '每人限领' . $coupon->get_max . '张,当前已领取' . $counts->count() . '张']);
  168. }
  169. $today_count = $counts->where('get_time','>',strtotime(date('Y-m-d',time())))->count();
  170. if($coupon->get_limit_type == 1 and $coupon->get_limit_max != -1 and $today_count >= $coupon->get_limit_max){
  171. throw new AppException('今日领取已达上限',['reason' => '每人每天限领' . $coupon->get_limit_max . '张']);
  172. }
  173. //验证是否达到优惠券总数上限
  174. if ($coupon->getReceiveCount() >= $coupon->total && ($coupon->total != -1)) {
  175. throw new AppException('该优惠券已经被抢光');
  176. }
  177. //验证会员标签
  178. if (app('plugins')->isEnabled('member-tags')) {
  179. $memberTags = \Yunshop\MemberTags\Common\models\MemberTagsRelationModel::uniacid()->where('member_id', $yzMember->member_id)->pluck('tag_id');
  180. if (!empty($coupon->member_tags_ids) && empty(array_intersect($memberTags->toArray(), $coupon->member_tags_ids))) {
  181. throw new AppException('不符合领取该优惠券的标签分组要求');
  182. }
  183. }
  184. //消费积分兑换优惠券
  185. if (app('plugins')->isEnabled('integral')) {
  186. $integralName = \Yunshop\Integral\Common\Services\SetService::getIntegralName();
  187. $integralMember = (float)\Yunshop\Integral\Common\Models\IntegralMemberModel::uniacid()->where('uid', $yzMember->member_id)->pluck('integral')->first(); //用户消费积分余额
  188. if ($coupon->is_integral_exchange_coupon && !empty($coupon->exchange_coupon_integral)) {
  189. if (bccomp($coupon->exchange_coupon_integral, $integralMember) == 1) {
  190. $exchangeIntegralMsg = str_replace('消费积分', $integralName, '兑换需要' . $coupon->exchange_coupon_integral . '消费积分,当前消费积分 ' . $integralMember . ',消费积分不足,不能进行兑换');
  191. $this->integralCanExchange = 0;
  192. throw new AppException($exchangeIntegralMsg);
  193. } else {
  194. $this->integralCanExchange = 1;
  195. }
  196. }
  197. }
  198. }
  199. private function deductIntegral()
  200. {
  201. $changeValue = bcmul($this->coupon->exchange_coupon_integral,$this->exchange_total,2);
  202. $plugin_name = INTEGRAL_NAME ?: '消费积分';
  203. try {
  204. $order_sn = MemberCoupon::createOrderSn('DIEC');//DIEC扣除消费积分兑换优惠券
  205. $changeData = [
  206. 'uid' => $this->member->uid,
  207. 'uniacid' => $this->member->uniacid,
  208. 'change_value' => $changeValue,
  209. 'order_sn' => $order_sn,
  210. 'source_type' => self::class,
  211. 'source_id' => \Yunshop\Integral\Common\Services\ConstService::EXCHANGE_COUPON_DEDUCT,
  212. 'remark' => $plugin_name.'兑换优惠券',
  213. 'type' => 0,//0为减
  214. ];
  215. (new \Yunshop\Integral\Common\Services\IntegralChangeServer())->exchangeCouponDeduct($changeData);
  216. } catch (\Exception $e) {
  217. \Log::error('消费积分兑换优惠券错误:' . $e->getMessage());
  218. }
  219. }
  220. }