<?php
|
|
namespace app\shop\model\plus\shareholder;
|
|
use app\common\model\plus\shareholder\Bonus as BonusModel;
|
use app\common\model\plus\shareholder\User as UserModel;
|
use app\shop\model\plus\shareholder\Order;
|
use app\shop\model\order\Order as OrderModel;
|
use app\shop\model\plus\team\Order as TeamOrderModel;
|
|
/**
|
* 分红结算模型
|
*/
|
class Bonus extends BonusModel
|
{
|
/**
|
* 获取列表
|
*/
|
public function getList($year = '', $month = '', $week = '')
|
{
|
$model = $this;
|
// 检索查询条件
|
if ($year) {
|
|
}
|
return $model->order(['create_time' => 'desc'])
|
->paginate(15);
|
}
|
|
/**
|
* 获取可分红结算数据
|
*/
|
public function getBonus()
|
{
|
$setting = Setting::getItem('basic');
|
if(!$setting['is_open']) {
|
$this->error = '未开启股东分红';
|
return false;
|
}
|
//是否有可分红订单,1有,0无
|
$is_bonus = 1;
|
$first_data = Order::orderFirst();
|
if (empty($first_data)||!isset($first_data)) {
|
$is_bonus = 0;
|
$first_data['create_time']=date('Y-m-d');
|
}
|
//可结算时间需要加上分红结算天数
|
$create_time = strtotime($first_data['create_time']) + intval(Setting::getItem('settlement')['settle_days']) * 86400;
|
$year = date('Y', $create_time) ?? '';
|
$mouth = date('m', $create_time) ?? '';
|
$day = date('d', $create_time) ?? '';
|
$week = '';
|
|
$first_day = '';
|
$last_day = '';
|
if ($setting['bonus_type'] == 10) { //按周
|
if ($day >= 1 && $day <= 7) {
|
$week = '第一周';
|
$first_day = $year . '-' . $mouth . '-01 00:00:00';
|
$last_day = $year . '-' . $mouth . '-07 23:59:59';
|
} else if ($day >= 8 && $day <= 14) {
|
$week = '第二周';
|
$first_day = $year . '-' . $mouth . '-08 00:00:00';
|
$last_day = $year . '-' . $mouth . '-14 23:59:59';
|
} else if ($day >= 15 && $day <= 21) {
|
$week = '第三周';
|
$first_day = $year . '-' . $mouth . '-15 00:00:00';
|
$last_day = $year . '-' . $mouth . '-21 23:59:59';
|
} else if ($day >= 22 && $day <= 31) {
|
$week = '第四周';
|
$first_day = $year . '-' . $mouth . '-22 00:00:00';
|
$last_day = date('Y-m-t 23:59:59', $create_time);//月末日期时间
|
}
|
} elseif ($setting['bonus_type'] == 20) {
|
$first_day = date('Y-m-01 00:00:00', $create_time);//月头日期时间
|
$last_day = date('Y-m-t 23:59:59', $create_time);//月末日期时间
|
} elseif($setting['bonus_type'] == 30) {
|
$first_day = date('Y-01-01 00:00:00', $create_time);//年头日期时间
|
$last_day = date('Y-12-t 23:59:59', $create_time);//年末日期时间
|
} else {
|
$this->error = '结算周期参数错误';
|
return false;
|
}
|
if (strtotime($last_day) >= time()) {
|
$is_bonus = 0;
|
}
|
$model = new Order;
|
$model = $model->where('is_settled', '=', 0)
|
->where('create_time', '>=', strtotime($first_day))
|
->where('create_time', '<=', strtotime($last_day));
|
$order_num = $model->count();
|
$order_price = $model->sum('order_price');
|
$orderData = [
|
'is_bonus' => $is_bonus,
|
'year' => $year . '年',
|
'mouth' => $mouth . '月',
|
'week' => $week,
|
'start_time' => $first_day,
|
'end_time' => $last_day,
|
'first_day' => substr($first_day, 0, 10),
|
'last_day' => substr($last_day, 0, 10),
|
'order_num' => $order_num,
|
'total_pay_price' => $order_price,
|
'bonus_price' => bcmul($order_price, $setting['total_rate'] / 100, 2),
|
'total_rate' => (string)$setting['total_rate'],
|
'shareholder_num' => UserModel::shareholderCount(), //股东数量
|
];
|
return $orderData;
|
}
|
|
/**
|
* 新增结算
|
*/
|
public function add($data)
|
{
|
$config = Setting::getItem('basic');
|
// 获取结算数据
|
$bonusData = (new self)->getBonus();
|
if (!$bonusData) {
|
return false;
|
}
|
if(empty($bonusData['total_rate'])) {
|
$this->error = '分红比例为0,不分红';
|
return false;
|
}
|
if(empty($bonusData['total_pay_price'])) {
|
$this->error = '没有可用的分红';
|
return false;
|
}
|
// 获取满足分红条件的股东数据
|
$userList = User::getEligibleListAll($bonusData);
|
if ($userList->isEmpty()) {
|
$this->error = '没有找到满足分红条件的股东,不分红';
|
return false;
|
}
|
$this->startTrans();
|
try {
|
$grade_arr = []; // 记录等级,分红比例,人数,对应用户ids
|
foreach ($userList as $item) {
|
// 第一个
|
if (empty($grade_arr)) {
|
$grade_arr[] = [
|
'grade_id' => $item['grade']['grade_id'],
|
'name' => $item['grade']['name'],
|
'share_type' => $item['grade']['share_type'], // 分红方式 10固定比例 20团队月业绩占平台月业绩比例
|
'bonus_rate' => $item['grade']['share_type'] == 10 ? $item['grade']['equity'] : 0, // 固定比例时的分红比例
|
'num' => 1,
|
'user' => [
|
[
|
'user_id' => $item['user_id'],
|
'referee_id' => $item['referee_id'],
|
'bonus_rate' => $item['grade']['share_type'] == 20 ? self::getBonusRate($item['user_id'], $bonusData['start_time'], $bonusData['end_time'], $item['grade']['share_type']) : 0
|
]
|
]
|
];
|
} else {
|
//第二个后每个对比是否存在同一个等级的记录
|
$is_have = false;
|
foreach ($grade_arr as &$value) {
|
if ($value['grade_id'] === $item['grade']['grade_id']) {
|
$push_data = ['user_id' => $item['user_id'], 'referee_id' => $item['referee_id']];
|
if ($item['grade']['share_type'] == 20) {
|
$push_data['bonus_rate'] = self::getBonusRate($item['user_id'], $bonusData['start_time'], $bonusData['end_time'], $item['grade']['share_type']);
|
}
|
array_push($value['user'], $push_data);
|
$value['num']++;
|
$is_have = true;//已存在
|
}
|
}
|
//不存在,则新增
|
if (!$is_have) {
|
$grade_arr[] = [
|
'grade_id' => $item['grade']['grade_id'],
|
'name' => $item['grade']['name'],
|
'share_type' => $item['grade']['share_type'], // 分红方式 10固定比例 20团队月业绩占平台月业绩比例
|
'bonus_rate' => $item['grade']['share_type'] == 10 ? $item['grade']['equity'] : 0, // 固定比例时的分红比例
|
'num' => 1,
|
'user' => [
|
[
|
'user_id' => $item['user_id'],
|
'referee_id' => $item['referee_id'],
|
'bonus_rate' => $item['grade']['share_type'] == 20 ? self::getBonusRate($item['user_id'], $bonusData['start_time'], $bonusData['end_time'], $item['grade']['share_type']) : 0
|
]
|
]
|
];
|
}
|
}
|
}
|
// 计算每个股东分红
|
bcscale(6);// 为了更精确
|
$all_rate = 0;
|
$bonus_price_total = bcmul($bonusData['total_pay_price'], $bonusData['total_rate'] / 100);
|
// 此计算只适用于固定比例模式
|
foreach ($grade_arr as &$a) {
|
$num = count($a['user']) ?? 0;
|
$all_rate = bcadd($all_rate, bcmul($a['bonus_rate'] / 100, $num)); //记录每个等级分红比例 10%*2+20%*5+30%*10
|
$a['bonus_price'] = bcmul($bonus_price_total, $a['bonus_rate'] / 100); // 第一次记录 10%*100元
|
}
|
// 记录分红
|
$data = [
|
'bonus_type' => $config['bonus_type'],
|
'bonus_price' => $bonus_price_total,
|
'bonus_rate' => $config['total_rate'],
|
'order_num' => $bonusData['order_num'],
|
'shareholder_num' => count($userList),
|
'start_time' => strtotime($bonusData['start_time']),
|
'end_time' => strtotime($bonusData['end_time']),
|
'app_id' => self::$app_id
|
];
|
$bonusModel = new BonusModel;
|
$bonusModel->save($data);
|
$bonus_id = $bonusModel->bonus_id;
|
// 记录每个股东分红
|
foreach ($grade_arr as $c) {
|
foreach ($c['user'] as $d) {
|
bcscale(2); // 四舍五入,防止最后分红大于总分红
|
if ($c['share_type'] == 10) {
|
$price = bcdiv($c['bonus_price'], $all_rate) ?? 0;
|
} else {
|
// 非固定模式时,直接乘比例
|
$price = bcmul($bonus_price_total, $d['bonus_rate'] / 100) ?? 0;
|
}
|
$log_data = [
|
'user_id' => $d['user_id'],
|
'grade_id' => $c['grade_id'],
|
'grade_name' => $c['name'],
|
'money' => $price,
|
'share_type' => $c['share_type'],
|
'bonus_rate' => $c['share_type'] == 10 ? $c['bonus_rate'] : $d['bonus_rate'],
|
'order_num' => $bonusData['order_num'],
|
'bonus_id' => $bonus_id,
|
'app_id' => self::$app_id
|
];
|
BonusLog::create($log_data);
|
// 发放分红给股东
|
if ($price) {
|
UserModel::grantMoney($d['user_id'], $price, 10);
|
// 发放平级奖
|
if ($d['referee_id'] && $config['pjaward'] && $config['pjaward_level']) {
|
$this->addPj($d['referee_id'], $log_data, $price, $config['pjaward_level']);
|
}
|
}
|
}
|
}
|
//分红后更新订单状态
|
$orderModel = new Order;
|
$orderModel->orderUpdate(
|
[
|
'is_settled' => 1,
|
'bonus_id' => $bonus_id,
|
'settle_time' => time()
|
],
|
[
|
'start_time' => $bonusData['start_time'],
|
'end_time' => $bonusData['end_time']
|
]
|
);
|
$this->commit();
|
return true;
|
} catch (\Exception $e) {
|
$this->error = $e->getMessage();
|
$this->rollback();
|
return false;
|
}
|
}
|
|
/**
|
* 计算等级分红比例
|
* @param $user_id
|
* @param $start_time
|
* @param $end_time
|
* @param $share_type
|
*/
|
private static function getBonusRate($user_id, $start_time, $end_time, $share_type)
|
{
|
// 按结算周期内团队业绩占平台业绩比例
|
if ($share_type == 20) {
|
// 获取当前周期平台总业绩
|
$data = (new OrderModel())->getOrderData($start_time, $end_time, 'order_total_price');
|
log_write('平台总业绩:'.$data);
|
if (empty($data)) {
|
return 0;
|
}
|
// 获取团队业绩
|
$teamData = (new TeamOrderModel)->getOrderData($user_id, $start_time, $end_time, 'order_total_price');
|
log_write('团队业绩:'.$teamData);
|
return round($teamData / $data * 100, 2);
|
}
|
return 0;
|
}
|
|
/**
|
* 平级奖
|
* @param $grade_id 股东等级id
|
* @param $referee_id
|
* @param $price
|
* @param $pjaward_level
|
* @param $ids 已发放过的user_id集合
|
*/
|
private function addPj($referee_id, $log_data, $bonus, $pjaward_level, $level = 1, $ids = [])
|
{
|
if ($referee_id) {
|
$model = UserModel::detail($referee_id, ['grade']);
|
if ($model && $model['grade_id'] == $log_data['grade_id'] && !in_array($referee_id, $ids) && $level <= $pjaward_level) {
|
bcscale(2); // 四舍五入,防止最后分红大于总分红
|
$price = bcmul($bonus, $model['grade']['pjaward_percent'] / 100) ?? 0;
|
$log_data['user_id'] = $referee_id;
|
$log_data['money'] = $price;
|
$log_data['log_type'] = 30;
|
$log_data['bonus_rate'] = $model['grade']['pjaward_percent'];
|
BonusLog::create($log_data);
|
// 发放分红给股东
|
if ($price) {
|
UserModel::grantMoney($referee_id, $price, 30);
|
}
|
array_push($ids, $referee_id);
|
$level++;
|
}
|
if ($model['referee_id'] && $level <= $pjaward_level) {
|
return $this->addPj($model['referee_id'], $log_data, $bonus, $pjaward_level, $level, $ids);
|
}
|
return true;
|
}
|
}
|
|
}
|