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.

277 lines
9.9 KiB

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