where('tenant_type', Tenant::TYPE_DEMO_TRIAL) ->where('tenant_st_code', '!=', 'expired') ->whereNotNull('demo_expires_at') ->where('demo_expires_at', '>', now()) ->where('demo_expires_at', '<=', now()->addDays(7)) ->get(); if ($expiringSoon->isNotEmpty()) { $this->info("만료 임박 테넌트: {$expiringSoon->count()}건"); foreach ($expiringSoon as $tenant) { $daysLeft = (int) now()->diffInDays($tenant->demo_expires_at, false); $this->line(" - [{$tenant->id}] {$tenant->company_name} (D-{$daysLeft})"); Log::info('데모 체험 만료 임박', [ 'tenant_id' => $tenant->id, 'company_name' => $tenant->company_name, 'expires_at' => $tenant->demo_expires_at->toDateString(), 'days_left' => $daysLeft, 'partner_id' => $tenant->demo_source_partner_id, ]); } } // 2. 이미 만료된 테넌트 → 상태 변경 $expired = Tenant::withoutGlobalScopes() ->where('tenant_type', Tenant::TYPE_DEMO_TRIAL) ->where('tenant_st_code', '!=', 'expired') ->whereNotNull('demo_expires_at') ->where('demo_expires_at', '<', now()) ->get(); if ($expired->isEmpty()) { $this->info('만료 처리 대상 없음'); return self::SUCCESS; } $this->info("만료 처리 대상: {$expired->count()}건"); foreach ($expired as $tenant) { $this->line(" - [{$tenant->id}] {$tenant->company_name} (만료: {$tenant->demo_expires_at->toDateString()})"); if (! $this->option('dry-run')) { $tenant->forceFill(['tenant_st_code' => 'expired']); $tenant->save(); Log::info('데모 체험 만료 처리', [ 'tenant_id' => $tenant->id, 'company_name' => $tenant->company_name, 'partner_id' => $tenant->demo_source_partner_id, ]); } } if ($this->option('dry-run')) { $this->warn('(dry-run 모드 — 실제 변경 없음)'); } else { $this->info(" {$expired->count()}건 만료 처리 완료"); } return self::SUCCESS; } }