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.

290 lines
11 KiB

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