CommissionService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. <?php
  2. namespace addons\OperationCenter\common\services;
  3. use common\enums\UserWalletEnum;
  4. use services\common\UserWalletService;
  5. use addons\OperationCenter\common\models\Level;
  6. use addons\OperationCenter\common\models\MallUser;
  7. use addons\OperationCenter\common\models\MallOrder;
  8. use addons\OperationCenter\common\models\UserCenter;
  9. use addons\OperationCenter\common\models\CommissionLog;
  10. use addons\OperationCenter\common\models\MallCapitalLog;
  11. use addons\OperationCenter\common\models\MallOrderDetail;
  12. use addons\OperationCenter\common\models\UserAffiliation;
  13. use addons\OperationCenter\common\enums\OperationCenterEnum;
  14. use addons\OperationCenter\common\helpers\ArrayHelper;
  15. use addons\OperationCenter\common\models\ApplyList;
  16. use addons\OperationCenter\common\models\CommissionItemSetting;
  17. use addons\OperationCenter\common\models\CommissionItemSettingDetail;
  18. /**
  19. * 佣金服务类
  20. *
  21. * CommissionService
  22. * @package addons\OperationCenter\common\services
  23. */
  24. class CommissionService extends BaseService
  25. {
  26. /**
  27. * @var MallOrder
  28. */
  29. protected $order;
  30. /**
  31. * @var array
  32. */
  33. protected $center = [];
  34. /**
  35. * @var Level
  36. */
  37. protected $level;
  38. /**
  39. * @var array
  40. */
  41. protected $commissionAmounts;
  42. /**
  43. * 设置订单
  44. *
  45. * @param MallOrder $order
  46. * @return void
  47. */
  48. public function setOrder(MallOrder $order)
  49. {
  50. $this->order = $order;
  51. }
  52. /**
  53. * 获取佣金分页列表
  54. *
  55. * @param array $params
  56. * @return array
  57. */
  58. public function getPageList(array $params = [])
  59. {
  60. $name = $params['name'] ?? '';
  61. $status = $params['status'] ?? '';
  62. $mobile = $params['mobile'] ?? '';
  63. $user_id = $params['user_id'] ?? '';
  64. $user_keyword = $params['user_keyword'] ?? '';
  65. return CommissionLog::getPageList(
  66. $this->getPage($params), $this->getLimit($params), function ($query)
  67. use ($name, $status, $mobile, $user_id, $user_keyword)
  68. {
  69. $query->andWhere(['mall_id' => $this->mall_id]);
  70. // 会员ID
  71. if (!empty($user_id)) {
  72. $query->andWhere(['user_id' => $user_id]);
  73. }
  74. // 会员名称
  75. if (!empty($name)) {
  76. $query->andWhere(['user_id' => ApplyList::getUserIdByName(
  77. $this->mall_id, $name
  78. )]);
  79. }
  80. // 联系电话
  81. if (!empty($mobile)) {
  82. $query->andWhere(['user_id' => ApplyList::getUserIdByMobile(
  83. $this->mall_id, $mobile
  84. )]);
  85. }
  86. // 会员信息查询
  87. if (!empty($user_keyword)) {
  88. $query->andWhere(['user_id' => MallUser::getUserIdByUserKeyWord(
  89. $this->mall_id, $user_keyword
  90. )]);
  91. }
  92. // 状态
  93. if ($status !== '') {
  94. $query->andWhere(['status' => $status]);
  95. }
  96. $query->with([
  97. 'user' => function ($query) {
  98. $query->select(['id', 'nickname', 'username', 'mobile', 'avatar_url']);
  99. },
  100. 'levelInfo' => function ($query) {
  101. $query->select(['id', 'mall_id', 'level', 'name']);
  102. },
  103. 'order' => function ($query) {
  104. $query->select(['id', 'order_no']);
  105. },
  106. 'apply' => function ($query) {
  107. $query->select(['id', 'user_id', 'name', 'center_name']);
  108. },
  109. ]);
  110. }
  111. );
  112. }
  113. /**
  114. * 检测佣金
  115. *
  116. * @param MallOrder $order
  117. * @return void
  118. */
  119. public function checkCommission(MallOrder $order)
  120. {
  121. $this->setOrder($order);
  122. if (!$this->getSettingService()->isOpen()) {
  123. return false;
  124. }
  125. // 直推
  126. if (
  127. // $this->getSettingService()->hasCommission(1)
  128. // &&
  129. $user_id = $this->getSelectCenterUser()
  130. ) {
  131. // 添加佣金
  132. $this->addCommission($user_id, 1);
  133. }
  134. // 间推
  135. if (
  136. // $this->getSettingService()->hasCommission(2)
  137. // &&
  138. $user_id && ($parant_id = $this->getUserParentId($user_id))
  139. ) {
  140. $this->addCommission($parant_id, 2);
  141. }
  142. }
  143. /**
  144. * 发放佣金
  145. *
  146. * @param integer $order_id
  147. * @return void
  148. */
  149. public function paymentCommission(int $order_id, int $is_finish)
  150. {
  151. // 是否结算
  152. if ($this->getSettingService()->isSettlement($is_finish)) {
  153. $commission_logs = CommissionLog::getLogByOrderId($order_id);
  154. $ids = array_column($commission_logs, 'id');
  155. // 查询
  156. MallCapitalLog::$capitalType = 'commission_frozen';
  157. $list = MallCapitalLog::getListByIds($ids);
  158. // 分组
  159. $array = ArrayHelper::arrayGroupByField($list, 'user_id');
  160. foreach ($array as $user_id => $val) {
  161. // 增加已结算
  162. $sum = array_sum(array_column($val, 'change_num'));
  163. $sum && UserCenter::addSettlementAmount($user_id, $sum);
  164. }
  165. // 结算
  166. foreach ($list as $item) {
  167. UserWalletService::unfrozen($item['id'], 'commission');
  168. }
  169. // 修改状态
  170. CommissionLog::changeStatusByIds($ids);
  171. }
  172. }
  173. /**
  174. * 废弃佣金
  175. *
  176. * @param integer $order_detail_id
  177. * @return void
  178. */
  179. public function discardCommission(int $order_detail_id)
  180. {
  181. $commission_logs = CommissionLog::getLogByOrderDetailId($order_detail_id);
  182. $ids = array_column($commission_logs, 'id');
  183. // 分组
  184. $array = ArrayHelper::arrayGroupByField($commission_logs, 'user_id');
  185. foreach ($array as $user_id => $val) {
  186. // 增加已结算
  187. $sum = array_sum(array_column($val, 'commission_amount'));
  188. $sum && UserCenter::addDiscardAmount($user_id, $sum);
  189. }
  190. // 修改状态
  191. CommissionLog::changeStatusByIds($ids, 2);
  192. }
  193. /**
  194. * 添加佣金
  195. *
  196. * @param integer $user_id
  197. * @param integer $level 佣金等级 直推 间推
  198. * @return void
  199. */
  200. protected function addCommission(int $user_id, int $level)
  201. {
  202. // 获取设置记录ID
  203. $setting_id = $this->getSettingService()->getLastSettingId();
  204. $wallet_log = [];
  205. foreach ($this->order->detail as $detail) {
  206. // 是否已经创建佣金
  207. $has_commission = CommissionLog::hasCommissonByDetailId($detail->id, $level);
  208. if (!$has_commission) {
  209. $this->commissionAmounts[$level] = $commission_amount = $this->getCommissionAmount($level, $detail);
  210. if (
  211. $commission_amount
  212. &&
  213. $this->getSettingService()->hasCommission($level) // 查看设置是否拥有佣金
  214. ) {
  215. // 添加分佣
  216. $id = CommissionLog::addCommissionLog(
  217. $this->mall_id, $user_id, $this->order->user_id, $detail->goods_name,
  218. $detail->price, $this->order->order_no, $this->level->level, $level,
  219. $this->order->id, $detail->id, $setting_id, $commission_amount
  220. );
  221. $id && $wallet_log[] = [
  222. 'mall_id' => $this->mall_id,
  223. 'user_id' => $user_id,
  224. 'is_frozen' => true,
  225. 'wallet_type' => 'commission',
  226. 'money' => $commission_amount,
  227. 'desc' => sprintf('运营中心%s级佣金', $level),
  228. 'source_table' => CommissionLog::tableName(),
  229. 'source_table_id' => $id,
  230. 'from_type' => OperationCenterEnum::ADDONS_NAME_OPERATION_CENTER,
  231. 'capital_type' => 'operation_center_' . $level,
  232. ];
  233. }
  234. }
  235. }
  236. // 待结算金额
  237. $sum = array_sum(array_column($wallet_log, 'money'));
  238. $sum && UserCenter::addSettlementAmountTotal($user_id, $sum);
  239. $wallet_log && UserWalletService::batchHandleByQueue($wallet_log);
  240. }
  241. /**
  242. * 获取佣金数量
  243. *
  244. * @param int $level
  245. * @return float|false
  246. */
  247. protected function getCommissionAmount($level, MallOrderDetail $order_detail)
  248. {
  249. /**
  250. * @var Level
  251. */
  252. $level_info = $this->center[$level]->levelInfo;
  253. if (empty($level_info)) return false;
  254. // level
  255. $this->level = $level_info;
  256. // 商品独立分佣
  257. $item_setting_detail = $this->hasGoodsAloneCommissionByDetail($order_detail, $level);
  258. // 不参与分佣
  259. if ($item_setting_detail && ($item_setting_detail->itemSetting->is_partake == 0)) {
  260. return false;
  261. }
  262. // 独立分佣
  263. if ($item_setting_detail && $item_setting_detail->itemSetting->is_enable) {
  264. // 分佣类型
  265. $type = $item_setting_detail->getCommissionTypeByLevel($level);
  266. // 分佣数量
  267. $amount = $item_setting_detail->getCommissionValueByLevel($level);
  268. } else {
  269. // 分佣类型
  270. $type = $level_info->getCommissionTypeByLevel($level);
  271. // 分佣数量
  272. $amount = $level_info->getCommissionValueByLevel($level);
  273. }
  274. // 固定金额
  275. if ($type == Level::FIXED) {
  276. return bcmul($amount, $order_detail->num);
  277. }
  278. // 获取订单金额
  279. $order_amount = $this->getOrderCommissionAmount($order_detail, $level);
  280. return bcdiv(bcmul($order_amount, $amount), 100, 2);
  281. }
  282. /**
  283. * 是否商品独立分佣
  284. *
  285. * @param MallOrderDetail $detail
  286. * @param int $level 分佣级别
  287. * @return false|CommissionItemSettingDetail
  288. */
  289. protected function hasGoodsAloneCommissionByDetail(MallOrderDetail $detail)
  290. {
  291. /**
  292. * @var CommissionItemSetting|null
  293. */
  294. $item_setting = $detail->goods->itemSetting;
  295. if (empty($item_setting)) return false;
  296. // 未开启独立分佣
  297. // if (!($item_setting->is_partake && $item_setting->is_enable)) return false;
  298. return $item_setting->getCommissionDetailByLevel($this->level->level);
  299. }
  300. /**
  301. * 获取订单金额进行分佣金额
  302. *
  303. * @return float
  304. */
  305. protected function getOrderCommissionAmount($order_detail, $level)
  306. {
  307. // 间推佣金使用1级佣金的分佣金额进行计算
  308. if ($level == 2) return $this->commissionAmounts[1];
  309. $computing_method = $this->getSettingService()->getComputingMethod();
  310. // 支付金额
  311. if ($computing_method == OperationCenterEnum::COMPUTING_METHOD_PAY_PRICE) {
  312. return $order_detail->goods_price;
  313. }
  314. // 商品售价
  315. if ($computing_method == OperationCenterEnum::COMPUTING_METHOD_GOODS_PRICE) {
  316. return $order_detail->original_goods_price;
  317. }
  318. // 商品利润
  319. if ($computing_method == OperationCenterEnum::COMPUTING_METHOD_GOODS_PROFIT) {
  320. return bcadd(
  321. bcsub($order_detail->goods_price, $order_detail->cost_price, 2),
  322. $order_detail->adjust_money, 2
  323. );
  324. }
  325. return 0;
  326. }
  327. /**
  328. * 获取直推
  329. *
  330. * @return int|false
  331. */
  332. protected function getSelectCenterUser()
  333. {
  334. if (empty($this->order)) return false;
  335. $buy_user_id = $this->order->user_id;
  336. // 获取选择
  337. $user_affiliation = UserAffiliation::getUserAffiliationByUserId($buy_user_id);
  338. // 为选择运营中心
  339. if (empty($user_affiliation->center)) {
  340. return false;
  341. }
  342. // 设置直推
  343. $this->center[1] = $user_affiliation->center;
  344. return $user_affiliation->center->user_id;
  345. }
  346. /**
  347. * 获取间推
  348. *
  349. * @param int $user_id
  350. * @return int|false
  351. */
  352. protected function getUserParentId(int $user_id)
  353. {
  354. $user_id = MallUser::getParentId($user_id);
  355. if (empty($user_id)) return false;
  356. $center = UserCenter::getCenterByUserId($user_id);
  357. if (empty($center)) return false;
  358. $this->center[2] = $center;
  359. return $user_id;
  360. }
  361. }