bztang-admin/app/common/services/withdraw/AuditService.php

342 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Created by PhpStorm.
*
* User: king/QQ995265288
* Date: 2018/6/20 下午2:33
* Email: livsyitian@163.com
*/
namespace app\common\services\withdraw;
use app\common\events\withdraw\WithdrawAuditedEvent;
use app\common\events\withdraw\WithdrawAuditEvent;
use app\common\events\withdraw\WithdrawAuditingEvent;
use app\common\events\withdraw\WithdrawFailedEvent;
use app\common\exceptions\ShopException;
use app\common\models\Income;
use app\common\models\IncomeFreezeSet;
use app\common\models\Withdraw;
use app\common\services\income\WithdrawIncomeApplyService;
use app\common\services\income\WithdrawIncomeService;
use Illuminate\Support\Facades\DB;
use app\common\services\finance\BalanceNoticeService;
use app\common\services\finance\MessageService;
use app\common\models\WithdrawMergeServicetaxRate;
use Yunshop\ShareholderDividend\models\ShareholderDividendModel;
class AuditService
{
/**
* @var Withdraw
*/
private $withdrawModel;
/**
* @var float
*/
private $audit_amount;
private $set;
public function __construct(Withdraw $withdrawModel)
{
$this->withdrawModel = $withdrawModel;
$this->setAuditAmount();
$this->set = \Setting::get('withdraw.income');
}
/**
* 提现审核接口
*
* @return bool
* @throws ShopException
*/
public function withdrawAudit()
{
if ($this->withdrawModel->status == Withdraw::STATUS_INITIAL || $this->withdrawModel->status == Withdraw::STATUS_INVALID) {
try {
// 判断:如果存在冻结金额 不支持独立操作,必须全部统一操作
$operate[] = (int)count($this->withdrawModel->audit_ids) > 0;
$operate[] = (int)count($this->withdrawModel->rebut_ids) > 0;
$operate[] = (int)count($this->withdrawModel->invalid_ids) > 0;
$operateSum = array_sum($operate);
if($this->withdrawModel->freeze_money > 0 && $operateSum > 1){
throw new ShopException("存在冻结金额,仅支持全部统一操作,不支持每条信息单独存在!");
}
return $this->_withdrawAudit();
} catch (\Exception $e) {
event(new WithdrawFailedEvent($this->withdrawModel));
$this->sendMessage();
\Log::debug("提现审核失败ID{$this->withdrawModel->id}",$e->getMessage());
\Log::debug("提现审核失败ID{$this->withdrawModel->id}",$e->getTraceAsString());
throw new ShopException($e->getMessage(),"提现审核ID{$this->withdrawModel->id}",);
}
}
throw new ShopException("提现审核ID{$this->withdrawModel->id},不符合审核规则");
}
/**
* @return bool
*/
private function _withdrawAudit()
{
DB::transaction(function () {
// 减少冻结金额
$this->audit_amount = $this->audit_amount - $this->withdrawModel->freeze_money;
// 计算实际提现信息 并且修改申请状态
$this->audit();
WithdrawIncomeApplyService::apply($this->withdrawModel,'backend');
// 判断:如果存在冻结金额 根据类型进行对应的解冻操作
$incomeFreezeSet = IncomeFreezeSet::getInfo($this->withdrawModel->member_id);
$currentFreezeSet = $incomeFreezeSet[$this->withdrawModel->key_name]['set_info'] ?? [];
if($this->withdrawModel->freeze_money > 0 && count($this->withdrawModel->audit_ids) > 0 && $currentFreezeSet){
switch($this->withdrawModel->key_name){
case 'shaerholderDividend':
if($currentFreezeSet['freeze_type'] == 1){
// 独立设置
$levelList = $currentFreezeSet['level_list'] ?? [];
$lvAmountList = ShareholderDividendModel::getIncome((int)$this->withdrawModel->member_id,(int)0)
->whereIn('yz_member_income.id',$this->withdrawModel->audit_ids)
->select(['yz_shareholder_dividend.team_level',DB::raw("sum(ims_yz_member_income.amount) as lv_sum_amount")])
->groupBy('yz_shareholder_dividend.team_level')
->get()
->toArray();
foreach($lvAmountList as $lvAmountInfo){
// 当前等级设置的冻结金额
$lvSetFreezeMoney = $levelList[$lvAmountInfo['team_level']]['freeze_money'] ?? 0;
// 判断:当前等级存在冻结金额;且提现佣金大于冻结金额
if($lvSetFreezeMoney > 0 && $lvAmountInfo['lv_sum_amount'] > $lvSetFreezeMoney){
// 解冻
$levelList[$lvAmountInfo['team_level']]['freeze_money'] = 0;
}
}
$currentFreezeSet['level_list'] = $levelList;
}else{
// 统一设置
$currentFreezeSet['total'] = 0;
}
break;
}
// 修改设置信息
$incomeFreezeSet[$this->withdrawModel->key_name]['set_info'] = $currentFreezeSet;
IncomeFreezeSet::setInfo($this->withdrawModel->member_id,$incomeFreezeSet);
}
});
return true;
}
private function audit()
{
event(new WithdrawAuditEvent($this->withdrawModel));
$this->auditing();
}
private function auditing()
{
$this->withdrawModel->status = $this->getAuditStatus();
$this->withdrawModel->audit_at = time();
$this->withdrawModel->actual_poundage = $this->getActualPoundage();
$this->withdrawModel->actual_servicetax = $this->getActualServiceTax();
$this->withdrawModel->actual_amounts = $this->getActualAmount();
event(new WithdrawAuditingEvent($this->withdrawModel));
$this->audited();
}
private function getAuditStatus()
{
$type_ids_count = count(array_filter(explode(',', $this->withdrawModel->type_id)));
//$audit_count = count($this->withdrawModel->audit_ids);
$rebut_count = count($this->withdrawModel->rebut_ids);
$invalid_count = count($this->withdrawModel->invalid_ids);
//如果全无效
if ($invalid_count > 0 && $invalid_count == $type_ids_count) {
return Withdraw::STATUS_INVALID;
}
//如果全驳回
if ($rebut_count > 0 && $rebut_count == $type_ids_count) {
return Withdraw::STATUS_REBUT;
}
//如果是无效 + 驳回 [同全驳回,直接完成]
if ($invalid_count > 0 && $rebut_count > 0 && ($invalid_count + $rebut_count) == $type_ids_count) {
// return Withdraw::STATUS_PAY;
return Withdraw::STATUS_REBUT;
}
return Withdraw::STATUS_AUDIT;
}
/**
* @throws ShopException
*/
private function audited()
{
$validator = $this->withdrawModel->validator();
if ($validator->fails()) {
throw new ShopException($validator->messages()->first());
}
if (!$this->withdrawModel->save()) {
throw new ShopException("提现审核ID{$this->withdrawModel->id},记录更新失败");
}
event(new WithdrawAuditedEvent($this->withdrawModel));
}
/**
* 审核后最终手续费
*
* @return float
*/
private function getActualPoundage()
{
$amount = $this->audit_amount;
$rate = $this->withdrawModel->poundage_rate;
if ($this->withdrawModel->poundage_type == 1) {
if ($amount != 0) {
return $rate;
} else {
return 0;
}
}
return bcdiv(bcmul($amount, $rate, 4), 100, 2);
}
/**
* 审核后最终劳务税
* @return string
* @throws ShopException
*/
private function getActualServiceTax()
{
$withdraw_set = \Setting::get('withdraw.income');
$audit_amount = $this->audit_amount; //收入总和
if (!$withdraw_set['service_tax_calculation']) {
$poundage = $this->getActualPoundage(); //手续费
$audit_amount = bcsub($audit_amount, $poundage, 2); //收入总和减去手续费
}
if ($audit_amount < 0 && $audit_amount != 0) {
throw new ShopException("驳回部分后提现金额小于手续费,不能通过申请!");
}
//计算劳务税
// $rate = $this->withdrawModel->servicetax_rate;
$rate = $this->getLastActualServiceTax($audit_amount, $withdraw_set);
$this->withdrawModel->servicetax_rate = $rate;
return bcdiv(bcmul($audit_amount, $rate, 4), 100, 2);
}
/**
* 审核后最终金额
*
* @return float
*/
private function getActualAmount()
{
$amount = $this->audit_amount;
$poundage = $this->getActualPoundage();
$service_tax = $this->getActualServiceTax();
return bcsub(bcsub($amount, $poundage, 2), $service_tax, 2);
}
private function setAuditAmount()
{
!isset($this->audit_amount) && $this->audit_amount = $this->auditIncomeAmount();
}
/**
* 审核通过的收入金额和
*
* @return float
*/
private function auditIncomeAmount()
{
$audit_ids = $this->withdrawModel->audit_ids;
$amount = Income::uniacid()->whereIn('id', $audit_ids)->sum('amount');
return $this->audit_amount = $amount;
}
/**
* 增加劳务税梯度
* @param $amount
* @return mixed
*/
private function getLastActualServiceTax($amount, $withdraw_set)
{
if (in_array($this->withdrawModel->type,Withdraw::$noDeductionServicetax)) {//这些提现不收劳务税
return 0;
}
if ($this->withdrawModel->pay_way != 'balance' || !$withdraw_set['balance_special']){
if ($merage_rate = WithdrawMergeServicetaxRate::uniacid()->where('withdraw_id', $this->withdrawModel->id)->where('is_disabled', 0)->first()) {
return $merage_rate->servicetax_rate;
}
}
$servicetax_rate = $withdraw_set['servicetax_rate'];
if ($this->withdrawModel->servicetax_rate != $servicetax_rate) {
return $this->withdrawModel->servicetax_rate;
}
$servicetax = $withdraw_set['servicetax'];
if (empty($servicetax)) {
return $servicetax_rate;
}
$max_money = array_column($servicetax, 'servicetax_money');
array_multisort($max_money, SORT_DESC, $servicetax);
foreach ($servicetax as $value) {
if ($amount >= $value['servicetax_money'] && !empty($value['servicetax_money'])) {
return $value['servicetax_rate'];
break;
}
}
return $servicetax_rate;
}
private function sendMessage()
{
if ($this->set['free_audit'] == 1) {
if ($this->withdrawModel->type == 'balance') {
//余额提现失败通知
BalanceNoticeService::withdrawFailureNotice($this->withdrawModel);
} else {
$ids = \Setting::get('withdraw.notice.withdraw_user');
foreach ($ids as $k => $v) {
(new MessageService($this->withdrawModel))->failureNotice($v['uid']);
}
}
}
}
}