wallets->adjust($agent->id, $amount, 'recharge', '充值', $key, 'system', null, 'agent_recharge', 1); } private function setUpEquity(int $lockDays = 7): void { $this->wallets = new AgentWalletService(); AgentSetting::current(); DB::table('agent_settings')->where('id', 1)->update(['equity_enabled' => 1, 'equity_price_per_percent' => 1000, 'equity_min_percent' => 0.1, 'equity_max_percent' => 1, 'equity_recharge_lock_days' => $lockDays]); } public function test_recharge_is_locked_for_seven_days_then_withdrawable(): void { $this->setUpEquity(); $this->paymentChannels(); $agent = $this->agent(Agent::TYPE_EQUITY); $this->recharge($agent, '1000', 'r1'); $agent = $agent->fresh(); $this->assertSame('0.0000', $this->wallets->withdrawable($agent)); $funds = $this->wallets->funds($agent); $this->assertSame(['1000.0000', '1000.0000', '0.0000', 7], [$funds['balance'], $funds['locked_amount'], $funds['withdrawable_amount'], $funds['recharge_lock_days']]); $locks = $this->wallets->activeLocks($agent); $this->assertSame('2026-09-14 12:00:00', $locks[0]['unlock_at']); $account = AgentWithdrawAccount::query()->create(['agent_id' => $agent->id, 'type' => 'usdt', 'network' => 'TRC20', 'account' => 'TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE', 'status' => 1]); try { (new AgentWithdrawalService($this->wallets))->request($agent, $account->id, '10', 'withdraw-old', 'locked'); $this->fail('locked'); } catch (\RuntimeException $e) { $this->assertSame('可提现余额不足(充值未满 7 天的金额暂不可提现)', $e->getMessage()); } Carbon::setTestNow(Carbon::parse('2026-09-14 12:00:01')); $this->assertSame('1000.0000', $this->wallets->withdrawable($agent->fresh())); $this->assertSame([], $this->wallets->activeLocks($agent)); $this->assertSame('0.0000', $this->wallets->funds($agent->fresh())['locked_amount']); } public function test_share_purchase_uses_locked_recharge_first(): void { $this->setUpEquity(); $agent = $this->agent(Agent::TYPE_EQUITY); $this->wallets->adjust($agent->id, '500', 'credit', '分红', 'c1', 'admin', 1); // 人工加款不锁定 $this->recharge($agent, '1000', 'r1'); $this->assertSame('500.0000', $this->wallets->withdrawable($agent->fresh())); $order = (new AgentEquityService($this->wallets))->order($agent->fresh(), '0.6'); // 600 $this->assertSame('completed', $order->status); $agent = $agent->fresh(); $this->assertSame('900.0000', $agent->balance); $this->assertSame('400.0000', $this->wallets->lockedAmount($agent)); $this->assertSame('500.0000', $this->wallets->withdrawable($agent), 'the unlocked dividend stays withdrawable'); } public function test_joint_agents_and_zero_days_are_not_locked(): void { $this->setUpEquity(0); $equity = $this->agent(Agent::TYPE_EQUITY); $this->recharge($equity, '300', 'r-equity'); $this->assertSame('300.0000', $this->wallets->withdrawable($equity->fresh())); DB::table('agent_settings')->where('id', 1)->update(['equity_recharge_lock_days' => 7]); $joint = $this->agent(Agent::TYPE_JOINT); $this->recharge($joint, '300', 'r-joint'); $this->assertSame(0, AgentRechargeLock::query()->count(), 'joint recharges are margin, not locked'); $this->assertArrayNotHasKey('locked_amount', $this->wallets->funds($joint->fresh())); } }