diff --git a/app/backend/modules/member/controllers/MemberIncomeController.php b/app/backend/modules/member/controllers/MemberIncomeController.php index 7d5e2200..c00b68c9 100644 --- a/app/backend/modules/member/controllers/MemberIncomeController.php +++ b/app/backend/modules/member/controllers/MemberIncomeController.php @@ -13,8 +13,10 @@ use app\backend\modules\member\models\MemberGroup; use app\backend\modules\member\models\MemberLevel; use app\backend\modules\member\services\MemberServices; use app\common\components\BaseController; +use app\common\models\IncomeFreezeSet; use Yunshop\Commission\models\Agents; use app\common\models\Income; +use Yunshop\TeamDividend\models\TeamDividendLevelModel; /** * 收入 @@ -88,4 +90,70 @@ class MemberIncomeController extends BaseController 'item' => $incomeData ]); } + + + /** + * Common: 佣金冻结设置 + * Author: wu-hui + * Time: 2023/12/20 15:36 + * @return array|\Illuminate\Http\JsonResponse|string + * @throws \Throwable + */ + public function incomeFreezeSet(){ + // 获取设置信息 判断是否为设置 + $memberId = request()->input('member_id'); + $setInfo = request()->input('set_income_list'); + if ($setInfo) { + // 设置信息 + if (IncomeFreezeSet::setInfo($memberId,$setInfo)) return $this->successJson('编辑成功'); + else return $this->errorJson('设置失败'); + }else{ + // 获取信息 + $userSetInfo = IncomeFreezeSet::getInfo($memberId); + $teamDividendLevel = TeamDividendLevelModel::uniacid()->select(['id','level_name'])->get()->toArray(); + $incomeList = \app\backend\modules\income\Income::current()->getItems(); + $setIncomeList = []; + # 每种提现类型的设置全部放在set_info中;字段内容及类型自定义,但是需要在前端进行独立处理 + foreach($incomeList as $incomeInfo){ + // 单独处理内容 + switch($incomeInfo['type']){ + // 权重收益 + case 'shaerholderDividend': + $currentUserSetInfo = $userSetInfo['shaerholderDividend']['set_info']; + $levelList = $currentUserSetInfo['level_list']; + $levelList = array_map(function($lvInfo) use ($levelList){ + return [ + 'level_id' => $lvInfo['id'], + 'level_name' => $lvInfo['level_name'], + 'freeze_money' => $levelList[$lvInfo['id']] ? $levelList[$lvInfo['id']]['freeze_money'] : 0,// 冻结金额 + ]; + },$teamDividendLevel); + $incomeInfo['set_info'] = [ + 'total' => $currentUserSetInfo['total'] ?? 0, + 'freeze_type' => $currentUserSetInfo['freeze_type'] ?? 0,// 冻结设置:0=统一设置,1=每个等级独立设置 + 'level_list' => array_column($levelList,NULL,'level_id'), + ]; + break; + } + // 是否支持设置冻结金额 + if(!empty($incomeInfo['set_info'])){ + $setIncomeList[] = [ + 'title' => $incomeInfo['title'], + 'type' => $incomeInfo['type'], + 'set_info' => $incomeInfo['set_info'], + ]; + } + } + + return view('member.income.set', [ + 'set_income_list' => $setIncomeList, + 'member_id' => $memberId + ])->render(); + } + } + + + + + } \ No newline at end of file diff --git a/app/backend/modules/menu/Menu.php b/app/backend/modules/menu/Menu.php index 53be58e9..9ee3d470 100644 --- a/app/backend/modules/menu/Menu.php +++ b/app/backend/modules/menu/Menu.php @@ -3304,6 +3304,18 @@ class Menu ], ] ], + 'member_income_freeze_set' => [ + 'name' => '佣金冻结设置', + 'url' => 'member.member-income.incomeFreezeSet', + 'url_params' => '', + 'permit' => 1, + 'menu' => 0, + 'icon' => '', + 'sort' => 0, + 'item' => 'member_income_freeze_set', + 'parents' => ['Member', 'member_all'], + 'child' => [] + ], ], ], diff --git a/app/common/models/IncomeFreezeSet.php b/app/common/models/IncomeFreezeSet.php new file mode 100644 index 00000000..8068810c --- /dev/null +++ b/app/common/models/IncomeFreezeSet.php @@ -0,0 +1,54 @@ +where('member_id',$memberId)->first(); + if(!$info) { + $info = new static; + $info->uniacid = \YunShop::app()->uniacid; + $info->member_id = $memberId; + } + $info->set_info = json_encode($setInfo,JSON_UNESCAPED_UNICODE); + + return $info->save(); + } + /** + * Common: 获取冻结设置 + * Author: wu-hui + * Time: 2023/12/20 15:11 + * @param $memberId + * @return array|mixed + */ + public static function getInfo($memberId){ + $setInfo = self::uniacid()->where('member_id',$memberId)->value('set_info'); + if($setInfo) { + $setInfo = json_decode($setInfo,TRUE); + + return array_column($setInfo,null,'type'); + } + + return []; + } + + +} \ No newline at end of file diff --git a/app/common/services/withdraw/AuditService.php b/app/common/services/withdraw/AuditService.php index f23a6dbb..b46bc8c0 100644 --- a/app/common/services/withdraw/AuditService.php +++ b/app/common/services/withdraw/AuditService.php @@ -16,6 +16,7 @@ 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; @@ -23,6 +24,7 @@ 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 { @@ -57,15 +59,23 @@ class AuditService { 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("提现审核:ID{$this->withdrawModel->id}",$e->getMessage()); + throw new ShopException($e->getMessage(),"提现审核:ID{$this->withdrawModel->id}",); } } throw new ShopException("提现审核:ID{$this->withdrawModel->id},不符合审核规则"); @@ -81,6 +91,41 @@ class AuditService $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; } diff --git a/app/frontend/modules/finance/controllers/IncomeWithdrawController.php b/app/frontend/modules/finance/controllers/IncomeWithdrawController.php index 9f27f27b..06e329c9 100644 --- a/app/frontend/modules/finance/controllers/IncomeWithdrawController.php +++ b/app/frontend/modules/finance/controllers/IncomeWithdrawController.php @@ -13,11 +13,13 @@ use app\backend\modules\withdraw\models\WithdrawRichText; use app\common\components\ApiController; use app\common\facades\Setting; use app\common\models\Income; +use app\common\models\IncomeFreezeSet; use app\common\models\MemberShopInfo; use app\common\services\finance\IncomeService; use app\framework\Database\Eloquent\Collection; use app\frontend\modules\finance\models\Withdraw; use app\frontend\modules\member\models\MemberBankCard; +use Illuminate\Support\Facades\DB; use Yunshop\Commission\models\CommissionOrder; use Yunshop\ShareholderDividend\models\ShareholderDividendModel; use Yunshop\ShopEsignV2\common\models\BaseSetting; @@ -82,6 +84,7 @@ class IncomeWithdrawController extends ApiController //计算佣金相关内容 $contentType:cultural_space=文创空间、broker=非文创空间 public function computeWithdraw($contentType = 'all'){ $shopEsign = $this->shopEsign(); + $uid = \YunShop::app()->getMemberId(); // 区分 是否仅获取文创空间 || 非文创空间 $income_config = \app\backend\modules\income\Income::current()->getItems(); @@ -114,6 +117,7 @@ class IncomeWithdrawController extends ApiController 'deduction_status' => 0, ]; $all_withdraw_income = 0; + $incomeFreezeSet = IncomeFreezeSet::getInfo($uid); foreach ($income_config as $key => $income) { //余额不计算 拍卖预付款不计算 if ($income['type'] == 'balance' || $income['type'] == 'auction_prepayment') continue; @@ -133,7 +137,10 @@ class IncomeWithdrawController extends ApiController $this->setSpecialServiceTaxRate($income['type']); } - $data = $this->getItemData($key, $income); + + // 提现信息处理 + $currentFreezeSet = $incomeFreezeSet[$income['type']]['set_info'] ?? []; + $data = $this->getItemData($key, $income, $currentFreezeSet); if ($data['income'] > 0) { $all_withdraw_income += $data['income']; $income_data[] = $data; @@ -166,6 +173,262 @@ class IncomeWithdrawController extends ApiController ]; } + /** + * 可提现数据 item + * @return array + */ + private function getItemData($key, $income, $currentFreezeSet){ + $uid = \YunShop::app()->getMemberId(); + $amountList = []; + + // 获取佣金信息 + if($income['type'] == 'teamDividend'){ + // 普通经销商佣金 + $amountList = Income::uniacid() + ->select(['yz_member_income.id','yz_member_income.amount']) + ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') + ->where('yz_member_income.incometable_type', $income['class']) + ->where('yz_member_income.status', Income::STATUS_INITIAL) + ->where('yz_member_income.member_id', $uid) + ->whereNotIn('yz_team_dividend.type', [4,5,6]) + ->get()->toArray(); + } + else if($income['type'] == 'teamDividendCultural'){ + // 文创经销商补贴 仅查询一个月前的未提现金额 + $startTime = strtotime(date("Y-m-1"));// 本月1号0点 + $amountList = Income::uniacid() + ->select(['yz_member_income.id','yz_member_income.amount']) + ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') + ->where('yz_member_income.incometable_type', $income['class']) + ->where('yz_member_income.status', Income::STATUS_INITIAL) + ->where('yz_member_income.member_id', $uid) + ->where('yz_member_income.created_at', '<',$startTime) + ->whereIn('yz_team_dividend.type', [4,5]) + ->get()->toArray(); + } + else if($income['type'] == 'ecological_services'){ + // 生态服务 + $amountList = Income::uniacid() + ->select(['yz_member_income.id','yz_member_income.amount']) + ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') + ->where('yz_member_income.incometable_type', $income['class']) + ->where('yz_member_income.status', Income::STATUS_INITIAL) + ->where('yz_member_income.member_id', $uid) + ->where('yz_team_dividend.type',6) + ->get()->toArray(); + } + else if($income['type'] == 'ecological_construction'){ + // 生态建设 经销商受益 + // $startTime = strtotime(date("Y-m-1"));// 本月1号0点 + $amountList = Income::uniacid() + ->select(['yz_member_income.id','yz_member_income.amount']) + ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') + ->where('yz_member_income.incometable_type', $income['class']) + ->where('yz_member_income.status', Income::STATUS_INITIAL) + ->where('yz_member_income.member_id', $uid) + // ->where('yz_member_income.created_at', '<',$startTime) + ->where('yz_team_dividend.type', 4) + ->get()->toArray(); + } + else if($income['type'] == 'ecological_contribution'){ + // 生态贡献 + $amountList = Income::uniacid() + ->select(['yz_member_income.id','yz_member_income.amount']) + ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') + ->where('yz_member_income.incometable_type', $income['class']) + ->where('yz_member_income.status', Income::STATUS_INITIAL) + ->where('yz_member_income.member_id', $uid) + ->where('yz_team_dividend.type', 5) + ->get()->toArray(); + } + else if($income['type'] == 'shaerholderDividend'){ + // 股东分红 - 权重分红 + $amountList = ShareholderDividendModel::getIncome((int)$uid,(int)0,'undrawn') + ->select(['yz_member_income.id','yz_member_income.amount']) + ->get() + ->toArray(); + } + else if($income['type'] == 'weight_income'){ + // 股东分红 - 加权收益 合伙人受益 + $amountList = ShareholderDividendModel::getIncome((int)$uid,(int)1,'undrawn') + ->select(['yz_member_income.id','yz_member_income.amount']) + ->get()->toArray(); + } + else if($income['type'] == 'commission'){ + // 分销商分红 - 分销商分红 + $amountList = CommissionOrder::getIncome((int)$uid,(int)0,'undrawn') + ->select(['yz_member_income.id','yz_member_income.amount']) + ->get()->toArray(); + } + else if($income['type'] == 'commission_share_reward'){ + // 分销商分红 - 销售受益( todo 修改:2023-12-15 提取分销商直推奖) + $amountList = CommissionOrder::getIncome((int)$uid,(int)1,'undrawn',1) + ->select(['yz_member_income.id','yz_member_income.amount']) + ->get()->toArray(); + } + else if($income['type'] == 'commission_service_reward'){ + // 分销商分红 - 服务受益( todo 修改:2023-12-15 提取分销商间推奖) + $amountList = CommissionOrder::getIncome((int)$uid,(int)1,'undrawn',2) + ->select(['yz_member_income.id','yz_member_income.amount']) + // ->where('yz_member_income.created_at', '<',$startTime) + ->get() + ->toArray(); + } + else{ + $amountList = $this->getIncomeModel()->select(['id','amount'])->where('incometable_type', $income['class'])->get()->toArray(); + } + // 获取实际提现金额 计算相关手续费等内容 处理冻结金额等禁止提现金额 + $this->withdraw_amounts = sprintf("%.2f",array_sum(array_column($amountList,'amount'))); + $withdraw_amounts_ids = implode(',',array_column($amountList,'id')); + $freezeMoney = 0;//冻结金额 + if($income['type'] == 'shaerholderDividend'){ + // 股东分红 - 权重分红 freeze_type:冻结设置:0=统一设置,1=每个等级独立设置 + if($currentFreezeSet['freeze_type'] == 1){ + // 每个等级独立设置 + // 冻结金额获取:循环每个等级的佣金,判断是否存在冻结金额,存在则进行比较 + // 提现佣金大于设置冻结金额 - 使用设置冻结金额, + // 提现佣金小于设置冻结金额 - 冻结金额为提现佣金 + // 每个等级独立设置 + $levelList = $currentFreezeSet['level_list'] ?? []; + $lvAmountList = ShareholderDividendModel::getIncome((int)$uid,(int)0,'undrawn') + ->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(); + $freezeMoney = 0; + foreach($lvAmountList as $lvAmountInfo){ + // 当前等级设置的冻结金额 + $lvSetFreezeMoney = $levelList[$lvAmountInfo['team_level']]['freeze_money'] ?? 0; + // 判断:设置冻结金额大于提现佣金,冻结金额=提现佣金,否则冻结金额=设置冻结金额; + $freezeMoney += $lvSetFreezeMoney > $lvAmountInfo['lv_sum_amount'] ? $lvAmountInfo['lv_sum_amount'] : $lvSetFreezeMoney ; + } + }else{ + // 统一设置 + $freezeMoney = (float)$currentFreezeSet['total'];// 冻结金额 + } + $withdrawAmounts = (float)$this->withdraw_amounts - (float)$freezeMoney; + $this->withdraw_amounts = $withdrawAmounts < 0 ? 0 : $withdrawAmounts; + } + + + + $can = $this->incomeIsCanWithdraw(); + if ($income['type'] == 'commission') { + $max = $this->getWithdrawLog($income['class']); + $commission_is_can_withdraw = $this->commissionIsCanWithdraw($max); + if (!$commission_is_can_withdraw['can']) { + $can = $commission_is_can_withdraw['can']; + $can_amount = 0; + } else { + $can_amount = $commission_is_can_withdraw['can_amount']; + } + } + $withdraw_amounts = isset($can_amount) && $can_amount >0 ? $can_amount : $this->withdraw_amounts; + //手续费 + $poundage = $this->poundageMath($withdraw_amounts, $this->poundage_rate); + if ($this->poundage_type == 1) { + $poundage = number_format($this->poundage_rate, 2, '.', ''); + } + //劳务税 + //因为增加阶梯劳务税,这里重新赋值付费比例 + $this->service_tax_rate = $this->getLastServiceTaxRate($income['type'], $withdraw_amounts); + if (array_get($this->withdraw_set, 'service_tax_calculation', 0) == 1) { + $service_tax = $this->poundageMath($withdraw_amounts, $this->service_tax_rate); + } else { + $service_tax = $this->poundageMath($withdraw_amounts - $poundage, $this->service_tax_rate); + } + // 提现到余额独立手续费 + $special_poundage = $this->poundageMath($withdraw_amounts, $this->special_poundage_rate); + if ($this->isUseBalanceSpecialSet()) { + if ($this->special_poundage_type == 1) { + $special_poundage = number_format($this->special_poundage_rate, 2, '.', ''); + } + } + // 提现到余额独立劳务税 + if (array_get($this->withdraw_set, 'service_tax_calculation', 0) == 1) { + $special_service_tax = $this->poundageMath($withdraw_amounts, $this->special_service_tax_rate); + } else { + $special_service_tax = $this->poundageMath(($withdraw_amounts - $special_poundage), $this->special_service_tax_rate); + } + $actualAmount = bcsub(bcsub($this->withdraw_amounts, $poundage, 2), $service_tax, 2); + + $data = [ + 'type' => $income['class'], + 'key_name' => $income['type'], + 'type_name' => $this->getLangTitle($key) ? $this->getLangTitle($key) : $income['title'], + 'income' => $this->withdraw_amounts, + 'poundage' => $poundage, + 'poundage_type' => $this->poundage_type ?: 0, + 'poundage_rate' => $this->poundage_rate, + 'servicetax' => $service_tax, + 'servicetax_rate' => $this->service_tax_rate ?: 0, + 'roll_out_limit' => $this->getIncomeAmountFetter(), + 'max_roll_out_limit' => $this->getIncomeAmountMax(), + 'max_time_out_limit' => $this->getIncomeTimeMax(), + 'can' => $can, + 'selected' => $this->incomeIsCanWithdraw(), + 'type_id' => $can ? $withdraw_amounts_ids : '', + 'special_poundage' => $special_poundage, + 'special_poundage_rate' => $this->special_poundage_rate, + 'special_service_tax' => $special_service_tax, + 'special_service_tax_rate' => $this->special_service_tax_rate, + 'actual_amount' => $actualAmount, + 'income_type' => $this->incomeType($income['type']), + ]; + // 是否允许提现判断 + if ($income['type'] == 'commission') { + $data['can_all'] = $this->withdraw_amounts > $this->getIncomeAmountMax() && is_numeric($this->getIncomeAmountMax()) && $can == true; + $data['can_amount'] = $can_amount; + $data['residue_amount'] = bcsub($this->withdraw_amounts, $data['can_amount'], 2); + } + else if ($income['type'] == 'storeManager') { + // 判断:类型为店补 判断今天是否可以提现 + $set = Setting::get('plugin.team_dividend'); + $withdrawDate = $set['withdraw_date']; + $toDay = date("j"); + // 今天是可提现日期,并且允许提现 - 最终允许提现,否则不允许提现 + if(in_array($toDay,$withdrawDate) && $data['can']) $data['can'] = true; + else $data['can'] = false; + // 允许提现日期 + unset($withdrawDate[0]); + + $data['allow_withdrawal_date'] = implode(',',$withdrawDate); + } + else if($income['type'] == 'shaerholderDividend'){ + // 股东分红 - 股东分红 + $data['income'] = sprintf("%.2f",array_sum(array_column($amountList,'amount')));// 可提现金额 + $data['freeze_money'] = $freezeMoney;// 总手续费 + // 可以提现的前提下;根据冻结设置 再次判断是否可以提现 + if($data['can']){ + if((int)$currentFreezeSet['freeze_type'] == 1){ + // 每个等级独立设置 + $levelList = $currentFreezeSet['level_list'] ?? []; + $lvAmountList = ShareholderDividendModel::getIncome((int)$uid,(int)0,'undrawn') + ->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(); + // 循环判断: 只要有一个允许提现 则都允许提现 + $isLvCan = false;// 默认:禁止提现 + foreach($lvAmountList as $lvAmountInfo){ + $lvFreezeMoney = $levelList[$lvAmountInfo['team_level']]['freeze_money']; + if($lvAmountInfo['lv_sum_amount'] > $lvFreezeMoney) { + $isLvCan = true; + break; + } + } + + $data['can'] = $isLvCan; + }else{ + // 统一设置 + $data['can'] = $data['income'] > $freezeMoney;// 提现金额是否大于冻结金额 小于禁止提现 + } + } + } + + return $data; + } + private function needSign() { @@ -479,199 +742,6 @@ class IncomeWithdrawController extends ApiController //->where('incometable_type', $this->item['class']); } - /** - * 可提现数据 item - * @return array - */ - private function getItemData($key, $income){ - $uid = \YunShop::app()->getMemberId(); - $amountList = []; - - // 获取佣金信息 - if($income['type'] == 'teamDividend'){ - // 普通经销商佣金 - $amountList = Income::uniacid() - ->select(['yz_member_income.id','yz_member_income.amount']) - ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') - ->where('yz_member_income.incometable_type', $income['class']) - ->where('yz_member_income.status', Income::STATUS_INITIAL) - ->where('yz_member_income.member_id', $uid) - ->whereNotIn('yz_team_dividend.type', [4,5,6]) - ->get()->toArray(); - } - else if($income['type'] == 'teamDividendCultural'){ - // 文创经销商补贴 仅查询一个月前的未提现金额 - $startTime = strtotime(date("Y-m-1"));// 本月1号0点 - $amountList = Income::uniacid() - ->select(['yz_member_income.id','yz_member_income.amount']) - ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') - ->where('yz_member_income.incometable_type', $income['class']) - ->where('yz_member_income.status', Income::STATUS_INITIAL) - ->where('yz_member_income.member_id', $uid) - ->where('yz_member_income.created_at', '<',$startTime) - ->whereIn('yz_team_dividend.type', [4,5]) - ->get()->toArray(); - } - else if($income['type'] == 'ecological_services'){ - // 生态服务 - $amountList = Income::uniacid() - ->select(['yz_member_income.id','yz_member_income.amount']) - ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') - ->where('yz_member_income.incometable_type', $income['class']) - ->where('yz_member_income.status', Income::STATUS_INITIAL) - ->where('yz_member_income.member_id', $uid) - ->where('yz_team_dividend.type',6) - ->get()->toArray(); - } - else if($income['type'] == 'ecological_construction'){ - // 生态建设 经销商受益 - // $startTime = strtotime(date("Y-m-1"));// 本月1号0点 - $amountList = Income::uniacid() - ->select(['yz_member_income.id','yz_member_income.amount']) - ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') - ->where('yz_member_income.incometable_type', $income['class']) - ->where('yz_member_income.status', Income::STATUS_INITIAL) - ->where('yz_member_income.member_id', $uid) - // ->where('yz_member_income.created_at', '<',$startTime) - ->where('yz_team_dividend.type', 4) - ->get()->toArray(); - } - else if($income['type'] == 'ecological_contribution'){ - // 生态贡献 - $amountList = Income::uniacid() - ->select(['yz_member_income.id','yz_member_income.amount']) - ->leftJoin('yz_team_dividend','yz_team_dividend.id','yz_member_income.incometable_id') - ->where('yz_member_income.incometable_type', $income['class']) - ->where('yz_member_income.status', Income::STATUS_INITIAL) - ->where('yz_member_income.member_id', $uid) - ->where('yz_team_dividend.type', 5) - ->get()->toArray(); - } - else if($income['type'] == 'shaerholderDividend'){ - // 股东分红 - 股东分红 - $amountList = ShareholderDividendModel::getIncome((int)$uid,(int)0,'undrawn') - ->select(['yz_member_income.id','yz_member_income.amount']) - ->get()->toArray(); - } - else if($income['type'] == 'weight_income'){ - // 股东分红 - 加权收益 合伙人受益 - $amountList = ShareholderDividendModel::getIncome((int)$uid,(int)1,'undrawn') - ->select(['yz_member_income.id','yz_member_income.amount']) - ->get()->toArray(); - } - else if($income['type'] == 'commission'){ - // 分销商分红 - 分销商分红 - $amountList = CommissionOrder::getIncome((int)$uid,(int)0,'undrawn') - ->select(['yz_member_income.id','yz_member_income.amount']) - ->get()->toArray(); - } - else if($income['type'] == 'commission_share_reward'){ - // 分销商分红 - 销售受益( todo 修改:2023-12-15 提取分销商直推奖) - $amountList = CommissionOrder::getIncome((int)$uid,(int)1,'undrawn',1) - ->select(['yz_member_income.id','yz_member_income.amount']) - ->get()->toArray(); - } - else if($income['type'] == 'commission_service_reward'){ - // 分销商分红 - 服务受益( todo 修改:2023-12-15 提取分销商间推奖) - $amountList = CommissionOrder::getIncome((int)$uid,(int)1,'undrawn',2) - ->select(['yz_member_income.id','yz_member_income.amount']) - // ->where('yz_member_income.created_at', '<',$startTime) - ->get() - ->toArray(); - } - else{ - $amountList = $this->getIncomeModel()->select(['id','amount'])->where('incometable_type', $income['class'])->get()->toArray(); - } - $this->withdraw_amounts = sprintf("%.2f",array_sum(array_column($amountList,'amount'))); - $withdraw_amounts_ids = implode(',',array_column($amountList,'id')); - - - - $can = $this->incomeIsCanWithdraw(); - if ($income['type'] == 'commission') { - $max = $this->getWithdrawLog($income['class']); - $commission_is_can_withdraw = $this->commissionIsCanWithdraw($max); - if (!$commission_is_can_withdraw['can']) { - $can = $commission_is_can_withdraw['can']; - $can_amount = 0; - } else { - $can_amount = $commission_is_can_withdraw['can_amount']; - } - } - $withdraw_amounts = isset($can_amount) && $can_amount >0 ? $can_amount : $this->withdraw_amounts; - //手续费 - $poundage = $this->poundageMath($withdraw_amounts, $this->poundage_rate); - if ($this->poundage_type == 1) { - $poundage = number_format($this->poundage_rate, 2, '.', ''); - } - //劳务税 - //因为增加阶梯劳务税,这里重新赋值付费比例 - $this->service_tax_rate = $this->getLastServiceTaxRate($income['type'], $withdraw_amounts); - if (array_get($this->withdraw_set, 'service_tax_calculation', 0) == 1) { - $service_tax = $this->poundageMath($withdraw_amounts, $this->service_tax_rate); - } else { - $service_tax = $this->poundageMath($withdraw_amounts - $poundage, $this->service_tax_rate); - } - // 提现到余额独立手续费 - $special_poundage = $this->poundageMath($withdraw_amounts, $this->special_poundage_rate); - if ($this->isUseBalanceSpecialSet()) { - if ($this->special_poundage_type == 1) { - $special_poundage = number_format($this->special_poundage_rate, 2, '.', ''); - } - } - // 提现到余额独立劳务税 - if (array_get($this->withdraw_set, 'service_tax_calculation', 0) == 1) { - $special_service_tax = $this->poundageMath($withdraw_amounts, $this->special_service_tax_rate); - } else { - $special_service_tax = $this->poundageMath(($withdraw_amounts - $special_poundage), $this->special_service_tax_rate); - } - $actualAmount = bcsub(bcsub($this->withdraw_amounts, $poundage, 2), $service_tax, 2); - - $data = [ - 'type' => $income['class'], - 'key_name' => $income['type'], - 'type_name' => $this->getLangTitle($key) ? $this->getLangTitle($key) : $income['title'], - 'income' => $this->withdraw_amounts, - 'poundage' => $poundage, - 'poundage_type' => $this->poundage_type ?: 0, - 'poundage_rate' => $this->poundage_rate, - 'servicetax' => $service_tax, - 'servicetax_rate' => $this->service_tax_rate ?: 0, - 'roll_out_limit' => $this->getIncomeAmountFetter(), - 'max_roll_out_limit' => $this->getIncomeAmountMax(), - 'max_time_out_limit' => $this->getIncomeTimeMax(), - 'can' => $can, - 'selected' => $this->incomeIsCanWithdraw(), - 'type_id' => $can ? $withdraw_amounts_ids : '', - 'special_poundage' => $special_poundage, - 'special_poundage_rate' => $this->special_poundage_rate, - 'special_service_tax' => $special_service_tax, - 'special_service_tax_rate' => $this->special_service_tax_rate, - 'actual_amount' => $actualAmount, - 'income_type' => $this->incomeType($income['type']), - ]; - if ($income['type'] == 'commission') { - $data['can_all'] = $this->withdraw_amounts > $this->getIncomeAmountMax() && is_numeric($this->getIncomeAmountMax()) && $can == true; - $data['can_amount'] = $can_amount; - $data['residue_amount'] = bcsub($this->withdraw_amounts, $data['can_amount'], 2); - }else if ($income['type'] == 'storeManager') { - // 判断:类型为店补 判断今天是否可以提现 - $set = Setting::get('plugin.team_dividend'); - $withdrawDate = $set['withdraw_date']; - $toDay = date("j"); - // 今天是可提现日期,并且允许提现 - 最终允许提现,否则不允许提现 - if(in_array($toDay,$withdrawDate) && $data['can']) $data['can'] = true; - else $data['can'] = false; - // 允许提现日期 - unset($withdrawDate[0]); - - $data['allow_withdrawal_date'] = implode(',',$withdrawDate); - } - - return $data; - } - - /** * 兼容开发,为了处理门店提现、收银台提现、连锁店提现设置独立的提现打款方式(最快的解决办法,todo 需要优化) * diff --git a/app/frontend/modules/withdraw/controllers/ApplyController.php b/app/frontend/modules/withdraw/controllers/ApplyController.php index d6212b5c..c94a88cf 100644 --- a/app/frontend/modules/withdraw/controllers/ApplyController.php +++ b/app/frontend/modules/withdraw/controllers/ApplyController.php @@ -19,6 +19,7 @@ use app\common\facades\Setting; use app\common\listeners\income\WithdrawPayedListener; use app\common\models\Income; use app\common\models\income\WithdrawIncomeApply; +use app\common\models\IncomeFreezeSet; use app\common\services\income\IncomeService; use app\common\services\income\WithdrawIncomeApplyService; use app\common\services\income\WithdrawIncomeDeductionService; @@ -31,6 +32,7 @@ use app\common\helpers\Url; use Yunshop\Commission\models\Agents; use app\common\models\WithdrawMergeServicetaxRate; use Yunshop\Love\Common\Services\CommonService; +use Yunshop\ShareholderDividend\models\ShareholderDividendModel; use Yunshop\WithdrawalLimit\Common\models\MemberWithdrawalLimit; use app\common\services\finance\Withdraw as WithdrawService; @@ -75,7 +77,7 @@ class ApplyController extends ApiController public function index() { $this->withdrawLimitation(); - list($amount, $pay_way, $poundage, $withdraw_data) = $this->getPostValue(); + [$amount, $pay_way, $poundage, $withdraw_data] = $this->getPostValue(); $this->amount = $amount; $this->pay_way = $pay_way; $this->poundage = $poundage; @@ -358,42 +360,67 @@ class ApplyController extends ApiController $merge_servicetax_amount = 0; //劳务税计算金额 } } - + $uid = \YunShop::app()->getMemberId(); + $incomeFreezeSet = IncomeFreezeSet::getInfo($uid); + $totalFreezeMoney = 0;// 总冻结金额 foreach ($this->withdraw_data as $key => $item) { + // 冻结金额处理 + $currentFreezeSet = $incomeFreezeSet[$item['key_name']]['set_info'] ?? []; + if($currentFreezeSet['freeze_type'] == 1){ + // 独立设置 + $levelList = $currentFreezeSet['level_list'] ?? []; + $lvAmountList = ShareholderDividendModel::getIncome((int)$uid,(int)0,'undrawn') + ->select([ + 'yz_shareholder_dividend.team_level', + DB::raw("sum(ims_yz_member_income.amount) as lv_sum_amount,GROUP_CONCAT(ims_yz_member_income.id) AS ids") + ]) + ->groupBy('yz_shareholder_dividend.team_level') + ->get() + ->toArray(); + $item['freeze_money'] = 0; + $typeId = explode(',',$item['type_id']); + foreach($lvAmountList as $lvAmountInfo){ + // 当前等级设置的冻结金额 + $lvSetFreezeMoney = $levelList[$lvAmountInfo['team_level']]['freeze_money'] ?? 0; + // 判断:当前等级存在冻结金额 且该等级提现佣金小于等于冻结金额,冻结金额为0且不提现该等级佣金 + if($lvSetFreezeMoney > 0 && $lvAmountInfo['lv_sum_amount'] <= $lvSetFreezeMoney){ + // 当前等级佣金不提现 + $item['income'] = (float)$item['income'] - (float)$lvAmountInfo['lv_sum_amount'];// 减少当前提现金额 + $this->amount = $this->amount - (float)$lvAmountInfo['lv_sum_amount'];// 减少当前总提现金额 + $typeId = array_diff($typeId,explode(',',$lvAmountInfo['ids'])); + }else{ + $item['freeze_money'] += $lvSetFreezeMoney; + } + } + $item['type_id'] = implode(',',$typeId); + }else{ + // 统一设置 + $item['freeze_money'] = $currentFreezeSet['total']; + } + + // 提交金额处理 $withdrawModel = new Withdraw(); - $withdrawModel->mark = $item['key_name']; $withdrawModel->withdraw_set = $this->withdraw_set; $withdrawModel->income_set = $this->getIncomeSet($item['key_name']); - $withdrawModel->fill($this->getWithdrawData($item)); - event(new WithdrawApplyEvent($withdrawModel)); - $validator = $withdrawModel->validator(); - if ($validator->fails()) { - throw new AppException("ERROR:Data anomaly -- {$item['key_name']}::{$validator->messages()->first()}"); - } - + if ($validator->fails()) throw new AppException("ERROR:Data anomaly -- {$item['key_name']}::{$validator->messages()->first()}"); event(new WithdrawApplyingEvent($withdrawModel)); - - if (!$withdrawModel->save()) { throw new AppException("ERROR:Data storage exception -- {$item['key_name']}"); } - //判断收入是否已提现 $apply_count = WithdrawIncomeApply::whereIn('income_id', array_filter(explode(',', $item['type_id'])))->whereIn('status', [0, 1, -1])->lockForUpdate()->count(); if ($apply_count > 0) { throw new AppException("ERROR:Data storage exception repeat-- {$item['key_name']}"); } - //插入提现收入申请表 if (!WithdrawIncomeApplyService::insert($withdrawModel)) { throw new AppException("ERROR:Data storage exception -- {$item['key_name']}"); } - //插入提现收入扣除爱心值记录 if (!empty($this->need_deduction_love_data) && !WithdrawIncomeDeductionService::insert($withdrawModel,$this->need_deduction_love_data,proportionMath($withdrawModel->amounts,$this->need_deduction_love_data['rate']))) { throw new AppException("ERROR:Data2 storage exception -- {$item['key_name']}"); @@ -414,8 +441,9 @@ class ApplyController extends ApiController $merge_servicetax_amount = bcadd($merge_servicetax_amount, $this_servicetax_amount, 2); } - } + $totalFreezeMoney += $withdrawModel->freeze_money; + } if (!empty($merge_servicetax_withdraw_id)) { $service_tax_data = WithdrawService::getWithdrawServicetaxPercent($merge_servicetax_amount, $withdrawModel); @@ -434,14 +462,19 @@ class ApplyController extends ApiController } } - - if (bccomp($amount, $this->amount, 2) != 0) { + $realMoney = bcadd($amount, $totalFreezeMoney, 2); + if (bccomp($realMoney, $this->amount, 2) != 0) { throw new AppException('提现失败:提现金额错误'); } return true; } + + + + + /** * @param $withdraw_item * @return array @@ -449,7 +482,11 @@ class ApplyController extends ApiController */ private function getWithdrawData($withdraw_item) { - //dd($withdraw_item); + // 判断:如果存在冻结金额 减少冻结金额 + $freezeMoney = $withdraw_item['freeze_money'] ?? 0; + $withdraw_item['income'] = (float)$withdraw_item['income'] - (float)$freezeMoney; + + $set = Setting::get('withdraw.commission'); if ($set['max_roll_out_limit'] && $set['max_roll_out_limit'] > 0) { @@ -461,6 +498,7 @@ class ApplyController extends ApiController 'withdraw_sn' => Withdraw::createOrderSn('WS', 'withdraw_sn'), 'uniacid' => \YunShop::app()->uniacid, 'member_id' => $this->getMemberId(), + 'key_name' => $withdraw_item['key_name'], 'type' => $withdraw_item['type'], 'type_name' => $withdraw_item['type_name'], 'type_id' => $withdraw_item['type_id'], @@ -481,6 +519,7 @@ class ApplyController extends ApiController 'arrival_at' => null, 'created_at' => time(), 'updated_at' => time(), + 'freeze_money' => $freezeMoney, ]; } diff --git a/app/frontend/modules/withdraw/services/DataValidatorService.php b/app/frontend/modules/withdraw/services/DataValidatorService.php index 55e9fda0..20a86296 100644 --- a/app/frontend/modules/withdraw/services/DataValidatorService.php +++ b/app/frontend/modules/withdraw/services/DataValidatorService.php @@ -62,7 +62,7 @@ class DataValidatorService } $real_amount = $this->getIncomeAmount(); - if (bccomp($amount, $real_amount, 2) != 0) { + if (bccomp(bcadd($amount,$this->withdrawModel->freeze_money,2), $real_amount, 2) != 0) { throw new AppException("{$type_name}提现金额错误!"); } diff --git a/plugins/shareholder-dividend/src/services/CycleAmounyService.php b/plugins/shareholder-dividend/src/services/CycleAmounyService.php index 7651bd87..6079b535 100644 --- a/plugins/shareholder-dividend/src/services/CycleAmounyService.php +++ b/plugins/shareholder-dividend/src/services/CycleAmounyService.php @@ -202,7 +202,7 @@ class CycleAmounyService * @param $method * @param $rate * @param $levelId - * @return float|int + * @return array|float|int */ public static function getOrderAmountNew($orderId, $method, $rate, $levelId){ $orderGoodsList = OrderGoods::uniacid() @@ -237,7 +237,7 @@ class CycleAmounyService * @param $method * @param $rate * @param $levelId - * @return float|int + * @return array|float|int */ public static function getCycleAmountNew($startTime,$endTime, $method, $rate, $levelId){ $orderGoodsList = OrderGoods::uniacid() diff --git a/resources/views/member/income/set.blade.php b/resources/views/member/income/set.blade.php new file mode 100644 index 00000000..eb782ba7 --- /dev/null +++ b/resources/views/member/income/set.blade.php @@ -0,0 +1,102 @@ +@extends('layouts.base') +@section('title', '佣金冻结设置') +@section('content') + + +
+ +
+
+
+
+
[[ item.title ]] - 佣金冻结设置
+
+
+ +
+ 统一设置 + 独立设置 +
+
+ + + + +
+
+ + + +
+
+
+
+
+ {{--保存按钮--}} + + 保存 + +
+
+
+ +@endsection diff --git a/resources/views/member/index.blade.php b/resources/views/member/index.blade.php index 31b481af..0f765da2 100644 --- a/resources/views/member/index.blade.php +++ b/resources/views/member/index.blade.php @@ -954,6 +954,11 @@ class: "fa fa-truck", title: "银行卡管理" }, + { + link: "{!! yzWebUrl('member.member-income.incomeFreezeSet') !!}&member_id=", + class: "fa fa-truck", + title: "佣金冻结设置" + }, ], member_tag:member_tag, merge_member_form: {}, diff --git a/resources/views/withdraw/detail.blade.php b/resources/views/withdraw/detail.blade.php index 4866868e..60cabbec 100644 --- a/resources/views/withdraw/detail.blade.php +++ b/resources/views/withdraw/detail.blade.php @@ -111,7 +111,8 @@
姓名:[[withdraw.member.realname]]
手机号:[[withdraw.member.mobile]]
会员等级:[[withdraw.member.level_name]]
-
提现金额:[[withdraw.amounts||"0.00"]] 元 +
+ 提现金额:[[ (Number(withdraw.amounts) + Number(withdraw.freeze_money)).toFixed(2) || "0.00" ]] 元
收入类型:[[withdraw.type_name]]
提现方式:[[withdraw.pay_way_name]]
@@ -169,24 +170,25 @@
打款信息: