CalcChannel.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. namespace App\Modules\Finance\Services;
  3. use App\Modules\Channel\Models\Channel;
  4. use App\Modules\Finance\Models\Bill;
  5. use App\Modules\Finance\Models\CommissionRate;
  6. use App\Modules\Finance\Models\FinancialPayMerchantBalance;
  7. use App\Modules\Finance\Models\FinancialStat;
  8. use App\Modules\Trade\Models\Order;
  9. use DB;
  10. use Exception;
  11. /**
  12. * 渠道结算
  13. *
  14. * @property \App\Modules\Channel\Models\Channel $channel 渠道Model
  15. * @property string $day 日期
  16. * @property float $rate 结算比例
  17. */
  18. class CalcChannel
  19. {
  20. private $channel;
  21. private $day;
  22. private $rate;
  23. public function __construct(Channel $channel)
  24. {
  25. $this->day = date('Y-m-d', strtotime("-1 day"));
  26. $this->channel = $channel;
  27. $this->rate = $this->getRate();
  28. }
  29. /**
  30. * 获取渠道当前结算比例
  31. * @return float
  32. */
  33. private function getRate()
  34. {
  35. $rate = 0.0;
  36. $commissionRates = CommissionRate::where('distribution_channel_id', $this->channel->id)
  37. ->orderBy('begin_amount', 'asc')
  38. ->get()
  39. ->all();
  40. if (count($commissionRates) == 1) {
  41. $commissionRate = $commissionRates[0];
  42. $rate = $commissionRate->rate;
  43. } else if ($commissionRates) {
  44. $startMonth = date('Y-m-01');
  45. $endMonth = date('Y-m-d', strtotime("$startMonth +1 month -1 day"));
  46. $rechargeAmountCount = Bill::where('distribution_channel_id', $this->channel->id)
  47. ->where('date', '<=', $endMonth)
  48. ->where('date', '>=', $startMonth)
  49. ->sum('recharge_amount');
  50. foreach ($commissionRates as $commissionRate) {
  51. if ($rechargeAmountCount >= $commissionRate->begin_amount) {
  52. //结束金额存在,并且结算金额小于结束金额,结束
  53. if (
  54. is_numeric($commissionRate->end_amount) &&
  55. $commissionRate->end_amount > 0 &&
  56. $rechargeAmountCount < $commissionRate->end_amount
  57. ) {
  58. $rate = $commissionRate->rate;
  59. break;
  60. }
  61. $rate = $commissionRate->rate;
  62. }
  63. }
  64. }
  65. return $rate;
  66. }
  67. /**
  68. * 计算结算数据
  69. */
  70. public function calc()
  71. {
  72. $amount = $this->getChannelOrdersAmount();
  73. $pay_merchants_amount = $this->getChannelPayMerchantsOrdersAmount();
  74. try {
  75. DB::beginTransaction();
  76. $this->createBill($amount);
  77. $this->createPayMerchantBills($pay_merchants_amount);
  78. DB::commit();
  79. } catch (Exception $e) {
  80. DB::rollback();
  81. }
  82. }
  83. /**
  84. * 获取结算金额
  85. * @return float
  86. */
  87. private function getChannelOrdersAmount()
  88. {
  89. return Order::join('pay_merchants', 'pay_merchants.id', 'orders.pay_merchant_id')
  90. ->where('orders.status', 'PAID')->where('orders.distribution_channel_id', $this->channel->id)
  91. ->where('orders.created_at', '<=', $this->day . '23:59:59')->where('orders.created_at', '>=', $this->day)
  92. ->where('pay_merchants.is_self_channel', 1)
  93. ->sum('orders.price');
  94. }
  95. /**
  96. * 创建结算单
  97. */
  98. private function createBill(float $amount)
  99. {
  100. $params = [
  101. 'distribution_channel_id' => $this->channel->id,
  102. 'distribution_channel_name' => $this->channel->nickname,
  103. 'date' => $this->day,
  104. 'recharge_amount' => $amount,
  105. 'settlement_price' => $amount * $this->rate,
  106. 'rate' => $this->rate,
  107. 'tallage' => 0,
  108. ];
  109. Bill::create($params);
  110. $this->updateFinance($params);
  111. }
  112. /**
  113. * 更新渠道可提现金额
  114. */
  115. private function updateFinance(array $data)
  116. {
  117. $financialStat = FinancialStat::where('distribution_channel_id', $this->channel->id)->first();
  118. if ($financialStat) {
  119. $financialStat->enable_withdrawal_amount = (float) $financialStat->enable_withdrawal_amount + (float) $data['settlement_price'];
  120. $financialStat->commission_rate = $this->rate;
  121. $financialStat->save();
  122. } else {
  123. $params = [
  124. 'distribution_channel_id' => $this->channel->id,
  125. 'accumulative_withdrawal_amount' => 0,
  126. 'enable_withdrawal_amount' => $data['settlement_price'],
  127. 'latest_withdrawal_amount' => 0,
  128. 'withdraw_pending_amount' => 0,
  129. 'commission_rate' => $this->rate
  130. ];
  131. FinancialStat::create($params);
  132. }
  133. }
  134. /**
  135. * 获取不同的支付通道的结算金额
  136. * @return array
  137. */
  138. private function getChannelPayMerchantsOrdersAmount()
  139. {
  140. return Order::join('pay_merchants', 'pay_merchants.id', 'orders.pay_merchant_id')
  141. ->where('orders.status', 'PAID')->where('orders.distribution_channel_id', $this->channel->id)
  142. ->where('orders.created_at', '<=', $this->day . '23:59:59')->where('orders.created_at', '>=', $this->day)
  143. ->where('pay_merchants.is_self_channel', 1)
  144. ->groupBy('pay_merchants.pay_company_id')
  145. ->selectRaw('sum(orders.price) as amount,pay_company_id,pay_company_name')
  146. ->get()
  147. ->all();
  148. }
  149. /**
  150. * 创建不同支付通道的结算单
  151. */
  152. private function createPayMerchantBills(array $pay_merchants_amount)
  153. {
  154. foreach ($pay_merchants_amount as $item) {
  155. $params = [
  156. 'distribution_channel_id' => $this->channel->id,
  157. 'date' => $this->day,
  158. 'recharge_amount' => $item->amount,
  159. 'settlement_price' => $item->amount * $this->rate,
  160. 'rate' => $this->rate,
  161. 'pay_company_id' => $item->pay_company_id,
  162. 'tallage' => 0,
  163. ];
  164. BillPayMerchant::create($params);
  165. $this->updatePayMerchantFinance($params);
  166. }
  167. }
  168. /**
  169. * 更新不同支付通道的可提现金额
  170. */
  171. private function updatePayMerchantFinance(array $data)
  172. {
  173. $financialStat = FinancialPayMerchantBalance::where('distribution_channel_id', $this->channel->id)
  174. ->where('pay_merchant_company_id', $data['pay_company_id'])
  175. ->first();
  176. if ($financialStat) {
  177. $financialStat->enable_withdrawal_amount = (float) $financialStat->enable_withdrawal_amount + (float) $data['settlement_price'];
  178. $financialStat->commission_rate = $this->rate;
  179. $financialStat->save();
  180. } else {
  181. $params = [
  182. 'distribution_channel_id' => $this->channel->id,
  183. 'pay_merchant_company_id' => $data['pay_company_id'],
  184. 'accumulative_withdrawal_amount' => 0,
  185. 'enable_withdrawal_amount' => $data['settlement_price'],
  186. 'latest_withdrawal_amount' => 0,
  187. 'withdraw_pending_amount' => 0,
  188. 'commission_rate' => $this->rate
  189. ];
  190. FinancialPayMerchantBalance::create($params);
  191. }
  192. }
  193. }