RedpackMarketing.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. /**
  3. * 红包抵扣计算
  4. */
  5. namespace addons\Redpack\common\logic\order;
  6. use addons\Redpack\common\enums\RedpackEnum;
  7. use addons\Redpack\common\models\RedpackGoodsSetting;
  8. use addons\Redpack\common\models\RedpackWallet;
  9. use common\enums\AppEnum;
  10. use common\enums\StatusEnum;
  11. use common\traits\ErrorTrait;
  12. use yii\helpers\Json;
  13. class RedpackMarketing
  14. {
  15. use ErrorTrait;
  16. /**
  17. * 红包抵扣处理
  18. * @Author: lun
  19. * @DateTime: 2021/10/6 0006 11:02
  20. * @Copyright: copyright (c) 2021 广东七件事集团
  21. * @param $item
  22. * @param $form
  23. * @param array $extra
  24. * @return mixed
  25. */
  26. public static function computeOld($item, &$form, array &$extra = [])
  27. {
  28. try {
  29. $mall_id = $item['mch_order_info']['mall_id'];
  30. $user_id = $item['mch_order_info']['user_id'];
  31. $redpack_text_arr = RedpackEnum::getRedpackText('', $mall_id);// 红包中文名称
  32. $deduct_money = 0;// 抵扣总额
  33. $deduct_arr = [];// 抵扣冻结跟金额数组
  34. // 商品处理
  35. foreach ($item['goods'] as $goods_id => &$goods) {
  36. // 查询该商品是否设置了红包抵扣
  37. $redpack = RedpackGoodsSetting::find()->where(['goods_id' => $goods_id, 'is_enable' => StatusEnum::ENABLED, 'status' => StatusEnum::ENABLED])->asArray()->all();
  38. if (empty($redpack)) continue;
  39. // 单件抵扣:比如单件抵扣10元,购买A商品共3件,每件50元,总价=150元,可抵扣的金额10元
  40. // 多件抵扣:比如多件抵扣10元,购买A商品共3件,每件50元,总价=150元,可抵扣的金额30元
  41. $num = $goods['num'];// 商品数量
  42. foreach ($redpack as $value) {
  43. $money = $value['deduct_type'] == 1 ? $value['deduct_money'] : $value['deduct_money'] * $num;// 计算抵扣金额
  44. if ($money <= 0) continue;
  45. $redpack_text = $redpack_text_arr[$value['redpack_wallet_type']];// 红包中文名称
  46. $redpack_en = $value['redpack_wallet_type'];// 红包英文标识
  47. // 检查是否有被选中
  48. $is_use = !empty($form->data['is_use_' . $redpack_en]) ? true : false;
  49. // 前端抵扣数据展示组合
  50. if ($form->action == AppEnum::ACTION_PREVIEW) {
  51. $form->marketing['deduct'][$redpack_en] = [
  52. 'name' => $redpack_text,
  53. 'deduct_val' => empty($form->marketing['deduct'][$redpack_en]['deduct_val']) ? $money : $form->marketing['deduct'][$redpack_en]['deduct_val'] + $money,
  54. 'money' => empty($form->marketing['deduct'][$redpack_en]['money']) ? $money : $form->marketing['deduct'][$redpack_en]['money'] + $money,
  55. 'is_show_radio' => true,// 是否显示单选按钮
  56. 'is_use' => $is_use,// 是否被选中单选按钮
  57. ];
  58. }
  59. // 组合订单优惠表数据
  60. if (!empty($form->data['is_use_' . $redpack_en])) {
  61. $deduct_currency = $goods['goods_details'][0]['marketing']['deduct_currency'];
  62. if($deduct_currency){
  63. $deduct_currency = (array_merge($deduct_currency, [$redpack_en => ['name' => RedpackEnum::getRedpackText($redpack_en, $mall_id),'money' => $money]]));// 将合并的数组转为json字符串
  64. }else{
  65. $deduct_currency = [$redpack_en => ['name' => RedpackEnum::getRedpackText($redpack_en, $mall_id),'money' => $money]];
  66. }
  67. $goods['goods_details'][0]['marketing']['deduct_currency'] = $deduct_currency;// 插入order_marketing表数据
  68. $goods_price = $item['goods'][$goods_id]['goods_price'];
  69. $item['goods'][$goods_id]['goods_price'] -= $money;// 此商品减扣后的金额计算
  70. if($item['goods'][$goods_id]['goods_price']<0){
  71. $item['goods'][$goods_id]['goods_price'] = 0;
  72. $money = $goods_price;
  73. }
  74. $deduct_money += $money;
  75. $deduct_arr[$redpack_en] = empty($deduct_arr[$redpack_en]) ? $money : $deduct_arr[$redpack_en] + $money;
  76. }
  77. }
  78. $goods['goods_details'][0]['marketing']['deduct_currency'] = json_encode($goods['goods_details'][0]['marketing']['deduct_currency']);
  79. }
  80. // 计算订单减扣后的金额
  81. if ($deduct_money > 0) {
  82. $item['mch_order_info']['pay_money'] -= $deduct_money;
  83. $item['mch_order_info']['goods_price'] -= $deduct_money;
  84. // 扣减红包金额
  85. if ($form->action == AppEnum::ACTION_CREATE) {
  86. foreach ($deduct_arr as $key => $deduct_redpack_money) {
  87. $res = RedpackWallet::setData([
  88. 'mall_id' => $mall_id,
  89. 'user_id' => $user_id,
  90. 'is_frozen' => $key == RedpackEnum::WALLET_REDPACK ? false : true,
  91. 'money' => -$deduct_redpack_money,
  92. 'from_type' => RedpackEnum::FROM_DEDUTION,
  93. ], false);
  94. if ($res == false) throw new \Exception(RedpackWallet::getStaticError());
  95. }
  96. }
  97. }
  98. return $item;
  99. } catch (\Exception $e) {
  100. self::setStaticError($e->getMessage());
  101. return false;
  102. }
  103. }
  104. public static function compute($item, &$form, array &$extra = [])
  105. {
  106. try {
  107. $mall_id = $item['mch_order_info']['mall_id'];
  108. $user_id = $item['mch_order_info']['user_id'];
  109. $redpack_text_arr = RedpackEnum::getRedpackText('', $mall_id);// 红包中文名称
  110. $deduct_money = 0;// 抵扣总额
  111. $deduct_arr = [];// 抵扣冻结跟金额数组
  112. // 商品处理
  113. $user_red_pack_wallet = RedpackWallet::findOne(['user_id'=>$user_id, 'status' => StatusEnum::ENABLED]);
  114. foreach ($item['goods'] as $goods_id => &$goods) {
  115. // 查询该商品是否设置了红包抵扣
  116. $redpack = RedpackGoodsSetting::find()->where(['goods_id' => $goods_id, 'is_enable' => StatusEnum::ENABLED, 'status' => StatusEnum::ENABLED])->asArray()->all();
  117. if (empty($redpack)) continue;
  118. // 单件抵扣:比如单件抵扣10元,购买A商品共3件,每件50元,总价=150元,可抵扣的金额30元
  119. // 多件抵扣:比如多件抵扣10元,购买A商品共3件,每件50元,总价=150元,可抵扣的金额10元
  120. foreach ($redpack as $value) {
  121. $total_goods_price = array_sum(array_column($goods['goods_details'],'goods_price'));//同一种商品不同规格总价格
  122. $total_num = array_sum(array_column($goods['goods_details'],'num'));// 同一种商品不同规格总数量
  123. if (!empty($value['is_deduct_percent'])) {
  124. // 按照百分比抵扣 = 商品金额 * 设置比例 / 100;百分比抵扣跟商品数量无关
  125. $money = $item['goods'][$goods_id]['goods_price'] * $value['deduct_money'] / 100;
  126. } else {
  127. // 固定金额抵扣
  128. $money = $value['deduct_type'] == 2 ? $value['deduct_money'] : $value['deduct_money'] * $total_num;// 计算抵扣金额
  129. }
  130. if($user_red_pack_wallet[$value['redpack_wallet_type']]<$money){
  131. $money = $user_red_pack_wallet[$value['redpack_wallet_type']];
  132. }
  133. $user_red_pack_wallet[$value['redpack_wallet_type']] -= $money;// 余额逐步减少
  134. if($money<=0) continue;
  135. $redpack_text = $redpack_text_arr[$value['redpack_wallet_type']];// 红包中文名称
  136. $redpack_en = $value['redpack_wallet_type'];// 红包英文标识
  137. // 检查是否有被选中
  138. $temp_total_deduct_money = 0;
  139. $is_use = false;
  140. if($total_goods_price<=0) continue;
  141. if (!empty($form->data['is_use_' . $redpack_en])) $is_use = true;
  142. foreach ($goods['goods_details'] as $k=>&$detail) {
  143. $rate = $detail['goods_price']/$total_goods_price;
  144. if(!isset($goods['goods_details'][$k+1])){
  145. //最后一个
  146. $temp_deduct_money = bcsub($money, $temp_total_deduct_money, 2);
  147. } else {
  148. $temp_deduct_money = bcmul($rate, $money, 2);
  149. }
  150. if( $detail['goods_price']>$temp_deduct_money){
  151. $is_use && $detail['goods_price'] -= $temp_deduct_money;
  152. }else{
  153. // $temp_deduct_money = $detail['goods_price'];
  154. $is_use && $detail['goods_price'] =0;
  155. }
  156. $temp_total_deduct_money += $temp_deduct_money;
  157. if ($is_use) {
  158. $deduct_currency = $detail['marketing']['deduct_currency'];
  159. if($deduct_currency){
  160. $deduct_currency = json_decode($deduct_currency,true);
  161. $deduct_currency = (array_merge($deduct_currency, [$redpack_en => ['name' => RedpackEnum::getRedpackText($redpack_en, $mall_id),'money' => $temp_deduct_money]]));// 将合并的数组转为json字符串
  162. }else{
  163. $deduct_currency = [$redpack_en => ['name' => RedpackEnum::getRedpackText($redpack_en, $mall_id),'money' => $temp_deduct_money]];
  164. }
  165. $detail['marketing']['deduct_currency'] = json_encode($deduct_currency);// 插入order_marketing表数据
  166. }
  167. }
  168. if ($is_use) {
  169. $item['goods'][$goods_id]['goods_price'] -= $temp_total_deduct_money;// 此商品减扣后的金额计算
  170. if($item['goods'][$goods_id]['goods_price']<0) $item['goods'][$goods_id]['goods_price'] = 0;
  171. $deduct_arr[$redpack_en] = empty($deduct_arr[$redpack_en]) ? $temp_total_deduct_money : $deduct_arr[$redpack_en] + $temp_total_deduct_money;
  172. }
  173. // 前端抵扣数据展示组合
  174. if ($form->action == AppEnum::ACTION_PREVIEW) {
  175. $form->marketing['deduct'][$redpack_en] = [
  176. 'name' => $redpack_text,
  177. 'deduct_val' => empty($form->marketing['deduct'][$redpack_en]['deduct_val']) ? round($temp_total_deduct_money, 2) : bcadd($form->marketing['deduct'][$redpack_en]['deduct_val'], $temp_total_deduct_money, 2),
  178. 'money' => empty($form->marketing['deduct'][$redpack_en]['money']) ? round($temp_total_deduct_money, 2) : bcadd($form->marketing['deduct'][$redpack_en]['money'], $temp_total_deduct_money, 2),
  179. 'is_show_radio' => true,// 是否显示单选按钮
  180. 'is_use' => $is_use,// 是否被选中单选按钮
  181. ];
  182. }
  183. $is_use && $deduct_money += $temp_total_deduct_money;
  184. }
  185. }
  186. // 计算订单减扣后的金额
  187. if ($deduct_money > 0) {
  188. $item['mch_order_info']['pay_money'] -= $deduct_money;
  189. $item['mch_order_info']['goods_price'] = bcsub(floatval($item['mch_order_info']['goods_price']), $deduct_money, 2);
  190. // 扣减红包金额
  191. if ($form->action == AppEnum::ACTION_CREATE && $deduct_arr) {
  192. foreach ($deduct_arr as $key => $deduct_redpack_money) {
  193. self::checkRedpack($mall_id, $user_id, $deduct_redpack_money, $key);
  194. }
  195. }
  196. }
  197. return $item;
  198. } catch (\Exception $e) {
  199. self::setStaticError($e->getMessage());
  200. return false;
  201. }
  202. }
  203. /**
  204. * 检测用户余额是否足够
  205. * @param $mall_id
  206. * @param $user_id
  207. * @param $money
  208. * @param $redpack_type
  209. * @return void
  210. * @throws \Exception
  211. */
  212. public static function checkRedpack($mall_id, $user_id, $money, $redpack_type)
  213. {
  214. $wallet = RedpackWallet::findOne(['user_id' => $user_id, 'status' => StatusEnum::ENABLED]);
  215. if (empty($wallet)) throw new \Exception(RedpackEnum::getRedpackText($redpack_type, $mall_id) . "余额不足");
  216. if ($wallet[$redpack_type] < $money) throw new \Exception(RedpackEnum::getRedpackText($redpack_type, $mall_id) . "余额不足");
  217. }
  218. }