FullGift.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. namespace addons\shopro\library\activity\provider;
  3. use addons\shopro\library\activity\traits\GiveGift;
  4. use app\admin\model\shopro\Coupon;
  5. use app\admin\model\shopro\order\Order;
  6. /**
  7. * 满额赠送
  8. */
  9. class FullGift extends Base
  10. {
  11. use GiveGift;
  12. protected $rules = [
  13. "limit_num" => "number|egt:0",
  14. "type" => "require",
  15. "event" => "require",
  16. "discounts" => "require|array"
  17. ];
  18. protected $message = [
  19. "discounts.require" => '请填写优惠规则',
  20. "discounts.array" => '请填写优惠规则',
  21. ];
  22. protected $default = [
  23. "limit_num" => 0, // 每人可参与次数 0:不限制
  24. "type" => "money", // money=满足金额|num=满足件数
  25. "event" => "confirm", // 赠送时机 paid=支付完成|confirm=确认收货(必须全部确认收货才可以)|finish=订单完成(评价完成)
  26. "discounts" => [] //{"full":"100",
  27. // "types":"coupon=优惠券|score=积分|money=余额|goods=商品",
  28. // "coupon_ids":"赠优惠券时存在",
  29. // "total":"赠送优惠券总金额",
  30. // "score":"积分",
  31. // "money":"余额",
  32. // "goods_ids":"商品时存在",
  33. // "gift_num":"礼品份数"}
  34. ];
  35. protected $giftType = [
  36. 'money' => '余额',
  37. 'score' => '积分',
  38. 'coupon' => '优惠券',
  39. 'goods' => '商品',
  40. ];
  41. public function check($params, $activity_id = 0)
  42. {
  43. // 数据验证
  44. $params = parent::check($params);
  45. // 验证赠送规则字段
  46. $this->checkGiftDiscount($params['rules']['discounts']);
  47. // 检测活动之间是否存在冲突
  48. $this->checkActivityConflict($params, $params['goods_list'], $activity_id);
  49. return $params;
  50. }
  51. /**
  52. * 获取 赠送的优惠券列表
  53. *
  54. * @param string $type
  55. * @param array $rules
  56. * @return array
  57. */
  58. public function rulesInfo($type, $rules)
  59. {
  60. $discounts = $rules['discounts'];
  61. foreach ($discounts as &$discount) {
  62. $discount['coupon_list'] = [];
  63. if (in_array('coupon', $discount['types']) && isset($discount['coupon_ids']) && $discount['coupon_ids']) {
  64. $discount['coupon_list'] = Coupon::statusHidden()->whereIn('id', $discount['coupon_ids'])->select();
  65. }
  66. }
  67. $rules['discounts'] = $discounts;
  68. return $rules;
  69. }
  70. public function formatTags($rules, $type)
  71. {
  72. $tags = [];
  73. $discounts = $rules['discounts'] ?? [];
  74. foreach ($discounts as $discount) {
  75. $tags[] = $this->formatTag([
  76. 'type' => $rules['type'],
  77. 'simple' => $rules['simple'] ?? false, // 简单信息展示
  78. 'full' => $discount['full'],
  79. 'discount' => $discount
  80. ]);
  81. }
  82. return array_values(array_filter($tags));
  83. }
  84. /**
  85. * 格式化 discount 折扣为具体优惠标签
  86. *
  87. * @param string $type
  88. * @param array $discountData
  89. * @return string
  90. */
  91. public function formatTag($discountData)
  92. {
  93. $discount = $discountData['discount'];
  94. $gift_type_text = '';
  95. foreach ($discount['types'] as $type) {
  96. $gift_type_text = $gift_type_text . (isset($this->giftType[$type]) ? ',' . $this->giftType[$type] : '');
  97. }
  98. $tag = '满' . $discountData['full'] . ($discountData['type'] == 'money' ? '元' : '件');
  99. $tag .= '赠送' . ($discountData['simple'] ? '礼品' : trim($gift_type_text, ','));
  100. return $tag;
  101. }
  102. public function formatTexts($rules, $type)
  103. {
  104. $texts = [];
  105. $discounts = $rules['discounts'] ?? [];
  106. foreach ($discounts as $discount) {
  107. $text = '消费满' . $discount['full'] . ($rules['type'] == 'money' ? '元' : '件');
  108. $text .= '';
  109. foreach ($discount['types'] as $type) {
  110. $text .= ',';
  111. if ($type == 'money') {
  112. $text .= '赠送' . $discount['money'] . '元余额 ';
  113. } elseif ($type == 'score') {
  114. $text .= '赠送' . $discount['score'] . '积分 ';
  115. } elseif ($type == 'coupon') {
  116. $text .= '赠送价值' . $discount['total'] . '元优惠券 ';
  117. }
  118. }
  119. $text .= ' (条件:活动礼品共 ' . $discount['gift_num'] . ' 份';
  120. if ($rules['limit_num'] > 0) {
  121. $text .= ',每人仅限参与 ' . $rules['limit_num'] . ' 次';
  122. }
  123. $text .= ')';
  124. $texts[] = $text;
  125. }
  126. return array_values(array_filter($texts));
  127. }
  128. public function getPromoInfo($promo, $data = [])
  129. {
  130. extract($this->promoGoodsData($promo));
  131. $rules = $promo['rules'];
  132. // 是按金额,还是按件数比较
  133. $compareif = $rules['type'] == 'num' ? 'promo_goods_num' : 'promo_goods_amount';
  134. // 将规则按照从大到校排列,优先比较是否满足最大规则
  135. $rulesDiscounts = isset($rules['discounts']) && $rules['discounts'] ? array_reverse($rules['discounts']) : []; // 数组反转
  136. // 满减, 满折多个规则从大到小匹配最优惠
  137. foreach ($rulesDiscounts as $d) {
  138. unset($d['coupon_list']); // 移除规则里面的 coupon_list
  139. if (${$compareif} < $d['full']) {
  140. // 不满足条件,接着循环下个规则
  141. continue;
  142. }
  143. // 记录该活动的一些统计信息
  144. $promo_discount_info = [
  145. 'activity_id' => $promo['id'], // 活动id
  146. 'activity_title' => $promo['title'], // 活动标题
  147. 'activity_type' => $promo['type'], // 活动类型
  148. 'activity_type_text' => $promo['type_text'], // 活动类型中文
  149. 'promo_discount_money' => 0, // 优惠金额 (赠送,不优惠)
  150. 'promo_goods_amount' => $promo_goods_amount, // 当前活动商品总金额
  151. 'rule_type' => $rules['type'], // 满多少元|还是满多少件
  152. 'discount_rule' => $d, // 满足的那条规则
  153. "limit_num" => $rules['limit_num'], // 每个人可参与次数
  154. "event" => $rules['event'], // 赠送时机
  155. 'goods_ids' => $goodsIds // 这个活动包含的这次购买的商品
  156. ];
  157. break;
  158. }
  159. return $promo_discount_info ?? null;
  160. }
  161. /**
  162. * 支付成功(货到付款下单),添加礼品记录
  163. *
  164. * @param array|object $order
  165. * @param array|object $user
  166. * @return void
  167. */
  168. public function buyOk($order, $user)
  169. {
  170. // 满赠送
  171. $ext = $order->ext;
  172. $promoInfos = $ext['promo_infos'];
  173. foreach ($promoInfos as $info) {
  174. if ($info['activity_type'] == 'full_gift') {
  175. // 满赠,开始赠送
  176. $this->addGiftsLog($order, $user, $info);
  177. }
  178. }
  179. $event = $order->status == Order::STATUS_PENDING ? 'pending' : 'paid'; // 货到付款不是真的付款,不能发放礼品 event 改为 pending
  180. // 检测并赠送礼品
  181. $this->checkAndGift($order, $user, $promoInfos, $event);
  182. }
  183. /**
  184. * 促销购买失败(退款)
  185. *
  186. * @param \think\Model $order
  187. * @param string $type
  188. * @return void
  189. */
  190. public function buyFail($order, $type)
  191. {
  192. if ($type == 'refund') {
  193. // 退款,将礼品标记为已退款,如果已经送出去的不扣除
  194. $this->checkAndFailGift($order, '订单全额退款');
  195. } else if ($type == 'invalid') {
  196. if ($order->pay_mode == 'offline') {
  197. // 只有线下付款取消时才需要标记礼品赠送失败
  198. $this->checkAndFailGift($order, '货到付款订单取消');
  199. }
  200. }
  201. }
  202. }