MarketingGiftService.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. namespace common\services\mall\order;
  3. use addons\Mch\common\models\Mch;
  4. use common\enums\StatusEnum;
  5. use common\enums\UserWalletEnum;
  6. use common\models\goods\GoodsExtra;
  7. use common\models\mall\MallAddons;
  8. use common\models\order\Order;
  9. use common\models\order\OrderDetail;
  10. use common\models\user\User;
  11. use common\models\user\UserWallet;
  12. use services\common\UserWalletService;
  13. use Yii;
  14. class MarketingGiftService
  15. {
  16. private $userInfo = []; // 用户信息
  17. private $insertWallets = []; // 插入钱包记录
  18. public function handle(array $data)
  19. {
  20. $transaction = Yii::$app->db->beginTransaction(); // 开启事务
  21. try {
  22. $order = Order::find()
  23. ->where(['id' => $data['id'], 'status' => StatusEnum::ENABLED])
  24. ->asArray()->one();
  25. // 因为需要 拼团(新) 插件订单不参与平台积分、余额等赠送
  26. if ($order['marketing_type'] == 'GroupBuyCopy') return false;
  27. // 获取订单详情
  28. $orderDetailList = $this->getOrderDetails($data['id']);
  29. if (empty($orderDetailList)) return false;
  30. // 获取商品成本价
  31. $order['cost_price'] = 0;
  32. $order['num'] = 0;
  33. foreach ($orderDetailList as $detail) {
  34. $order['cost_price'] += $detail['cost_price'] * $detail['num'];
  35. $order['num'] += $detail['num'];
  36. }
  37. // 获取用户信息
  38. $this->userInfo = User::find()
  39. ->where(['id' => $order['user_id'], 'status' => StatusEnum::ENABLED])
  40. ->asArray()->one();
  41. if (empty($this->userInfo)) return false;
  42. // 获取商品营销配置
  43. $goodsIds = array_column($orderDetailList, 'goods_id') ?? [];
  44. $goodsExtraList = $this->getGoodsExtraList($goodsIds);
  45. $isIndependentConfig = $this->checkIndependentConfig($goodsExtraList);
  46. // 根据配置处理赠送
  47. if ($isIndependentConfig) {
  48. Yii::$app->custom->logs('营销赠送商品独立配置', json_encode($goodsExtraList));
  49. $this->setIndependentGift($orderDetailList, $goodsExtraList);
  50. } else {
  51. // 获取全局营销配置:(并且判断条件是否满足)
  52. $marketingConfig = Yii::$app->services->setting->mall->get($order['mall_id'], 'marketing');
  53. // 判断是否开启营销配送。并且订单金额是否满足赠送条件
  54. if (empty($marketingConfig['enable_marketing']) || $order['goods_price'] < $marketingConfig['total_price']) return false;
  55. Yii::$app->custom->logs('营销赠送全局配置', json_encode($marketingConfig));
  56. $this->setGlobalGift($order, $marketingConfig);
  57. }
  58. // 出来金额赠送
  59. if (!empty($this->insertWallets)) {
  60. $res = UserWalletService::batchHandleByQueue($this->insertWallets);
  61. if (empty($res)) throw new \Exception(UserWalletService::getStaticError());
  62. }
  63. $transaction->commit();
  64. return true;
  65. } catch (\Exception $e) {
  66. Yii::$app->custom->logs('营销配置发送失败', $e->getMessage());
  67. $transaction->rollBack();
  68. return false;
  69. }
  70. }
  71. /**
  72. * @param $orderId
  73. * @return array|\yii\db\ActiveRecord[]
  74. */
  75. protected function getOrderDetails($orderId): array
  76. {
  77. return OrderDetail::find()
  78. ->where(['order_id' => $orderId, 'status' => StatusEnum::ENABLED])
  79. ->asArray()->all();
  80. }
  81. /**
  82. * 获取商品营销配置
  83. * @param $goodsIds
  84. * @return array|\yii\db\ActiveRecord[]
  85. */
  86. protected function getGoodsExtraList($goodsIds): array
  87. {
  88. return GoodsExtra::find()
  89. ->select(['score_give_setting', 'balance_give_setting', 'goods_id'])
  90. ->where(['goods_id' => $goodsIds, 'status' => StatusEnum::ENABLED])
  91. ->asArray()->indexBy('goods_id')->all();
  92. }
  93. /** 检测商品独立设置支付结算方式和全局不同需要修改
  94. * @param $goodsExtraList
  95. * @return bool
  96. */
  97. protected function checkIndependentConfig(&$goodsExtraList): bool
  98. {
  99. $is_check = false;
  100. foreach ($goodsExtraList as &$extra) {
  101. $extra['score_give_setting'] = json_decode($extra['score_give_setting'], true) ?: [];
  102. $extra['balance_give_setting'] = json_decode($extra['balance_give_setting'], true) ?: [];
  103. $extra['balance_give_setting']['settlement'] = !empty($extra['balance_give_setting']['settlement']) ? $extra['balance_give_setting']['settlement'] : 2;
  104. $extra['score_give_setting']['settlement'] = !empty($extra['score_give_setting']['settlement']) ? $extra['score_give_setting']['settlement'] : 2;
  105. if (!empty($extra['score_give_setting']['enable_give_score']) || !empty($extra['balance_give_setting']['enable_give_balance'])) {
  106. $is_check = true;
  107. }
  108. }
  109. unset($extra);
  110. return $is_check;
  111. }
  112. /**
  113. * 全局设置赠送
  114. * @param array $order
  115. * @param array $giftSystem
  116. * @return bool
  117. */
  118. protected function setGlobalGift(array $order, array $giftSystem)
  119. {
  120. $scoreGiftSystem = $balanceGiftSystem = [];
  121. // 获取全局积分赠送设置
  122. if (!empty($giftSystem['score_give_setting'])) {
  123. $scoreGiftSystem = json_decode($giftSystem['score_give_setting'], true);
  124. $scoreGiftSystem['enable_give_score'] = $giftSystem['enable_give_score'];
  125. $scoreGiftSystem['settlement'] = $giftSystem['settlement'];
  126. }
  127. // 获取全局余额赠送设置
  128. if (!empty($giftSystem['balance_give_setting'])) {
  129. $balanceGiftSystem = json_decode($giftSystem['balance_give_setting'], true);
  130. $balanceGiftSystem['enable_give_balance'] = $giftSystem['enable_give_balance'];
  131. $balanceGiftSystem['settlement'] = $giftSystem['settlement'];
  132. }
  133. // 判断条件是否满足商品类型限制
  134. if (!empty($order['store_id'])) return false; // 门店商品过滤
  135. if (!empty($order['mch_id']) && !in_array(1, $scoreGiftSystem['score_giving_goods_type'])) return false; // 如果商品为多商户商品。营销配置商品类型没有选择多商户商品过滤
  136. if (empty($order['mch_id']) && !in_array(0, $scoreGiftSystem['score_giving_goods_type'])) return false; // 如果商品为拼团商品。营销配置商品类型没有选择平台商品过滤
  137. $order['order_id'] = $order['id'];
  138. if (!empty($scoreGiftSystem['enable_give_score'])) {
  139. // 积分赠送
  140. $this->setGlobalGiftSystem($order, $scoreGiftSystem);
  141. }
  142. if (!empty($balanceGiftSystem['enable_give_balance'])) {
  143. // 余额赠送
  144. $this->setGlobalGiftSystem($order, $balanceGiftSystem, 'balance');
  145. }
  146. return true;
  147. }
  148. /**
  149. * 商品独立设置赠送
  150. * @return bool
  151. */
  152. protected function setIndependentGift(array $orderDetailList, array $goodsExtraList)
  153. {
  154. foreach ($orderDetailList as $detail) {
  155. $detail['cost_price'] = $detail['cost_price'] * $detail['num'] ?? 0;
  156. // 判断条件是否满足商品类型限制
  157. if (empty($goodsExtraList[$detail['goods_id']])) continue;
  158. if (!empty($goodsExtraList[$detail['goods_id']]['score_give_setting']['enable_give_score'])) { // 积分赠送
  159. // 判断是否开启等级限制
  160. $give_level_setting = true;
  161. if (!empty($goodsExtraList[$detail['goods_id']]['score_give_setting']['enable_limit_level'])) {
  162. if (!in_array($this->userInfo['level'], $goodsExtraList[$detail['goods_id']]['score_give_setting']['limit_level'])) {
  163. $give_level_setting = false;
  164. }
  165. }
  166. if ($give_level_setting) {
  167. // 因为独立积分赠送的计算方式和全局积分赠送的计算方式不一样,所以这些从新赋值
  168. $goodsExtraList[$detail['goods_id']]['score_give_setting']['score_giving_calculation'] = $goodsExtraList[$detail['goods_id']]['score_give_setting']['calculation_value'];
  169. $this->setGlobalGiftSystem($detail, $goodsExtraList[$detail['goods_id']]['score_give_setting'], 'score', 'order');
  170. }
  171. }
  172. if (!empty($goodsExtraList[$detail['goods_id']]['balance_give_setting']['enable_give_balance'])) { // 余额赠送
  173. $this->setGlobalGiftSystem($detail, $goodsExtraList[$detail['goods_id']]['balance_give_setting'], 'balance', 'order');
  174. }
  175. }
  176. return true;
  177. }
  178. /**
  179. * 积分赠送
  180. * @param $detail
  181. * @param $giftSystem
  182. * @param string $type
  183. * @param string $full
  184. * @return false|void
  185. */
  186. protected function setGlobalGiftSystem($detail, $giftSystem, string $type = 'score', string $full = 'full')
  187. {
  188. $goodsPrice = 0;
  189. if ($type == 'score') {
  190. switch ($giftSystem['score_giving_calculation']) {
  191. case 1: // 商品利润
  192. $goodsPrice = $detail['goods_price'] - $detail['cost_price'];
  193. break;
  194. case 2: // 商品售价
  195. $goodsPrice = $detail['original_goods_price'];
  196. break;
  197. default: // 订单支付金额
  198. $goodsPrice = $detail['goods_price'];
  199. break;
  200. }
  201. } else {
  202. $goodsPrice = $detail['goods_price'];
  203. }
  204. $money = $giftSystem['give_num'] * $detail['num'] ?? 0;
  205. // 计算赠送金额
  206. if ($giftSystem['give_type'] == 2) {
  207. $money = bcmul($goodsPrice, $giftSystem['give_num'] / 100, 2);
  208. }
  209. if ($money <= 0) return false;
  210. if ($full == 'full') {
  211. $desc = '满额赠送';
  212. $source_table = Order::tableName();
  213. $from_type = UserWalletEnum::REWARD;
  214. } else {
  215. $desc = '支付赠送';
  216. $source_table = OrderDetail::tableName();
  217. $from_type = UserWalletEnum::CONSUME;
  218. }
  219. if (!empty($detail['mch_id']) && $type == 'score') { // 如果是多商户订单。订单赠送积分。需要扣除多商户订单
  220. // 判断是否安装多商户插件
  221. if (!MallAddons::isInstall($detail['mall_id'], 'Mch')) return false;
  222. // 获取当前多商户绑定的会员信息
  223. $mch = Mch::findOne(['id' => $detail['mch_id'], 'status' => StatusEnum::ENABLED]);
  224. if (!$mch) return false;
  225. $userWallet = UserWallet::findOne(['user_id' => $mch->user_id, 'status' => StatusEnum::ENABLED]);
  226. if (!$userWallet) return false;
  227. if ($userWallet->score < $money) return false;
  228. $this->insertWallets[] = [
  229. 'mall_id' => $detail['mall_id'],
  230. 'user_id' => $mch->user_id,
  231. 'is_frozen' => $giftSystem['settlement'] == 2,
  232. 'wallet_type' => 'score',
  233. 'money' => -$money,
  234. 'desc' => '订单支付赠送用户积分,扣除商家用户账户积分',
  235. 'source_table' => OrderDetail::tableName(),
  236. 'source_table_id' => $detail['id'],
  237. 'from_type' => UserWalletEnum::CONSUME,
  238. 'capital_type' => UserWalletEnum::CONSUME_ORDER_GIVE,
  239. ];
  240. }
  241. $this->insertWallets[] = [
  242. 'mall_id' => $detail['mall_id'],
  243. 'user_id' => $detail['user_id'],
  244. 'is_frozen' => $giftSystem['settlement'] == 2,
  245. 'wallet_type' => $type,
  246. 'money' => $money,
  247. 'desc' => '订单(' . $detail['order_id'] . ')' . $desc,
  248. 'source_table' => $source_table,
  249. 'source_table_id' => $detail['id'],
  250. 'from_type' => $from_type,
  251. 'capital_type' => UserWalletEnum::CONSUME_ORDER_GIVE,
  252. ];
  253. }
  254. }