mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2025-04-06 03:58:04 +08:00
421 lines
18 KiB
PHP
421 lines
18 KiB
PHP
<?php
|
||
|
||
namespace app\data\service;
|
||
|
||
use think\admin\Exception;
|
||
use think\admin\Service;
|
||
|
||
/**
|
||
* 实时返利服务
|
||
* Class RebateCurrentService
|
||
* @package app\data\service
|
||
*/
|
||
class RebateCurrentService extends Service
|
||
{
|
||
const PRIZE_01 = 'PRIZE01';
|
||
const PRIZE_02 = 'PRIZE02';
|
||
const PRIZE_03 = 'PRIZE03';
|
||
const PRIZE_04 = 'PRIZE04';
|
||
const PRIZE_05 = 'PRIZE05';
|
||
const PRIZE_06 = 'PRIZE06';
|
||
const PRIZE_07 = 'PRIZE07';
|
||
|
||
const PRIZES = [
|
||
self::PRIZE_01 => ['code' => self::PRIZE_01, 'name' => '首推奖励', 'func' => '_prize01'],
|
||
self::PRIZE_02 => ['code' => self::PRIZE_02, 'name' => '复购奖励', 'func' => '_prize02'],
|
||
self::PRIZE_03 => ['code' => self::PRIZE_03, 'name' => '直属团队', 'func' => '_prize03'],
|
||
self::PRIZE_04 => ['code' => self::PRIZE_04, 'name' => '间接团队', 'func' => '_prize04'],
|
||
self::PRIZE_05 => ['code' => self::PRIZE_05, 'name' => '差额奖励', 'func' => '_prize05'],
|
||
self::PRIZE_06 => ['code' => self::PRIZE_06, 'name' => '管理奖励', 'func' => '_prize06'],
|
||
self::PRIZE_07 => ['code' => self::PRIZE_07, 'name' => '升级奖励', 'func' => '_prize07'],
|
||
];
|
||
|
||
/**
|
||
* 用户数据
|
||
* @var array
|
||
*/
|
||
protected $user;
|
||
|
||
/**
|
||
* 订单数据
|
||
* @var array
|
||
*/
|
||
protected $order;
|
||
|
||
/**
|
||
* 奖励到账时机
|
||
* @var integer
|
||
*/
|
||
protected $status;
|
||
|
||
/**
|
||
* 推荐用户
|
||
* @var array
|
||
*/
|
||
protected $from1;
|
||
protected $from2;
|
||
|
||
/**
|
||
* 绑定数据表
|
||
* @var string
|
||
*/
|
||
private $table = 'DataUserRebate';
|
||
|
||
/**
|
||
* 获取奖励名称
|
||
* @param string $prize
|
||
* @return string
|
||
*/
|
||
public function name(string $prize): string
|
||
{
|
||
return self::PRIZES[$prize]['name'] ?? $prize;
|
||
}
|
||
|
||
/**
|
||
* 确认收货订单处理
|
||
* @param string $orderNo
|
||
* @return array [status, message]
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function confirm(string $orderNo): array
|
||
{
|
||
$map = ['order_no' => $orderNo, 'status' => 6];
|
||
$order = $this->app->db->name('ShopOrder')->where($map)->find();
|
||
if (empty($order)) return [0, '需处理的订单状态异常!'];
|
||
$map = [['status', '=', 0], ['order_no', 'like', "{$orderNo}%"]];
|
||
$this->app->db->name($this->table)->where($map)->update(['status' => 1]);
|
||
if (UserUpgradeService::instance()->syncLevel($order['uid'])) {
|
||
return [1, '重新计算用户金额成功!'];
|
||
} else {
|
||
return [0, '重新计算用户金额失败!'];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 执行订单返利
|
||
* @param string $orderNo
|
||
* @throws Exception
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function execute(string $orderNo)
|
||
{
|
||
// 获取订单数据
|
||
$map = ['order_no' => $orderNo, 'payment_status' => 1];
|
||
$this->order = $this->app->db->name('ShopOrder')->where($map)->find();
|
||
if (empty($this->order)) throw new Exception('订单不存在');
|
||
// 同步订单用户余额
|
||
if ($this->order['reward_balance'] > 0) $this->_balance();
|
||
// 检查订单参与返利
|
||
if ($this->order['amount_total'] <= 0) throw new Exception('订单金额为零');
|
||
if ($this->order['rebate_amount'] <= 0) throw new Exception('订单返利为零');
|
||
// 获取用户数据
|
||
$map = ['id' => $this->order['uid'], 'deleted' => 0];
|
||
$this->user = $this->app->db->name('DataUser')->where($map)->find();
|
||
if (empty($this->user)) throw new Exception('用户不存在');
|
||
// 获取直接推荐人数据
|
||
if ($this->order['puid1'] > 0) {
|
||
$map = ['id' => $this->order['puid1']];
|
||
$this->from1 = $this->app->db->name('DataUser')->where($map)->find();
|
||
if (empty($this->from1)) throw new Exception('直接推荐人不存在');
|
||
}
|
||
// 获取间接推荐人数据
|
||
if ($this->order['puid2'] > 0) {
|
||
$map = ['id' => $this->order['puid2']];
|
||
$this->from2 = $this->app->db->name('DataUser')->where($map)->find();
|
||
if (empty($this->from2)) throw new Exception('间接推荐人不存在');
|
||
}
|
||
// 返利奖励到账时机
|
||
$this->status = $this->config('settl_type') > 1 ? 0 : 1;
|
||
// 批量发放配置奖励
|
||
foreach (self::PRIZES as $vo) {
|
||
if (method_exists($this, $vo['func'])) {
|
||
$this->{$vo['func']}();
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 来自订单余额充值
|
||
* @return array [total, count]
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
private function _balance(): array
|
||
{
|
||
data_save('DataUserBalance', [
|
||
'uid' => $this->order['uid'],
|
||
'code' => $this->order['order_no'],
|
||
'name' => "订单余额充值",
|
||
'remark' => "来自订单{$this->order['order_no']}的余额充值",
|
||
'amount' => $this->order['reward_balance'],
|
||
], 'code');
|
||
return UserUpgradeService::instance()->balance($this->order['uid']);
|
||
}
|
||
|
||
/**
|
||
* 首推奖励
|
||
* @return boolean
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
protected function _prize01(): bool
|
||
{
|
||
if (empty($this->from1)) return false;
|
||
$map = ['order_uid' => $this->user['id']];
|
||
if ($this->app->db->name($this->table)->where($map)->count() > 0) return false;
|
||
if (!$this->checkLevelPrize(self::PRIZE_01, $this->from1['vip_code'])) return false;
|
||
// 创建返利奖励记录
|
||
$key = "{$this->from1['id']}_{$this->user['id']}";
|
||
$map = ['type' => self::PRIZE_01, 'order_no' => $this->order['order_no'], 'order_uid' => $this->order['uid']];
|
||
if ($this->config("frist_state_vip_{$key}") && $this->app->db->name($this->table)->where($map)->count() < 1) {
|
||
$value = $this->config("frist_value_vip_{$key}");
|
||
if ($this->config("frist_type_vip_{$key}") == 1) {
|
||
$amount = $value ?: '0.00';
|
||
$name = "{$this->name(self::PRIZE_01)},每人 {$amount} 元";
|
||
} else {
|
||
$amount = $value * $this->order['rebate_amount'] / 100;
|
||
$name = "{$this->name(self::PRIZE_01)},订单 {$value}%";
|
||
}
|
||
$this->app->db->name($this->table)->insert(array_merge($map, [
|
||
'uid' => $this->from1['id'], 'name' => $name, 'amount' => $amount, 'status' => $this->status, 'order_amount' => $this->order['amount_total'],
|
||
]));
|
||
// 更新用户奖利金额
|
||
UserUpgradeService::instance()->syncLevel($this->from1['id']);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 复购奖励
|
||
* @return boolean
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
protected function _prize02(): bool
|
||
{
|
||
if (empty($this->from1)) return false;
|
||
$map = ['order_uid' => $this->user['id']];
|
||
if ($this->app->db->name($this->table)->where($map)->count() < 1) return false;
|
||
if (!$this->checkLevelPrize(self::PRIZE_02, $this->from1['vip_code'])) return false;
|
||
// 创建返利奖励记录
|
||
$key = "{$this->from1['id']}_{$this->user['id']}";
|
||
$map = ['type' => self::PRIZE_02, 'order_no' => $this->order['order_no'], 'order_uid' => $this->order['uid']];
|
||
if ($this->config("repeat_state_vip_{$key}") && $this->app->db->name($this->table)->where($map)->count() < 1) {
|
||
$value = $this->config("repeat_value_vip_{$key}");
|
||
if ($this->config("repeat_type_vip_{$key}") == 1) {
|
||
$amount = $value ?: '0.00';
|
||
$name = "{$this->name(self::PRIZE_02)},每人 {$amount} 元";
|
||
} else {
|
||
$amount = $value * $this->order['rebate_amount'] / 100;
|
||
$name = "{$this->name(self::PRIZE_02)},订单 {$value}%";
|
||
}
|
||
$this->app->db->name($this->table)->insert(array_merge($map, [
|
||
'uid' => $this->from1['id'], 'name' => $name, 'amount' => $amount, 'status' => $this->status, 'order_amount' => $this->order['amount_total'],
|
||
]));
|
||
// 更新用户奖利金额
|
||
UserUpgradeService::instance()->syncLevel($this->from1['id']);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 直属团队
|
||
* @return boolean
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
private function _prize03(): bool
|
||
{
|
||
if (empty($this->from1)) return false;
|
||
if (!$this->checkLevelPrize(self::PRIZE_03, $this->from1['vip_code'])) return false;
|
||
// 创建返利奖励记录
|
||
$key = "{$this->user['id']}";
|
||
$map = ['type' => self::PRIZE_03, 'order_no' => $this->order['order_no'], 'order_uid' => $this->order['uid']];
|
||
if ($this->config("direct_state_vip_{$key}") && $this->app->db->name($this->table)->where($map)->count() < 1) {
|
||
$value = $this->config("direct_value_vip_{$key}");
|
||
$amount = $value * $this->order['rebate_amount'] / 100;
|
||
$name = "{$this->name(self::PRIZE_03)},订单 {$value}%";
|
||
$this->app->db->name($this->table)->insert(array_merge($map, [
|
||
'uid' => $this->from1['id'], 'name' => $name, 'amount' => $amount, 'status' => $this->status, 'order_amount' => $this->order['amount_total'],
|
||
]));
|
||
// 更新用户奖利金额
|
||
UserUpgradeService::instance()->syncLevel($this->from1['id']);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 间接团队
|
||
* @return boolean
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
private function _prize04(): bool
|
||
{
|
||
if (empty($this->from2)) return false;
|
||
if (!$this->checkLevelPrize(self::PRIZE_04, $this->from2['vip_code'])) return false;
|
||
$key = "{$this->user['id']}";
|
||
$map = ['type' => self::PRIZE_04, 'order_no' => $this->order['order_no'], 'order_uid' => $this->order['uid']];
|
||
if ($this->config("indirect_state_vip_{$key}") && $this->app->db->name($this->table)->where($map)->count() < 1) {
|
||
$value = $this->config("indirect_value_vip_{$key}");
|
||
$amount = $value * $this->order['rebate_amount'] / 100;
|
||
$name = "{$this->name(self::PRIZE_04)},订单 {$value}%";
|
||
$this->app->db->name($this->table)->insert(array_merge($map, [
|
||
'uid' => $this->from2['id'], 'name' => $name, 'amount' => $amount, 'status' => $this->status, 'order_amount' => $this->order['amount_total'],
|
||
]));
|
||
// 更新代理奖利金额
|
||
UserUpgradeService::instance()->syncLevel($this->from2['id']);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 差额奖励
|
||
* @return false
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
private function _prize05(): bool
|
||
{
|
||
$puids = array_reverse(explode('-', trim($this->user['path'], '-')));
|
||
if (empty($puids) || $this->order['amount_total'] <= 0) return false;
|
||
// 获取可以参与奖励的代理
|
||
$sql = $this->app->db->name('DataUserUpgrade')->field('number')->whereLike('rebate_rule', '%,' . self::PRIZE_05 . ',%')->buildSql(true);
|
||
$users = $this->app->db->name('DataUser')->where("vip_code in {$sql}")->whereIn('id', $puids)->orderField('id', $puids)->select()->toArray();
|
||
// 查询需要计算奖励的商品
|
||
$map = [['order_no', '=', $this->order['order_no']], ['discount_rate', '<', 100]];
|
||
foreach ($this->app->db->name('StoreOrderItem')->where($map)->cursor() as $item) {
|
||
$itemJson = $this->app->db->name('DataUserDiscount')->where(['status' => 1, 'deleted' => 0])->value('items');
|
||
if (!empty($itemJson) && is_array($rules = json_decode($itemJson, true))) {
|
||
[$tVip, $tRate] = [$item['vip_code'], $item['discount_rate']];
|
||
foreach ($rules as $rule) if ($rule['level'] > $tVip) foreach ($users as $user) if ($user['vip_code'] > $tVip) {
|
||
if ($tRate > $rule['discount'] && $tRate < 100) {
|
||
$map = [
|
||
'type' => self::PRIZE_05, 'uid' => $user['id'],
|
||
'code' => "{$this->order['order_no']}#{$item['id']}#{$tVip}.{$user['vip_code']}",
|
||
];
|
||
if ($this->app->db->name($this->table)->where($map)->count() < 1) {
|
||
$dRate = ($tRate - $rule['discount']) / 100;
|
||
$this->app->db->name($this->table)->insert(array_merge($map, [
|
||
'name' => "等级差额奖励{$tVip}#{$user['vip_code']}商品的{$dRate}%",
|
||
'amount' => $dRate * $item['total_selling'],
|
||
'status' => $this->status,
|
||
'order_no' => $this->order['order_no'],
|
||
'order_uid' => $this->order['uid'],
|
||
'order_amount' => $this->order['amount_total'],
|
||
]));
|
||
}
|
||
[$tVip, $tRate] = [$user['vip_code'], $rule['discount']];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 管理奖励发放
|
||
* @return boolean
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
private function _prize06(): bool
|
||
{
|
||
$puids = array_reverse(explode('-', trim($this->user['path'], '-')));
|
||
if (empty($puids) || $this->order['amount_total'] <= 0) return false;
|
||
// 记录原始等级
|
||
$prevLevel = $this->user['vip_code'];
|
||
// 获取可以参与奖励的代理
|
||
$subsql = $this->app->db->name('DataUserUpgrade')->field('number')->whereLike('rebate_rule', '%,' . self::PRIZE_06 . ',%')->buildSql(true);
|
||
foreach ($this->app->db->name('DataUser')->where("vip_code in {$subsql}")->whereIn('id', $puids)->orderField('id', $puids)->cursor() as $user) {
|
||
if ($user['vip_code'] > $prevLevel) {
|
||
if (($amount = $this->_prize06amount($prevLevel, $user['vip_code'])) > 0.00) {
|
||
$map = ['type' => self::PRIZE_06, 'order_no' => $this->order['order_no'], 'order_uid' => $this->order['uid']];
|
||
$name = "{$this->name(self::PRIZE_06)},[ {$prevLevel} > {$user['vip_code']} ]每单 {$amount} 元";
|
||
$this->app->db->name($this->table)->insert(array_merge($map, [
|
||
'uid' => $this->from2['id'], 'name' => $name, 'amount' => $amount, 'status' => $this->status, 'order_amount' => $this->order['amount_total'],
|
||
]));
|
||
UserUpgradeService::instance()->syncLevel($this->from2['id']);
|
||
}
|
||
$prevLevel = $user['vip_code'];
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 计算两等级之间的管理奖差异
|
||
* @param integer $prevLevel
|
||
* @param integer $nextLevel
|
||
* @return float
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
private function _prize06amount(int $prevLevel, int $nextLevel): float
|
||
{
|
||
if ($this->config("manage_type_vip_{$nextLevel}") == 2) {
|
||
$amount = 0.00;
|
||
foreach (range($prevLevel, $nextLevel) as $level) {
|
||
[$state, $value] = [
|
||
$this->config("manage_state_vip_{$level}"),
|
||
$this->config("manage_value_vip_{$level}"),
|
||
];
|
||
if ($state && $value > 0) $amount += $value;
|
||
}
|
||
return floatval($amount);
|
||
} else {
|
||
if ($this->config("manage_state_vip_{$nextLevel}")) {
|
||
return floatval($this->config("manage_value_vip_{$nextLevel}"));
|
||
} else {
|
||
return floatval(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 升级奖励发放
|
||
*/
|
||
private function _prize07()
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* 获取配置数据
|
||
* @param ?string $name
|
||
* @return array|string
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function config(?string $name = null)
|
||
{
|
||
static $data = [];
|
||
if (empty($data)) $data = sysdata('RebateRule');
|
||
return is_null($name) ? $data : ($data[$name] ?? '');
|
||
}
|
||
|
||
/**
|
||
* 检查等级是否有奖励
|
||
* @param string $prize
|
||
* @param integer $level
|
||
* @return boolean
|
||
*/
|
||
protected function checkLevelPrize(string $prize, int $level): bool
|
||
{
|
||
$map = [['number', '=', $level], ['rebate_rule', 'like', "%,{$prize},%"]];
|
||
return $this->app->db->name('DataUserUpgrade')->where($map)->count() > 0;
|
||
}
|
||
} |