admin-api/app/common/repositories/user/UserBrokerageRepository.php

376 lines
15 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
namespace app\common\repositories\user;
use app\common\dao\user\UserBrokerageDao;
use app\common\model\store\order\StoreOrder;
use app\common\model\store\order\StoreOrderProduct;
use app\common\model\store\product\Spu;
use app\common\model\user\User;
use app\common\model\user\UserBrokerage;
use app\common\repositories\BaseRepository;
use app\common\repositories\system\CacheRepository;
use FormBuilder\Factory\Elm;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Log;
use think\facade\Route;
/**
* @mixin UserBrokerageDao
*/
class UserBrokerageRepository extends BaseRepository
{
// 基本升级条件 所有内容走基本升级条件流程统一处理,未添加到该数组中的升级条件为特殊升级条件,全部单独处理
public const BROKERAGE_RULE_TYPE = ['spread_user', 'pay_money', 'pay_num', 'spread_money', 'spread_pay_num'];
public function __construct(UserBrokerageDao $dao)
{
$this->dao = $dao;
}
public function getList(array $where, $page, $limit)
{
$query = $this->dao->search($where)->order('brokerage_level ASC,create_time DESC');
$count = $query->count();
$list = $query->page($page, $limit)->select();
return compact('list', 'count');
}
public function getNextLevel($level,$type = 0)
{
return $this->search(['next_level' => $level,'type' => $type])->order('brokerage_level ASC,create_time DESC')->find();
}
public function options(array $where)
{
return $this->dao->search($where)->field('brokerage_level as value,brokerage_name as label')->order('brokerage_level ASC,create_time DESC')->select();
}
public function all(int $type)
{
return $this->dao->search(['type' => $type])->order('brokerage_level ASC,create_time DESC')->select();
}
public function inc(User $user, $type, $inc)
{
$nextLevel = $this->getNextLevel($user->brokerage_level);
if (!$nextLevel) return false;
$make = app()->make(UserBillRepository::class);
$bill = $make->getWhere(['uid' => $user->uid, 'link_id' => $nextLevel->user_brokerage_id, 'category' => 'sys_brokerage', 'type' => $type]);
if ($bill) {
$bill->number = bcadd($bill->number, $inc, 2);
$bill->save();
} else {
$make->incBill($user->uid, 'sys_brokerage', $type, [
'number' => $inc,
'title' => $type,
'balance' => 0,
'status' => 0,
'link_id' => $nextLevel->user_brokerage_id
]);
}
return $this->checkLevel($user, $nextLevel);
}
public function checkLevel(User $user, UserBrokerage $nextLevel)
{
$info = app()->make(UserBillRepository::class)->search(['uid' => $user->uid, 'category' => 'sys_brokerage', 'link_id' => $nextLevel->user_brokerage_id])
->column('number', 'type');
foreach ($nextLevel['brokerage_rule'] as $k => $rule) {
if (!isset($info[$k]) && $rule['num'] > 0) return false;
if ($rule['num'] > 0 && $rule['num'] > $info[$k]) return false;
}
$nextLevel->user_num++;
Db::transaction(function () use ($nextLevel, $user) {
$nextLevel->save();
if ($user->brokerage && $user->brokerage->user_num > 0) {
$user->brokerage->user_num--;
$user->brokerage->save();
}
$user->brokerage_level = $nextLevel->brokerage_level;
$user->save();
$key = 'notice_brokerage_level_' . $user->uid;
app()->make(CacheRepository::class)->save($key,$nextLevel->brokerage_level);
});
return true;
}
/**
* Common: 分销商升级 - 流程开始
* Author: wu-hui
* Time: 2023/12/26 14:20
* @param User $user
* @param $data
* @return bool|void
*/
public function incV2(User $user, $data){
$type = $data['type'] ?? '';
$inc = $data['inc'] ?? 0;
// 判断:不存在下一级 升级失败
$nextLevel = $this->getNextLevel($user->brokerage_level);
if (!$nextLevel) return false;
// 判断:是否为基本升级条件 是则进行统一账单处理
if(in_array($type,self::BROKERAGE_RULE_TYPE)){
$make = app()->make(UserBillRepository::class);
$bill = $make->getWhere(['uid' => $user->uid, 'link_id' => $nextLevel->user_brokerage_id, 'category' => 'sys_brokerage', 'type' => $type]);
if ($bill) {
$bill->number = bcadd($bill->number, $inc, 2);
$bill->save();
} else {
$make->incBill($user->uid, 'sys_brokerage', $type, [
'number' => $inc,
'title' => $type,
'balance' => 0,
'status' => 0,
'link_id' => $nextLevel->user_brokerage_id
]);
}
}
// 升级判断流程开始
return $this->checkLevelV2($user, $nextLevel, $data);
}
/**
* Common: 分销商升级 - 升级判断及修改等级信息
* Author: wu-hui
* Time: 2023/12/26 14:20
* @param User $user
* @param UserBrokerage $nextLevel
* @param $data
* @return bool|void
*/
public function checkLevelV2(User $user, UserBrokerage $nextLevel, $data){
// 分销商升级条件判断
try{
// 循环判断是否达成所有升级条件 全部达成为true-成功升级未全部达成为false-升级失败;为空则未设置升级条件-不允许升级
$info = app()->make(UserBillRepository::class)->search(['uid' => $user->uid, 'category' => 'sys_brokerage', 'link_id' => $nextLevel->user_brokerage_id])->column('number', 'type');
$completeResult = [];// 每个条件达成情况:达成=true未达成=false未开启=空
foreach ($nextLevel['brokerage_rule'] as $upgradeKey => $rule) {
// 是否开启
if($rule['is_open'] != 1) continue;
// 根据类型进行对应的处理
if(in_array($upgradeKey,self::BROKERAGE_RULE_TYPE)){
// 基本升级条件 统一处理
if((float)$rule['num'] <= 0) continue;// 条件无效
// 判断:条件是否达标
$num = $info[$upgradeKey] ?? 0;
$completeResult[$upgradeKey] = (float)$rule['num'] >= (float)$num;
}else{
// 特殊升级条件 全部单独处理
$funName = 'upgradeJudge'.ucfirst(camelize($upgradeKey));
$judgeResult = $this->$funName($rule,$data);
if(gettype($judgeResult) == 'boolean') $completeResult[$upgradeKey] = $judgeResult;
}
}
// 判断:是否成功升级
if(array_sum($completeResult) != count($completeResult)) return false;// 结果为空,无有效升级条件;禁止升级
// 升级成功
$nextLevel->user_num++;
Db::transaction(function () use ($nextLevel, $user) {
$nextLevel->save();
if ($user->brokerage && $user->brokerage->user_num > 0) {
$user->brokerage->user_num--;
$user->brokerage->save();
}
// 不是推广员 开启推广员身份
if((int)$user->is_promoter != 1){
$user->is_promoter = 1;
$user->promoter_time = date('Y-m-d H:i:s');
}
$user->brokerage_level = $nextLevel->brokerage_level;
$user->save();
$key = 'notice_brokerage_level_' . $user->uid;
app()->make(CacheRepository::class)->save($key,$nextLevel->brokerage_level);
});
return true;
}catch(\Exception $e){
Log::info('分销商升级 - 错误: '.var_export([
'uid' => $user->uid,
'type' => $data['type'],
'msg' => $e->getMessage(),
],1));
}
}
/**
* Common: 分销商升级 - 升级条件判断 - 购买某个商品之一
* Author: wu-hui
* Time: 2023/12/26 14:35
* @param $rule
* @param $data
* @return bool|string
*/
private function upgradeJudgeManyGoods($rule,$data){
// 判断:条件是否有效
if(count($rule['ids']) <= 0) return '';// 条件无效 未设置商品
// 判断:是否存在订单信息 不存在直接返回false
if(!array_key_exists('group_order_id',$data)) return false;
// 处理订单信息
$orderIds = StoreOrder::where('group_order_id',$data['group_order_id'])->column('order_id');// 获取订单id
$productIds = StoreOrderProduct::whereIn('order_id',$orderIds)->column('product_id');// 获取当前订单中所有商品ID
$setNeedProductIds = Spu::whereIn('spu_id',$rule['ids'])->column('product_id');// 设置的需求商品ID
$intersectData = array_intersect($productIds,$setNeedProductIds);
return count($intersectData) > 0;
}
public function getLevelRate(User $user, UserBrokerage $nextLevel)
{
$info = app()->make(UserBillRepository::class)->search(['uid' => $user->uid, 'category' => 'sys_brokerage', 'link_id' => $nextLevel->user_brokerage_id])
->column('number', 'type');
$brokerage_rule = $nextLevel['brokerage_rule'];
foreach ($nextLevel['brokerage_rule'] as $k => $rule) {
if ($rule['num'] <= 0) {
unset($brokerage_rule[$k]);
continue;
}
if (!isset($info[$k])) {
$rate = 0;
} else if ($rule['num'] > $info[$k]) {
$rate = bcdiv($info[$k], $rule['num'], 2) * 100;
} else {
$rate = 100;
}
$brokerage_rule[$k]['rate'] = $rate;
$brokerage_rule[$k]['task'] = (float)(min($info[$k] ?? 0, $rule['num']));
}
return $brokerage_rule;
}
public function form(?int $id = null)
{
$formData = [];
if ($id) {
$form = Elm::createForm(Route::buildUrl('systemUserMemberUpdate', ['id' => $id])->build());
$data = $this->dao->get($id);
if (!$data) throw new ValidateException('数据不存在');
$formData = $data->toArray();
} else {
$form = Elm::createForm(Route::buildUrl('systemUserMemberCreate')->build());
}
$rules = [
Elm::number('brokerage_level', '会员等级')->required(),
Elm::input('brokerage_name', '会员名称')->required(),
Elm::frameImage('brokerage_icon', '会员图标', '/' . config('admin.admin_prefix') . '/setting/uploadPicture?field=brokerage_icon&type=1')
->required()
->value($formData['brokerage_icon'] ?? '')
->modal(['modal' => false])
->width('1000px')
->height('600px'),
Elm::number('value', ' 所需成长值',$formData['brokerage_rule']['value'] ?? 0)->required(),
Elm::frameImage('image', '背景图', '/' . config('admin.admin_prefix') . '/setting/uploadPicture?field=image&type=1')
->value($formData['brokerage_rule']['image']??'')
->required()
->modal(['modal' => false])
->width('1000px')
->height('600px'),
];
$form->setRule($rules);
return $form->setTitle(is_null($id) ? '添加会员等级' : '编辑会员等级')->formData($formData);
}
public function incMemberValue(int $uid, string $type, int $id)
{
if (!systemConfig('member_status')) return ;
$make = app()->make(UserBillRepository::class);
$count = $make->getWhereCount(['type' => $type, 'link_id' => $id]);
if ($count) return ;
$config = [
'member_pay_num' => '下单获得成长值',
'member_sign_num' => '签到获得成长值',
'member_reply_num' => '评价获得成长值',
'member_share_num' => '邀请获得成长值',
'member_community_num' => '种草图文获得成长值',
];
$inc = systemConfig($type) > 0 ? systemConfig($type) : 0;
$user = app()->make(UserRepository::class)->getWhere(['uid' => $uid],'*',['member']);
$svip_status = $user->is_svip > 0 && systemConfig('svip_switch_status') == '1';
if ($svip_status) {
$svipRate = app()->make(MemberinterestsRepository::class)->getSvipInterestVal(MemberinterestsRepository::HAS_TYPE_MEMBER);
if ($svipRate > 0) {
$inc = bcmul($svipRate, $inc, 0);
}
}
$this->checkMemberValue($user, $inc);
$make->incBill($user->uid, 'sys_members', $type, [
'number' => $inc,
'title' => $config[$type],
'balance' => $user->member_value,
'status' => 0,
'link_id' => $id,
'mark' => $config[$type].':'.$inc,
]);
}
/**
* TODO 连续升级
* @param $nextLevel
* @param $num
* @return array
* @author Qinii
* @day 1/11/22
*/
public function upUp($nextLevel, $num)
{
$newLevel = $this->getNextLevel($nextLevel->brokerage_level, 1);
if ($newLevel) {
$newNum = $num - $newLevel->brokerage_rule['value'];
if ($newNum > 0) {
[$nextLevel,$num] = $this->upUp($newLevel, $newNum);
}
}
return [$nextLevel,$num];
}
/**
* TODO 升级操作
* @param User $user
* @param int $inc
* @author Qinii
* @day 1/11/22
*/
public function checkMemberValue(User $user, int $inc)
{
/**
* 下一级所需经验值
* 当前的经验值加上增加经验值是否够升级
*/
Db::transaction(function () use ($inc, $user) {
$nextLevel = $this->getNextLevel($user->member_level, 1);
if (!$nextLevel) return ;
if (($user->member_value + $inc) >= $nextLevel->brokerage_rule['value']) {
$num = ($user->member_value + $inc) - $nextLevel->brokerage_rule['value'];
if ($num > 0) {
[$nextLevel,$num] = $this->upUp($nextLevel, $num);
}
if ($user->member) {
$user->member->user_num--;
$user->member->save();
}
$nextLevel->user_num++;
$nextLevel->save();
$user->member_level = $nextLevel->brokerage_level;
$key = 'notice_member_level_' . $user->uid;
app()->make(CacheRepository::class)->save($key,$nextLevel->brokerage_level);
} else {
$num = ($user->member_value + $inc);
}
$user->member_value = $num;
$user->save();
});
}
}