user = (object) ['id' => 7]; $this->app->instance('request', $request); return (new AdminAgent())->{$method}($request, new AgentEquityService(new AgentWalletService()))->getData(true); } public function test_admin_lists_all_purchases_with_summary_and_cancels_pending_orders(): void { AgentSetting::current()->update(['equity_enabled' => 1, 'equity_price_per_percent' => 10000, 'equity_min_percent' => 0.1, 'equity_max_percent' => 1]); $equity = new AgentEquityService(new AgentWalletService()); $rich = $this->agent(Agent::TYPE_EQUITY); Agent::query()->whereKey($rich->id)->update(['balance' => 5000, 'realtime_balance' => 5000]); $poor = $this->agent(Agent::TYPE_EQUITY); $done = $equity->order($rich->fresh(), '0.3'); // 3000,余额够,直接开通 $pending = $equity->order($poor, '0.5'); // 5000,待付款 $this->assertSame(AgentEquityOrder::STATUS_COMPLETED, $done->status); $all = $this->call('equityOrders', []); $this->assertSame(0, $all['code'], (string) $all['msg']); $this->assertSame(2, $all['data']['total']); $this->assertSame(['0.3000', '3000.0000', 1, '5000.0000', '0.3000'], [ $all['data']['summary']['completed_percent'], $all['data']['summary']['completed_amount'], $all['data']['summary']['pending_count'], $all['data']['summary']['pending_amount'], $all['data']['summary']['total_equity_percent'], ]); $first = $all['data']['list'][0]; $this->assertSame($pending->id, $first['id']); $this->assertSame($poor->username, $first['agent']['username']); $this->assertSame('待付款', $first['status_text']); $this->assertSame(1, $this->call('equityOrders', ['username' => $rich->username])['data']['total']); $this->assertSame(1, $this->call('equityOrders', ['status' => 'completed'])['data']['total']); $this->assertSame(0, $this->call('equityOrders', ['date_type' => 'completed_at', 'start_date' => '2026-09-08'])['data']['total']); $this->assertNotSame(0, $this->call('cancelEquityOrder', ['id' => $pending->id])['code'], 'remark required'); $this->assertSame('只有待付款订单可以取消', $this->call('cancelEquityOrder', ['id' => $done->id, 'remark' => 'x'])['msg']); $cancelled = $this->call('cancelEquityOrder', ['id' => $pending->id, 'remark' => '长期未充值']); $this->assertSame(0, $cancelled['code']); $this->assertSame(['cancelled', 7, '长期未充值'], [$cancelled['data']['status'], $cancelled['data']['cancelled_by'], $cancelled['data']['cancel_remark']]); $own = $equity->order($poor, '0.2'); $this->assertNull($equity->cancel($poor, $own->id)->cancelled_by, 'agent self-cancel has no admin'); } public function test_company_equity_setting_accounts_for_completed_and_pending_formal_purchases(): void { $admin = new AdminAgent(); $this->assertSame('0.0000', $admin->settings()->getData(true)['data']['company_equity_percent']); $saved = $this->saveSettings(['company_equity_percent' => '98.5000']); $this->assertSame(0, $saved['code'], $saved['msg']); $this->assertSame('98.5000', $saved['data']['company_equity_percent']); $this->assertSame('98.5000', $this->saveSettings([])['data']['company_equity_percent']); $this->assertNotSame(0, $this->saveSettings(['company_equity_percent' => '100.0001'])['code']); $this->assertNotSame(0, $this->saveSettings(['company_equity_percent' => '0.00001'])['code']); $equity = new AgentEquityService(new AgentWalletService()); $holder = $this->agent(Agent::TYPE_EQUITY); $buyer = $this->agent(Agent::TYPE_EQUITY); $another = $this->agent(Agent::TYPE_EQUITY); Agent::query()->whereKey($holder->id)->update(['balance' => 1000, 'realtime_balance' => 1000]); $this->assertSame(AgentEquityOrder::STATUS_COMPLETED, $equity->order($holder, '1')->status); $pending = $equity->order($buyer, '0.5'); $this->assertSame(AgentEquityOrder::STATUS_PENDING, $pending->status); $this->assertSame('0.0000', $equity->overview($another)['remaining_percent']); $this->assertNotSame(0, $this->saveSettings(['company_equity_percent' => '98.5001'])['code']); try { $equity->order($another, '0.1'); $this->fail('Pending purchases reserve the remaining allocation.'); } catch (\RuntimeException $e) { $this->assertSame('可购买股份不足', $e->getMessage()); } $equity->cancel($buyer, $pending->id); $this->assertSame('99.0000', $this->saveSettings(['company_equity_percent' => '99'])['data']['company_equity_percent']); $legacyOrder = $pending->replicate(['status', 'cancel_remark']); $legacyOrder->forceFill(['order_no' => 'legacy-overbooked', 'status' => AgentEquityOrder::STATUS_PENDING])->save(); Agent::query()->whereKey($buyer->id)->update(['balance' => 1000, 'realtime_balance' => 1000]); $this->assertSame(0, $equity->fulfillPending($buyer->id)); $this->assertSame('1000.0000', $buyer->fresh()->balance); $this->assertSame(AgentEquityOrder::STATUS_PENDING, $legacyOrder->fresh()->status); } private function saveSettings(array $params): array { $request = new class([], $params + [ 'margin_stop_percent' => 10, 'equity_enabled' => 1, 'equity_price_per_percent' => 1000, 'equity_min_percent' => '0.1', 'equity_max_percent' => '1', ]) extends Request { public object $user; }; $request->setMethod('POST'); $request->user = (object) ['id' => 7]; $this->app->instance('request', $request); return (new AdminAgent())->saveSettings($request)->getData(true); } }