添加:平台抽成 - 合伙人佣金周期结算(每周期结算记录,未实际结算到账)

This commit is contained in:
wuhui_zzw 2023-12-28 15:43:37 +08:00
parent b9a3852f19
commit efe5cf83c0
13 changed files with 376 additions and 41 deletions

View File

@ -0,0 +1,39 @@
<?php
declare (strict_types=1);
namespace app\command;
use app\common\repositories\store\platformCommission\PartnerSettlementCycleRepository;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\facade\Log;
class platformCommission extends Command{
protected function configure(){
// 指令配置
$this->setName('platformCommission')
->addArgument('run_type', Argument::OPTIONAL, "运行类型")
->setDescription('平台抽成相关任务');
}
protected function execute(Input $input,Output $output){
// 参数获取
$runType = trim($input->getArgument('run_type'));
$runType = $runType ?: '';
// 根据类型执行对应的操作
switch($runType){
// 合伙人佣金结算
case 'commission_partner_settlement':
Log::info('合伙人佣金结算 - 开始处理');
app()->make(PartnerSettlementCycleRepository::class)->settlementInit();
break;
default:
Log::info('平台抽成计划任务 - 错误 - 不明确的执行内容');
break;
}
// $output->writeln('接收参数:'. $runType);
// $output->writeln('success');
}
}

View File

