app/Console/Commands/ShjFourBCheckCommand.php を削除
Some checks failed
Deploy main / deploy (push) Has been cancelled

This commit is contained in:
go.unhi 2025-10-23 20:36:27 +09:00
parent 7be5e66430
commit 17cbd3c065

View File

@ -1,317 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\SettlementTransaction;
use App\Models\Batch\BatchLog;
use App\Jobs\ProcessSettlementJob;
use App\Services\ShjFourBService;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Queue;
use Carbon\Carbon;
/**
* SHJ-4B チェックコマンド
*
* 未処理の決済トランザクションを検索し、ProcessSettlementJobをディスパッチする兜底処理
*
* 実行方法:
* php artisan shj4b:check
* php artisan shj4b:check --dry-run # 実際の処理は行わず、対象のみ表示
* php artisan shj4b:check --limit=50 # 処理件数制限
*
* Cron設定例10分毎実行:
* 0,10,20,30,40,50 * * * * cd /path/to/project && php artisan shj4b:check > /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(),
];
}
}