feat(partner): 全网平级奖支持逐代10%级联递减至0.01元截断机制

这个提交包含在:
chen
2026-09-17 14:04:28 +08:00
父节点 1f67b0a970
当前提交 5f9b407e64
共有 6 个文件被更改,包括 450 次插入 和 78 次删除

查看文件

@@ -3,7 +3,7 @@
namespace addons\shopro\service\partner;
/**
* 创客平级(支持两代级联:第1代10%,第2代上级收益10%)/ 被超越 5%(只一层)
* 创客平级(逐代 10% 递减级联,最低发放 0.01 元后截断)/ 被超越 5%(只一层)
*/
class MakerPeerReward
{
@@ -12,7 +12,10 @@ class MakerPeerReward
$bonus = PartnerConfig::makerBonus();
$peerRate = (float) PartnerConfig::get('partner_maker_peer_rate', 0.10);
$overRate = (float) PartnerConfig::get('partner_maker_overtaken_rate', 0.05);
$maxPeerGenerations = (int) PartnerConfig::get('partner_maker_peer_max_generations', 2);
$maxPeerGenerations = (int) PartnerConfig::get('partner_maker_peer_max_generations', 50);
if ($maxPeerGenerations <= 0) {
$maxPeerGenerations = 50;
}
$paid = $diffResult['paid'] ?? [];
$indexByUser = [];
foreach ($chain as $i => $node) {
@@ -40,6 +43,9 @@ class MakerPeerReward
$peer = $chain[$peerIdx];
$amount = round($currentBase * $peerRate, 2);
if ($amount < 0.01) {
break;
}
if (!$active->isActive($peer['agent'] ?? $peer)) {
PartnerRewardService::writeSkip(
@@ -52,31 +58,29 @@ class MakerPeerReward
"平级创客(第{$gen}代) 30 日无自购"
);
} else {
if ($amount > 0) {
PartnerRewardService::account(
$order,
$buyerId,
$peer['user_id'],
'maker_peer',
'maker',
$amount,
$currentBase,
[
'generation' => $gen,
'formula' => "平级(第{$gen}代) {$currentBase} × " . ($peerRate * 100) . "% = {$amount}",
'from_user_id' => $sourceUserId,
'level' => $item['level'],
]
);
}
PartnerRewardService::account(
$order,
$buyerId,
$peer['user_id'],
'maker_peer',
'maker',
$amount,
$currentBase,
[
'generation' => $gen,
'formula' => "平级(第{$gen}代) {$currentBase} × " . ($peerRate * 100) . "% = {$amount}",
'from_user_id' => $sourceUserId,
'level' => $item['level'],
]
);
}
// 下一代平级的寻源起点与计算基数:以当前平级创客为基础,基数变为当前平级奖金(即 6.00)
// 下一代平级的寻源起点与计算基数:以当前平级创客为基础,基数变为当前平级奖金
$currentFrom = $peerIdx;
$currentBase = $amount;
$sourceUserId = $peer['user_id'];
if ($currentBase <= 0) {
if ($currentBase < 0.01) {
break;
}
}
@@ -98,7 +102,7 @@ class MakerPeerReward
PartnerRewardService::writeSkip($order, $buyerId, $lower['user_id'], 'maker_overtaken', 'maker', 'inactive_30d', '被超越创客 30 日无自购');
return;
}
if ($amount <= 0) {
if ($amount < 0.01) {
return;
}
PartnerRewardService::account($order, $buyerId, $lower['user_id'], 'maker_overtaken', 'maker', $amount, $highest['cap'], [

查看文件

@@ -3,7 +3,7 @@
namespace addons\shopro\service\partner;
/**
* 酒道馆 / 区县平级 10%,基数为本单该下级的团队奖
* 酒道馆 / 区县平级 10% 逐代递减级联,最低发放 0.01 元截断
*/
class PeerShareReward
{
@@ -22,29 +22,67 @@ class PeerShareReward
protected function peer($order, $buyerId, $chain, $from, $flag, $type, $role, $rate, ActiveService $active, $label)
{
$start = intval($from['index']) + 1;
$peer = null;
for ($i = $start; $i < count($chain); $i++) {
if (intval($chain[$i][$flag] ?? 0)) {
$peer = $chain[$i];
$maxGenerations = intval(PartnerConfig::get("partner_{$role}_peer_max_generations", 50));
if ($maxGenerations <= 0) {
$maxGenerations = 50;
}
$currentFrom = intval($from['index']);
$currentBase = (float) $from['amount'];
$sourceUserId = $from['user_id'];
for ($gen = 1; $gen <= $maxGenerations; $gen++) {
$peerIdx = -1;
for ($i = $currentFrom + 1; $i < count($chain); $i++) {
if (intval($chain[$i][$flag] ?? 0)) {
$peerIdx = $i;
break;
}
}
if ($peerIdx < 0) {
break;
}
$peer = $chain[$peerIdx];
$amount = round($currentBase * $rate, 2);
if ($amount < 0.01) {
break;
}
if (!$active->isActive($peer['agent'] ?? $peer)) {
PartnerRewardService::writeSkip(
$order,
$buyerId,
$peer['user_id'],
$type,
$role,
'inactive_30d',
"{$label}平级(第{$gen}代) 30 日无自购"
);
} else {
PartnerRewardService::account(
$order,
$buyerId,
$peer['user_id'],
$type,
$role,
$amount,
$currentBase,
[
'generation' => $gen,
'formula' => "{$label}平级(第{$gen}代) {$currentBase} × " . ($rate * 100) . "% = {$amount}",
'from_user_id' => $sourceUserId,
]
);
}
$currentFrom = $peerIdx;
$currentBase = $amount;
$sourceUserId = $peer['user_id'];
if ($currentBase < 0.01) {
break;
}
}
if (!$peer) {
return;
}
$base = (float) $from['amount'];
$amount = round($base * $rate, 2);
if (!$active->isActive($peer['agent'] ?? $peer)) {
PartnerRewardService::writeSkip($order, $buyerId, $peer['user_id'], $type, $role, 'inactive_30d', "{$label}平级 30 日无自购");
return;
}
if ($amount <= 0) {
return;
}
PartnerRewardService::account($order, $buyerId, $peer['user_id'], $type, $role, $amount, $base, [
'formula' => "{$label}平级 {$base} × " . ($rate * 100) . "% = {$amount}",
'from_user_id' => $from['user_id'],
]);
}
}

查看文件

@@ -31,6 +31,7 @@
body.login-body {
margin: 0;
overflow-x: hidden;
color: var(--text);
font-family: var(--font-ui);
background: var(--ink);
@@ -244,10 +245,13 @@
margin: 0 0 4px;
font-style: normal;
font-size: 12px;
letter-spacing: 0.14em;
letter-spacing: 0.08em;
color: var(--brass-deep);
font-family: var(--font-mono);
text-transform: uppercase;
}
.login-greet-text em {
letter-spacing: 0.14em;
}
.login-greet.has-user em {
@@ -475,16 +479,25 @@
}
.login-brand {
min-height: 240px;
padding: 28px 24px 24px;
min-height: 0;
justify-content: flex-start;
gap: 18px;
padding: 24px 20px 20px;
}
.login-brand::after {
font-size: 160px;
right: -6%;
bottom: -28%;
}
.brand-copy {
padding: 20px 0 8px;
padding: 4px 0 0;
}
.brand-copy h1 {
font-size: 32px;
margin-bottom: 0;
}
.brand-copy p,

查看文件

@@ -4,7 +4,7 @@ return [
'name' => '我的网站',
'beian' => '',
'cdnurl' => '',
'version' => '1.0.1',
'version' => '1.0.2',
'timezone' => 'Asia/Shanghai',
'forbiddenip' => '',
'languages' => [

查看文件

@@ -49,11 +49,11 @@ class MakerPeerTest
public function run()
{
echo "========================================================\n";
echo " 创客两代平级级联收益计算测试 (Maker Peer Cascading) \n";
echo " 创客多代平级级联至0.01截断测试 (Maker Peer to 0.01) \n";
echo "========================================================\n\n";
$this->testThreePeerCascade();
$this->testFourPeerCapLimit();
$this->testMultiPeerUntilCentCutoff();
$this->testInactiveIntermediaryCascade();
$this->testV1PeerCascade();
$this->testMultiSegmentPeers();
@@ -139,13 +139,19 @@ class MakerPeerTest
}
/**
* 测试 2:4 平级创客深度封顶(A -> B -> C -> D,均为 V3)
* 规则验证:
* 第3代创客 D 应严格封顶截断,不产生任何平级奖记录
* 测试 2:多代平级持续向上拿,最少达到 0.01 元后截断
* 链条:买家(7) -> A(2) -> B(3) -> C(4) -> D(5) -> E(6) -> F(8) (均为 V3,基数 60)
* 计算递推:
* A: 极差 60.00
* B(3): 第1代 60 * 10% = 6.00
* C(4): 第2代 6 * 10% = 0.60
* D(5): 第3代 0.6 * 10% = 0.06
* E(6): 第4代 0.06 * 10% = 0.006 -> round 0.01 元(平台最小分币)
* F(8): 第5代 0.01 * 10% = 0.001 -> round 0.00 < 0.01,严格截断,不发放
*/
public function testFourPeerCapLimit()
public function testMultiPeerUntilCentCutoff()
{
$testName = "场景2: 4个平级创客(A->B->C->D) 第3代D严格封顶截断不分佣";
$testName = "场景2: V3创客多代平级(6.00 -> 0.60 -> 0.06 -> 0.01) 到0.01后上层截断";
Db::startTrans();
try {
@@ -156,6 +162,8 @@ class MakerPeerTest
['user_id' => 3, 'level' => 4],
['user_id' => 4, 'level' => 4],
['user_id' => 5, 'level' => 4],
['user_id' => 6, 'level' => 4],
['user_id' => 8, 'level' => 4],
];
$diffResult = [
@@ -169,13 +177,20 @@ class MakerPeerTest
$reward = new MakerPeerReward();
$reward->run($order, $buyerId, $chain, $diffResult, $active);
$dReward = Db::name('shopro_partner_reward')
->where('order_id', 9902)
->where('user_id', 5)
->where('reward_type', 'maker_peer')
->find();
$b = Db::name('shopro_partner_reward')->where('order_id', 9902)->where('user_id', 3)->find();
$c = Db::name('shopro_partner_reward')->where('order_id', 9902)->where('user_id', 4)->find();
$d = Db::name('shopro_partner_reward')->where('order_id', 9902)->where('user_id', 5)->find();
$e = Db::name('shopro_partner_reward')->where('order_id', 9902)->where('user_id', 6)->find();
$f = Db::name('shopro_partner_reward')->where('order_id', 9902)->where('user_id', 8)->find();
$this->assert(empty($dReward), $testName, "第3代平级创客D应无平级奖记录");
$bAmt = $b ? floatval($b['amount']) : 0;
$cAmt = $c ? floatval($c['amount']) : 0;
$dAmt = $d ? floatval($d['amount']) : 0;
$eAmt = $e ? floatval($e['amount']) : 0;
$pass = ($bAmt == 6.00) && ($cAmt == 0.60) && ($dAmt == 0.06) && ($eAmt == 0.01) && empty($f);
$this->assert($pass, $testName, "B={$bAmt}(6), C={$cAmt}(0.6), D={$dAmt}(0.06), E={$eAmt}(0.01), F=" . (empty($f) ? '已截断' : '未截断'));
} catch (\Exception $e) {
$this->assert(false, $testName, "异常: " . $e->getMessage());
} finally {
@@ -241,15 +256,17 @@ class MakerPeerTest
}
/**
* 测试 4:V1 等级(level 2,基数 20 元)两代级联
* 测试 4:V1 等级(level 2,基数 20 元)多代级联
* 规则验证:
* A(2): 极差 20.00
* A: 极差 20.00
* B(3): 第1代 20 * 10% = 2.00
* C(4): 第2代 2 * 10% = 0.20
* D(5): 第3代 0.2 * 10% = 0.02
* E(6): 第4代 0.02 * 10% = 0.002 -> 0.00 < 0.01 截断,不发放
*/
public function testV1PeerCascade()
{
$testName = "场景4: V1等级(基数20元)两代级联 B得2.00元, C得0.20元";
$testName = "场景4: V1等级(基数20元)多代级联 (2.00 -> 0.20 -> 0.02) 到0.01以下截断";
Db::startTrans();
try {
@@ -259,6 +276,8 @@ class MakerPeerTest
['user_id' => 2, 'level' => 2], // Level 2 基数 20 (V1)
['user_id' => 3, 'level' => 2],
['user_id' => 4, 'level' => 2],
['user_id' => 5, 'level' => 2],
['user_id' => 6, 'level' => 2],
];
$diffResult = [
@@ -272,13 +291,18 @@ class MakerPeerTest
$reward = new MakerPeerReward();
$reward->run($order, $buyerId, $chain, $diffResult, $active);
$bReward = Db::name('shopro_partner_reward')->where('order_id', 9904)->where('user_id', 3)->find();
$cReward = Db::name('shopro_partner_reward')->where('order_id', 9904)->where('user_id', 4)->find();
$b = Db::name('shopro_partner_reward')->where('order_id', 9904)->where('user_id', 3)->find();
$c = Db::name('shopro_partner_reward')->where('order_id', 9904)->where('user_id', 4)->find();
$d = Db::name('shopro_partner_reward')->where('order_id', 9904)->where('user_id', 5)->find();
$e = Db::name('shopro_partner_reward')->where('order_id', 9904)->where('user_id', 6)->find();
$bAmount = $bReward ? floatval($bReward['amount']) : 0;
$cAmount = $cReward ? floatval($cReward['amount']) : 0;
$bAmt = $b ? floatval($b['amount']) : 0;
$cAmt = $c ? floatval($c['amount']) : 0;
$dAmt = $d ? floatval($d['amount']) : 0;
$this->assert($bAmount == 2.00 && $cAmount == 0.20, $testName, "B金额={$bAmount}(期2.00), C金额={$cAmount}(期0.20)");
$pass = ($bAmt == 2.00) && ($cAmt == 0.20) && ($dAmt == 0.02) && empty($e);
$this->assert($pass, $testName, "B={$bAmt}(2), C={$cAmt}(0.2), D={$dAmt}(0.02), E=" . (empty($e) ? '已截断' : '未截断'));
} catch (\Exception $e) {
$this->assert(false, $testName, "异常: " . $e->getMessage());
} finally {
@@ -289,13 +313,6 @@ class MakerPeerTest
/**
* 测试 5:多段平级并存(V1平级 + V3平级在同一推荐链)
* 链条:买家(7) -> A(2, V1) -> B(3, V1) -> C(4, V3) -> D(5, V3) -> E(6, V3)
* diff paid: A (level 2, cap 20), C (level 4, cap 60)
* 期望:
* A(2): 极差 20.00
* B(3): V1第1代平级 = 20 * 10% = 2.00
* C(4): 极差 60 - 20 = 40.00
* D(5): V3第1代平级 = 60 * 10% = 6.00
* E(6): V3第2代平级 = 6 * 10% = 0.60
*/
public function testMultiSegmentPeers()
{

查看文件

@@ -0,0 +1,300 @@
<?php
namespace tests\partner;
// 引导 ThinkPHP 环境
define('APP_PATH', __DIR__ . '/../../application/');
define('ROOT_PATH', dirname(realpath(APP_PATH)) . '/');
require_once __DIR__ . '/../../thinkphp/base.php';
require_once __DIR__ . '/../../thinkphp/helper.php';
require_once __DIR__ . '/../../application/common.php';
\think\Config::set(include APP_PATH . 'database.php', 'database');
\think\Loader::addNamespace('app', APP_PATH);
require_once __DIR__ . '/../../addons/shopro/helper/helper.php';
use addons\shopro\service\partner\PeerShareReward;
use addons\shopro\service\partner\ActiveService;
use addons\shopro\service\partner\PartnerRewardService;
use addons\shopro\service\partner\PartnerConfig;
use think\Db;
class MockPeerActiveService extends ActiveService
{
private $activeMap = [];
public function setActive($userId, $isActive)
{
$this->activeMap[$userId] = $isActive;
}
public function isActive($agent, $atTime = null)
{
$userId = is_array($agent) ? ($agent['user_id'] ?? 0) : ($agent->user_id ?? 0);
if (isset($this->activeMap[$userId])) {
return $this->activeMap[$userId];
}
return true;
}
}
class PeerShareTest
{
private $passed = 0;
private $failed = 0;
public function run()
{
echo "========================================================\n";
echo " 酒道馆/区县平级逐代递减级联至0.01截断测试 (Peer Share) \n";
echo "========================================================\n\n";
$this->testVenuePeerCascadeToCent();
$this->testCountyPeerWithVenueCascadeToCent();
$this->testCountyPeerNoVenueCascadeToCent();
$this->testVenuePeerInactiveIntermediary();
echo "\n--------------------------------------------------------\n";
echo "测试执行结果: 通过 {$this->passed} 项, 失败 {$this->failed} 项\n";
echo "========================================================\n";
return $this->failed === 0 ? 0 : 1;
}
private function assert($condition, $testName, $detail = '')
{
if ($condition) {
echo " [PASS] {$testName}\n";
$this->passed++;
} else {
echo " [FAIL] {$testName} - {$detail}\n";
$this->failed++;
}
}
/**
* 测试 1:酒道馆平级逐代递减级联(基数 50 元)
* 链条:买家(7) -> 馆A(2) -> 馆B(3) -> 馆C(4) -> 馆D(5) -> 馆E(6) -> 馆F(8)
* 预期:
* 馆B(3): 第1代 50 * 10% = 5.00
* 馆C(4): 第2代 5 * 10% = 0.50
* 馆D(5): 第3代 0.5 * 10% = 0.05
* 馆E(6): 第4代 0.05 * 10% = 0.005 -> round 0.01
* 馆F(8): 第5代 0.01 * 10% = 0.001 -> round 0.00 < 0.01,截断不发放
*/
public function testVenuePeerCascadeToCent()
{
$testName = "酒道馆: 平级逐代递减(5.00 -> 0.50 -> 0.05 -> 0.01) 到0.01截断";
Db::startTrans();
try {
$order = ['id' => 9911, 'user_id' => 7];
$buyerId = 7;
$chain = [
['user_id' => 2, 'is_venue' => 1], // 馆A
['user_id' => 3, 'is_venue' => 1], // 馆B
['user_id' => 4, 'is_venue' => 1], // 馆C
['user_id' => 5, 'is_venue' => 1], // 馆D
['user_id' => 6, 'is_venue' => 1], // 馆E
['user_id' => 8, 'is_venue' => 1], // 馆F
];
$teamResult = [
'venue' => ['user_id' => 2, 'amount' => 50.0, 'index' => 0],
'county' => null
];
$active = new MockPeerActiveService();
$reward = new PeerShareReward();
$reward->run($order, $buyerId, $chain, $teamResult, $active);
$b = Db::name('shopro_partner_reward')->where('order_id', 9911)->where('user_id', 3)->where('reward_type', 'venue_peer')->find();
$c = Db::name('shopro_partner_reward')->where('order_id', 9911)->where('user_id', 4)->where('reward_type', 'venue_peer')->find();
$d = Db::name('shopro_partner_reward')->where('order_id', 9911)->where('user_id', 5)->where('reward_type', 'venue_peer')->find();
$e = Db::name('shopro_partner_reward')->where('order_id', 9911)->where('user_id', 6)->where('reward_type', 'venue_peer')->find();
$f = Db::name('shopro_partner_reward')->where('order_id', 9911)->where('user_id', 8)->where('reward_type', 'venue_peer')->find();
$bAmt = $b ? floatval($b['amount']) : 0;
$cAmt = $c ? floatval($c['amount']) : 0;
$dAmt = $d ? floatval($d['amount']) : 0;
$eAmt = $e ? floatval($e['amount']) : 0;
$pass = ($bAmt == 5.00) && ($cAmt == 0.50) && ($dAmt == 0.05) && ($eAmt == 0.01) && empty($f);
$this->assert($pass, $testName, "B={$bAmt}(5), C={$cAmt}(0.5), D={$dAmt}(0.05), E={$eAmt}(0.01), F=" . (empty($f) ? '已截断' : '未截断'));
} catch (\Exception $e) {
$this->assert(false, $testName, "异常: " . $e->getMessage());
} finally {
Db::rollback();
}
}
/**
* 测试 2:区县代理(有馆拆分场景,基数 50 元)逐代递减级联至 0.01 截断
* 预期:
* 县B(3): 第1代 50 * 10% = 5.00
* 县C(4): 第2代 0.50
* 县D(5): 第3代 0.05
* 县E(6): 第4代 0.01
* 县F(8): 截断
*/
public function testCountyPeerWithVenueCascadeToCent()
{
$testName = "区县代理(有馆): 平级逐代递减(5.00 -> 0.50 -> 0.05 -> 0.01) 到0.01截断";
Db::startTrans();
try {
$order = ['id' => 9912, 'user_id' => 7];
$buyerId = 7;
$chain = [
['user_id' => 2, 'is_county' => 1],
['user_id' => 3, 'is_county' => 1],
['user_id' => 4, 'is_county' => 1],
['user_id' => 5, 'is_county' => 1],
['user_id' => 6, 'is_county' => 1],
['user_id' => 8, 'is_county' => 1],
];
$teamResult = [
'venue' => ['user_id' => 1, 'amount' => 50.0, 'index' => -1],
'county' => ['user_id' => 2, 'amount' => 50.0, 'index' => 0]
];
$active = new MockPeerActiveService();
$reward = new PeerShareReward();
$reward->run($order, $buyerId, $chain, $teamResult, $active);
$b = Db::name('shopro_partner_reward')->where('order_id', 9912)->where('user_id', 3)->where('reward_type', 'county_peer')->find();
$c = Db::name('shopro_partner_reward')->where('order_id', 9912)->where('user_id', 4)->where('reward_type', 'county_peer')->find();
$d = Db::name('shopro_partner_reward')->where('order_id', 9912)->where('user_id', 5)->where('reward_type', 'county_peer')->find();
$e = Db::name('shopro_partner_reward')->where('order_id', 9912)->where('user_id', 6)->where('reward_type', 'county_peer')->find();
$f = Db::name('shopro_partner_reward')->where('order_id', 9912)->where('user_id', 8)->where('reward_type', 'county_peer')->find();
$bAmt = $b ? floatval($b['amount']) : 0;
$cAmt = $c ? floatval($c['amount']) : 0;
$dAmt = $d ? floatval($d['amount']) : 0;
$eAmt = $e ? floatval($e['amount']) : 0;
$pass = ($bAmt == 5.00) && ($cAmt == 0.50) && ($dAmt == 0.05) && ($eAmt == 0.01) && empty($f);
$this->assert($pass, $testName, "B={$bAmt}(5), C={$cAmt}(0.5), D={$dAmt}(0.05), E={$eAmt}(0.01), F=" . (empty($f) ? '已截断' : '未截断'));
} catch (\Exception $e) {
$this->assert(false, $testName, "异常: " . $e->getMessage());
} finally {
Db::rollback();
}
}
/**
* 测试 3:区县代理(无馆独享全额 100 元)逐代递减级联至 0.01 截断
* 预期:
* 县B(3): 第1代 100 * 10% = 10.00
* 县C(4): 第2代 10 * 10% = 1.00
* 县D(5): 第3代 1 * 10% = 0.10
* 县E(6): 第4代 0.10 * 10% = 0.01
* 县F(8): 第5代 0.01 * 10% = 0.001 -> 0.00 截断
*/
public function testCountyPeerNoVenueCascadeToCent()
{
$testName = "区县代理(无馆): 平级逐代递减(10.00 -> 1.00 -> 0.10 -> 0.01) 到0.01截断";
Db::startTrans();
try {
$order = ['id' => 9913, 'user_id' => 7];
$buyerId = 7;
$chain = [
['user_id' => 2, 'is_county' => 1],
['user_id' => 3, 'is_county' => 1],
['user_id' => 4, 'is_county' => 1],
['user_id' => 5, 'is_county' => 1],
['user_id' => 6, 'is_county' => 1],
['user_id' => 8, 'is_county' => 1],
];
$teamResult = [
'venue' => null,
'county' => ['user_id' => 2, 'amount' => 100.0, 'index' => 0]
];
$active = new MockPeerActiveService();
$reward = new PeerShareReward();
$reward->run($order, $buyerId, $chain, $teamResult, $active);
$b = Db::name('shopro_partner_reward')->where('order_id', 9913)->where('user_id', 3)->where('reward_type', 'county_peer')->find();
$c = Db::name('shopro_partner_reward')->where('order_id', 9913)->where('user_id', 4)->where('reward_type', 'county_peer')->find();
$d = Db::name('shopro_partner_reward')->where('order_id', 9913)->where('user_id', 5)->where('reward_type', 'county_peer')->find();
$e = Db::name('shopro_partner_reward')->where('order_id', 9913)->where('user_id', 6)->where('reward_type', 'county_peer')->find();
$f = Db::name('shopro_partner_reward')->where('order_id', 9913)->where('user_id', 8)->where('reward_type', 'county_peer')->find();
$bAmt = $b ? floatval($b['amount']) : 0;
$cAmt = $c ? floatval($c['amount']) : 0;
$dAmt = $d ? floatval($d['amount']) : 0;
$eAmt = $e ? floatval($e['amount']) : 0;
$pass = ($bAmt == 10.00) && ($cAmt == 1.00) && ($dAmt == 0.10) && ($eAmt == 0.01) && empty($f);
$this->assert($pass, $testName, "B={$bAmt}(10), C={$cAmt}(1), D={$dAmt}(0.1), E={$eAmt}(0.01), F=" . (empty($f) ? '已截断' : '未截断'));
} catch (\Exception $e) {
$this->assert(false, $testName, "异常: " . $e->getMessage());
} finally {
Db::rollback();
}
}
/**
* 测试 4:酒道馆中间平级未自购跳过场景
*/
public function testVenuePeerInactiveIntermediary()
{
$testName = "酒道馆: 中间平级馆B未自购被跳过,上级馆C仍正常获得第2代平级0.50元";
Db::startTrans();
try {
$order = ['id' => 9914, 'user_id' => 7];
$buyerId = 7;
$chain = [
['user_id' => 2, 'is_venue' => 1],
['user_id' => 3, 'is_venue' => 1],
['user_id' => 4, 'is_venue' => 1],
];
$teamResult = [
'venue' => ['user_id' => 2, 'amount' => 50.0, 'index' => 0],
'county' => null
];
$active = new MockPeerActiveService();
$active->setActive(3, false); // 馆B 未自购
$active->setActive(4, true); // 馆C 活跃
$reward = new PeerShareReward();
$reward->run($order, $buyerId, $chain, $teamResult, $active);
$bSkip = Db::name('shopro_partner_reward')
->where('order_id', 9914)
->where('user_id', 3)
->where('status', -1)
->find();
$cReward = Db::name('shopro_partner_reward')
->where('order_id', 9914)
->where('user_id', 4)
->where('status', 1)
->find();
$bSkipped = !empty($bSkip) && floatval($bSkip['amount']) == 0;
$cReceived = !empty($cReward) && floatval($cReward['amount']) == 0.50;
$this->assert($bSkipped && $cReceived, $testName, "B被跳过记录, C正常结算0.50元");
} catch (\Exception $e) {
$this->assert(false, $testName, "异常: " . $e->getMessage());
} finally {
Db::rollback();
}
}
}
// 执行测试
if (php_sapi_name() === 'cli') {
$tester = new PeerShareTest();
exit($tester->run());
}