添加:用户佣金冻结功能 - 权重收益冻结

This commit is contained in:
wuhui_zzw 2023-12-21 13:39:42 +08:00
parent d4532c037b
commit e5c68398b3
11 changed files with 630 additions and 233 deletions

View File

@ -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();
}
}
}

View File

@ -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' => []
],
],
],

View File

@ -0,0 +1,54 @@
<?php
namespace app\common\models;
use app\common\observers\income\IncomeObserver;
class IncomeFreezeSet extends BaseModel{
protected $table = 'yz_member_income_freeze_set';
public $timestamps = false;
/**
* Common: 设置冻结信息
* Author: wu-hui
* Time: 2023/12/20 15:01
* @param $memberId
* @param $setInfo
* @return bool
*/
public static function setInfo($memberId,$setInfo){
$info = self::uniacid()->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 [];
}
}

View File

@ -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;
}

View File

@ -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
//计算佣金相关内容 $contentTypecultural_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 需要优化)
*

View File

@ -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,
];
}

View File

@ -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}提现金额错误!");
}

View File

@ -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()

View File

@ -0,0 +1,102 @@
@extends('layouts.base')
@section('title', '佣金冻结设置')
@section('content')
<link rel="stylesheet" type="text/css" href="{{static_url('yunshop/goods/vue-goods1.css')}}"/>
<style>
.vue-head{
max-width: 900px!important;
}
.form-item_tips {
margin-top:8px;
line-height:26px;
color: #b5b5b5;
font-size: 13px;
}
.el-autocomplete{
display: block;
}
.lv-set-content{
width: 100% !important;
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
}
.lv-set-content .lv-set-box{
width: calc((100% - 20px) / 3) !important;
margin-bottom: 10px;
margin-right: 10px;
}
.lv-set-content .lv-set-box:nth-child(3n){
margin-right: 0px!important;
}
</style>
<div class="all" id="app">
<el-form :model="set" label-width="170px">
<div class="vue-head">
<div v-for="(item,index) in set" :key="index">
<div class="vue-main-title">
<div class="vue-main-title-left"></div>
<div class="vue-main-title-content">[[ item.title ]] - 佣金冻结设置</div>
</div>
<div class="vue-main-form">
<el-form-item label="冻结金额类型">
<div style="line-height:40px">
<el-radio v-model.number="set[index].set_info.freeze_type" :label="0">统一设置</el-radio>
<el-radio v-model.number="set[index].set_info.freeze_type" :label="1">独立设置</el-radio>
</div>
</el-form-item>
<el-form-item v-if="item.set_info.freeze_type != 1" label="总冻结金额">
<el-input type="number" placeholder="请输入总冻结金额" v-model.number="set[index].set_info.total" step="0.01"></el-input>
</el-form-item>
<el-form-item v-else label="独立设置">
<div class="lv-set-content">
<div class="lv-set-box" v-for="(lvItem,lvIndex) in item.set_info.level_list" :key="lvIndex">
<el-input type="number" v-model.number="set[index].set_info.level_list[lvIndex].freeze_money" step="0.01">
<template slot="prepend">[[ lvItem.level_name ]]</template>
</el-input>
</div>
</div>
</el-form-item>
</div>
</div>
{{--保存按钮--}}
<el-form-item>
<el-button type="primary" size="small" @click="onSubmit">保存</el-button>
</el-form-item>
</div>
</el-form>
</div>
<script>
new Vue({
el:"#app",
delimiters: ['[[', ']]'],
name: 'test',
data() {
return{
set: JSON.parse('{!! json_encode($set_income_list) !!}') || {},
member_id: "{{ $member_id }}",
}
},
created() {},
mounted() {},
methods: {
// 提交
onSubmit() {
let _this = this;
_this.$http.post('{!! yzWebFullUrl('member.member-income.incomeFreezeSet') !!}', {
set_income_list: _this.set,
member_id: _this.member_id
}).then(function (response) {
let res = response.body;
_this.$message({
message: res.msg,
type: res.result == 1 ? 'success' : 'error'
});
});
},
},
})
</script>
@endsection

View File

@ -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: {},

View File

@ -111,7 +111,8 @@
<div class="item">姓名:[[withdraw.member.realname]]</div>
<div class="item">手机号:[[withdraw.member.mobile]]</div>
<div class="item">会员等级:[[withdraw.member.level_name]]</div>
<div class="item">提现金额:<span style="color: red;">[[withdraw.amounts||"0.00"]] </span>
<div class="item">
提现金额:<span style="color: red;">[[ (Number(withdraw.amounts) + Number(withdraw.freeze_money)).toFixed(2) || "0.00" ]] </span>
</div>
<div class="item">收入类型:[[withdraw.type_name]]</div>
<div class="item">提现方式:[[withdraw.pay_way_name]]</div>
@ -169,24 +170,25 @@
<div class="ui-row">
<div class="item">打款信息:</div>
<template v-if="withdraw.status==0">
<div class="item">审核金额:<span style="color: red;">[[withdraw.amounts||"0.00"]] </span>
</div>
<div class="item">预计手续费:<span style="color: red;">[[withdraw.poundage||"0.00"]] </span>
</div>
<div class="item">预计[[lang.special_service_tax]]<span
style="color: red;">[[withdraw.servicetax||"0.00"]] </span></div>
<div class="item">预计应打款:<span style="color: red;">[[(withdraw.amounts-withdraw.poundage-withdraw.servicetax).toFixed(2)]] </span>
<div class="item">
审核金额:<span style="color: red;">[[ (Number(withdraw.amounts) + Number(withdraw.freeze_money)).toFixed(2) ||"0.00"]] </span>
</div>
<div class="item">预计手续费:<span style="color: red;">[[withdraw.poundage||"0.00"]] </span></div>
<div class="item">预计[[lang.special_service_tax]]<span style="color: red;">[[withdraw.servicetax||"0.00"]] </span></div>
<div class="item">预计应打款:<span style="color: red;">[[(withdraw.amounts-withdraw.poundage-withdraw.servicetax).toFixed(2)]] </span></div>
<div class="item">冻结金额:<span style="color: red;">[[withdraw.freeze_money||"0.00"]] </span></div>
</template>
<template v-else>
<div class="item">审核金额:<span style="color: red;">[[(Number(withdraw.actual_amounts)+Number(withdraw.actual_servicetax)+Number(withdraw.actual_poundage)).toFixed(2)]] </span>
<div class="item">
审核金额:
<span style="color: red;">
[[(Number(withdraw.actual_amounts)+Number(withdraw.actual_servicetax)+Number(withdraw.actual_poundage)+Number(withdraw.freeze_money)).toFixed(2)]]
</span>
</div>
<div class="item">手续费:<span
style="color: red;">[[withdraw.actual_poundage||"0.00"]] </span></div>
<div class="item">[[lang.special_service_tax]]<span
style="color: red;">[[withdraw.actual_servicetax||"0.00"]] </span></div>
<div class="item">应打款:<span
style="color: red;">[[withdraw.actual_amounts||"0.00"]] </span></div>
<div class="item">手续费:<span style="color: red;">[[withdraw.actual_poundage||"0.00"]] </span></div>
<div class="item">[[lang.special_service_tax]]<span style="color: red;">[[withdraw.actual_servicetax||"0.00"]] </span></div>
<div class="item">应打款:<span style="color: red;">[[withdraw.actual_amounts||"0.00"]] </span></div>
<div class="item">冻结金额:<span style="color: red;">[[withdraw.freeze_money||"0.00"]] </span></div>
</template>
</div>
</box-item>