|
|
@@ -8,6 +8,7 @@ use App\Models\BalanceLog;
|
|
|
use App\Models\ShareCommissionRecord;
|
|
|
use App\Services\BalanceLogService;
|
|
|
use App\Services\ShareCommissionRecorder;
|
|
|
+use App\Services\ShareCommissionDiagnostics;
|
|
|
use App\Services\ShareEarningReportService;
|
|
|
use Illuminate\Config\Repository;
|
|
|
use Illuminate\Database\Capsule\Manager;
|
|
|
@@ -332,4 +333,120 @@ class ShareCommissionRecordingTest extends TestCase
|
|
|
$this->assertSame(1, $result->getStatusCode());
|
|
|
$this->assertSame(0, ShareCommissionRecord::count());
|
|
|
}
|
|
|
+
|
|
|
+ public function test_omitting_dates_is_not_full_history_and_all_can_backfill_old_receipts(): void
|
|
|
+ {
|
|
|
+ $rebate = $this->historicalRebate(['created_at' => '2020-01-01 00:00:00', 'updated_at' => '2020-01-01 00:00:00']);
|
|
|
+ $default = $this->command([]);
|
|
|
+ $this->assertSame(0, $default->getStatusCode());
|
|
|
+ $this->assertStringContainsString('省略日期仍默认最近31天', $default->getDisplay());
|
|
|
+ $this->assertSame(0, ShareCommissionRecord::count());
|
|
|
+ $all = $this->command(['--all' => true]);
|
|
|
+ $this->assertSame(0, $all->getStatusCode());
|
|
|
+ $this->assertStringContainsString('全部历史', $all->getDisplay());
|
|
|
+ $this->assertSame(0, ShareCommissionRecord::count());
|
|
|
+ $written = $this->command(['--all' => true, '--write' => true]);
|
|
|
+ $this->assertSame(0, $written->getStatusCode());
|
|
|
+ $this->assertSame((string)$rebate->id, ShareCommissionRecord::firstOrFail()->source_id);
|
|
|
+ $this->assertSame('2020-01-01', ShareCommissionRecord::firstOrFail()->stat_date->format('Y-m-d'));
|
|
|
+ $this->assertEquals('22.50', DB::table('wallets')->where('member_id', '1001')->value('available_balance'));
|
|
|
+ }
|
|
|
+
|
|
|
+ private function depositForDiagnosis(): void
|
|
|
+ {
|
|
|
+ BalanceLog::create(['member_id' => '1002', 'type' => 1, 'change_type' => '充值',
|
|
|
+ 'amount' => '100.00', 'before_balance' => '0.00', 'after_balance' => '100.00', 'remark' => '']);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_diagnostics_show_a_zero_legacy_rate_despite_configured_share_settings_without_writing(): void
|
|
|
+ {
|
|
|
+ $this->depositForDiagnosis();
|
|
|
+ DB::table('config')->where('field', 'recharge_rate')->update(['val' => '0']);
|
|
|
+ DB::connection()->getSchemaBuilder()->create('share_settings', function (Blueprint $t) {
|
|
|
+ $t->id(); $t->integer('enabled'); $t->decimal('tier_one_rate', 8, 4); $t->decimal('tier_two_rate', 8, 4);
|
|
|
+ });
|
|
|
+ DB::table('share_settings')->insert(['enabled' => 1, 'tier_one_rate' => '4.00', 'tier_two_rate' => '6.00']);
|
|
|
+ $tables = ['users', 'wallets', 'balance_logs', 'share_commission_records', 'config', 'share_settings'];
|
|
|
+ $before = [];
|
|
|
+ foreach ($tables as $table) $before[$table] = DB::table($table)->orderBy('id')->get()->toJson();
|
|
|
+ $data = (new ShareCommissionDiagnostics())->inspect(null);
|
|
|
+ $this->assertSame(':memory:', $data['database']);
|
|
|
+ $this->assertSame('bot_', $data['table_prefix']);
|
|
|
+ $this->assertSame('0', $data['recharge_rate']);
|
|
|
+ $this->assertEquals(4, $data['tier_one_rate']);
|
|
|
+ $this->assertSame(0, $data['counts']['rebate_logs_all']);
|
|
|
+ $this->assertSame(1, $data['counts']['real_invitee_deposit_logs_all']);
|
|
|
+ $this->assertSame(1, $data['counts']['linked_real_invitee_deposit_logs_all']);
|
|
|
+ $this->assertSame(1, $data['counts']['with_promoter_wallet_deposit_logs_all']);
|
|
|
+ $run = $this->command(['--diagnose' => true, '--all' => true]);
|
|
|
+ $this->assertSame(0, $run->getStatusCode(), $run->getDisplay());
|
|
|
+ $this->assertStringContainsString('全部历史没有', $run->getDisplay());
|
|
|
+ $this->assertStringContainsString('当前 recharge_rate 缺失、无效或为0', $run->getDisplay());
|
|
|
+ $this->assertStringContainsString('share_enabled: 1', $run->getDisplay());
|
|
|
+ foreach ($tables as $table) $this->assertSame($before[$table], DB::table($table)->orderBy('id')->get()->toJson(), $table);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_diagnostics_separate_type_amount_and_date_filters(): void
|
|
|
+ {
|
|
|
+ $this->historicalRebate(['created_at' => '2020-01-01 00:00:00']);
|
|
|
+ $this->historicalRebate(['type' => 2]);
|
|
|
+ $this->historicalRebate(['amount' => '0', 'after_balance' => '20']);
|
|
|
+ $selected = $this->historicalRebate();
|
|
|
+ (new ShareCommissionRecorder())->record($selected);
|
|
|
+ $data = (new ShareCommissionDiagnostics())->inspect(['2026-10-01 00:00:00', '2026-10-02 23:59:59']);
|
|
|
+ $this->assertSame(4, $data['counts']['rebate_logs_all']);
|
|
|
+ $this->assertSame(3, $data['counts']['type1_rebate_logs_all']);
|
|
|
+ $this->assertSame(2, $data['counts']['positive_type1_rebate_logs_all']);
|
|
|
+ $this->assertSame(1, $data['counts']['selected_rebate_logs']);
|
|
|
+ $this->assertSame('2020-01-01 00:00:00', $data['first_rebate_at']);
|
|
|
+ $this->assertSame('2026-10-01 01:02:03', $data['last_rebate_at']);
|
|
|
+ $this->assertSame(1, $data['counts']['active_commission_records_selected']);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static function brokenReferralStages(): array
|
|
|
+ {
|
|
|
+ return [
|
|
|
+ [2, 'PROMO', false, [0, 0, 0, 0, 0]],
|
|
|
+ [1, 'MISSING', false, [1, 0, 1, 0, 0]],
|
|
|
+ [1, 'PROMO', true, [1, 1, 1, 1, 0]],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /** @dataProvider brokenReferralStages */
|
|
|
+ public function test_diagnostics_locate_real_user_referral_and_wallet_gaps(int $from, string $code, bool $missingWallet, array $expected): void
|
|
|
+ {
|
|
|
+ DB::table('users')->where('member_id', '1002')->update(['from' => $from, 'agent_user_code' => $code]);
|
|
|
+ if ($missingWallet) DB::table('wallets')->where('member_id', '1001')->delete();
|
|
|
+ $this->depositForDiagnosis();
|
|
|
+ $counts = (new ShareCommissionDiagnostics())->inspect(null)['counts'];
|
|
|
+ $this->assertSame(1, $counts['invited_members_all']);
|
|
|
+ foreach (['real_invited_members_all', 'linked_real_invited_members_all', 'real_invitee_deposit_logs_all',
|
|
|
+ 'linked_real_invitee_deposit_logs_all', 'with_promoter_wallet_deposit_logs_all'] as $i => $key) {
|
|
|
+ $this->assertSame($expected[$i], $counts[$key], $key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_read_only_diagnostics_cannot_be_combined_with_write_or_all_with_dates(): void
|
|
|
+ {
|
|
|
+ $this->historicalRebate();
|
|
|
+ $run = $this->command(['--diagnose' => true, '--write' => true]);
|
|
|
+ $this->assertSame(1, $run->getStatusCode());
|
|
|
+ $this->assertSame(0, ShareCommissionRecord::count());
|
|
|
+ $conflict = $this->command(['--all' => true, '--start-date' => '2026-10-01', '--write' => true]);
|
|
|
+ $this->assertSame(1, $conflict->getStatusCode());
|
|
|
+ $this->assertSame(0, ShareCommissionRecord::count());
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_diagnostic_referral_matches_the_existing_php_empty_zero_code_rule(): void
|
|
|
+ {
|
|
|
+ DB::table('users')->where('member_id', '1001')->update(['user_code' => '0']);
|
|
|
+ DB::table('users')->where('member_id', '1002')->update(['agent_user_code' => '0']);
|
|
|
+ $this->depositForDiagnosis();
|
|
|
+ $counts = (new ShareCommissionDiagnostics())->inspect(null)['counts'];
|
|
|
+ $this->assertSame(1, $counts['invited_members_all']);
|
|
|
+ $this->assertSame(1, $counts['real_invited_members_all']);
|
|
|
+ $this->assertSame(0, $counts['linked_real_invited_members_all']);
|
|
|
+ $this->assertSame(0, $counts['linked_real_invitee_deposit_logs_all']);
|
|
|
+ $this->assertSame(0, $counts['with_promoter_wallet_deposit_logs_all']);
|
|
|
+ }
|
|
|
}
|