jh-admin/addon/commission/model/Legumes.php

465 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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]);
}
}