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.10截断测试 (Peer Share) \n"; echo "========================================================\n\n"; $this->testVenuePeerCascadeToTenCent(); $this->testCountyPeerWithVenueCascadeToTenCent(); $this->testCountyPeerNoVenueCascadeToTenCent(); $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 元) * 预期: * 馆B(3): 第1代 50 * 10% = 5.00 * 馆C(4): 第2代 5 * 10% = 0.50 * 馆D(5): 第3代 0.5 * 10% = 0.05 < 0.10,截断不发放 * 馆E(6): 截断不发放 */ public function testVenuePeerCascadeToTenCent() { $testName = "酒道馆: 实发2代(5.00 -> 0.50),第3代(0.05<0.10)截断不发"; 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 ]; $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(); $bAmt = $b ? floatval($b['amount']) : 0; $cAmt = $c ? floatval($c['amount']) : 0; $pass = ($bAmt == 5.00) && ($cAmt == 0.50) && empty($d) && empty($e); $this->assert($pass, $testName, "B={$bAmt}(5), C={$cAmt}(0.5), D=" . (empty($d) ? '已截断' : '未截断') . ", E=" . (empty($e) ? '已截断' : '未截断')); } catch (\Exception $e) { $this->assert(false, $testName, "异常: " . $e->getMessage()); } finally { Db::rollback(); } } /** * 测试 2:区县代理(有馆拆分场景,基数 50 元)逐代递减级联至 0.10 截断 * 预期: * 县B(3): 第1代 50 * 10% = 5.00 * 县C(4): 第2代 0.50 * 县D(5): 第3代 0.05 < 0.10,截断 */ public function testCountyPeerWithVenueCascadeToTenCent() { $testName = "区县代理(有馆): 实发2代(5.00 -> 0.50),第3代(0.05<0.10)截断"; 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], ]; $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(); $bAmt = $b ? floatval($b['amount']) : 0; $cAmt = $c ? floatval($c['amount']) : 0; $pass = ($bAmt == 5.00) && ($cAmt == 0.50) && empty($d); $this->assert($pass, $testName, "B={$bAmt}(5), C={$cAmt}(0.5), D=" . (empty($d) ? '已截断' : '未截断')); } catch (\Exception $e) { $this->assert(false, $testName, "异常: " . $e->getMessage()); } finally { Db::rollback(); } } /** * 测试 3:区县代理(无馆独享全额 100 元)逐代递减级联实发3代(10.00 -> 1.00 -> 0.10),第4代截断 * 预期: * 县B(3): 第1代 100 * 10% = 10.00 * 县C(4): 第2代 10 * 10% = 1.00 * 县D(5): 第3代 1 * 10% = 0.10 (>= 0.10) * 县E(6): 第4代 0.10 * 10% = 0.01 < 0.10,截断 */ public function testCountyPeerNoVenueCascadeToTenCent() { $testName = "区县代理(无馆): 实发3代(10.00 -> 1.00 -> 0.10),第4代(0.01<0.10)截断"; 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], ]; $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(); $bAmt = $b ? floatval($b['amount']) : 0; $cAmt = $c ? floatval($c['amount']) : 0; $dAmt = $d ? floatval($d['amount']) : 0; $pass = ($bAmt == 10.00) && ($cAmt == 1.00) && ($dAmt == 0.10) && empty($e); $this->assert($pass, $testName, "B={$bAmt}(10), C={$cAmt}(1), D={$dAmt}(0.10), E=" . (empty($e) ? '已截断' : '未截断')); } 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()); }