diff --git a/app/Console/Commands/ShjFourBCheckCommand.php b/app/Console/Commands/ShjFourBCheckCommand.php deleted file mode 100644 index b19c7af..0000000 --- a/app/Console/Commands/ShjFourBCheckCommand.php +++ /dev/null @@ -1,317 +0,0 @@ - /dev/null 2>&1 - */ -class ShjFourBCheckCommand extends Command -{ - /** - * コマンド名と説明 - * - * @var string - */ - protected $signature = 'shj4b:check - {--dry-run : 実際の処理を行わず対象のみ表示} - {--limit=100 : 処理する最大件数} - {--hours=24 : 指定時間以内の決済のみ対象}'; - - /** - * コマンドの説明 - * - * @var string - */ - protected $description = 'SHJ-4B 兜底チェック - 未処理の決済トランザクションを検索してProcessSettlementJobをディスパッチ'; - - /** - * SHJ-4B サービス - * - * @var ShjFourBService - */ - protected $shjFourBService; - - /** - * コンストラクタ - */ - public function __construct(ShjFourBService $shjFourBService) - { - parent::__construct(); - $this->shjFourBService = $shjFourBService; - } - - /** - * コマンド実行 - * - * @return int - */ - public function handle() - { - $startTime = now(); - $isDryRun = $this->option('dry-run'); - $limit = (int) $this->option('limit'); - $hours = (int) $this->option('hours'); - - $this->info("SHJ-4B チェックコマンド開始"); - $this->info("実行モード: " . ($isDryRun ? "ドライラン(実際の処理なし)" : "本実行")); - $this->info("処理制限: {$limit}件"); - $this->info("対象期間: {$hours}時間以内"); - - // バッチログ作成 - $batch = BatchLog::createBatchLog( - 'shj4b_check', - BatchLog::STATUS_START, - [ - 'command' => 'shj4b:check', - 'options' => [ - 'dry_run' => $isDryRun, - 'limit' => $limit, - 'hours' => $hours, - ], - 'start_time' => $startTime, - ], - 'SHJ-4B チェックコマンド開始' - ); - - try { - // 未処理の決済トランザクション取得 - $unprocessedSettlements = $this->getUnprocessedSettlements($hours, $limit); - - $this->info("未処理決済トランザクション: " . $unprocessedSettlements->count() . "件"); - - if ($unprocessedSettlements->isEmpty()) { - $this->info("処理対象なし"); - - $batch->update([ - 'status' => BatchLog::STATUS_SUCCESS, - 'end_time' => now(), - 'message' => 'SHJ-4B チェック完了 - 処理対象なし', - 'success_count' => 0, - ]); - - return 0; - } - - // 対象一覧表示 - $this->displayTargets($unprocessedSettlements); - - if ($isDryRun) { - $this->info("ドライランモードのため、実際の処理はスキップします"); - - $batch->update([ - 'status' => BatchLog::STATUS_SUCCESS, - 'end_time' => now(), - 'message' => 'SHJ-4B チェック完了 - ドライラン', - 'success_count' => 0, - 'parameters' => json_encode(['targets' => $unprocessedSettlements->pluck('settlement_transaction_id')->toArray()]), - ]); - - return 0; - } - - // 実際の処理実行 - $processed = $this->processSettlements($unprocessedSettlements); - - $this->info("処理完了: {$processed['success']}件成功, {$processed['failed']}件失敗"); - - $batch->update([ - 'status' => $processed['failed'] > 0 ? BatchLog::STATUS_ERROR : BatchLog::STATUS_SUCCESS, - 'end_time' => now(), - 'message' => "SHJ-4B チェック完了 - 成功:{$processed['success']}件, 失敗:{$processed['failed']}件", - 'success_count' => $processed['success'], - 'error_count' => $processed['failed'], - 'parameters' => json_encode($processed), - ]); - - return $processed['failed'] > 0 ? 1 : 0; - - } catch (\Throwable $e) { - $this->error("SHJ-4B チェック処理でエラーが発生しました: " . $e->getMessage()); - Log::error('SHJ-4B チェックコマンドエラー', [ - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - ]); - - $batch->update([ - 'status' => BatchLog::STATUS_ERROR, - 'end_time' => now(), - 'message' => 'SHJ-4B チェック失敗: ' . $e->getMessage(), - 'error_details' => $e->getTraceAsString(), - 'error_count' => 1, - ]); - - return 1; - } - } - - /** - * 未処理の決済トランザクション取得 - * - * @param int $hours - * @param int $limit - * @return \Illuminate\Database\Eloquent\Collection - */ - private function getUnprocessedSettlements(int $hours, int $limit) - { - $cutoffTime = Carbon::now()->subHours($hours); - - // 条件: - // 1. 指定時間以内に作成された - // 2. contract_payment_numberがnullでない - // 3. まだregular_contractのsettlement_transaction_idに関連付けられていない - // 4. ProcessSettlementJobが実行されていない(batch_logで確認) - $query = SettlementTransaction::where('created_at', '>=', $cutoffTime) - ->whereNotNull('contract_payment_number') - ->whereNotNull('pay_date') - ->whereNotNull('settlement_amount') - ->orderBy('created_at', 'asc'); - - $settlements = $query->limit($limit)->get(); - - // 既に処理済みのものを除外 - $unprocessed = $settlements->filter(function ($settlement) { - return !$this->isAlreadyProcessed($settlement); - }); - - return $unprocessed; - } - - /** - * 既に処理済みかチェック - * - * @param SettlementTransaction $settlement - * @return bool - */ - private function isAlreadyProcessed(SettlementTransaction $settlement): bool - { - // 1. regular_contractの同一contract_payment_numberが既に処理済みかチェック - $linkedContract = DB::table('regular_contract') - ->where('contract_payment_number', $settlement->contract_payment_number) - ->whereNotNull('contract_payment_day') - ->exists(); - - if ($linkedContract) { - return true; - } - - // 2. batch_logで処理完了記録があるかチェック - $processedInBatch = BatchLog::where('process_name', 'shj4b') - ->where('status', BatchLog::STATUS_SUCCESS) - ->where('parameters', 'like', '%"settlement_transaction_id":' . $settlement->settlement_transaction_id . '%') - ->exists(); - - if ($processedInBatch) { - return true; - } - - // 3. 現在キューに入っているかチェック(簡易版) - // 注: より正確にはRedis/DBキューの内容を確認する必要がある - $recentJobDispatched = BatchLog::where('process_name', 'shj4b') - ->where('parameters', 'like', '%"settlement_transaction_id":' . $settlement->settlement_transaction_id . '%') - ->where('created_at', '>=', Carbon::now()->subHours(1)) - ->exists(); - - return $recentJobDispatched; - } - - /** - * 対象一覧表示 - * - * @param \Illuminate\Database\Eloquent\Collection $settlements - */ - private function displayTargets($settlements) - { - $this->info("対象の決済トランザクション:"); - $this->table( - ['ID', '契約支払番号', '決済金額', '支払日', '作成日時'], - $settlements->map(function ($settlement) { - return [ - $settlement->settlement_transaction_id, - $settlement->contract_payment_number, - number_format($settlement->settlement_amount) . '円', - Carbon::parse($settlement->pay_date)->format('Y-m-d H:i:s'), - $settlement->created_at->format('Y-m-d H:i:s'), - ]; - })->toArray() - ); - } - - /** - * 決済処理実行 - * - * @param \Illuminate\Database\Eloquent\Collection $settlements - * @return array - */ - private function processSettlements($settlements): array - { - $success = 0; - $failed = 0; - $results = []; - - foreach ($settlements as $settlement) { - try { - $this->info("処理中: 決済トランザクションID {$settlement->settlement_transaction_id}"); - - // ProcessSettlementJobをディスパッチ - ProcessSettlementJob::dispatch( - $settlement->settlement_transaction_id, - [ - 'source' => 'shj4b_check_command', - 'triggered_at' => now()->toISOString(), - ] - ); - - $success++; - $results[] = [ - 'settlement_transaction_id' => $settlement->settlement_transaction_id, - 'status' => 'dispatched', - 'message' => 'ProcessSettlementJobディスパッチ成功', - ]; - - $this->info("✓ 成功: {$settlement->settlement_transaction_id}"); - - } catch (\Throwable $e) { - $failed++; - $results[] = [ - 'settlement_transaction_id' => $settlement->settlement_transaction_id, - 'status' => 'failed', - 'error' => $e->getMessage(), - ]; - - $this->error("✗ 失敗: {$settlement->settlement_transaction_id} - {$e->getMessage()}"); - - Log::error('SHJ-4B チェック 個別処理失敗', [ - 'settlement_transaction_id' => $settlement->settlement_transaction_id, - 'error' => $e->getMessage(), - ]); - } - } - - return [ - 'success' => $success, - 'failed' => $failed, - 'results' => $results, - 'total' => $settlements->count(), - ]; - } -} \ No newline at end of file