diff --git a/app/Services/ShjThreeService.php b/app/Services/ShjThreeService.php deleted file mode 100644 index 53cb893..0000000 --- a/app/Services/ShjThreeService.php +++ /dev/null @@ -1,796 +0,0 @@ -parkModel = $parkModel; - $this->userModel = $userModel; - $this->contractModel = $contractModel; - $this->batchLogModel = $batchLogModel; - $this->mailSendService = $mailSendService; - } - - /** - * SHJ-3 定期更新リマインダー処理メイン実行 - * - * 処理フロー: - * 【処理0】駐輪場マスタの情報を取得する - * 【判断0】当該駐輪場実行タイミングチェック - * 【処理2】定期更新対象者を取得する - * 【判断2】利用者有無をチェック - * 【処理3】対象者向けにメール送信、またはオペレーターキュー追加処理 - * 【処理4】バッチ処理ログを作成する - * - * @return array 処理結果 - */ - public function executeReminderProcess(): array - { - $batchLogId = null; - $processedParksCount = 0; - $totalTargetUsers = 0; - $mailSuccessCount = 0; - $mailErrorCount = 0; - $operatorQueueCount = 0; - - try { - // バッチ処理開始ログ作成 - $batchLog = BatchLog::createBatchLog( - 'shj3', - BatchLog::STATUS_START, - [], - 'SHJ-3 定期更新リマインダー処理開始' - ); - $batchLogId = $batchLog->id; - - Log::info('SHJ-3 定期更新リマインダー処理開始', [ - 'batch_log_id' => $batchLogId - ]); - - // 【処理0】駐輪場マスタの情報を取得する - $parkList = $this->getParkMasterInfo(); - - if (empty($parkList)) { - $message = '対象の駐輪場マスタが見つかりません'; - - $batchLog->update([ - 'status' => BatchLog::STATUS_ERROR, - 'end_time' => now(), - 'message' => $message, - 'error_details' => $message, - 'error_count' => 1 - ]); - - return [ - 'success' => false, - 'message' => $message, - 'processed_parks_count' => 0, - 'total_target_users' => 0, - 'mail_success_count' => 0, - 'mail_error_count' => 0, - 'operator_queue_count' => 0, - 'batch_log_id' => $batchLogId - ]; - } - - // 各駐輪場に対する処理ループ - foreach ($parkList as $park) { - Log::info('駐輪場処理開始', [ - 'park_id' => $park->park_id, - 'park_name' => $park->park_name - ]); - - // 【判断0】当該駐輪場実行タイミングチェック - $timingCheckResult = $this->checkExecutionTiming($park); - - if (!$timingCheckResult['should_execute']) { - Log::info('実行タイミング対象外', [ - 'park_id' => $park->park_id, - 'reason' => $timingCheckResult['reason'] - ]); - continue; - } - - $processedParksCount++; - - // 【処理2】定期更新対象者を取得する - $targetUsers = $this->getRegularUpdateTargetUsers($park->park_id); - - // 【判断2】利用者有無をチェック - if (empty($targetUsers)) { - Log::info('利用者なし', [ - 'park_id' => $park->park_id - ]); - continue; - } - - $totalTargetUsers += count($targetUsers); - - // 【処理3】対象者向けにメール送信、またはオペレーターキュー追加処理 - foreach ($targetUsers as $targetUser) { - $processResult = $this->processTargetUser($targetUser); - - if ($processResult['type'] === 'mail_success') { - $mailSuccessCount++; - } elseif ($processResult['type'] === 'mail_error') { - $mailErrorCount++; - } elseif ($processResult['type'] === 'operator_queue') { - $operatorQueueCount++; - } - } - - Log::info('駐輪場処理完了', [ - 'park_id' => $park->park_id, - 'target_users_count' => count($targetUsers) - ]); - } - - // 【処理4】バッチ処理ログを作成する(SHJ-8呼び出し) - $this->createShjBatchLog([ - 'processed_parks_count' => $processedParksCount, - 'total_target_users' => $totalTargetUsers, - 'mail_success_count' => $mailSuccessCount, - 'mail_error_count' => $mailErrorCount, - 'operator_queue_count' => $operatorQueueCount - ]); - - // バッチ処理完了ログ更新 - $batchLog->update([ - 'status' => BatchLog::STATUS_SUCCESS, - 'end_time' => now(), - 'message' => 'SHJ-3 定期更新リマインダー処理正常完了', - 'success_count' => 1, - 'parameters' => [ - 'processed_parks_count' => $processedParksCount, - 'total_target_users' => $totalTargetUsers, - 'mail_success_count' => $mailSuccessCount, - 'mail_error_count' => $mailErrorCount, - 'operator_queue_count' => $operatorQueueCount, - 'executed_at' => now()->toISOString() - ] - ]); - - Log::info('SHJ-3 定期更新リマインダー処理完了', [ - 'batch_log_id' => $batchLogId, - 'processed_parks_count' => $processedParksCount, - 'total_target_users' => $totalTargetUsers - ]); - - return [ - 'success' => true, - 'message' => 'SHJ-3 定期更新リマインダー処理が正常に完了しました', - 'processed_parks_count' => $processedParksCount, - 'total_target_users' => $totalTargetUsers, - 'mail_success_count' => $mailSuccessCount, - 'mail_error_count' => $mailErrorCount, - 'operator_queue_count' => $operatorQueueCount, - 'batch_log_id' => $batchLogId - ]; - - } catch (\Exception $e) { - $errorMessage = 'SHJ-3 定期更新リマインダー処理でエラーが発生: ' . $e->getMessage(); - - if (isset($batchLog) && $batchLog) { - $batchLog->update([ - 'status' => BatchLog::STATUS_ERROR, - 'end_time' => now(), - 'message' => $errorMessage, - 'error_details' => $e->getMessage(), - 'error_count' => 1 - ]); - } - - Log::error('SHJ-3 定期更新リマインダー処理エラー', [ - 'batch_log_id' => $batchLogId, - 'exception' => $e->getMessage(), - 'trace' => $e->getTraceAsString() - ]); - - return [ - 'success' => false, - 'message' => $errorMessage, - 'details' => $e->getMessage(), - 'processed_parks_count' => $processedParksCount, - 'total_target_users' => $totalTargetUsers, - 'mail_success_count' => $mailSuccessCount, - 'mail_error_count' => $mailErrorCount, - 'operator_queue_count' => $operatorQueueCount, - 'batch_log_id' => $batchLogId - ]; - } - } - - /** - * 【処理0】駐輪場マスタの情報を取得する - * - * 仕様書に基づくSQLクエリ: - * SELECT 駐輪場ID, 駐輪場名, 更新期間開始日, 更新期間開始時, - * 更新期間終了日, 更新期間終了時, リマインダー種別, リマインダー時間 - * FROM 駐輪場マスタ - * WHERE 閉設フラグ = 0 - * ORDER BY 駐輪場ふりがな asc - * - * @return array 駐輪場マスタ情報 - */ - private function getParkMasterInfo(): array - { - try { - $parkInfo = DB::table('park') - ->select([ - 'park_id', - 'park_name', - 'renew_start_date', - 'renew_start_time', - 'renew_end_date', - 'renew_end_time', - 'reminder_type', - 'reminder_time' - ]) - ->where('park_close_flag', 0) - ->orderBy('park_ruby', 'asc') - ->get() - ->toArray(); - - Log::info('駐輪場マスタ情報取得完了', [ - 'park_count' => count($parkInfo) - ]); - - return $parkInfo; - - } catch (\Exception $e) { - Log::error('駐輪場マスタ情報取得エラー', [ - 'error' => $e->getMessage() - ]); - - throw $e; - } - } - - /** - * 【判断0】当該駐輪場実行タイミングチェック - * - * 仕様書に基づく複雑なリマインダー時期判定: - * - パターンA: 月を跨らない場合(更新期間開始日 <= 更新期間終了日) - * - パターンB: 月を跨る場合(更新期間開始日 > 更新期間終了日) - * - リマインダー種別による実行判定 - * - * @param object $park 駐輪場情報 - * @return array 実行タイミング判定結果 - */ - private function checkExecutionTiming($park): array - { - try { - $today = Carbon::now(); - $currentDate = $today->format('Y-m-d'); - - // 更新期間の日付を取得 - $startDate = Carbon::parse($park->renew_start_date); - $endDate = Carbon::parse($park->renew_end_date); - - Log::info('実行タイミングチェック開始', [ - 'park_id' => $park->park_id, - 'current_date' => $currentDate, - 'start_date' => $startDate->format('Y-m-d'), - 'end_date' => $endDate->format('Y-m-d'), - 'reminder_type' => $park->reminder_type - ]); - - // パターン判定: 月を跨るかどうか - $isPatternA = $startDate->lte($endDate); // パターンA: 月を跨らない - $isPatternB = !$isPatternA; // パターンB: 月を跨る - - // 現在日付が更新期間内かチェック - $isWithinUpdatePeriod = false; - - if ($isPatternA) { - // パターンA: 更新期間開始日 <= 現在日 <= 更新期間終了日 - $isWithinUpdatePeriod = $today->between($startDate, $endDate); - } else { - // パターンB: 月を跨る場合の判定 - // 現在日 >= 更新期間開始日 OR 現在日 <= 更新期間終了日 - $isWithinUpdatePeriod = $today->gte($startDate) || $today->lte($endDate); - } - - if (!$isWithinUpdatePeriod) { - return [ - 'should_execute' => false, - 'reason' => '更新期間外のため実行対象外', - 'pattern' => $isPatternA ? 'A' : 'B' - ]; - } - - // リマインダー種別による実行判定 - $reminderExecutionResult = $this->checkReminderTiming($park, $today, $startDate, $endDate, $isPatternA); - - Log::info('実行タイミングチェック完了', [ - 'park_id' => $park->park_id, - 'should_execute' => $reminderExecutionResult['should_execute'], - 'pattern' => $isPatternA ? 'A' : 'B', - 'reminder_result' => $reminderExecutionResult - ]); - - return $reminderExecutionResult; - - } catch (\Exception $e) { - Log::error('実行タイミングチェックエラー', [ - 'park_id' => $park->park_id, - 'error' => $e->getMessage() - ]); - - throw $e; - } - } - - /** - * リマインダー時期の詳細判定 - * - * 仕様書の複雑なリマインダー種別判定を実装 - * パターンA/Bに基づく詳細な日付計算ロジック - * - * @param object $park 駐輪場情報 - * @param Carbon $today 現在日 - * @param Carbon $startDate 更新期間開始日 - * @param Carbon $endDate 更新期間終了日 - * @param bool $isPatternA パターンAかどうか - * @return array リマインダー実行判定結果 - */ - private function checkReminderTiming($park, Carbon $today, Carbon $startDate, Carbon $endDate, bool $isPatternA): array - { - $reminderType = $park->reminder_type ?? 0; - - // リマインダー種別 = 0 の場合は実行しない - if ($reminderType == 0) { - return [ - 'should_execute' => false, - 'reason' => 'リマインダー種別=0のため実行対象外' - ]; - } - - // 仕様書に基づく詳細なリマインダー時期判定 - $executionCheck = $this->performDetailedReminderCheck($park, $today, $startDate, $endDate, $isPatternA); - - return [ - 'should_execute' => $executionCheck['should_execute'], - 'reason' => $executionCheck['reason'], - 'reminder_type' => $reminderType, - 'pattern' => $isPatternA ? 'A' : 'B', - 'execution_details' => $executionCheck - ]; - } - - /** - * 仕様書に基づく詳細なリマインダー実行判定 - * - * 複雑な条件分岐を含む実行フラグ判定処理 - * - パターンA/Bによる分岐 - * - リマインダー種別による日数計算 - * - 月跨ぎ処理の考慮 - * - * @param object $park 駐輪場情報 - * @param Carbon $today 現在日 - * @param Carbon $startDate 更新期間開始日 - * @param Carbon $endDate 更新期間終了日 - * @param bool $isPatternA パターンAかどうか - * @return array 実行判定詳細結果 - */ - private function performDetailedReminderCheck($park, Carbon $today, Carbon $startDate, Carbon $endDate, bool $isPatternA): array - { - $reminderType = $park->reminder_type ?? 0; - - // 内部変数 更新パターン判定 - $updatePattern = ''; - - if ($isPatternA) { - // パターンA: 月を跨らない場合 - if ($startDate->lte($endDate)) { - $updatePattern = 'A'; - } else { - $updatePattern = 'B'; // 実際はパターンBになる - } - } else { - // パターンB: 月を跨る場合 - $updatePattern = 'B'; - } - - // 実行フラグ判定処理 - $executionFlag = $this->calculateExecutionFlag($today, $startDate, $endDate, $reminderType, $updatePattern); - - Log::info('詳細リマインダー判定完了', [ - 'park_id' => $park->park_id, - 'reminder_type' => $reminderType, - 'update_pattern' => $updatePattern, - 'execution_flag' => $executionFlag, - 'today' => $today->format('Y-m-d'), - 'start_date' => $startDate->format('Y-m-d'), - 'end_date' => $endDate->format('Y-m-d') - ]); - - return [ - 'should_execute' => $executionFlag['should_execute'], - 'reason' => $executionFlag['reason'], - 'update_pattern' => $updatePattern, - 'execution_details' => $executionFlag - ]; - } - - /** - * 実行フラグ計算処理 - * - * 仕様書の複雑な分岐条件に基づく実行判定 - * - * @param Carbon $today 現在日 - * @param Carbon $startDate 更新期間開始日 - * @param Carbon $endDate 更新期間終了日 - * @param int $reminderType リマインダー種別 - * @param string $updatePattern 更新パターン(A/B) - * @return array 実行フラグ判定結果 - */ - private function calculateExecutionFlag(Carbon $today, Carbon $startDate, Carbon $endDate, int $reminderType, string $updatePattern): array - { - // リマインダー種別による実行判定 - switch ($reminderType) { - case 1: // -1日前 - return $this->checkReminderType1($today, $startDate, $endDate, $updatePattern); - case 2: // -2日前 - return $this->checkReminderType2($today, $startDate, $endDate, $updatePattern); - default: - return [ - 'should_execute' => false, - 'reason' => "未対応のリマインダー種別: {$reminderType}" - ]; - } - } - - /** - * リマインダー種別=1(-1日前)の判定 - * - * @param Carbon $today 現在日 - * @param Carbon $startDate 更新期間開始日 - * @param Carbon $endDate 更新期間終了日 - * @param string $updatePattern 更新パターン - * @return array 判定結果 - */ - private function checkReminderType1(Carbon $today, Carbon $startDate, Carbon $endDate, string $updatePattern): array - { - // 更新期間終了日の1日前が実行日 - $executionDate = $endDate->copy()->subDay(); - - if ($today->isSameDay($executionDate)) { - return [ - 'should_execute' => true, - 'reason' => '-1日前のリマインダー実行日', - 'execution_date' => $executionDate->format('Y-m-d') - ]; - } - - return [ - 'should_execute' => false, - 'reason' => "リマインダー実行日({$executionDate->format('Y-m-d')})ではない(現在: {$today->format('Y-m-d')})", - 'execution_date' => $executionDate->format('Y-m-d') - ]; - } - - /** - * リマインダー種別=2(-2日前)の判定 - * - * @param Carbon $today 現在日 - * @param Carbon $startDate 更新期間開始日 - * @param Carbon $endDate 更新期間終了日 - * @param string $updatePattern 更新パターン - * @return array 判定結果 - */ - private function checkReminderType2(Carbon $today, Carbon $startDate, Carbon $endDate, string $updatePattern): array - { - // 更新期間終了日の2日前が実行日 - $executionDate = $endDate->copy()->subDays(2); - - if ($today->isSameDay($executionDate)) { - return [ - 'should_execute' => true, - 'reason' => '-2日前のリマインダー実行日', - 'execution_date' => $executionDate->format('Y-m-d') - ]; - } - - return [ - 'should_execute' => false, - 'reason' => "リマインダー実行日({$executionDate->format('Y-m-d')})ではない(現在: {$today->format('Y-m-d')})", - 'execution_date' => $executionDate->format('Y-m-d') - ]; - } - - /** - * 【処理2】定期更新対象者を取得する - * - * 仕様書に基づく複雑なSQLクエリ: - * 定期契約マスタ T1 と 利用者マスタ T2 を結合して - * 更新対象者の情報を取得する - * - * @param int $parkId 駐輪場ID - * @return array 定期更新対象者情報 - */ - private function getRegularUpdateTargetUsers(int $parkId): array - { - try { - $currentDate = Carbon::now()->format('Y-m-d'); - - // 仕様書に記載されたSQLクエリに基づく対象者取得 - $targetUsers = DB::table('regular_contract as T1') - ->select([ - 'T1.contract_id as 定期契約内ID', - 'T1.park_id as 駐輪場ID', - 'T2.user_id as 利用者ID', - 'T2.user_manual_regist_flag as 手動登録フラグ', - 'T2.user_primemail as メールアドレス', - 'T2.user_submail as 予備メールアドレス', - 'T2.user_name as 氏名', - 'T1.contract_periode as 有効期間E' - ]) - ->join('user as T2', 'T1.user_id', '=', 'T2.user_id') - ->where('T1.park_id', $parkId) - ->where('T1.contract_periode', '<=', $currentDate) // 更新可能日チェック - ->where('T1.contract_cancel_flag', 0) // 解約フラグ = 0 - ->where('T2.user_quit_flag', 0) // 退会フラグ = 0 - ->where('T1.contract_flag', 1) // 承認フラグ = 1 - ->whereNull('T1.contract_permission') // 更新済フラグ is null - ->get() - ->toArray(); - - Log::info('定期更新対象者取得完了', [ - 'park_id' => $parkId, - 'target_users_count' => count($targetUsers) - ]); - - return $targetUsers; - - } catch (\Exception $e) { - Log::error('定期更新対象者取得エラー', [ - 'park_id' => $parkId, - 'error' => $e->getMessage() - ]); - - throw $e; - } - } - - /** - * 【処理3】対象者の処理実行 - * - * 手動登録フラグによって処理を分岐: - * - = 0 (ウェブ申込み): SHJ-7メール送信を呼び出し - * - その他: 内部変数のカウントアップ(オペレーターキュー処理) - * - * @param object $targetUser 対象者情報 - * @return array 処理結果 - */ - private function processTargetUser($targetUser): array - { - try { - $manualRegistFlag = $targetUser->手動登録フラグ ?? 1; - - if ($manualRegistFlag == 0) { - // ウェブ申込み: SHJ-7メール送信処理 - return $this->sendReminderMail($targetUser); - } else { - // その他: オペレーターキュー追加処理(内部変数カウントアップ) - Log::info('オペレーターキュー対象者', [ - 'user_id' => $targetUser->利用者ID, - 'contract_id' => $targetUser->定期契約内ID, - 'manual_regist_flag' => $manualRegistFlag - ]); - - return [ - 'type' => 'operator_queue', - 'success' => true, - 'message' => 'オペレーターキュー対象として処理' - ]; - } - - } catch (\Exception $e) { - Log::error('対象者処理エラー', [ - 'user_id' => $targetUser->利用者ID ?? 'unknown', - 'error' => $e->getMessage() - ]); - - return [ - 'type' => 'error', - 'success' => false, - 'message' => $e->getMessage() - ]; - } - } - - /** - * リマインダーメール送信処理 - * - * SHJ-7メール送信処理を呼び出し、使用プログラムID=200を使用 - * - * @param object $targetUser 対象者情報 - * @return array 送信結果 - */ - private function sendReminderMail($targetUser): array - { - try { - $mailAddress = $targetUser->メールアドレス ?? ''; - $backupMailAddress = $targetUser->予備メールアドレス ?? ''; - $mailTemplateId = 200; // 使用プログラムID - - Log::info('SHJ-7メール送信処理呼び出し', [ - 'user_id' => $targetUser->利用者ID, - 'contract_id' => $targetUser->定期契約内ID, - 'mail_address' => $mailAddress, - 'backup_mail_address' => $backupMailAddress, - 'mail_template_id' => $mailTemplateId - ]); - - // SHJ-7メール送信処理実行 - $mailResult = $this->mailSendService->executeMailSend( - $mailAddress, - $backupMailAddress, - $mailTemplateId - ); - - if ($mailResult['success']) { - return [ - 'type' => 'mail_success', - 'success' => true, - 'message' => 'メール送信成功', - 'mail_result' => $mailResult - ]; - } else { - return [ - 'type' => 'mail_error', - 'success' => false, - 'message' => 'メール送信失敗: ' . $mailResult['message'], - 'mail_result' => $mailResult - ]; - } - - } catch (\Exception $e) { - Log::error('リマインダーメール送信エラー', [ - 'user_id' => $targetUser->利用者ID ?? 'unknown', - 'error' => $e->getMessage() - ]); - - return [ - 'type' => 'mail_error', - 'success' => false, - 'message' => 'メール送信エラー: ' . $e->getMessage() - ]; - } - } - - /** - * 【処理4】SHJ-8バッチ処理ログ作成 - * - * 仕様書に基づくSHJ-8共通処理呼び出し - * - * @param array $statistics 処理統計情報 - * @return void - */ - private function createShjBatchLog(array $statistics): void - { - try { - // 仕様書に基づくSHJ-8パラメータ設定 - $deviceId = 9999; // テスト用デバイスID(規格書では"-"だが、既存実装に合わせて9999使用) - $processName = 'SHJ-3定期更新リマインダー'; - $jobName = 'success'; - $status = 'success'; - - // ステータスコメント生成 - $statusComment = "メール正常終了件数: {$statistics['mail_success_count']}" . - " + メール異常終了件数: {$statistics['mail_error_count']}" . - " + キュー登録正常終了件数: {$statistics['operator_queue_count']}"; - - $createdDate = now()->format('Y/m/d'); - $updatedDate = now()->format('Y/m/d'); - - Log::info('SHJ-8バッチ処理ログ作成', [ - 'device_id' => $deviceId, - 'process_name' => $processName, - 'job_name' => $jobName, - 'status' => $status, - 'status_comment' => $statusComment, - 'created_date' => $createdDate, - 'updated_date' => $updatedDate - ]); - - // 共通処理SHJ-8バッチ処理ログ作成を呼び出し - // 注意: 実際の運用では外部コマンド呼び出しまたは専用サービス経由で実行 - BatchLog::createBatchLog( - $processName, - $status, - [ - 'device_id' => $deviceId, - 'job_name' => $jobName, - 'status_comment' => $statusComment, - 'statistics' => $statistics, - 'shj8_params' => [ - 'device_id' => $deviceId, - 'process_name' => $processName, - 'job_name' => $jobName, - 'status' => $status, - 'created_date' => $createdDate, - 'updated_date' => $updatedDate - ] - ], - $statusComment - ); - - } catch (\Exception $e) { - Log::error('SHJ-8バッチ処理ログ作成エラー', [ - 'error' => $e->getMessage(), - 'statistics' => $statistics - ]); - - // SHJ-8でエラーが発生してもメイン処理は継続 - // エラーログのみ出力 - } - } -}