CommissionLogic.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. <?php
  2. namespace addons\BusinessActivity\common\logic;
  3. use addons\BusinessActivity\common\enums\BusinessActivityEnum;
  4. use addons\BusinessActivity\common\enums\ConfigEnum;
  5. use addons\BusinessActivity\common\models\AddonsBusinessActivityCommissionModel;
  6. use addons\BusinessActivity\common\models\AddonsBusinessActivityGoodsModel;
  7. use addons\BusinessActivity\common\models\AddonsBusinessActivityModel;
  8. use addons\BusinessActivity\common\models\AddonsBusinessActivityOrderModel;
  9. use addons\BusinessActivity\common\service\SettingService;
  10. use common\enums\StatusEnum;
  11. use common\helpers\FormatHelper;
  12. use common\models\mall\MallAddons;
  13. use common\models\order\Order;
  14. use common\models\order\OrderDetail;
  15. use common\models\user\User;
  16. use Exception;
  17. use services\common\UserWalletService;
  18. use Yii;
  19. use yii\helpers\Json;
  20. class CommissionLogic
  21. {
  22. public function exec(Order $order, array $config, array $ext)
  23. {
  24. $t = Yii::$app->db->beginTransaction();
  25. try {
  26. $this->execMain($order, $config, $ext);
  27. $t->commit();
  28. } catch (\Exception $e) {
  29. $t->rollBack();
  30. $exception = FormatHelper::exception($e, "订单支付触发社区团购插件事件: 分润失败 {$order->id} " . Json::encode($ext) . " " . Json::encode($config));
  31. Yii::error($exception);
  32. }
  33. }
  34. /**
  35. * @throws Exception
  36. */
  37. public function execMain(Order $order, array $config, int $activity_id)
  38. {
  39. $mall_id = $order['mall_id'];
  40. $order_id = $order['id'];
  41. $user_id = $order['user_id'];
  42. $activity_order = AddonsBusinessActivityOrderModel::find()
  43. ->where(['mall_id' => $mall_id])
  44. ->andWhere(['order_id' => $order_id])
  45. ->andWhere(['activity_id' => $activity_id])
  46. ->with(['activity'])
  47. ->one();
  48. if (empty($activity_order)) {
  49. Yii::error("活动订单不存在: activity_id: {$activity_id}, order_id: {$order_id}");
  50. return;
  51. }
  52. $activity = $activity_order->activity;
  53. // 取出可以订单商品ID?
  54. $activity_goods_ids = Json::decode($activity_order->goods_ids);
  55. // 取出下单时参与的商品,不管删除与否都参与进来
  56. $goods = AddonsBusinessActivityGoodsModel::find()->where(['activity_id' => $activity_id])
  57. ->andWhere(['id' => $activity_goods_ids])
  58. ->asArray()
  59. ->all();
  60. $goods = array_reduce($goods, function (&$goods, $val) {
  61. $goods[$val['goods_id']] = $val;
  62. return $goods;
  63. });
  64. $goods_ids = array_column($goods, 'goods_id'); // 获取商品ID
  65. $params['where'] = [['order_id' => $order_id], ['user_id' => $user_id], ['mall_id' => $mall_id], ['order_status' => $order->order_status],
  66. ['goods_id' => $goods_ids]];
  67. $order_detail_list = OrderDetail::lists($params);
  68. if (empty($order_detail_list)) {
  69. Yii::error("订单详情不存在: {$order_id}");
  70. return;
  71. }
  72. $insert_wallet = [];
  73. $insert_plugin = [];
  74. $config = (new SettingService())->get($order->mall_id);
  75. foreach ($order_detail_list as $item) {
  76. $merchants_commission = 0; // 招商
  77. $merchants_commission_parent = 0; // 招商上级
  78. $venue_commission = 0; // 场地
  79. $venue_commission_parent = 0; // 场地上级
  80. $g_item = $goods[$item['goods_id']] ?? null;
  81. if (!empty($g_item)) { // 存在
  82. if ($g_item['is_alone_commission'] == StatusEnum::ENABLED) { // 这里是独立设置
  83. $merchants_commission = bcmul($g_item['merchants_commission'], $item['num'], 2);
  84. $merchants_commission_parent = bcmul($g_item['merchants_parent_commission'], $item['num'], 2);
  85. $venue_commission = bcmul($g_item['venue_commission'], $item['num'], 2);
  86. $venue_commission_parent = bcmul($g_item['venue_parent_commission'], $item['num'], 2);
  87. if ($g_item['commission_type'] == StatusEnum::ENABLED) { // 1百分比, 2固定值
  88. $base_amount = 0;
  89. switch ($config['payment_type']) {
  90. case ConfigEnum::CALCULATE_TYPE_PAY_AMOUNT: // 实际支付金额
  91. $base_amount = $item['goods_price']; // 已经包含数量
  92. break;
  93. case ConfigEnum::CALCULATE_TYPE_GOODS_PRICE: // 商品售价
  94. // 计算商品售价
  95. $base_amount = bcmul($item['price'], $item['num'], 2);
  96. break;
  97. case ConfigEnum::CALCULATE_TYPE_GOODS_PROFIT: // 商品利润
  98. $base_amount = bcmul(bcsub($item['price'], $item['cost_price'], 2), $item['num'], 2);
  99. break;
  100. }
  101. $merchants_commission = bcmul($base_amount, bcmul($g_item['merchants_commission'], 0.01, 2), 2);
  102. $merchants_commission_parent = bcmul($base_amount, bcmul($g_item['merchants_parent_commission'], 0.01, 2), 2);
  103. $venue_commission = bcmul($base_amount, bcmul($g_item['venue_commission'], 0.01, 2), 2);
  104. $venue_commission_parent = bcmul($base_amount, bcmul($g_item['venue_parent_commission'], 0.01, 2), 2);
  105. }
  106. } else { // 走公共提成设置
  107. if ($config['is_commission'] != StatusEnum::ENABLED) {
  108. Yii::error("Business Activity reward 未开启奖励");
  109. continue;
  110. }
  111. switch ($config['commission_type']) {
  112. case ConfigEnum::BUSINESS_ACTIVITY_COMMISSION_TYPE_FIXED: // 固定金额
  113. $merchants_commission = bcmul($config['investment_scale'], $item['num'], 2);
  114. $venue_commission = bcmul($config['site_scale'], $item['num'], 2);
  115. break;
  116. case ConfigEnum::BUSINESS_ACTIVITY_COMMISSION_TYPE_RATE: // 百分比
  117. $base_amount = 0;
  118. switch ($config['payment_type']) {
  119. case ConfigEnum::CALCULATE_TYPE_PAY_AMOUNT: // 实际支付金额
  120. $base_amount = $item['goods_price']; // 已经包含数量
  121. break;
  122. case ConfigEnum::CALCULATE_TYPE_GOODS_PRICE: // 商品售价
  123. // 计算商品售价
  124. $base_amount = bcmul($item['price'], $item['num'], 2);
  125. break;
  126. case ConfigEnum::CALCULATE_TYPE_GOODS_PROFIT: // 商品利润
  127. $base_amount = bcmul(bcsub($item['price'], $item['cost_price'], 2), $item['num'], 2);
  128. break;
  129. }
  130. $merchants_commission = bcmul($base_amount, bcmul($config['investment_scale'], 0.01, 2), 2);
  131. $merchants_commission_parent = bcmul($base_amount, bcmul($config['investment_scale_parent'], 0.01, 2), 2);
  132. $venue_commission = bcmul($base_amount, bcmul($config['site_scale'], 0.01, 2), 2);
  133. $venue_commission_parent = bcmul($base_amount, bcmul($config['site_scale_parent'], 0.01, 2), 2);
  134. break;
  135. }
  136. }
  137. }
  138. if (!empty($merchants_commission)) { // 如果奖励给招商人不为空
  139. $insert_wallet[] = $this->genInsertWallet($activity, $order, $item, $activity->merchants_user_id, $merchants_commission,
  140. "用户 ({$activity->merchants_user_id}) ,[招商负责人]获得招商活动订单 ({$order['id']}) 奖励, 奖励类型:(佣金), 共奖励 ({$merchants_commission}) 元佣金");
  141. $insert_plugin[] = $this->genInsertPlugin($activity, $order, $item, $activity->merchants_user_id, $merchants_commission,
  142. "用户[{$order->user->nickname}]通过招商活动[{$activity->name}]下单, 单号为[{$order['order_no']}]共支付[{$order->pay_money}],奖励[招商负责人]佣金[{$merchants_commission}]");
  143. }
  144. // 招商负责人上级
  145. $merchants_commission_parent_user_id = User::find()
  146. ->where(['id' => $activity->merchants_user_id])->select('parent_id')->scalar();
  147. if (!empty($merchants_commission_parent) && !empty($merchants_commission_parent_user_id)) { // 如果奖励给招商人上级不为空
  148. $insert_wallet[] = $this->genInsertWallet($activity, $order, $item, $merchants_commission_parent_user_id, $merchants_commission_parent,
  149. "用户 ({$merchants_commission_parent_user_id}) ,[招商负责人上级]获得招商活动订单 ({$order['id']}) 奖励, 奖励类型:(佣金), 共奖励 ({$merchants_commission_parent}) 元佣金");
  150. $insert_plugin[] = $this->genInsertPlugin($activity, $order, $item, $merchants_commission_parent_user_id, $merchants_commission_parent,
  151. "用户[{$order->user->nickname}]通过招商活动[{$activity->name}]下单, 单号为[{$order['order_no']}]共支付[{$order->pay_money}],奖励[招商负责人上级]佣金[{$merchants_commission_parent}]");
  152. }
  153. // 场地负责人
  154. if (!empty($venue_commission)) { // 如果奖励给场地负则人不为空
  155. $insert_wallet[] = $this->genInsertWallet($activity, $order, $item, $activity->venue_user_id, $venue_commission,
  156. "用户 ({$activity->venue_user_id}) ,[场地负责人]获得招商活动订单 ({$order['id']}) 奖励, 奖励类型:(佣金), 共奖励 ({$venue_commission}) 元佣金");
  157. // 用户[xxx]通过招商活动[xxx]下单,单号为[xxx]共支付[xxx],获得佣金[xxx]
  158. $insert_plugin[] = $this->genInsertPlugin($activity, $order, $item, $activity->venue_user_id, $venue_commission,
  159. "用户[{$order->user->nickname}]通过招商活动[{$activity->name}]下单, 单号为[{$order['order_no']}]共支付[{$order->pay_money}],奖励[场地负责人]佣金[{$venue_commission}]");
  160. }
  161. // 场地负责人上级
  162. $venue_commission_parent_user_id = User::find()
  163. ->where(['id' => $activity->venue_user_id])->select('parent_id')->scalar();
  164. if (!empty($venue_commission_parent) && !empty($venue_commission_parent_user_id)) { // 如果奖励给场地负则人上级不为空
  165. $insert_wallet[] = $this->genInsertWallet($activity, $order, $item, $venue_commission_parent_user_id, $venue_commission_parent,
  166. "用户 ({$venue_commission_parent_user_id}) ,[场地负责人上级]获得招商活动订单 ({$order['id']}) 奖励, 奖励类型:(佣金), 共奖励 ({$venue_commission_parent}) 元佣金");
  167. // 用户[xxx]通过招商活动[xxx]下单,单号为[xxx]共支付[xxx],获得佣金[xxx]
  168. $insert_plugin[] = $this->genInsertPlugin($activity, $order, $item, $venue_commission_parent_user_id, $venue_commission_parent,
  169. "用户[{$order->user->nickname}]通过招商活动[{$activity->name}]下单, 单号为[{$order['order_no']}]共支付[{$order->pay_money}],奖励[场地负责人上级]佣金[{$venue_commission_parent}]");
  170. }
  171. }
  172. if (!empty($insert_wallet)) { // 不为空的情况下
  173. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  174. if (empty($res)) throw new \Exception(UserWalletService::getStaticError());
  175. Yii::$app->db->createCommand()->batchInsert(AddonsBusinessActivityCommissionModel::tableName(),
  176. array_keys($insert_plugin[0]), $insert_plugin)->execute();
  177. }
  178. }
  179. /**
  180. * @param AddonsBusinessActivityModel $activity
  181. * @param Order $order
  182. * @param array $item
  183. * @param int $user_id
  184. * @param $merchants_commission
  185. * @param $desc
  186. * @return array
  187. */
  188. protected function genInsertWallet(AddonsBusinessActivityModel $activity, Order $order, array $item, int $user_id, $merchants_commission, $desc): array
  189. {
  190. return [
  191. 'mall_id' => $activity->mall_id,
  192. 'user_id' => $user_id,
  193. 'is_frozen' => false,
  194. 'source_table' => OrderDetail::tableName(),
  195. 'source_table_id' => $item['id'], // 取出订单ID?
  196. 'from_type' => BusinessActivityEnum::ADDONS_NAME,
  197. 'capital_type' => BusinessActivityEnum::BUSINESS_ACTIVITY_PRIZE,
  198. 'contributor_name' => '',
  199. 'order_no' => $order['order_no'], // 这里需要订单号
  200. 'wallet_type' => UserWalletService::WALLET_TYPE_COMMISSION,
  201. 'money' => $merchants_commission,
  202. 'desc' => $desc,
  203. ];
  204. }
  205. /**
  206. * @param AddonsBusinessActivityModel $activity
  207. * @param Order $order
  208. * @param array $item
  209. * @param int $user_id
  210. * @param $merchants_commission
  211. * @param $desc
  212. * @return array
  213. */
  214. protected function genInsertPlugin(AddonsBusinessActivityModel $activity, Order $order, array $item, int $user_id, $merchants_commission, $desc): array
  215. {
  216. return [
  217. 'mall_id' => $activity->mall_id,
  218. 'user_id' => $user_id,
  219. 'commission' => bcmul($merchants_commission, 100),
  220. 'intro' => $desc,
  221. 'order_id' => $order->id,
  222. 'order_detail_id' => $item['id'],
  223. 'activity_id' => $activity->id,
  224. 'order_no' => $order->order_no,
  225. 'created_at' => time(),
  226. 'updated_at' => time(),
  227. ];
  228. }
  229. /**
  230. * 佣金退回
  231. * @param array $commission_list
  232. * @param array $score_list
  233. * @return void
  234. */
  235. public function refund(array $commission_list, array $score_list)
  236. {
  237. /*
  238. $t = Yii::$app->db->beginTransaction();
  239. try {
  240. $order_no = !empty($commission_list) ? $commission_list[0]['order_no'] : $score_list[0]['order_no'];
  241. if (empty($order_no)) throw new \Exception('没有订单编号');
  242. $order = Order::find()->where(['order_no' => $order_no])->one();
  243. if (empty($order)) throw new \Exception('订单不存在');
  244. // 获取团长信息
  245. if ($order->shipping_type == OrderStatusEnum::SHIPMENTS && !empty($order->extra_info)) { // 如果是自提订单
  246. $ext = Json::decode($order->extra_info);
  247. if (empty($ext['head_id'])) {
  248. throw new \Exception("OrderPaidRewardListener 非站点自提订单: {$order->id}");
  249. }
  250. }
  251. $insert_wallet = [];
  252. $insert_plugin = [];
  253. $wallet_main = [
  254. 'mall_id' => $order->mall_id,
  255. 'user_id' => $user_id,
  256. 'is_frozen' => false,
  257. 'source_table' => OrderDetail::tableName(),
  258. 'source_table_id' => $item['id'], // 取出订单ID?
  259. 'from_type' => CommunityEnum::ADDONS_NAME,
  260. 'capital_type' => CommunityEnum::COMMUNITY_PICKUP_PRIZE,
  261. 'contributor_name' => '',
  262. 'order_no' => $order['order_no'], // 这里需要订单号
  263. ];
  264. $plugin_main = [
  265. 'mall_id' => $mall_id,
  266. 'user_id' => $head_user_id, // 获奖用户 - 团长用户ID
  267. 'head_id' => $ext['head_id'],
  268. 'order_id' => $order['id'],
  269. 'buyer_user_id' => $user_id,
  270. 'is_inflow' => StatusEnum::DISABLED, // 非流入
  271. ];
  272. // order_no
  273. if (!empty($commission_list)) {
  274. foreach ($commission_list as $item) {
  275. }
  276. }
  277. if (!empty($score_list)) {
  278. foreach ($score_list as $item) {
  279. }
  280. }
  281. $t->commit();
  282. } catch (\Exception $e) {
  283. $t->rollBack();
  284. $exception = FormatHelper::exception($e, "社区团购退回佣金失败");
  285. \Yii::error($exception);
  286. }
  287. */
  288. }
  289. }