添加:贡献值分红计算及结算到佣金

This commit is contained in:
wuhui_zzw 2023-11-03 15:32:00 +08:00
parent 32415773b0
commit 25c8dad298
8 changed files with 405 additions and 14 deletions

View File

@ -207,6 +207,7 @@ class IncomeService
const QUICKEN_INCOME_REWARD = 190;//加速收益分红
const REWARD_POOL_DIVIDEND = 191;//奖金池分红
const STORE_MANAGER = 200;// 经销商店长-店补
const CULTURAL_SPACE_CONTRIBUTION_BONUS = 201;// 文创空间 - 贡献值分红
/**
* @param $data 会员idmember_id分红类型dividend_code分红表iddividend_table_id金额amount订单号order_sn详情detail
@ -677,6 +678,7 @@ class IncomeService
self::QUICKEN_INCOME_REWARD => defined('QUICKEN_INCOME_DIY_NAME') ? QUICKEN_INCOME_DIY_NAME : "加速收益分红",
self::REWARD_POOL_DIVIDEND => defined('REWARD_POOL_DIVIDEND_DIY_NAME') ? REWARD_POOL_DIVIDEND_DIY_NAME : "奖金池分红",
self::STORE_MANAGER => '店补',
self::CULTURAL_SPACE_CONTRIBUTION_BONUS => '贡献值分红',
];
if (empty($income_config_desc[$code])) {
if ($func = app('ShopAsset')->getData('income')[$code]) {
@ -877,6 +879,7 @@ class IncomeService
self::QUICKEN_INCOME_REWARD => 'Yunshop\QuickenIncome\models\EquityDetailModel',
self::REWARD_POOL_DIVIDEND => 'Yunshop\RewardPoolDividend\common\models\DividendUpgradeRecord',
self::STORE_MANAGER => 'Yunshop\TeamDividend\Common\models\StoreManagerRecordModel',
self::CULTURAL_SPACE_CONTRIBUTION_BONUS => 'Yunshop\CulturalSpace\models\ContributionBonusLog'
];
if (empty($income_config_class[$code])) {
if ($func = app('ShopAsset')->getData('income')[$code]) {

View File

@ -4,6 +4,7 @@ namespace Yunshop\CulturalSpace;
use Yunshop\CulturalSpace\listener\OrderPaidListener;
use Yunshop\CulturalSpace\models\ContributionBonusLog;
class PluginApplication extends \app\common\services\PluginApplication{
@ -146,6 +147,17 @@ class PluginApplication extends \app\common\services\PluginApplication{
);
}
public function getIncomeItems(){
return [
'contributionBonus' => [
'title' => '贡献值分红',
'type' => 'contributionBonus',
'type_name' => '贡献值分红',
'class' => 'Yunshop\CulturalSpace\models\ContributionBonusLog',
]
];
}
public function boot(){
$events = app('events');
@ -154,12 +166,24 @@ class PluginApplication extends \app\common\services\PluginApplication{
}
public function cronConfig(){
\Event::listen('cron.collectJobs', function () {
// 每天0点30 执行一次贡献值分红处理
\Cron::add('cultural-space-contribution-bonus', '30 0 * * *', function () {
\Log::debug('--- 文创空间 - 贡献值分红 - 开始 ----');
(new ContributionBonusLog())->bonusInit();
return;
});
// 每天1点30 执行一次贡献值分红结算
\Cron::add('cultural-space-contribution-bonus-settlement', '30 1 * * *', function () {
\Log::debug('--- 文创空间 - 贡献值分红 - 结算开始 ----');
(new ContributionBonusLog())->contributionBonusSettlement();
return;
});
});
}
}

View File

@ -3,6 +3,7 @@ namespace Yunshop\CulturalSpace\admin;
use app\common\components\BaseController;
use app\common\facades\Setting;
use Yunshop\CulturalSpace\models\ContributionBonusLog;
class IndexController extends BaseController{
@ -42,10 +43,8 @@ class IndexController extends BaseController{
public function test(){
// (new CulturalSpace())->buyGoodsGiveContribution(19,76);// 订单支付成功奖励贡献值
// (new ContributionBonusLog())->bonusInit();
// (new ContributionBonusLog())->contributionBonusSettlement();
}

View File

@ -0,0 +1,26 @@
<?php
namespace Yunshop\CulturalSpace\models;
use app\common\models\BaseModel;
use app\common\models\Order;
use app\common\models\OrderGoods;
use app\common\models\UniAccount;
use app\common\facades\Setting;
use Illuminate\Support\Facades\DB;
class ContributionBonus extends BaseModel{
public $table = 'yz_cultural_space_contribution_bonus';
public $timestamps = false;
protected $hidden = ['uniacid'];
public $casts = [
'created_at' => 'datetime:Y-m-d H:i:s',
];
protected $fillable = ['uniacid','uid','order_total_money','contribution_bonus_ratio','total_money','start_time','end_time','created_at'];
}

View File

@ -0,0 +1,311 @@
<?php
namespace Yunshop\CulturalSpace\models;
use app\common\models\BaseModel;
use app\common\models\Order;
use app\common\models\OrderGoods;
use app\common\models\UniAccount;
use app\common\facades\Setting;
use app\common\services\income\IncomeService;
use Illuminate\Support\Facades\DB;
class ContributionBonusLog extends BaseModel{
public $table = 'yz_cultural_space_contribution_bonus_log';
public $timestamps = false;
protected $hidden = ['uniacid'];
public $casts = [
'created_at' => 'datetime:Y-m-d H:i:s',
];
protected $fillable = ['uniacid','uid','total_money','money','total_contribution','hold_contribution','proportion','created_at'];
// 贡献值分红相关内容
private $orderTotalMoney = 0;// 周期订单总金额
private $bonusTotalMoney = 0;// 分红总销售额(周期订单总金额的N%)
/**
* Common: 贡献值分红 - 分红处理开始
* Author: wu-hui
* Time: 2023/11/03 15:09
*/
public function bonusInit(){
set_time_limit(0);
DB::beginTransaction();
try{
[$startTime,$endTime] = getTimeStamp('yesterday');
// 循环平台 进行处理
$uniAccount = UniAccount::getEnable() ?: [];
foreach ($uniAccount as $u) {
Setting::$uniqueAccountId = \YunShop::app()->uniacid = $u->uniacid;
$set = Setting::get('plugin.cultural_space_set');
// 判断:是否符合执行条件
$isRun = (boolean)$this->isRun($set,$startTime,$endTime);
// 判断:允许下一步
if ($isRun) $this->bonusHandle($set,$startTime,$endTime);
}
\Log::debug('--- 文创空间 - 贡献值分红 - 结束 end----');
DB::commit();
}catch(\Exception $e){
\Log::debug('--- 文创空间 - 贡献值分红 - 错误:'.$e->getMessage());
DB::rollBack();
}
}
/**
* Common: 贡献值分红 - 判断是否允许继续执行
* Author: wu-hui
* Time: 2023/11/03 13:43
* @param $set
* @param $startTime
* @param $endTime
* @return bool
*/
private function isRun($set,$startTime,$endTime){
$time = time();
// 判断:时间上是否允许继续执行(上一个周期结束时间存在 & 当前时间小于下一个周期开始时间 禁止继续执行)
$upCycleEndTime = ContributionBonus::uniacid()->max('end_time');
$lastRunTime = strtotime(date("Y-m-d H:i:s",$upCycleEndTime)." +1 day");// 下一个周期结束时间
if($upCycleEndTime > 0 && $time < $lastRunTime) {
\Log::debug("执行时间错误(上一个周期结束时间{$upCycleEndTime},下一个周期结束时间{$lastRunTime})",\YunShop::app()->uniacid);
return false;
}
// 判断:设置是否允许执行 未开启贡献值 || 分红总额比例为0或未设置
if((int)$set['is_give_contribution'] != 1 || (float)$set['contribution_bonus_ratio'] <= 0) {
\Log::debug("未开启贡献值或者分红总额比例为0或未设置",\YunShop::app()->uniacid);
return false;
}
// 判断:是否存在分红总金额
$this->orderTotalMoney = (float)Order::uniacid()
->where('pay_time','>=',$startTime)
->where('pay_time','<',$endTime)
->where('price','>',0)
->whereIn('status',[Order::WAIT_SEND,Order::WAIT_RECEIVE,Order::COMPLETE])
->sum('price');
$this->bonusTotalMoney = (float)sprintf("%.2f",$this->orderTotalMoney * (float)$set['contribution_bonus_ratio'] / 100);
if($this->bonusTotalMoney <= 0) {
\Log::debug("分红总金额为0",\YunShop::app()->uniacid);
return false;
}
return true;
}
/**
* Common: 贡献值分红 - 处理每个站点所有用户的分红
* Author: wu-hui
* Time: 2023/11/03 15:09
* @param $set
* @param $startTime
* @param $endTime
* @return false|void
*/
private function bonusHandle($set,$startTime,$endTime){
// 获取贡献值信息截止昨天24时
$userList = ContributionLog::getAllList($endTime);
$totalContribution = (float)array_sum($userList);
if($totalContribution <= 0){
\Log::debug("不存在分红用户或截至当前周期结束时间总共的贡献值为0",\YunShop::app()->uniacid);
return false;
}
// 记录周期分红信息
$culturalSpaceContributionBonusId = ContributionBonus::insertGetId([
'uniacid' => \YunShop::app()->uniacid,
'order_total_money' => $this->orderTotalMoney,
'contribution_bonus_ratio' => (float)$set['contribution_bonus_ratio'],
'total_money' => $this->bonusTotalMoney,
'start_time' => $startTime,
'end_time' => $endTime,
'created_at' => time(),
]);
// 循环处理所有用户
$logInsertData = [];// 明细记录
$time = time();
$uniacid = \YunShop::app()->uniacid;
foreach($userList as $userId => $contributionValue){
// 添加贡献值分红信息记录 这里必须进行100的偏移计算
$radio = (float)sprintf("%.2f",$contributionValue / $totalContribution * 100);// 佣金比例
$money = (float)sprintf("%.2f",$this->bonusTotalMoney * $radio / 100);// 实际获得佣金
if($money > 0){
$logInsertData[] = [
'uniacid' => $uniacid,
'uid' => $userId,
'total_money' => $this->bonusTotalMoney,
'money' => $money,
'total_contribution' => $totalContribution,
'hold_contribution' => $contributionValue,
'proportion' => $radio,
'cultural_space_contribution_bonus_id' => $culturalSpaceContributionBonusId,
'created_at' => $time,
];
}
}
self::insert($logInsertData);
}
/**
* Common: 贡献值分红 - 结算
* Author: wu-hui
* Time: 2023/11/03 15:24
*/
public function contributionBonusSettlement(){
set_time_limit(0);
DB::beginTransaction();
try{
// 循环平台 进行处理
$uniAccount = UniAccount::getEnable() ?: [];
foreach ($uniAccount as $u) {
Setting::$uniqueAccountId = \YunShop::app()->uniacid = $u->uniacid;
// 获取未结算列表
$list = self::uniacid()
->select(['id','uid','money'])
->where('is_settlement',0)
->get()
->toArray();
if($list){
// 循环处理数据
$incomeData = [];
foreach($list as $item){
$incomeData[] = [
'uniacid' => \YunShop::app()->uniacid,
'member_id' => $item['uid'],
'amount' => $item['money'],
'detail' => '',
'dividend_table_id' => $item['id'],
'dividend_code' => IncomeService::CULTURAL_SPACE_CONTRIBUTION_BONUS,
'order_sn' => '',
];
}
IncomeService::insertIncome($incomeData);
// 修改为已经结算
$ids = array_column($list,'id');
self::whereIn('id',$ids)->update([
'is_settlement' => 1
]);
}
}
DB::commit();
}catch(\Exception $e){
\Log::debug('--- 文创空间 - 贡献值分红结算 - 错误:'.$e->getMessage());
DB::rollBack();
}
}
/**
* Common: 店长信息统计 - 初始化
* Author: wu-hui
* Time: 2023/09/18 14:46
*/
public function infoStatistics(){
set_time_limit(0);
try{
// 循环平台 进行处理
$uniAccount = UniAccount::getEnable() ?: [];
foreach ($uniAccount as $u) {
Setting::$uniqueAccountId = \YunShop::app()->uniacid = $u->uniacid;
$set = Setting::get('plugin.team_dividend');
$isRun = (boolean)$this->isRun($set);
// 判断:允许下一步 开启店长 店补比例大于0
if ($isRun && (int)$set['store_manager_switch'] == 1 && (float)$set['store_manager_proportion'] > 0) {
\Log::debug('--- 经销商 - 店长统计 - 满足条件,开始处理:'.$u->uniacid);
$this->infoStatisticsHandle($set);
} else {
\Log::debug('--- 经销商 - 店长统计 - 不满足条件:'.$u->uniacid);
}
}
}catch(\Exception $e){
\Log::debug('--- 经销商 - 店长统计 - 错误:'.$e->getMessage());
}
}
/**
* Common: 店长信息统计 - 开始处理
* Author: wu-hui
* Time: 2023/09/18 14:03
* @param $set
*/
public function infoStatisticsHandle($set){
// 获取所有店长
$storeManagerList = self::uniacid()
->select(['id','uid'])
->where('status',1)
->orderBy('id','DESC')
->get();
if(!$storeManagerList){
\Log::debug('--- 经销商 - 店长统计 - 没有店长信息');
return;
}
// 订单查询条件
$storeManagerCycle = $set['store_manager_cycle'] ?? 'last_month';
[$startTime,$endTime] = getTimeStamp($storeManagerCycle);
$where = [
['yz_order.pay_time','>=',$startTime],
['yz_order.pay_time','<',$endTime],
['yz_order_goods.payment_amount','>',0],// 实际支付金额必须大于0
];
// 循环处理店长
$storeIds = array_column($storeManagerList->toArray(),'uid');
$insertData = [];
$time = time();
foreach($storeManagerList as $storeInfo){
// 获取全部有效下级
$validChild = $this->getValidChild($storeInfo->uid,$storeIds);
$validChild[] = $storeInfo->uid;// 包括本人
// 获取团队全部订单,这里以订单商品的实际支付价格算;统计已支付-待发货,已支付-待收货,已完成订单
$totalMoney = (float)OrderGoods::uniacid()
->join('yz_order', 'yz_order_goods.order_id', '=','yz_order.id')
->where($where)
->whereIn('yz_order.status',[Order::WAIT_SEND,Order::WAIT_RECEIVE,Order::COMPLETE])
->whereIn('yz_order.uid',$validChild)
->sum('yz_order_goods.payment_amount');
$insertData[] = [
'uniacid' => \YunShop::app()->uniacid,
'uid' => $storeInfo->uid,
'total_money' => $totalMoney,
'money' => sprintf("%.2f",$totalMoney * (float)$set['store_manager_proportion'] / 100),
'proportion' => (float)$set['store_manager_proportion'],
'start_time' => $startTime,
'end_time' => $endTime,
'created_at' => $time,
];
}
// 添加记录
StoreManagerRecordModel::insert($insertData);
return;
}
/**
* Common: 店长信息统计 - 获取店长全部有效下级(去除店长及其团队的全部下级)
* Author: wu-hui
* Time: 2023/09/18 13:34
* @param $uid
* @param $storeIds
* @return array
*/
public function getValidChild($uid,$storeIds){
$allChild = MemberChild::uniacid()->where('member_id',$uid)->pluck('child_id')->toArray();
$diff = array_values(array_intersect($allChild,$storeIds));// 获取交集 判断下级中是否存在店长
if(count($diff) > 0){
// 下级中存在店长 进行处理,剔除所有店长及其团队成员
$subAllChild = MemberChild::uniacid()->whereIn('member_id',$diff)->pluck('child_id')->toArray();
$delIds = array_values(array_merge($diff,$subAllChild));
$allChild = array_diff($allChild,$delIds);
}
return $allChild;
}
}

