You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
10 KiB

  1. <?php
  2. namespace App\Service;
  3. use App\Commons\Log;
  4. use App\Constants\LogLabel;
  5. use App\Model\FinancialRecord;
  6. use App\Model\Order;
  7. use App\Model\OrderMain;
  8. use App\Model\ServiceReward;
  9. use App\Model\Store;
  10. use App\Model\StoreAccount;
  11. use App\Model\SystemConfig;
  12. use App\Model\UserBalance;
  13. use App\Model\UserRelationBind;
  14. use Hyperf\DbConnection\Db;
  15. use Hyperf\Di\Annotation\Inject;
  16. class SeparateAccountsService implements SeparateAccountsServiceInterface
  17. {
  18. /**
  19. * @Inject
  20. * @var Log
  21. */
  22. protected $log;
  23. /**
  24. * @Inject
  25. * @var UserServiceInterface
  26. */
  27. protected $userService;
  28. /**
  29. * @Inject
  30. * @var FinancialRecordServiceInterface
  31. */
  32. protected $financialRecordService;
  33. /**
  34. * @Inject
  35. * @var MiniprogramServiceInterface
  36. */
  37. protected $miniprogramService;
  38. /**
  39. * @inheritDoc
  40. */
  41. public function orderOnlinePaid($global_order_id)
  42. {
  43. // 线上订单支付完成
  44. // 订单
  45. $orderMain = OrderMain::query()
  46. ->where(['global_order_id' => $global_order_id])
  47. ->first();
  48. if (empty($orderMain)) {
  49. return false;
  50. }
  51. // =======用户支付流水 / Start=======
  52. $this->financialRecordService->userByOFLOrderPaid($orderMain->user_id, $orderMain->id, $orderMain->money);
  53. // =======用户支付流水 / End=======
  54. }
  55. /**
  56. * @inheritDoc
  57. */
  58. public function orderOnlineCompleted($global_order_id)
  59. {
  60. // 线上订单完成(用户点击确认收货完成/管理后台点击完成/配送员点击完成/自动收货等),进行相关分账
  61. // 订单
  62. $orderMain = OrderMain::query()
  63. ->where(['global_order_id' => $global_order_id])
  64. ->whereIn('state', [OrderMain::ORDER_STATE_COMPLETE,OrderMain::ORDER_STATE_EVALUATED,OrderMain::ORDER_STATE_UNREFUND])
  65. ->first();
  66. if (empty($orderMain)) {
  67. return false;
  68. }
  69. $currentTime = time();
  70. Db::beginTransaction();
  71. try {
  72. // =======商户订单收入流水 / Start=======
  73. // 查询子订单
  74. $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time'])
  75. ->where(['order_main_id' => $orderMain->id])
  76. ->get()->toArray();
  77. foreach ($orders as $key => &$order) {
  78. // 商户
  79. $store = Store::find($order['store_id']);
  80. // 旧商户流水基础数据 TODO 直接移除或后续考虑移除
  81. $storeAccountBase = [
  82. 'user_id' => $order['user_id'],
  83. 'order_id' => $order['id'],
  84. 'store_id' => $order['store_id'],
  85. 'type' => 1,
  86. 'time' => date('Y-m-d H:i:s', $currentTime),
  87. 'add_time' => $currentTime,
  88. ];
  89. // 旧商户流水 TODO 直接移除或后续考虑移除
  90. $storeAccount = [
  91. 'money' => $order['money'],
  92. 'note' => '线上订单',
  93. 'category' => 1,
  94. ];
  95. StoreAccount::query()->insert(array_merge($storeAccountBase, $storeAccount));
  96. // 新商户流水
  97. $this->financialRecordService->storeByOLOrderComp($store->user_id, $orderMain->id ,$order['money']);
  98. }
  99. // =======商户订单收入流水 / End=======
  100. // =======社区服务点分账 / Start=======
  101. // 前提:用户线上下单并且订单完成
  102. // 奖励规则A:用户是平台新用户,奖励社区服务点平台新用户奖励x元+平台新用户首单奖励y元+订单商品金额z%的分成
  103. // 奖励规则B:用户是非新用户,奖励社区服务点订单实际支付金额z%的分成
  104. // =======社区服务点分账 / Start=======
  105. // 当前用户的社区服务点绑定关系
  106. $communityBind = UserRelationBind::query()
  107. ->where(['bind_type' => UserRelationBind::BIND_TYPE_COMMUNITY, 'user_id' => $orderMain->user_id])
  108. ->first();
  109. if ($communityBind) {
  110. // 奖励/分账金额
  111. $award = ServiceReward::query()->where(['type' => ServiceReward::TYPE_COMMUNITY])->first();
  112. if (empty($award)) {
  113. Db::rollBack();
  114. return false;
  115. }
  116. $award = $award->set_reward;
  117. // 平台新用户
  118. if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->id)) {
  119. $this->financialRecordService->communityAwardByPlatNewUser($communityBind->source_id, $orderMain->global_order_id, $award['new_user_reward']);
  120. $this->financialRecordService->communityAwardByPlatNewUserFirstOLOrder($communityBind->source_id, $orderMain->global_order_id, $award['first_reward']);
  121. }
  122. // 账单分成
  123. $money = bcmul($orderMain->money, bcdiv($award['flow_reward'], 100, 6), 2);
  124. $this->financialRecordService->communitySeparateAccountsByOrderComp($communityBind->source_id, $orderMain->global_order_id, $money);
  125. }
  126. // =======社区服务点分账 / End=======
  127. Db::commit();
  128. return true;
  129. } catch (\Exception $e) {
  130. $this->log->event(LogLabel::SEPARATE_ACCOUNTS_LOG, ['exception' => $e->getMessage(), 'order_main' => json_encode($orderMain)]);
  131. Db::rollBack();
  132. return false;
  133. }
  134. }
  135. /**
  136. * @inheritDoc
  137. */
  138. public function orderOfflinePaid($global_order_id)
  139. {
  140. // 线下订单支付完成
  141. // 订单
  142. $orderMain = OrderMain::query()
  143. ->where(['global_order_id' => $global_order_id])
  144. ->first();
  145. if (empty($orderMain)) {
  146. return false;
  147. }
  148. // 查询子订单,当面付目前实际上只有一个子订单
  149. $order = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time'])
  150. ->where(['order_main_id' => $orderMain->id])
  151. ->first();
  152. if (empty($order)) {
  153. return false;
  154. }
  155. $currentTime = time();
  156. Db::beginTransaction();
  157. try {
  158. // =======用户支付流水 / Start=======
  159. $this->financialRecordService->userByOFLOrderPaid($orderMain->user_id, $orderMain->id, $orderMain->money);
  160. // =======用户支付流水 / End=======
  161. // =======线下订单支付完成商户分账 / Start=======
  162. // 前提:用户线上下单并且支付完成
  163. // 奖励规则A:用户是平台新用户,奖励商户2元
  164. // 奖励规则B:用户是非新用户,但是是商户当日首单,奖励商户0.05元
  165. // =======线下订单支付完成商户分账 / Start=======
  166. // 旧商户订单流水基础数据 TODO 直接移除或后续考虑移除
  167. $storeAccountBase = [
  168. 'user_id' => $order->user_id,
  169. 'order_id' => $order->id,
  170. 'store_id' => $order->store_id,
  171. 'type' => 1,
  172. 'time' => date('Y-m-d H:i:s', $currentTime),
  173. 'add_time' => $currentTime,
  174. ];
  175. // 旧商户订单流水 TODO 直接移除或后续考虑移除
  176. $storeAccount = [
  177. 'money' => $order->money,
  178. 'note' => '当面付订单收入',
  179. 'category' => 2,
  180. ];
  181. StoreAccount::query()->insert(array_merge($storeAccountBase, $storeAccount));
  182. // 商户
  183. $store = Store::find($order->store_id);
  184. // 新商户订单流水
  185. $this->financialRecordService->storeByOFLOrderComp($store->user_id, $orderMain->id, $order->money);
  186. $needAward = false;
  187. $awardAmount = 0;
  188. // 新用户商户奖励
  189. if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->id)) {
  190. $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_new_user'])->value('value');
  191. // 旧商户流水 TODO 直接移除或后续考虑移除
  192. $storeAccount = [
  193. 'money' => $awardAmount,
  194. 'note' => '新用户下单成功,平台奖励',
  195. 'category' => 3,
  196. ];
  197. // 新商户流水
  198. $this->financialRecordService->storeAwardByPlatNewUserOFLOrder($store->user_id, $orderMain->id, $awardAmount);
  199. $needAward = true;
  200. } else {
  201. // 商户当日首单奖励
  202. if (
  203. $this->userService->isStoreFirstOrderToday(
  204. $order->user_id,
  205. $order->store_id,
  206. $order->id,
  207. FinancialRecord::OFL_FIRST_AWARD_LIMIT_AMOUNT
  208. )
  209. ) {
  210. $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_each_order'])->value('value');
  211. // 旧商户流水 TODO 直接移除或后续考虑移除
  212. $storeAccount = [
  213. 'money' => $awardAmount,
  214. 'note' => '用户下单成功,平台奖励',
  215. 'category' => 4,
  216. ];
  217. // 新商户流水
  218. $this->financialRecordService->storeAwardByTodayFirstOFLOrder($store->user_id, $orderMain->id, $awardAmount);
  219. $needAward = true;
  220. }
  221. }
  222. if ($needAward && $awardAmount) {
  223. // 旧商户流水 TODO 直接移除或后续考虑移除
  224. StoreAccount::query()->insert(array_merge($storeAccountBase, $storeAccount));
  225. // 发模板消息
  226. $openid = Users::query()->where(['id' => $store['user_id']])->value('openid');
  227. $res = $this->miniprogramService->sendTemMsgForAward($storeAccount['money'], $storeAccount['note'], $openid, $storeAccountBase['time']);
  228. }
  229. // =======线下订单支付完成商户分账 / End=======
  230. Db::commit();
  231. return true;
  232. } catch (\Exception $e) {
  233. $this->log->event(LogLabel::SEPARATE_ACCOUNTS_LOG, ['exception' => $e->getMessage(), 'order_main' => json_encode($orderMain)]);
  234. Db::rollBack();
  235. return false;
  236. }
  237. }
  238. }