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
This commit is contained in:
147
app/Console/Commands/PurgeAgentDataCommand.php
Normal file
147
app/Console/Commands/PurgeAgentDataCommand.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user