Files
lotteryLaravel/app/Console/Commands/PurgeAgentDataCommand.php
kang 395e1c7400 feat: refactor super admin to use is_super_admin flag and enhance site deletion logic
- Changed super admin detection from role-based to `is_super_admin` flag in AdminUser model
- Added `requireDefaultAdminSiteId()` method to throw validation error when no integration site exists
- Enhanced site deletion to migrate platform role bindings to fallback site and auto-delete site-specific admin accounts
- Made agent line code optional with auto-generation fallback using `{site_code}-agent-{counter}` format
2026-06-12 20:47:40 +08:00

148 lines
5.6 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\AgentNode;
use App\Services\Agent\AgentNodeService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* 清空信用占成盘代理业务数据,并删除所有非根代理节点(保留各站点 depth=0 根节点)。
*
* 不删:期号、注单、钱包玩家、站点财务账号。
*/
final class PurgeAgentDataCommand extends Command
{
protected $signature = 'lottery:purge-agent-data
{--dry-run : 只预览,不写入}
{--force : 跳过交互确认(危险)}';
protected $description = '清空代理账期/授信流水,删除全部非根代理(保留站点根节点)';
public function handle(AgentNodeService $agentNodeService): int
{
$dryRun = (bool) $this->option('dry-run');
$force = (bool) $this->option('force');
$connection = (string) config('database.default');
$database = (string) config('database.connections.'.$connection.'.database');
$environment = (string) config('app.env');
$nonRootAgents = AgentNode::query()
->where('depth', '>', 0)
->orderByDesc('depth')
->orderByDesc('id')
->get();
$nonRootIds = $nonRootAgents->pluck('id')->map(static fn ($id): int => (int) $id)->all();
$rootBySite = DB::table('agent_nodes')
->where('depth', 0)
->get(['id', 'admin_site_id'])
->groupBy('admin_site_id')
->map(static fn ($rows) => (int) $rows->first()->id);
$playersToReassign = $nonRootIds === []
? 0
: (int) DB::table('players')->whereIn('agent_node_id', $nonRootIds)->count();
$metrics = [
['Database', $connection.' / '.$database],
['Environment', $environment],
['Non-root agents', (string) count($nonRootIds)],
['Players to reassign to root', (string) $playersToReassign],
['settlement_periods', (string) DB::table('settlement_periods')->count()],
['settlement_bills', (string) DB::table('settlement_bills')->count()],
['payment_records', (string) DB::table('payment_records')->count()],
['settlement_adjustments', (string) DB::table('settlement_adjustments')->count()],
['rebate_records', (string) DB::table('rebate_records')->count()],
['share_ledger', (string) DB::table('share_ledger')->count()],
['credit_ledger', (string) DB::table('credit_ledger')->count()],
['agent_delegation_grants', (string) DB::table('agent_delegation_grants')->count()],
];
$this->table(['Metric', 'Value'], $metrics);
if ($nonRootAgents->isNotEmpty()) {
$this->line('Non-root agents to delete:');
foreach ($nonRootAgents as $node) {
$this->line(sprintf(
' - #%d depth=%d %s (%s)',
(int) $node->id,
(int) $node->depth,
(string) $node->code,
(string) $node->name,
));
}
}
if ($dryRun) {
$this->info('Dry run only — no changes written.');
return self::SUCCESS;
}
if (! $force && ! $this->confirm('This permanently deletes agent settlement data and non-root agents. Continue?', false)) {
$this->warn('Aborted.');
return self::FAILURE;
}
DB::transaction(function () use ($agentNodeService, $nonRootAgents, $nonRootIds, $rootBySite): void {
DB::table('settlement_adjustments')->delete();
DB::table('payment_records')->delete();
DB::table('rebate_allocations')->delete();
DB::table('rebate_records')->delete();
DB::table('share_ledger')->delete();
DB::table('settlement_bills')->delete();
DB::table('settlement_periods')->delete();
DB::table('credit_ledger')->delete();
DB::table('player_credit_accounts')->update([
'used_credit' => 0,
'frozen_credit' => 0,
'updated_at' => now(),
]);
DB::table('agent_profiles')->update([
'allocated_credit' => 0,
'used_credit' => 0,
'updated_at' => now(),
]);
if ($nonRootIds !== []) {
DB::table('agent_delegation_grants')
->whereIn('parent_agent_id', $nonRootIds)
->orWhereIn('child_agent_id', $nonRootIds)
->delete();
$players = DB::table('players')
->whereIn('agent_node_id', $nonRootIds)
->get(['id', 'agent_node_id', 'site_code']);
foreach ($players as $player) {
$agentNodeId = (int) $player->agent_node_id;
$siteId = (int) (DB::table('agent_nodes')->where('id', $agentNodeId)->value('admin_site_id') ?? 0);
$rootId = $rootBySite->get($siteId);
if ($rootId === null) {
continue;
}
DB::table('players')
->where('id', (int) $player->id)
->update(['agent_node_id' => $rootId]);
}
foreach ($nonRootAgents as $node) {
$agentNodeService->destroy($node);
}
}
});
$this->info('Agent settlement data cleared; non-root agents removed. Root nodes kept.');
return self::SUCCESS;
}
}