AgentDashboardTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <?php
  2. namespace Tests\Integration;
  3. use App\Http\Controllers\agent\ProfileController;
  4. use App\Models\Agent\Agent;
  5. use App\Models\Agent\AgentSetting;
  6. use App\Services\Agent\AgentPeriodReportService;
  7. use App\Services\Agent\AgentReportService;
  8. use App\Services\PaymentOrderService;
  9. use Illuminate\Http\Request;
  10. use Illuminate\Database\Schema\Blueprint;
  11. use Illuminate\Support\Facades\DB;
  12. use Illuminate\Support\Facades\Schema;
  13. use PHPUnit\Framework\TestCase;
  14. use Tests\Support\AgentTestEnvironment;
  15. /** 代理首页 GET /agent/dashboard:只统计本代理名下会员,按日期汇总资金和投注。 */
  16. class AgentDashboardTest extends TestCase
  17. {
  18. use AgentTestEnvironment;
  19. public function test_dashboard_sums_only_own_members_within_the_date_range(): void
  20. {
  21. $agent = $this->agent();
  22. $other = $this->agent();
  23. foreach (['m1' => $agent, 'm2' => $agent, 'x1' => $other] as $memberId => $owner) {
  24. DB::table('users')->insert(['member_id' => $memberId, 'username' => $memberId, 'agent_id' => $owner->id, 'created_at' => now()]);
  25. DB::table('wallets')->insert(['member_id' => $memberId, 'available_balance' => 100]);
  26. }
  27. $in = '2026-09-07 10:00:00';
  28. $out = '2026-09-01 10:00:00';
  29. foreach ([['m1', 500, $in], ['m2', 300, $in], ['m1', 999, $out], ['x1', 777, $in]] as [$member, $amount, $at]) {
  30. DB::table('recharges')->insert(['member_id' => $member, 'status' => 1, 'amount' => $amount, 'created_at' => $at]);
  31. }
  32. DB::table('recharges')->insert(['member_id' => 'm1', 'status' => 0, 'amount' => 50, 'created_at' => $in]); // 未到账
  33. DB::table('payment_orders')->insert(['member_id' => 'm2', 'status' => 2, 'type' => '1', 'amount' => 200, 'created_at' => $in]);
  34. DB::table('withdraws')->insert(['member_id' => 'm1', 'status' => 1, 'amount' => 150, 'created_at' => $in]);
  35. foreach ([['人工充值', null, 80], ['人工扣款', null, -30], ['优惠活动', null, 20], ['返水', null, 10], ['人工充值', 0, 5]] as [$type, $related, $amount]) {
  36. DB::table('balance_logs')->insert(['member_id' => 'm1', 'change_type' => $type, 'related_id' => $related, 'amount' => $amount, 'created_at' => $in]);
  37. }
  38. $request = Request::create('/agent/dashboard', 'GET', ['start_date' => '2026-09-07', 'end_date' => '2026-09-07']);
  39. $request->attributes->set('agent', $agent);
  40. $this->app->instance('request', $request);
  41. $data = (new ProfileController())->dashboard($request, new AgentReportService())->getData(true);
  42. $this->assertSame(0, $data['code'], (string) $data['msg']);
  43. $summary = $data['data'];
  44. $this->assertSame(2, $summary['member_count']);
  45. $this->assertSame('200.0000', $summary['member_balance']);
  46. $this->assertSame('1000.0000', $summary['deposit_amount'], 'recharges + paid online orders in range');
  47. $this->assertSame('150.0000', $summary['withdraw_amount']);
  48. $this->assertSame('80.0000', $summary['manual_credit']);
  49. $this->assertSame('30.0000', $summary['manual_debit']);
  50. $this->assertSame('25.0000', $summary['bonus_amount'], '优惠活动 + 人工充值(赠送)');
  51. $this->assertSame('10.0000', $summary['rebate_amount']);
  52. $this->assertSame('815.0000', $summary['company_profit'], '1000 - 150 - 25 - 10');
  53. $this->assertSame('0.0000', $summary['commission_amount']);
  54. $this->assertSame(0, $summary['agent_count']);
  55. $this->assertSame('own', $summary['scope']);
  56. foreach (['bet_count', 'bet_amount', 'valid_bet_amount', 'win_loss'] as $field) $this->assertArrayHasKey($field, $summary);
  57. $request = Request::create('/agent/dashboard', 'GET', ['start_date' => '2026-09-08', 'end_date' => '2026-09-07']);
  58. $request->attributes->set('agent', $agent);
  59. $this->assertNotSame(0, (new ProfileController())->dashboard($request, new AgentReportService())->getData(true)['code']);
  60. }
  61. public function test_equity_agent_sees_whole_platform_excluding_demo_accounts(): void
  62. {
  63. if (!Schema::hasColumn('users', 'from')) Schema::table('users', fn (Blueprint $t) => $t->integer('from')->nullable());
  64. $joint = $this->agent();
  65. $equity = $this->agent(Agent::TYPE_EQUITY);
  66. foreach (['a1' => [$joint->id, 1], 'a2' => [null, 1], 'a3' => [null, null], 'demo' => [null, 2]] as $memberId => [$agentId, $from]) {
  67. DB::table('users')->insert(['member_id' => $memberId, 'username' => $memberId, 'agent_id' => $agentId, 'from' => $from, 'created_at' => now()]);
  68. DB::table('recharges')->insert(['member_id' => $memberId, 'status' => 1, 'amount' => 100, 'created_at' => '2026-09-07 10:00:00']);
  69. }
  70. $summary = (new AgentReportService())->dashboard($equity, '2026-09-07', '2026-09-07');
  71. $this->assertSame('platform', $summary['scope']);
  72. $this->assertSame(3, $summary['member_count'], 'all real members, no demo account, regardless of agent');
  73. $this->assertSame('300.0000', $summary['deposit_amount']);
  74. $this->assertSame('0.0000', $summary['commission_amount']);
  75. $own = (new AgentReportService())->dashboard($joint, '2026-09-07', '2026-09-07');
  76. $this->assertSame(['own', 1, '100.0000'], [$own['scope'], $own['member_count'], $own['deposit_amount']]);
  77. $rows = array_column((new AgentReportService())->reportRows(null, ['start_date' => '2026-09-07'])['list'], null, 'id');
  78. $this->assertSame(0, $rows[$equity->id]['member_count'], 'admin agent report still counts only the equity agent\'s own members');
  79. }
  80. public function test_charts_group_registrations_and_deduplicate_successful_daily_deposits_across_channels(): void
  81. {
  82. $agent = $this->agent();
  83. $other = $this->agent();
  84. foreach ([['a', $agent, '2026-08-31'], ['b', $agent, '2026-09-02'], ['c', $other, '2026-09-02']] as [$id, $owner, $day]) {
  85. DB::table('users')->insert(['member_id' => $id, 'username' => $id, 'agent_id' => $owner->id, 'created_at' => $day . ' 00:00:00']);
  86. }
  87. DB::table('recharges')->insert(['member_id' => 'a', 'status' => 1, 'amount' => 100,
  88. 'exchange_rate' => '7.1250', 'created_at' => '2026-09-02 10:00:00']);
  89. DB::table('recharges')->insert(['member_id' => 'a', 'status' => 1, 'amount' => 20, 'created_at' => '2026-09-03 00:00:00']);
  90. foreach ([
  91. ['a', PaymentOrderService::TYPE_PAY, PaymentOrderService::STATUS_SUCCESS, 30],
  92. ['b', PaymentOrderService::TYPE_SELF_PAY, PaymentOrderService::STATUS_SUCCESS, 40],
  93. ['c', PaymentOrderService::TYPE_PAY, PaymentOrderService::STATUS_SUCCESS, 1000],
  94. ['a', PaymentOrderService::TYPE_PAYOUT, PaymentOrderService::STATUS_SUCCESS, 1000],
  95. ['a', PaymentOrderService::TYPE_PAY, PaymentOrderService::STATUS_STAY, 1000],
  96. ] as [$member, $type, $status, $amount]) {
  97. DB::table('payment_orders')->insert(['member_id' => $member, 'type' => $type, 'status' => $status,
  98. 'amount' => $amount, 'created_at' => '2026-09-02 23:59:59']);
  99. }
  100. $range = ['start_date' => '2026-08-31', 'end_date' => '2026-09-07'];
  101. $days = $this->charts($agent, $range);
  102. $this->assertSame('own', $days['scope']);
  103. $this->assertNull($days['equity']);
  104. $this->assertSame([1, 0, 1, 0, 0, 0, 0, 0], array_column($days['registrations'], 'new_members'));
  105. $this->assertSame([0, 0, 2, 1, 0, 0, 0, 0], array_column($days['daily_deposits'], 'deposit_members'));
  106. $this->assertSame(['0.0000', '0.0000', '782.5000', '20.0000', '0.0000', '0.0000', '0.0000', '0.0000'], array_column($days['daily_deposits'], 'deposit_amount'));
  107. $weeks = $this->charts($agent, $range + ['period' => 'week']);
  108. $this->assertSame(['2026-W36', '2026-W37'], array_column($weeks['registrations'], 'period_key'));
  109. $this->assertSame([2, 0], array_column($weeks['registrations'], 'new_members'));
  110. $this->assertSame($days['daily_deposits'], $weeks['daily_deposits']);
  111. $months = $this->charts($agent, $range + ['period' => 'month']);
  112. $this->assertSame(['2026-08', '2026-09'], array_column($months['registrations'], 'period_key'));
  113. $this->assertSame([1, 1], array_column($months['registrations'], 'new_members'));
  114. }
  115. public function test_shareholder_chart_shows_current_formal_holdings_and_real_platform_members(): void
  116. {
  117. Schema::table('users', function (Blueprint $table) {
  118. $table->integer('from')->default(1);
  119. $table->integer('user_type')->default(0);
  120. });
  121. $holder = $this->agent(Agent::TYPE_EQUITY);
  122. $other = $this->agent(Agent::TYPE_EQUITY);
  123. $test = $this->agents->create(['username' => 'test-holder', 'password' => 'secret1', 'type' => Agent::TYPE_EQUITY, 'is_test' => 1]);
  124. foreach ([[$holder, '12.3456'], [$other, '7.6544'], [$test, '9.5000']] as [$shareholder, $percent]) {
  125. Agent::query()->whereKey($shareholder->id)->update(['equity_percent' => $percent]);
  126. }
  127. AgentSetting::current()->update(['company_equity_percent' => '60.5000']);
  128. foreach ([['real', null, 1, 0], ['test', $test->id, 1, 0], ['guest', null, 2, 1], ['simulated', null, 1, 2]] as [$id, $agentId, $from, $type]) {
  129. DB::table('users')->insert(['member_id' => $id, 'username' => $id, 'agent_id' => $agentId,
  130. 'from' => $from, 'user_type' => $type, 'created_at' => now()]);
  131. DB::table('recharges')->insert(['member_id' => $id, 'status' => 1, 'amount' => 100, 'created_at' => now()]);
  132. }
  133. $charts = $this->charts($holder, ['start_date' => '2026-09-07']);
  134. $this->assertSame('platform', $charts['scope']);
  135. $this->assertSame([1], array_column($charts['registrations'], 'new_members'));
  136. $this->assertSame([1], array_column($charts['daily_deposits'], 'deposit_members'));
  137. $this->assertSame(['100.0000'], array_column($charts['daily_deposits'], 'deposit_amount'));
  138. $this->assertSame([
  139. 'own_percent' => '12.3456', 'other_percent' => '7.6544', 'company_percent' => '60.5000', 'remaining_percent' => '19.5000',
  140. ], $charts['equity']);
  141. }
  142. private function charts(Agent $agent, array $params): array
  143. {
  144. $request = Request::create('/agent/dashboard/charts', 'GET', $params);
  145. $request->attributes->set('agent', $agent);
  146. $this->app->instance('request', $request);
  147. $response = (new ProfileController())->dashboardCharts($request, new AgentPeriodReportService(), new AgentReportService())->getData(true);
  148. $this->assertSame(0, $response['code'], (string) $response['msg']);
  149. return $response['data'];
  150. }
  151. }