ThinkAdmin/app/data/service/RebateCurrentService.php
2021-03-15 11:54:29 +08:00

368 lines
16 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 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 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
* @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->{$vo['func']}();
}
}
}
/**
* 首推奖励
* @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, '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, '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, '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, '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'],
'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, '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;
}
}