RewardLogic.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <?php
  2. namespace addons\ReservationService\common\logic;
  3. use addons\ReservationService\common\enums\ReservationServiceEnum;
  4. use addons\ReservationService\common\models\ReservationServiceGoodsSetting;
  5. use addons\ReservationService\common\models\ReservationServiceLevel;
  6. use addons\ReservationService\common\models\ReservationServiceOrder;
  7. use addons\ReservationService\common\models\ReservationServiceUser;
  8. use addons\ReservationService\common\services\UserService;
  9. use common\enums\OrderStatusEnum;
  10. use common\enums\StatusEnum;
  11. use common\helpers\FormatHelper;
  12. use common\models\common\CapitalLog;
  13. use common\models\order\Order;
  14. use common\models\order\OrderDetail;
  15. use common\models\user\User;
  16. use common\models\user\UserPartitionRelationship;
  17. use services\common\UserWalletService;
  18. class RewardLogic
  19. {
  20. public function exec(array $data)
  21. {
  22. try {
  23. // 取出订单
  24. /**
  25. * @var $rOrder ReservationServiceOrder
  26. */
  27. $rOrder = ReservationServiceOrder::getOne([
  28. ['order_id' => $data['id']],
  29. ['service_status' => [ReservationServiceEnum::RESERVE_ORDER_STATUS_FINISH,
  30. ReservationServiceEnum::RESERVE_ORDER_STATUS_UNDERWRITER,
  31. ReservationServiceEnum::RESERVE_ORDER_STATUS_TALKING]]
  32. ]);
  33. if (empty($rOrder)) {
  34. return true;
  35. }
  36. // 取出技师
  37. /**
  38. * @var $staff ReservationServiceUser
  39. */
  40. $staff = $rOrder->getStaff()->one();
  41. if (empty($staff)) {
  42. return true;
  43. }
  44. // 取出等级
  45. /**
  46. * @var $level ReservationServiceLevel
  47. */
  48. $level = $staff->getLevel()->andWhere(['mall_id' => $rOrder->mall_id])->one();
  49. if (empty($level)) {
  50. return true;
  51. }
  52. // 取出平台订单
  53. /**
  54. * @var $order Order
  55. */
  56. $order = $rOrder->getOrder()->one();
  57. // 门店/商户订单不做分佣处理
  58. if (empty($order) || !empty($order->store_id) || !empty($order->mch_id)) {
  59. return true;
  60. }
  61. // 取出订单详情
  62. /**
  63. * @var $orderDetails OrderDetail[]
  64. */
  65. $orderDetails = $order->getDetail()->all();
  66. if (empty($orderDetails)) {
  67. return true;
  68. }
  69. // 取出上级
  70. $parent_id_arr = UserPartitionRelationship::getParentIdArr($rOrder->staff_user_id);
  71. $parent_id_arr = array_reverse($parent_id_arr);
  72. // 只需要前面两个
  73. $reward_map = [
  74. ReservationServiceEnum::CAPITAL_TYPE_COMMISSION_FIRST,
  75. ReservationServiceEnum::CAPITAL_TYPE_COMMISSION_SECOND,
  76. ];
  77. $insert_wallet = [];
  78. $settlement_method = \Yii::$app->services->setting->addons->get($staff->mall_id, ReservationServiceEnum::ADDONS_NAME, 'basic.settlement_method');
  79. $is_frozen = $settlement_method == OrderStatusEnum::ACCOMPLISH; // 如果需要确认[签收]后才发放,那么就是冻结状态
  80. foreach ($orderDetails as $orderDetail) {
  81. if ($orderDetail->id != $rOrder->order_detail_id) continue;
  82. $commission = $rOrder->commission;
  83. // $commission = $level->item_commission;
  84. // if (empty($level->item_commission_type)) {
  85. // $commission = bcmul(bcmul($commission, $orderDetail->goods_price, 2), 0.01, 2);
  86. // }
  87. //
  88. // 判断是否有独立启用
  89. /**
  90. * @var $goods_setting ReservationServiceGoodsSetting
  91. */
  92. $goods_setting = ReservationServiceGoodsSetting::getOne([
  93. ['mall_id' => $rOrder->mall_id],
  94. ['status' => StatusEnum::ENABLED],
  95. ['item_id' => $orderDetail->goods_id],
  96. ['item_type' => 'goods'],
  97. ['is_enable' => StatusEnum::ENABLED],
  98. ['commission_type' => UserWalletService::WALLET_TYPE_COMMISSION]
  99. ]);
  100. //
  101. // if (!empty($goods_setting)) {
  102. // $commission = $goods_setting->commission;
  103. // if (!empty($goods_setting->is_percent)) {
  104. // $commission = bcmul(bcmul($commission, $orderDetail->goods_price, 2), 0.01, 2);
  105. // }
  106. // }
  107. // 如果佣金小于等于0那么就不进行分佣
  108. if (empty($commission) || $commission <= 0) continue;
  109. // 技师获得的奖励
  110. $insert_wallet[] = $this->packData($order, $orderDetail, $commission, $rOrder->user_id, $rOrder->staff_user_id,
  111. ReservationServiceEnum::CAPITAL_TYPE_COMMISSION, UserWalletService::WALLET_TYPE_COMMISSION,
  112. "技师 [$rOrder->staff_user_id] 为用户 [$rOrder->user_id] 完成订单 [$order->order_no] 提供 [$orderDetail->goods_name] 服务获得 [$commission] " .
  113. ReservationServiceEnum::CAPITAL_TYPE_MAP[ReservationServiceEnum::CAPITAL_TYPE_COMMISSION], $is_frozen, $orderDetail->goods_price);
  114. // 享受分销提成奖励; 0关闭,1开启
  115. if (!empty($parent_id_arr) && !empty($level->enable_distribution_commission)) {
  116. if (empty($goods_setting) || !empty($goods_setting->is_enable_distribution)) {
  117. foreach ($parent_id_arr as $key => $parent_id) {
  118. $capital_type = $reward_map[$key] ?? null;
  119. if (empty($capital_type)) break;
  120. $deep_index = $key + 1;
  121. $commission_key = "level{$deep_index}_commission";
  122. $commission_type_key = "level{$deep_index}_commission_type";
  123. // 获取上级
  124. // 一级佣金
  125. $commission_level = $level[$commission_key] ?? 0;
  126. if (empty($level[$commission_type_key])) {
  127. $commission_level = bcmul(bcmul($commission_level, $commission, 0.01), 0.01, 2);
  128. }
  129. // 是否有独立设置
  130. if (!empty($goods_setting)) {
  131. $commission = $goods_setting->distribution_config[$deep_index]['commission'] ?? 0;
  132. if (!empty($goods_setting->distribution_config[$deep_index]['is_percent'])) {
  133. $commission = bcmul(bcmul($commission, $orderDetail->goods_price, 2), 0.01, 2);
  134. }
  135. }
  136. // 如果佣金小于等于0 那么就不进行分佣
  137. if (empty($commission_level) || $commission_level < 0) break;
  138. $insert_wallet[] = $this->packData($order, $orderDetail, $commission_level, $rOrder->staff_user_id, $parent_id, $capital_type,
  139. UserWalletService::WALLET_TYPE_COMMISSION,
  140. "用户 [$parent_id] 推荐技师 [$rOrder->staff_user_id] 完成订单 [$order->order_no] 服务获得 [$commission_level] " .
  141. ReservationServiceEnum::CAPITAL_TYPE_MAP[$capital_type], $is_frozen, $orderDetail->goods_price);
  142. }
  143. }
  144. }
  145. }
  146. if (!empty($insert_wallet)) {
  147. $t = \Yii::$app->db->beginTransaction();
  148. if (!$is_frozen) { // 如果是非冻结的情况下,那么累加佣金,否则不累加
  149. $userService = new UserService();
  150. foreach ($insert_wallet as $item) {
  151. $userService->addCommission($item['user_id'], $item['money']);
  152. }
  153. }
  154. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  155. if (empty($res)) throw new \Exception(UserWalletService::getStaticError());
  156. $t->commit();
  157. }
  158. } catch (\Exception $e) {
  159. if (!empty($t)) $t->rollBack();
  160. \Yii::error("123123123213 999 " . var_export($data, true));
  161. \Yii::error(FormatHelper::exception($e, __METHOD__));
  162. return false;
  163. }
  164. \Yii::error("123123123213 101010 " . var_export($data, true));
  165. return true;
  166. }
  167. /**
  168. * @param Order $order
  169. * @param OrderDetail $orderDetail
  170. * @param string $commission
  171. * @param int $from_user_id
  172. * @param int $to_user_id
  173. * @param string $capital_type
  174. * @param string $wallet_type
  175. * @param string $desc
  176. * @param bool $is_frozen
  177. * @param $contributor_money
  178. * @return array
  179. */
  180. protected function packData(Order $order, OrderDetail $orderDetail,
  181. string $commission, int $from_user_id, int $to_user_id, string $capital_type,
  182. string $wallet_type, string $desc, bool $is_frozen, $contributor_money)
  183. {
  184. return [
  185. 'mall_id' => $order->mall_id,
  186. 'user_id' => $to_user_id,
  187. 'is_frozen' => $is_frozen,
  188. 'source_table' => 'order_detail',
  189. 'source_table_id' => $orderDetail->id, // 取出订单ID?
  190. 'from_type' => ReservationServiceEnum::ADDONS_NAME,
  191. 'capital_type' => $capital_type,
  192. 'contributor_name' => $orderDetail->goods_name,
  193. 'order_no' => $order->order_no, // 这里需要订单号
  194. 'money'=> $commission,
  195. 'wallet_type' => $wallet_type,
  196. 'desc' => $desc,
  197. 'contributor_id' => $from_user_id,
  198. 'contributor_money' => $contributor_money
  199. ];
  200. }
  201. /**
  202. * 解冻
  203. * @param array $order
  204. * @return bool
  205. */
  206. public function unfreeze(array $order)
  207. {
  208. $t = \Yii::$app->db->beginTransaction();
  209. try {
  210. $capital_types = [
  211. ReservationServiceEnum::CAPITAL_TYPE_COMMISSION,
  212. ReservationServiceEnum::CAPITAL_TYPE_COMMISSION_FIRST,
  213. ReservationServiceEnum::CAPITAL_TYPE_COMMISSION_SECOND,
  214. ];
  215. $where = [
  216. ['source_table' => 'order_detail'],
  217. ['order_no' => $order['order_no']],
  218. ['from_type' => ReservationServiceEnum::ADDONS_NAME],
  219. ['capital_type' => $capital_types],
  220. ['status' => CapitalLog::STATUS_WAIT_SEND]
  221. ];
  222. $params['where'] = $where;
  223. //佣金
  224. $wallet_type = 'commission';
  225. CapitalLog::$capitalType = "{$wallet_type}_frozen";
  226. $commission_list = CapitalLog::lists($params);
  227. $userService = new UserService();
  228. if (!empty($commission_list)) { // 默认会删除?
  229. foreach ($commission_list as $item) {
  230. $userService->addCommission($item['user_id'], $item['change_num']);
  231. UserWalletService::unfrozen($item['id'], $wallet_type);
  232. }
  233. }
  234. $wallet_type = 'score';
  235. CapitalLog::$capitalType = "{$wallet_type}_frozen";
  236. $score_list = CapitalLog::lists($params);
  237. if (!empty($score_list)) {
  238. foreach ($score_list as $item) {
  239. UserWalletService::unfrozen($item['id'], $wallet_type);
  240. }
  241. }
  242. $t->commit();
  243. } catch (\Exception $e) {
  244. $t->rollBack();
  245. \Yii::error(FormatHelper::exception($e, __METHOD__));
  246. return false;
  247. }
  248. return true;
  249. }
  250. }