@ -1247,3 +1247,74 @@ if (!function_exists('camelize')) {
return ltrim(str_replace(" ", "", ucwords($string)), $separator ); return ltrim(str_replace(" ", "", ucwords($string)), $separator );
} }
} }
// 根据类型获取对应的时间戳
if (!function_exists('getTimeStamp')) {
function getTimeStamp($type){
$startTime = $endTime =0;
#year=本年,month=本月,today=今日,yesterday=昨日,last_week=上周,week=本周,quarter=季度,half_a_year=半年,last_month=上一个月
switch($type){
// 本年
case "year":
$startTime = strtotime(date("Y-1-1"));// 本年1号0点
$endTime = strtotime(date("Y-1-1"). " +1 year");// 下一年1号0点
break;
// 本月
case "month":
$startTime = strtotime(date("Y-m-1"));// 本月1号0点
$endTime = strtotime(date("Y-m-1"). " +1 month ");// 下一个月1号0点
break;
// 今日
case "today":
$startTime = strtotime(date("Y-m-d"));// 今日0点
$endTime = strtotime(date("Y-m-d"). " +1 day ");// 明日0点
break;
// 昨日
case "yesterday":
$startTime = strtotime(date("Y-m-d"). " -1 day ");// 昨日0点
$endTime = strtotime(date("Y-m-d"));// 今日0点
break;
// 上周
case "last_week":
$week = date('w') == 0 ? 7 : date('w');
$startTime = strtotime('today -' . ($week - 1) . 'day -1 week');// 上周一 0点
$endTime = strtotime('today +' . (8 - $week) . 'day -1 week');// 本周一 0点
break;
// 本周
case "week":
$week = date('w') == 0 ? 7 : date('w');
$startTime = strtotime('today -' . ($week - 1) . 'day');// 本周一 0点
$endTime = strtotime('today +' . (8 - $week) . 'day');// 下周一 0点
break;
// 季度
case "quarter":
$currentMonth = date('n'); // 获取当前月份
$currentQuarter = ceil($currentMonth / 3); // 计算当前是第几个季度
$currentYear = date('Y'); // 获取当前年份
// 本季度开始时间
$startTime = strtotime(($currentQuarter - 1) * 3 . ' months', strtotime("$currentYear-01-01"));
// 下一个季度开始时间
$endTime = strtotime(($currentQuarter * 3) . ' months', strtotime("$currentYear-01-01"));
break;
// 上半年/下半年
case "half_a_year":
$currentMonth = date('n'); // 获取当前月份
$currentYear = date('Y'); // 获取当前年份
if($currentMonth <= 6){
// 获取上半年时间
$startTime = strtotime("$currentYear-01-01");// 本年1号 0点
$endTime = strtotime("$currentYear-07-01");// 本年7月1号 0点
}else{
// 获取下半年时间
$startTime = strtotime("$currentYear-07-01");// 本年7月1号 0点
$endTime = strtotime("$currentYear-01-01 +1 years");// 明年1号 0点
}
break;
// 上一个月
case "last_month":
$startTime = strtotime(date("Y-m-1")." -1 month");// 上一个月1号0点
$endTime = strtotime(date("Y-m-1"));// 本月1号0点
break;
}
return [$startTime,$endTime];
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace app\common\dao\store\platformCommission;
use app\common\dao\BaseDao;
use app\common\model\store\platformCommission\PartnerSettlementCycle;
class PartnerSettlementCycleDao extends BaseDao{
protected function getModel():string{
return PartnerSettlementCycle::class;
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace app\common\dao\store\platformCommission;
use app\common\dao\BaseDao;
use app\common\model\store\platformCommission\PartnerSettlement;
class PartnerSettlementDao extends BaseDao{
protected function getModel():string{
return PartnerSettlement::class;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace app\common\model\store\platformCommission;
use app\common\model\BaseModel;
class PartnerSettlement extends BaseModel{
public static function tablePk():string{
return 'id';
}
public static function tableName():string{
return 'platform_commission_partner_settlement';
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace app\common\model\store\platformCommission;
use app\common\model\BaseModel;
class PartnerSettlementCycle extends BaseModel{
public static function tablePk():string{
return 'id';
}
public static function tableName():string{
return 'platform_commission_partner_settlement_cycle';
}
}

View File

@ -0,0 +1,124 @@
<?php
namespace app\common\repositories\store\platformCommission;
use app\common\dao\store\platformCommission\PartnerSettlementCycleDao;
use app\common\model\store\platformCommission\PartnerSettlement;
use app\common\model\store\platformCommission\PartnerSettlementCycle;
use app\common\repositories\BaseRepository;
use Exception;
use think\facade\Db;
use think\facade\Log;
class PartnerSettlementCycleRepository extends BaseRepository{
protected $dao;
private $set;
private $startTime,$endTime;
private $totalCommission;
public function __construct(PartnerSettlementCycleDao $dao){
$this->dao = $dao;
}
/**
* Common: 合伙人结算 - 开始
* Author: wu-hui
* Time: 2023/12/28 15:22
*/
public function settlementInit(){
$this->set = app()->make(RecordRepository::class)->getBaseConfig();
Db::startTrans();
try{
// 获取周期时间 0=天1=周2=月
if($this->set['commission_partner_cycle'] == 1) [$this->startTime,$this->endTime] = getTimeStamp('last_week');// 周
else if($this->set['commission_partner_cycle'] == 2) [$this->startTime,$this->endTime] = getTimeStamp('last_month');// 月
else [$this->startTime,$this->endTime] = getTimeStamp('yesterday');// 天
// 判断:是否允许执行
$this->settlementIsRun();
// 佣金分红计算并且记录
$this->settlementBonusHandle();
Db::commit();
}catch(Exception $e){
Db::rollback();
Log::info('合伙人佣金结算 - 错误:'.$e->getMessage());
}
}
/**
* Common: 合伙人结算 - 判断是否继续允许;获取分佣金额
* Author: wu-hui
* Time: 2023/12/28 14:23
* @throws Exception
*/
private function settlementIsRun(){
$time = time();
// 判断:是否开启
if($this->set['is_open'] != 1) throw new Exception('未开启平台抽成');
// 下一个周期结束时间
$upCycleEndTime = PartnerSettlementCycle::max('end_time');
if($this->set['commission_partner_cycle'] == 1) {
// 周 获取下一周开始时间
$monday = strtotime('Monday this week', $upCycleEndTime);
$lastRunTime = strtotime(date("Y-m-d 00:00:00",$monday)." +1 week");
}
else if($this->set['commission_partner_cycle'] == 2) {
// 月 获取下一月开始时间
$lastRunTime = strtotime(date("Y-m-1 00:00:00",$upCycleEndTime)." +1 month");
}
else{
// 天 获取下一天开始时间
$lastRunTime = strtotime(date("Y-m-d 00:00:00",$upCycleEndTime)." +1 day");
}
// 判断:时间上是否允许继续执行(上一个周期结束时间存在 & 当前时间小于下一个周期结束时间 禁止继续执行)
if($upCycleEndTime > 0 && $time < $lastRunTime) {
$upCycleEndDate = date('Y-m-d H:i:s',$upCycleEndTime);
$nextCycleEndDate = date('Y-m-d H:i:s',$lastRunTime);
throw new Exception("执行时间错误(上一个周期结束时间{$upCycleEndDate},下一个周期结束时间{$nextCycleEndDate})");
}
// 判断分红总金额是否大于0
$this->totalCommission = (float)app()->make(RecordRepository::class)->getTotalCommission($this->startTime,$this->endTime);
if($this->totalCommission <= 0) throw new Exception('分红总金额为0');
}
/**
* Common: 合伙人结算 - 佣金计算并且记录
* Author: wu-hui
* Time: 2023/12/28 15:22
* @return bool
* @throws Exception
*/
private function settlementBonusHandle(){
$userList = app()->make(WeightValueLogRepository::class)->getHoldList($this->endTime);
$totalWeightValue = (float)array_sum($userList);// 总权重值
if($totalWeightValue <= 0) throw new Exception('不存在分红用户或截至当前周期结束时间总共的权重值为0');
// 记录周期分红信息
$cycleId = PartnerSettlementCycle::insertGetId([
'total_commission' => $this->totalCommission,
'total_weight_value' => $totalWeightValue,
'total_people' => count($userList),
'start_time' => $this->startTime,
'end_time' => $this->endTime,
]);
// 循环处理所有用户
$logInsertData = [];// 明细记录
foreach($userList as $userId => $weightValue){
// 添加贡献分享分红信息记录 这里必须进行100的偏移计算
$radio = (float)sprintf("%.2f",($weightValue / $totalWeightValue) * 100);// 佣金比例
$money = (float)sprintf("%.2f",($this->totalCommission * $radio) / 100);// 实际获得佣金
if($money > 0){
$logInsertData[] = [
'uid' => $userId,
'cycle_id' => $cycleId,
'money' => $money,
'hold_contribution' => $totalWeightValue,
'total_contribution' => $weightValue,
'proportion' => $radio,
];
}
}
PartnerSettlement::insertAll($logInsertData);
return true;
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace app\common\repositories\store\platformCommission;
use app\common\dao\store\platformCommission\PartnerSettlementDao;
use app\common\repositories\BaseRepository;
class PartnerSettlementRepository extends BaseRepository{
protected $dao;
public function __construct(PartnerSettlementDao $dao){
$this->dao = $dao;
}
}

View File

@ -100,6 +100,20 @@ class RecordRepository extends BaseRepository{
return compact('count','list'); return compact('count','list');
} }
/**
* Common: 获取指定时间内总合伙人佣金
* Author: wu-hui
* Time: 2023/12/28 14:22
* @param $startTime
* @param $endTime
* @return float
*/
public function getTotalCommission($startTime,$endTime):float{
return (float)$this->dao->getSearch([])
->whereBetweenTime('create_time', $startTime, $endTime)
->sum('commission_partner_money');
}

View File

@ -44,8 +44,30 @@ class WeightValueLogRepository extends BaseRepository{
return compact('count','list'); return compact('count','list');
} }
/**
* Common: 根据截止时间 获取用户权重值持有信息
* Author: wu-hui
* Time: 2023/12/28 14:59
* @param $endTime
* @return array
*/
public function getHoldList($endTime):array{
$idList = $this->dao->getSearch([])
->field('max(id) as max_id,CONCAT(uid,"_", brokerage_level) as group_key')
->where('create_time','<=',date("Y-m-d H:i:s",$endTime))
->group('group_key')
->select()
->toArray();
$ids = array_column($idList,'max_id');
$list = $this->dao->getSearch([])
->field('uid,sum(change_after) as change_after')
->whereIn('id',$ids)
->group('uid')
->select()
->toArray();
return array_column($list,'change_after','uid');
}

View File

@ -6,31 +6,19 @@
namespace app\controller\api; namespace app\controller\api;
use app\common\model\store\platformCommission\WeightValue;
use app\common\model\store\platformCommission\WeightValueLog;
use app\common\model\system\merchant\Merchant;
use app\common\repositories\store\order\StoreGroupOrderRepository;
use app\common\repositories\store\order\StoreOrderRepository; use app\common\repositories\store\order\StoreOrderRepository;
use app\common\repositories\store\order\StoreRefundOrderRepository; use app\common\repositories\store\order\StoreRefundOrderRepository;
use app\common\repositories\store\platformCommission\RecordRepository;
use app\common\repositories\store\platformCommission\WeightValueRepository;
use app\common\repositories\system\merchant\MerchantRepository;
use app\common\repositories\system\notice\SystemNoticeConfigRepository;
use app\common\repositories\user\UserBillRepository;
use app\common\repositories\user\UserBrokerageRepository;
use app\common\repositories\user\UserRepository; use app\common\repositories\user\UserRepository;
use app\common\repositories\user\UserSignRepository; use app\common\repositories\user\UserSignRepository;
use app\common\repositories\wechat\RoutineQrcodeRepository; use app\common\repositories\wechat\RoutineQrcodeRepository;
use app\common\repositories\wechat\WechatUserRepository; use app\common\repositories\wechat\WechatUserRepository;
use app\jobs\store\platformCommission\GiveWeightValueJob;
use app\validate\api\ChangePasswordValidate; use app\validate\api\ChangePasswordValidate;
use app\validate\api\UserAuthValidate; use app\validate\api\UserAuthValidate;
use crmeb\basic\BaseController; use crmeb\basic\BaseController;
use crmeb\jobs\UserBrokerageLevelJob;
use crmeb\services\MiniProgramService; use crmeb\services\MiniProgramService;
use crmeb\services\SmsService; use crmeb\services\SmsService;
use crmeb\services\WechatService; use crmeb\services\WechatService;
use crmeb\services\WechatTemplateMessageService;
use Exception; use Exception;
use Firebase\JWT\JWT; use Firebase\JWT\JWT;
use Gregwar\Captcha\CaptchaBuilder; use Gregwar\Captcha\CaptchaBuilder;
@ -42,9 +30,6 @@ use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException; use think\exception\ValidateException;
use think\facade\Cache; use think\facade\Cache;
use think\facade\Log;
use think\facade\Queue;
use crmeb\jobs\SendSmsJob;
/** /**
* Class Auth * Class Auth
@ -54,29 +39,6 @@ use crmeb\jobs\SendSmsJob;
*/ */
class Auth extends BaseController class Auth extends BaseController
{ {
public function test(){
// 分销商升级模拟
// $user = app()->make(UserRepository::class)->get(327706);
// $res = app()->make(UserBrokerageRepository::class)->incV2($user, [
// 'type' => 'pay_num',
// 'inc' => 0
// ]);
// debug(['升级结果'=>$res]);
// $userList = app()->make(WeightValueRepository::class)->getUserHoldList(327706);
// debug(['用户列表'=>$userList]);
// 订单支付成功 触发购买商品赠送上级权重值
// Queue::push(GiveWeightValueJob::class,[
// 'uid' => 327706,
// 'group_order_id' => 133
// ]);
}
/** /**
* @param UserRepository $repository * @param UserRepository $repository

View File

@ -29,5 +29,7 @@ return [
'clear:cache' => 'app\command\clearCache', 'clear:cache' => 'app\command\clearCache',
//更新热卖榜单 //更新热卖榜单
'change:hotTop' => 'app\command\changeHotTop', 'change:hotTop' => 'app\command\changeHotTop',
// 平台抽成相关任务
'platformCommission' => 'app\command\platformCommission',
], ],
]; ];

View File

@ -12,7 +12,7 @@ use app\common\middleware\RequestLockMiddleware;
use think\facade\Route; use think\facade\Route;
Route::group('api/', function () { Route::group('api/', function () {
Route::any('test', 'api.Auth/test'); Route::any('test', 'api.Test/test');
//强制登录 //强制登录
Route::group(function () { Route::group(function () {
Route::group('v2', function () { Route::group('v2', function () {