465 lines
18 KiB
PHP
465 lines
18 KiB
PHP
<?php
|
||
/**
|
||
* SaaSMall商城系统 - 团队十年电商经验汇集巨献!
|
||
* =========================================================
|
||
* Copy right 2019-2029 成都SAAS云科技有限公司, 保留所有权利。
|
||
* ----------------------------------------------
|
||
* 官方网址: https://www.gobuysaas.com
|
||
* =========================================================
|
||
*/
|
||
|
||
namespace addon\commission\model;
|
||
|
||
|
||
use addon\commission\job\AllocationLegumesJob;
|
||
use app\model\BaseModel;
|
||
use app\model\member\Member;
|
||
use think\Exception;
|
||
use think\facade\Db;
|
||
use think\facade\Queue;
|
||
|
||
|
||
class Legumes extends BaseModel
|
||
{
|
||
/**
|
||
* Common: 获取总统计信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/13 10:28
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function getTotalStatistics($params)
|
||
{
|
||
// 生成查询条件
|
||
$where = [];
|
||
if (isset($params['member_id']) && $params['member_id'] !== '') $where[] = ['member_id', '=', $params['member_id']];
|
||
if (isset($params['legumes_id']) && $params['legumes_id'] !== '') $where[] = ['legumes_id', '=', $params['legumes_id']];
|
||
if (isset($params['status']) && $params['status'] !== '') $where[] = ['status', '=', $params['status']];
|
||
$freezeWhere = $where;
|
||
$freezeWhere[] = ['status', '=', 0];
|
||
// 关联查询
|
||
return [
|
||
'total_get_legumes' => model('commission_legumes_log')->getSum($where, 'get_legumes'),
|
||
'total_order_money' => model('commission_legumes_log')->getSum($where, 'order_money'),
|
||
'total_get_integral' => model('commission_legumes_log')->getSum($where, 'get_integral'),
|
||
'total_use_integral' => model('commission_legumes_log')->getSum($where, 'use_integral'),
|
||
'total_freeze_integral' => model('commission_legumes_log')->getSum($freezeWhere, 'get_integral'),
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Common: 获取豆豆周期结算信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/09 11:49
|
||
* @param $page
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function getCycleList($page, $params)
|
||
{
|
||
// 生成查询条件
|
||
$where = [];
|
||
// 关联查询
|
||
$result = model('commission_legumes')->pageList($where, true, 'id DESC', $page, PAGE_LIST_ROWS);
|
||
|
||
return $this->success($result);
|
||
}
|
||
|
||
/**
|
||
* Common: 获取豆豆分配明细
|
||
* Author: wu-hui
|
||
* Time: 2024/05/09 11:58
|
||
* @param $page
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function getLegumesLogList($page, $params)
|
||
{
|
||
$pageSize = $params['page_size'] ?? PAGE_LIST_ROWS;
|
||
// 生成查询条件
|
||
$where = [];
|
||
if (isset($params['member_id']) && $params['member_id'] !== '') {
|
||
if (is_array($params['member_id'])) $where[] = ['a.member_id', 'in', $params['member_id']];
|
||
else $where[] = ['a.member_id', '=', $params['member_id']];
|
||
}
|
||
if (isset($params['legumes_id']) && $params['legumes_id'] !== '') $where[] = ['a.legumes_id', '=', $params['legumes_id']];
|
||
if (isset($params['status']) && $params['status'] !== '') $where[] = ['a.status', '=', $params['status']];
|
||
// 关联查询
|
||
$join = [
|
||
['member m', 'm.member_id = a.member_id', 'left'],
|
||
];
|
||
$field = [
|
||
'a.*',
|
||
'm.nickname',
|
||
'm.username',
|
||
'm.headimg',
|
||
];
|
||
$result = model('commission_legumes_log')->pageList($where, $field, 'id DESC', $page, $pageSize, 'a', $join);
|
||
|
||
return $this->success($result);
|
||
}
|
||
|
||
/**
|
||
* Common: 获取积分释放明细
|
||
* Author: wu-hui
|
||
* Time: 2024/05/15 15:06
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function legumesReleaseLog($params)
|
||
{
|
||
$pageSize = $params['page_size'] ?? PAGE_LIST_ROWS;
|
||
$page = $params['page'] ?? 1;
|
||
// 生成查询条件
|
||
$where = [];
|
||
if (isset($params['member_id']) && $params['member_id'] !== '') $where[] = ['member_id', '=', $params['member_id']];
|
||
if (isset($params['legumes_log_id']) && $params['legumes_log_id'] !== '') $where[] = ['legumes_log_id', '=', $params['legumes_log_id']];
|
||
// 关联查询
|
||
$result = model('commission_legumes_release_log')->pageList($where, true, 'id DESC', $page, $pageSize);
|
||
|
||
return $this->success($result);
|
||
}
|
||
|
||
/**
|
||
* Common: 获取用户持有信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/09 13:45
|
||
* @param $page
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function getHoldList($page, $params)
|
||
{
|
||
$result = $this->getHoldListData($page, $params);
|
||
|
||
return $this->success($result);
|
||
}
|
||
|
||
/**
|
||
* Common: 获取用户持有信息(返回信息数组)
|
||
* Author: wu-hui
|
||
* Time: 2024/05/29 11:23
|
||
* @return mixed
|
||
*/
|
||
public function getHoldListData($page, $params)
|
||
{
|
||
// 生成查询条件
|
||
$where = [
|
||
['a.status', 'in', [0, 1]],
|
||
];
|
||
if (isset($params['member_id']) && $params['member_id'] !== '') {
|
||
if (is_array($params['member_id'])) $where[] = ['a.member_id', 'in', $params['member_id']];
|
||
else $where[] = ['a.member_id', '=', $params['member_id']];
|
||
}
|
||
// 关联查询
|
||
$join = [
|
||
['member m', 'm.member_id = a.member_id', 'left'],
|
||
];
|
||
$field = [
|
||
'a.member_id',
|
||
'sum(a.order_money) as total_order_money',
|
||
'sum(a.get_legumes) as total_get_legumes',
|
||
'sum(a.refund_order_money) as total_refund_order_money',
|
||
'sum(a.refund_get_legumes) as total_refund_get_legumes',
|
||
'sum(a.get_integral) as total_get_integral',
|
||
'sum(a.use_integral) as total_use_integral',
|
||
'm.nickname',
|
||
'm.username',
|
||
'm.headimg',
|
||
];
|
||
$result = model('commission_legumes_log')->pageList($where, $field, 'id DESC', $page, PAGE_LIST_ROWS, 'a', $join, 'a.member_id');
|
||
// 获取冻结中积分
|
||
$memberIds = array_column($result['list'], 'member_id');
|
||
$freezeWhere = [
|
||
['member_id', 'in', $memberIds],
|
||
['status', '=', 0],
|
||
];
|
||
$freezeField = 'member_id,sum(get_integral) as total_get_integral';
|
||
$freeze = model('commission_legumes_log')->getList($freezeWhere, $freezeField, '', 'a', [], 'member_id');
|
||
$freeze = array_column($freeze, 'total_get_integral', 'member_id');
|
||
foreach ($result['list'] as &$singleInfo) {
|
||
// 总冻结积分
|
||
$singleInfo['total_freeze_integral'] = $freeze[$singleInfo['member_id']] ?? 0;
|
||
// 可使用积分
|
||
$reduce = (float)sprintf("%.2f", $singleInfo['total_freeze_integral'] + $singleInfo['total_use_integral']);// 冻结 + 已使用积分
|
||
$singleInfo['surplus_use_integral'] = (float)sprintf("%.2f", $singleInfo['total_get_integral'] - $reduce);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Common: 获取单个用户持有信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/09 16:06
|
||
* @param $memberId
|
||
* @return array|mixed
|
||
*/
|
||
public function getMemberHoldInfo($memberId)
|
||
{
|
||
$result = $this->getHoldListData(1, ['member_id' => $memberId]);
|
||
$info = $result['list'] ?? [];
|
||
|
||
return $info[0] ?? [];
|
||
}
|
||
|
||
|
||
/**
|
||
* Common: 获取全平台用户持有总积分信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/29 11:40
|
||
* @param $memberId
|
||
* @return array
|
||
*/
|
||
public function getAllSiteHoldInfo($memberId)
|
||
{
|
||
$memberId = (new Member())->getAllMemberIds($memberId);
|
||
// 根据用户id 获取全部相关持有信息
|
||
$list = $this->getAllSiteHoldAllList(1, $memberId, true);
|
||
return [
|
||
'total_order_money' => sprintf("%.2f", array_sum(array_column($list, 'total_order_money'))),
|
||
'total_get_legumes' => sprintf("%.2f", array_sum(array_column($list, 'total_get_legumes'))),
|
||
'total_refund_order_money' => sprintf("%.2f", array_sum(array_column($list, 'total_refund_order_money'))),
|
||
'total_refund_get_legumes' => sprintf("%.2f", array_sum(array_column($list, 'total_refund_get_legumes'))),
|
||
'total_get_integral' => sprintf("%.2f", array_sum(array_column($list, 'total_get_integral'))),
|
||
'total_use_integral' => sprintf("%.2f", array_sum(array_column($list, 'total_use_integral'))),
|
||
'total_freeze_integral' => sprintf("%.2f", array_sum(array_column($list, 'total_freeze_integral'))),
|
||
'surplus_use_integral' => sprintf("%.2f", array_sum(array_column($list, 'surplus_use_integral')))
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Common: 获取全平台用户持有积分信息列表(递归获取全部列表)
|
||
* Author: wu-hui
|
||
* Time: 2024/05/29 11:34
|
||
* @param $page
|
||
* @param $memberId
|
||
* @param false $isGetAll
|
||
* @param array $allList
|
||
* @return array
|
||
*/
|
||
public function getAllSiteHoldAllList($page, $memberId, $isGetAll = false, $allList = [])
|
||
{
|
||
// 获取信息
|
||
$result = $this->getHoldListData($page, ['member_id' => $memberId]);
|
||
$pageCount = $result['page_count'] ?? 1;
|
||
$allList = array_merge($allList, $result['list']);
|
||
// 判断:是否递归查询全部
|
||
if ($pageCount > $page && $isGetAll) {
|
||
return $this->getAllSiteHoldAllList(++$page, $memberId, true, $allList);
|
||
}
|
||
// 返回列表信息
|
||
return $allList;
|
||
}
|
||
|
||
|
||
/**
|
||
* Common: 豆豆计算 - 计算昨天产生的豆豆总数
|
||
* Author: wu-hui
|
||
* Time: 2024/05/08 18:13
|
||
*/
|
||
public function computeYesterdayLegumes()
|
||
{
|
||
// 获取总平台配置信息
|
||
$config = (new Setting())->getConfig();
|
||
$legumesPrice = (new Setting())->getLegumesPrice();
|
||
// 获取周期时间
|
||
[$startTime, $endTime] = getTimeStamp('yesterday');// 天
|
||
Db::startTrans();
|
||
try {
|
||
// 判断:当前时间周期是否已经结算
|
||
$maxTime = model('commission_legumes')->getMax([], 'end_time');
|
||
if ($endTime <= $maxTime) throw new Exception('当前周期积分抽成已结算!');
|
||
// [$startTime,$endTime] = getTimeStamp('today');// todo:调试信息
|
||
// $startTime = mktime(0, 0, 0, date('m'), date('d') - 1, date('Y'));
|
||
// $endTime = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
|
||
// 获取周期内积分抽成信息
|
||
$integralInfo = $this->getIntegralInfo($startTime, $endTime);
|
||
if ((float)$integralInfo['reality_money'] <= 0) throw new Exception('周期内无积分抽成信息');
|
||
// 计算豆豆数量 豆豆数量 = 积分抽成金额(昨日总金额) * 0.2 / 豆豆当前价格
|
||
$legumesNum = (float)sprintf("%.4f", (float)$integralInfo['reality_money'] * 0.2 / $legumesPrice); // 今日豆豆数量
|
||
// 计算豆豆价格 下次豆豆价格 = 积分抽成金额(全平台总金额) ➗ 文创豆数量(全平台总数量)
|
||
$allIntegralInfo = $this->getIntegralInfo();
|
||
$allLegumes = model('commission_legumes')->getSum([], 'legumes_num');
|
||
$tomorrowLegumesPrice = sprintf("%.4f", $allIntegralInfo['reality_money'] / ($allLegumes + $legumesNum));
|
||
// 记录
|
||
$recordId = model('commission_legumes')->add([
|
||
'total_integral_money' => $integralInfo['total_money'],
|
||
'refund_money' => $integralInfo['refund_money'],
|
||
'reality_money' => $integralInfo['reality_money'],
|
||
'legumes_price' => $legumesPrice,
|
||
'legumes_num' => $legumesNum,
|
||
'tomorrow_legumes_price' => $tomorrowLegumesPrice,
|
||
'start_time' => $startTime,
|
||
'end_time' => $endTime,
|
||
]);
|
||
// 修改豆豆实时价格
|
||
(new Setting())->setLegumesPrice(0, $tomorrowLegumesPrice);
|
||
// 触发事件 开始给每个消费用户分豆豆
|
||
Queue::push(AllocationLegumesJob::class, [
|
||
'legumes_id' => $recordId
|
||
]);
|
||
Db::commit();
|
||
} catch (Exception $e) {
|
||
Db::rollback();
|
||
$data = [
|
||
'start' => date("Y-m-d H:i:s", $startTime),
|
||
'end' => date("Y-m-d H:i:s", $endTime),
|
||
'msg' => $e->getMessage()
|
||
];
|
||
trace($data, '计算昨天产生的豆豆总数 - 错误');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Common: 豆豆计算 - 获取时间段内总积分抽成金额
|
||
* Author: wu-hui
|
||
* Time: 2024/05/08 17:50
|
||
* @param int $startTime
|
||
* @param int $endTime
|
||
* @return array
|
||
*/
|
||
public function getIntegralInfo(int $startTime = 0, int $endTime = 0): array
|
||
{
|
||
$where = [];
|
||
if ($startTime > 0 && $endTime > 0) {
|
||
$where[] = ['create_time', 'between', [date("Y-m-d H:i:s", $startTime), date("Y-m-d H:i:s", $endTime)]];
|
||
}
|
||
// 总佣金
|
||
$info['total_money'] = (float)model('commission_record')->getSum($where, 'integral_money');
|
||
// 获取退款金额
|
||
$info['refund_money'] = (float)model('commission_record')->getValue($where, 'sum((integral_money * refund_ratio / 100)) as refund_money');
|
||
// 实际金额
|
||
$info['reality_money'] = (float)sprintf("%.3f", (float)$info['total_money'] - (float)$info['refund_money']);
|
||
|
||
return $info;
|
||
}
|
||
|
||
|
||
/**
|
||
* Common: 查询需要使用的分配信息 尽可能仅查询需要使用的信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/11 9:45
|
||
* @param int $memberId
|
||
* @param float $useLegumesIntegral
|
||
* @param int $page
|
||
* @return array|mixed
|
||
*/
|
||
public function getUseList(int $memberId, float $useLegumesIntegral, int $limit = 10)
|
||
{
|
||
$where = [
|
||
['status', '=', 1],
|
||
// [ 'member_id', '=', $memberId],
|
||
['', 'exp', Db::raw('get_integral > use_integral')]
|
||
];
|
||
// 多平台同用户积分兼容
|
||
$memberId = (new Member())->getAllMemberIds($memberId);
|
||
if (is_array($memberId)) $where[] = ['member_id', 'in', $memberId];
|
||
else $where[] = ['member_id', '=', $memberId];
|
||
|
||
// 查询
|
||
$field = 'id,member_id,get_integral,use_integral,(get_integral - use_integral) as surplus_integral';
|
||
$result = model('commission_legumes_log')->pageList($where, $field, 'id ASC', 1, $limit);
|
||
$list = $result['list'] ?? [];
|
||
$pageCount = $result['page_count'] ?? 1;
|
||
// 判断:总页数 大于当前页 判断是否需要递归
|
||
if ($pageCount > 1) {
|
||
$totalSurplusIntegral = array_sum(array_column($list, 'surplus_integral'));
|
||
if ($useLegumesIntegral > $totalSurplusIntegral) {
|
||
$limit += 10;
|
||
return $this->getUseList($memberId, $useLegumesIntegral, $limit);
|
||
}
|
||
}
|
||
|
||
return $list;
|
||
}
|
||
|
||
/**
|
||
* Common: 查询已使用积分的分配信息 尽可能查询需要的信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/13 16:19
|
||
* @param int $memberId
|
||
* @param float $maxIntegral
|
||
* @param int $limit
|
||
* @return array|mixed
|
||
*/
|
||
public function getUsedList(int $memberId, float $maxIntegral, int $limit = 10)
|
||
{
|
||
$where = [
|
||
['status', '=', 1],
|
||
// [ 'member_id', '=', $memberId],
|
||
['use_integral', '>', 0],
|
||
];
|
||
// 多平台同用户积分兼容
|
||
$memberId = (new Member())->getAllMemberIds($memberId);
|
||
if (is_array($memberId)) $where[] = ['member_id', 'in', $memberId];
|
||
else $where[] = ['member_id', '=', $memberId];
|
||
// 查询
|
||
$result = model('commission_legumes_log')->pageList($where, 'id,get_integral,use_integral', 'id DESC', 1, $limit);
|
||
$list = $result['list'] ?? [];
|
||
$pageCount = $result['page_count'] ?? 1;
|
||
if ($pageCount > 1) {
|
||
$totalSurplusIntegral = array_sum(array_column($list, 'use_integral'));
|
||
if ($maxIntegral > $totalSurplusIntegral) {
|
||
$limit += 10;
|
||
return $this->getUseList($memberId, $maxIntegral, $limit);
|
||
}
|
||
}
|
||
|
||
return $list;
|
||
}
|
||
|
||
|
||
/**
|
||
* Common: 获取统计信息
|
||
* Author: wu-hui
|
||
* Time: 2024/05/11 15:09
|
||
* @param array $params
|
||
* @return array
|
||
*/
|
||
public function getStatistics(array $params)
|
||
{
|
||
// 获取当前用户可用豆豆积分
|
||
$legumes = (new Legumes())->getAllSiteHoldInfo((int)$params['member_id']);
|
||
// 获取统计信息
|
||
$data = [
|
||
'integral_upper_limit' => $this->getModel($params)->sum('order_money'),// 积分释放上限(总)
|
||
'get_legumes' => $this->getModel($params)->sum('get_legumes'),// 总获得豆豆
|
||
'refund_get_legumes' => $this->getModel($params)->sum('refund_get_legumes'),// 退款减少豆豆
|
||
'get_integral' => $this->getModel($params)->sum('get_integral'),// 获得积分
|
||
'freeze_integral' => $this->getModel($params)->where('status', 0)->sum('get_integral'),// 冻结中积分
|
||
'used_integral' => $legumes['surplus_use_integral'] ?? 0,// 可用积分
|
||
'use_integral' => $this->getModel($params)->sum('use_integral'),// 已使用积分
|
||
];
|
||
// 未释放积分 = 积分释放上限 - 已获得积分
|
||
$data['not_integral'] = (float)sprintf("%.4f", $data['integral_upper_limit'] - $data['get_integral']);
|
||
// 实际获得豆豆
|
||
$data['reality_get_legumes'] = (float)sprintf("%.4f", $data['get_legumes'] - $data['refund_get_legumes']);
|
||
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* Common: 查询model(统计查询使用)
|
||
* Author: wu-hui
|
||
* Time: 2024/05/11 15:00
|
||
* @param $params
|
||
* @return Db
|
||
*/
|
||
public function getModel($params)
|
||
{
|
||
return Db::name('commission_legumes_log')
|
||
->when((int)$params['member_id'] > 0, function ($query) use ($params) {
|
||
$memberId = (new Member())->getAllMemberIds((int)$params['member_id']);
|
||
if (is_array($memberId)) $query->whereIn('member_id', $memberId);
|
||
else $query->where('member_id', $memberId);
|
||
})
|
||
->when(isset($params['status']) && $params['status'] !== '', function ($query) use ($params) {
|
||
$query->where('status', $params['status']);
|
||
})
|
||
->whereIn('status', [0, 1]);
|
||
}
|
||
|
||
|
||
}
|