ThinkAdmin/app/data/service/RebateService.php
2021-03-17 18:42:35 +08:00

412 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
namespace app\data\service;
use think\admin\Exception;
use think\admin\Service;
/**
* 系统实时返利服务
* Class RebateService
* @package app\data\service
*/
class RebateService 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';
/**
* 返利服务初始化
* @return void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function initialize()
{
// 返利奖励到账时机
$this->status = $this->config('settl_type') > 1 ? 0 : 1;
}
/**
* 获取奖励名称
* @param string $prize
* @return string
*/
public function name(string $prize): string
{
return self::PRIZES[$prize]['name'] ?? $prize;
}
/**
* 执行订单返利处理
* @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['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('间接推荐人不存在');
}
// 批量发放配置奖励
foreach (self::PRIZES as $vo) {
if (method_exists($this, $vo['func'])) {
$this->app->log->notice("订单 {$orderNo} 开始发放 [{$vo['func']}] {$vo['name']}");
$this->{$vo['func']}();
$this->app->log->notice("订单 {$orderNo} 完成发放 [{$vo['func']}] {$vo['name']}");
}
}
}
/**
* 用户首推奖励
* @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()->upgrade($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()->upgrade($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()->upgrade($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()->upgrade($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(str2arr($this->user['path'], '-'));
if (empty($puids) || $this->order['amount_total'] <= 0) return false;
// 获取可以参与奖励的代理
$vips = $this->app->db->name('DataUserUpgrade')->whereLike('rebate_rule', '%,' . self::PRIZE_05 . ',%')->column('number');
$users = $this->app->db->name('DataUser')->whereIn('vip_code', $vips)->whereIn('id', $puids)->orderField('id', $puids)->select()->toArray();
// 查询需要计算奖励的商品
$map = [['order_no', '=', $this->order['order_no']], ['discount_rate', '<', 100]];
foreach ($this->app->db->name('ShopOrderItem')->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(str2arr($this->user['path'], '-'));
if (empty($puids) || $this->order['amount_total'] <= 0) return false;
// 记录原始等级
$prevLevel = $this->user['vip_code'];
// 获取可以参与奖励的代理
$vips = $this->app->db->name('DataUserUpgrade')->whereLike('rebate_rule', '%,' . self::PRIZE_06 . ',%')->column('number');
foreach ($this->app->db->name('DataUser')->whereIn('vip_code', $vips)->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()->upgrade($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);
}
}
}
/**
* 用户升级奖励发放
* @return boolean
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function _prize07(): bool
{
if ($this->order['order_no'] !== $this->user['vip_order']) return false;
if (!$this->checkLevelPrize(self::PRIZE_07, $this->from1['vip_code'])) return false;
// 创建返利奖励记录
$key = "{$this->user['id']}";
$map = ['type' => self::PRIZE_07, 'order_no' => $this->order['order_no'], 'order_uid' => $this->order['uid']];
if ($this->config("upgrade_state_vip_{$key}") && $this->app->db->name($this->table)->where($map)->count() < 1) {
$value = $this->config("upgrade_value_vip_{$key}");
if ($this->config("upgrade_type_vip_{$key}") == 1) {
$amount = $value ?: '0.00';
$name = "{$this->name(self::PRIZE_07)},每人 {$amount}";
} else {
$amount = $value * $this->order['rebate_amount'] / 100;
$name = "{$this->name(self::PRIZE_07)},订单 {$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()->upgrade($this->from1['id']);
}
return true;
}
/**
* 获取配置数据
* @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;
}
}