View File

@ -4,13 +4,14 @@ namespace Yunshop\CulturalSpace\models;
use app\common\models\BaseModel;
use app\common\models\Member;
use Illuminate\Support\Facades\DB;
class ContributionLog extends BaseModel{
public $table = 'yz_cultural_space_contribution_log';
public $timestamps = false;
public $casts = [
'created_at' => 'datetime:Y-m-d h:i:s'
'created_at' => 'datetime:Y-m-d H:i:s'
];
protected $fillable = [
'uniacid',
@ -56,7 +57,29 @@ class ContributionLog extends BaseModel{
return $list ? $list->toArray() : [];
}
/**
* Common: 根据截至时间 获取全部用户持有的贡献值
* Author: wu-hui
* Time: 2023/11/03 14:13
* @param $endTime
* @return array|false|null
*/
public static function getAllList($endTime){
$idList = self::uniacid()
->select([DB::raw('max(id) as max_id')])
->where('created_at','<=',$endTime)
->groupBy('uid')
->get()
->toArray();
$ids = array_column($idList,'max_id');
$list = self::uniacid()
->select(['uid','change_after'])
->whereIn('id',$ids)
->get()
->toArray();
return array_column($list,'change_after','uid');
}

View File

@ -35,14 +35,18 @@
</el-input>
<div class="form-item_tips">订单实际支付的N%奖励给用户及直推上级作为贡献值。0或者空则无贡献值奖励</div>
</el-form-item>
<el-form-item label="分红比例" prop="contribution_bonus_ratio">
<el-input type="number" placeholder="贡献值分红比例" v-model.number="set.contribution_bonus_ratio" step="0.01">
<el-form-item label="分红总额比例" prop="contribution_bonus_ratio">
<el-input type="number" placeholder="贡献值分红总额比例" v-model.number="set.contribution_bonus_ratio" step="0.01">
<template slot="append">%</template>
</el-input>
<div class="form-item_tips">周期销售额的N%用作分红总金额根据每个人当前贡献值比例进行分红0或者空则无贡献值奖励</div>
</el-form-item>
</div>
</div>
{{--保存按钮--}}
<el-form-item>
<el-button type="primary" size="small" @click="onSubmit">保存</el-button>
@ -59,6 +63,7 @@
return{
set: JSON.parse('{!! json_encode($set) !!}') || {
is_give_contribution: 0,
is_open_contribution_bonus: 0,
},
}
},

View File

@ -10,7 +10,7 @@ class WeightValueLog extends BaseModel{
public $timestamps = false;
public $table = 'yz_weight_value_log';
public $casts = [
'created_at' => 'datetime:Y-m-d h:i:s'
'created_at' => 'datetime:Y-m-d H:i:s'
];
protected $fillable = [
'uniacid',