AuditService.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. *
  5. * User: king/QQ:995265288
  6. * Date: 2018/6/20 下午2:33
  7. * Email: livsyitian@163.com
  8. */
  9. namespace app\common\services\withdraw;
  10. use app\common\events\withdraw\WithdrawAuditedEvent;
  11. use app\common\events\withdraw\WithdrawAuditEvent;
  12. use app\common\events\withdraw\WithdrawAuditingEvent;
  13. use app\common\events\withdraw\WithdrawFailedEvent;
  14. use app\common\exceptions\ShopException;
  15. use app\common\models\Income;
  16. use app\common\models\Withdraw;
  17. use app\common\services\income\WithdrawIncomeApplyService;
  18. use app\common\services\income\WithdrawIncomeService;
  19. use Illuminate\Support\Facades\DB;
  20. use app\common\services\finance\BalanceNoticeService;
  21. use app\common\services\finance\MessageService;
  22. use app\common\models\WithdrawMergeServicetaxRate;
  23. class AuditService
  24. {
  25. /**
  26. * @var Withdraw
  27. */
  28. private $withdrawModel;
  29. /**
  30. * @var float
  31. */
  32. private $audit_amount;
  33. private $set;
  34. public function __construct(Withdraw $withdrawModel)
  35. {
  36. $this->withdrawModel = $withdrawModel;
  37. $this->setAuditAmount();
  38. $this->set = \Setting::get('withdraw.income');
  39. }
  40. /**
  41. * 提现审核接口
  42. *
  43. * @return bool
  44. * @throws ShopException
  45. */
  46. public function withdrawAudit()
  47. {
  48. if ($this->withdrawModel->status == Withdraw::STATUS_INITIAL || $this->withdrawModel->status == Withdraw::STATUS_INVALID) {
  49. try {
  50. return $this->_withdrawAudit();
  51. } catch (\Exception $e) {
  52. event(new WithdrawFailedEvent($this->withdrawModel));
  53. $this->sendMessage();
  54. }
  55. }
  56. throw new ShopException("提现审核:ID{$this->withdrawModel->id},不符合审核规则");
  57. }
  58. /**
  59. * @return bool
  60. */
  61. private function _withdrawAudit()
  62. {
  63. DB::transaction(function () {
  64. $this->audit();
  65. //提现收入申请表
  66. WithdrawIncomeApplyService::apply($this->withdrawModel,'backend');
  67. });
  68. return true;
  69. }
  70. private function audit()
  71. {
  72. event(new WithdrawAuditEvent($this->withdrawModel));
  73. $this->auditing();
  74. }
  75. private function auditing()
  76. {
  77. $this->withdrawModel->status = $this->getAuditStatus();
  78. $this->withdrawModel->audit_at = time();
  79. $this->withdrawModel->actual_poundage = $this->getActualPoundage();
  80. $this->withdrawModel->actual_servicetax = $this->getActualServiceTax();
  81. $this->withdrawModel->actual_amounts = $this->getActualAmount();
  82. event(new WithdrawAuditingEvent($this->withdrawModel));
  83. $this->audited();
  84. }
  85. private function getAuditStatus()
  86. {
  87. $type_ids_count = count(array_filter(explode(',', $this->withdrawModel->type_id)));
  88. //$audit_count = count($this->withdrawModel->audit_ids);
  89. $rebut_count = count($this->withdrawModel->rebut_ids);
  90. $invalid_count = count($this->withdrawModel->invalid_ids);
  91. //如果全无效
  92. if ($invalid_count > 0 && $invalid_count == $type_ids_count) {
  93. return Withdraw::STATUS_INVALID;
  94. }
  95. //如果全驳回
  96. if ($rebut_count > 0 && $rebut_count == $type_ids_count) {
  97. return Withdraw::STATUS_REBUT;
  98. }
  99. //如果是无效 + 驳回 [同全驳回,直接完成]
  100. if ($invalid_count > 0 && $rebut_count > 0 && ($invalid_count + $rebut_count) == $type_ids_count) {
  101. // return Withdraw::STATUS_PAY;
  102. return Withdraw::STATUS_REBUT;
  103. }
  104. return Withdraw::STATUS_AUDIT;
  105. }
  106. /**
  107. * @throws ShopException
  108. */
  109. private function audited()
  110. {
  111. $validator = $this->withdrawModel->validator();
  112. if ($validator->fails()) {
  113. throw new ShopException($validator->messages()->first());
  114. }
  115. if (!$this->withdrawModel->save()) {
  116. throw new ShopException("提现审核:ID{$this->withdrawModel->id},记录更新失败");
  117. }
  118. event(new WithdrawAuditedEvent($this->withdrawModel));
  119. }
  120. /**
  121. * 审核后最终手续费
  122. *
  123. * @return float
  124. */
  125. private function getActualPoundage()
  126. {
  127. $amount = $this->audit_amount;
  128. $rate = $this->withdrawModel->poundage_rate;
  129. if ($this->withdrawModel->poundage_type == 1) {
  130. if ($amount != 0) {
  131. return $rate;
  132. } else {
  133. return 0;
  134. }
  135. }
  136. return bcdiv(bcmul($amount, $rate, 4), 100, 2);
  137. }
  138. /**
  139. * 审核后最终劳务税
  140. * @return string
  141. * @throws ShopException
  142. */
  143. private function getActualServiceTax()
  144. {
  145. $withdraw_set = \Setting::get('withdraw.income');
  146. $audit_amount = $this->audit_amount; //收入总和
  147. if (!$withdraw_set['service_tax_calculation']) {
  148. $poundage = $this->getActualPoundage(); //手续费
  149. $audit_amount = bcsub($audit_amount, $poundage, 2); //收入总和减去手续费
  150. }
  151. if ($audit_amount < 0 && $audit_amount != 0) {
  152. throw new ShopException("驳回部分后提现金额小于手续费,不能通过申请!");
  153. }
  154. //计算劳务税
  155. // $rate = $this->withdrawModel->servicetax_rate;
  156. $rate = $this->getLastActualServiceTax($audit_amount, $withdraw_set);
  157. $this->withdrawModel->servicetax_rate = $rate;
  158. return bcdiv(bcmul($audit_amount, $rate, 4), 100, 2);
  159. }
  160. /**
  161. * 审核后最终金额
  162. *
  163. * @return float
  164. */
  165. private function getActualAmount()
  166. {
  167. $amount = $this->audit_amount;
  168. $poundage = $this->getActualPoundage();
  169. $service_tax = $this->getActualServiceTax();
  170. return bcsub(bcsub($amount, $poundage, 2), $service_tax, 2);
  171. }
  172. private function setAuditAmount()
  173. {
  174. !isset($this->audit_amount) && $this->audit_amount = $this->auditIncomeAmount();
  175. }
  176. /**
  177. * 审核通过的收入金额和
  178. *
  179. * @return float
  180. */
  181. private function auditIncomeAmount()
  182. {
  183. $audit_ids = $this->withdrawModel->audit_ids;
  184. $amount = Income::uniacid()->whereIn('id', $audit_ids)->sum('amount');
  185. return $this->audit_amount = $amount;
  186. }
  187. /**
  188. * 增加劳务税梯度
  189. * @param $amount
  190. * @return mixed
  191. */
  192. private function getLastActualServiceTax($amount, $withdraw_set)
  193. {
  194. if (in_array($this->withdrawModel->type,Withdraw::$noDeductionServicetax)) {//这些提现不收劳务税
  195. return 0;
  196. }
  197. if ($this->withdrawModel->pay_way != 'balance' || !$withdraw_set['balance_special']){
  198. if ($merage_rate = WithdrawMergeServicetaxRate::uniacid()->where('withdraw_id', $this->withdrawModel->id)->where('is_disabled', 0)->first()) {
  199. return $merage_rate->servicetax_rate;
  200. }
  201. }
  202. $servicetax_rate = $withdraw_set['servicetax_rate'];
  203. if ($this->withdrawModel->servicetax_rate != $servicetax_rate) {
  204. return $this->withdrawModel->servicetax_rate;
  205. }
  206. $servicetax = $withdraw_set['servicetax'];
  207. if (empty($servicetax)) {
  208. return $servicetax_rate;
  209. }
  210. $max_money = array_column($servicetax, 'servicetax_money');
  211. array_multisort($max_money, SORT_DESC, $servicetax);
  212. foreach ($servicetax as $value) {
  213. if ($amount >= $value['servicetax_money'] && !empty($value['servicetax_money'])) {
  214. return $value['servicetax_rate'];
  215. break;
  216. }
  217. }
  218. return $servicetax_rate;
  219. }
  220. private function sendMessage()
  221. {
  222. if ($this->set['free_audit'] == 1) {
  223. if ($this->withdrawModel->type == 'balance') {
  224. //余额提现失败通知
  225. BalanceNoticeService::withdrawFailureNotice($this->withdrawModel);
  226. } else {
  227. $ids = \Setting::get('withdraw.notice.withdraw_user');
  228. foreach ($ids as $k => $v) {
  229. (new MessageService($this->withdrawModel))->failureNotice($v['uid']);
  230. }
  231. }
  232. }
  233. }
  234. }