parkModel = $parkModel; $this->userModel = $userModel; $this->contractModel = $contractModel; $this->operatorQueModel = $operatorQueModel; $this->mailSendService = $mailSendService; $this->shjEightService = $shjEightService; } /** * SHJ-3 定期更新リマインダー処理メイン実行 * * 処理フロー(仕様書準拠): * 【処理0】駐輪場マスタの情報を取得する * 【判断0】当該駐輪場実行タイミングチェック * 【処理2】定期更新対象者を取得する * 【判断2】利用者有無をチェック * 【処理3】対象者向けにメール送信、またはオペレーターキュー追加処理 * 【処理4】バッチ処理ログを作成する(各駐輪場ごとに実行) * * @return array 処理結果 */ public function executeReminderProcess(): array { $overallProcessedParksCount = 0; $overallTotalTargetUsers = 0; $overallMailSuccessCount = 0; $overallMailErrorCount = 0; $overallQueueSuccessCount = 0; $overallQueueErrorCount = 0; try { Log::info('SHJ-3 定期更新リマインダー処理開始'); // 【処理0】駐輪場マスタの情報を取得する $parkList = $this->getParkMasterInfo(); if (empty($parkList)) { $message = '対象の駐輪場マスタが見つかりません'; Log::warning($message); // 駐輪場が見つからない場合でも実行ログを記録 $this->createOverallBatchLog(0, 0, 0, 0, 0, 0); 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 ]; } // 取得レコード数分【判断0】を繰り返す foreach ($parkList as $park) { // 各駐輪場ごとの内部変数(仕様書:場景A) $mailSuccessCount = 0; $mailErrorCount = 0; $queueSuccessCount = 0; $queueErrorCount = 0; $batchComment = ''; 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; } $overallProcessedParksCount++; // 【処理2】定期更新対象者を取得する $targetUsers = $this->getRegularUpdateTargetUsers( $park, $timingCheckResult['update_pattern'] ); // 【判断2】利用者有無をチェック if (empty($targetUsers)) { // 仕様書:利用者なしの結果を設定する $batchComment = "定期更新リマインダー:今月の定期更新対象者は無しです / {$park->park_name}"; Log::info('利用者なし', [ 'park_id' => $park->park_id, 'batch_comment' => $batchComment ]); // 【処理4】バッチ処理ログを作成する $this->createShjBatchLog( $park, $batchComment, $mailSuccessCount, $mailErrorCount, $queueSuccessCount, $queueErrorCount ); // 次の駐輪場マスタへ continue; } $overallTotalTargetUsers += count($targetUsers); // 【処理3】処理2の対象レコード数分繰り返す foreach ($targetUsers as $targetUser) { $processResult = $this->processTargetUser($targetUser, $park); if ($processResult['type'] === 'mail_success') { $mailSuccessCount++; } elseif ($processResult['type'] === 'mail_error') { $mailErrorCount++; // バッチコメントに異常情報を追加 if (!empty($processResult['error_info'])) { $batchComment .= ($batchComment ? ' / ' : '') . $processResult['error_info']; } } elseif ($processResult['type'] === 'queue_success') { $queueSuccessCount++; } elseif ($processResult['type'] === 'queue_error') { $queueErrorCount++; } } // 全体集計用に加算 $overallMailSuccessCount += $mailSuccessCount; $overallMailErrorCount += $mailErrorCount; $overallQueueSuccessCount += $queueSuccessCount; $overallQueueErrorCount += $queueErrorCount; Log::info('駐輪場処理完了', [ 'park_id' => $park->park_id, 'target_users_count' => count($targetUsers), 'mail_success' => $mailSuccessCount, 'mail_error' => $mailErrorCount, 'queue_success' => $queueSuccessCount, 'queue_error' => $queueErrorCount ]); // 【処理4】バッチ処理ログを作成する(各駐輪場ごと) $this->createShjBatchLog( $park, $batchComment, $mailSuccessCount, $mailErrorCount, $queueSuccessCount, $queueErrorCount ); } Log::info('SHJ-3 定期更新リマインダー処理完了', [ 'processed_parks_count' => $overallProcessedParksCount, 'total_target_users' => $overallTotalTargetUsers, 'mail_success_count' => $overallMailSuccessCount, 'mail_error_count' => $overallMailErrorCount, 'queue_success_count' => $overallQueueSuccessCount, 'queue_error_count' => $overallQueueErrorCount ]); // 駐輪場が0件でも全体の実行ログを記録する $this->createOverallBatchLog( $overallProcessedParksCount, $overallTotalTargetUsers, $overallMailSuccessCount, $overallMailErrorCount, $overallQueueSuccessCount, $overallQueueErrorCount ); return [ 'success' => true, 'message' => 'SHJ-3 定期更新リマインダー処理が正常に完了しました', 'processed_parks_count' => $overallProcessedParksCount, 'total_target_users' => $overallTotalTargetUsers, 'mail_success_count' => $overallMailSuccessCount, 'mail_error_count' => $overallMailErrorCount, 'operator_queue_count' => $overallQueueSuccessCount + $overallQueueErrorCount ]; } catch (\Exception $e) { $errorMessage = 'SHJ-3 定期更新リマインダー処理でエラーが発生: ' . $e->getMessage(); Log::error('SHJ-3 定期更新リマインダー処理エラー', [ 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); // エラー時も実行ログを記録 $this->createOverallBatchLog( $overallProcessedParksCount, $overallTotalTargetUsers, $overallMailSuccessCount, $overallMailErrorCount, $overallQueueSuccessCount, $overallQueueErrorCount ); return [ 'success' => false, 'message' => $errorMessage, 'details' => $e->getMessage(), 'processed_parks_count' => $overallProcessedParksCount, 'total_target_users' => $overallTotalTargetUsers, 'mail_success_count' => $overallMailSuccessCount, 'mail_error_count' => $overallMailErrorCount, 'operator_queue_count' => $overallQueueSuccessCount + $overallQueueErrorCount ]; } } /** * 【処理0】駐輪場マスタの情報を取得する * * 仕様書に基づくSQLクエリ: * SELECT 駐輪場ID, 駐輪場名, 更新期間開始日, 更新期間開始時, * 更新期間終了日, 更新期間終了時, リマインダー種別, リマインダー時間 * FROM 駐輪場マスタ * WHERE 閉設フラグ = 0 * ORDER BY 駐輪場ふりがな asc * * @return array 駐輪場マスタ情報 */ private function getParkMasterInfo(): array { try { $parkInfo = DB::table('park') ->select([ 'park_id', // 駐輪場ID 'park_name', // 駐輪場名 'update_grace_period_start_date', // 更新期間開始日(例:"20") 'update_grace_period_start_time', // 更新期間開始時(例:"09:00") 'update_grace_period_end_date', // 更新期間終了日(例:"6") 'update_grace_period_end_time', // 更新期間終了時(例:"23:59") // 注意:reminder_type と reminder_time フィールドはまだ存在しない // 暫定的に0(毎日)と開始時刻をデフォルト値として使用 ]) ->where('park_close_flag', 0) // 閉設フラグ = 0 ->orderBy('park_ruby', 'asc') // 駐輪場ふりがな 昇順 ->get() ->toArray(); // reminder_type と reminder_time をデフォルト値で補完 foreach ($parkInfo as $park) { $park->reminder_type = 0; // 0=毎日 $park->reminder_time = $park->update_grace_period_start_time; // 開始時刻を使用 } Log::info('駐輪場マスタ情報取得完了', [ 'park_count' => count($parkInfo) ]); return $parkInfo; } catch (\Exception $e) { Log::error('駐輪場マスタ情報取得エラー', [ 'error' => $e->getMessage() ]); throw $e; } } /** * 【判断0】当該駐輪場実行タイミングチェック * * 仕様書に基づく実行タイミング判定: * 1. リマインダー時間 = 現在の時間 のチェック * 2. 内部変数.更新パターン の設定(A or B) * 3. 内部変数.更新期間開始日からの経過日数 の算出 * 4. 内部変数.実行フラグ の判定 * * @param object $park 駐輪場情報 * @return array 実行タイミング判定結果 */ private function checkExecutionTiming($park): array { try { $now = Carbon::now(); $currentTime = $now->format('H:i'); $todayDay = (int)$now->format('d'); // 本日の日(1-31) Log::info('実行タイミングチェック開始', [ 'park_id' => $park->park_id, 'current_time' => $currentTime, 'today_day' => $todayDay, 'reminder_time' => $park->reminder_time, 'reminder_type' => $park->reminder_type ]); // 仕様書:駐輪場マスタ.リマインダー時間 = [現在の時間] の場合 if ($park->reminder_time !== $currentTime) { return [ 'should_execute' => false, 'reason' => "リマインダー時間不一致(設定:{$park->reminder_time} vs 現在:{$currentTime})" ]; } // 内部変数.更新パターン を設定 // DBから返る値は文字列なので、型変換して使用 $startDay = (int)$park->update_grace_period_start_date; // 例:"20" → 20 $endDay = (int)$park->update_grace_period_end_date; // 例:"6" → 6 $updatePattern = ''; if ($startDay <= $endDay) { // パターンA: 月を跨らない場合 $updatePattern = 'A'; } else { // パターンB: 月を跨る場合 $updatePattern = 'B'; } // 内部変数.更新期間開始日からの経過日数 を設定 $elapsedDays = 99; // デフォルト: 対象外 if ($updatePattern === 'A') { // パターンA の場合 if ($endDay < $todayDay) { // 駐輪場マスタ.更新期間終了日 > [本日の日付]の日 の場合 $elapsedDays = 99; // 対象外 } elseif ($startDay <= $todayDay) { // 駐輪場マスタ.更新期間開始日 <= [本日の日付]の日 の場合 $elapsedDays = $todayDay - $startDay; } else { // その他の場合 $elapsedDays = 99; // 対象外 } } else { // パターンB の場合 if ($startDay <= $todayDay) { // 駐輪場マスタ.更新期間開始日 <= [本日の日付]の日 の場合 $elapsedDays = $todayDay - $startDay; } elseif ($endDay >= $todayDay) { // 駐輪場マスタ.更新期間終了日 >= [本日の日付]の日 の場合 // 仕様書の計算式: ([先月の月末日]の日 − 駐輪場マスタ.更新期間開始日) + [本日の日付]の日 $lastMonthEnd = $now->copy()->subMonth()->endOfMonth()->day; $elapsedDays = ($lastMonthEnd - $startDay) + $todayDay; } else { // その他の場合 $elapsedDays = 99; // 対象外 } } Log::info('経過日数算出完了', [ 'park_id' => $park->park_id, 'update_pattern' => $updatePattern, 'start_day' => $startDay, 'end_day' => $endDay, 'today_day' => $todayDay, 'elapsed_days' => $elapsedDays ]); // 内部変数.実行フラグ を設定 $executionFlag = 0; if ($elapsedDays !== 99) { // DBから返る値は文字列なので、型変換して比較 $reminderType = (int)($park->reminder_type ?? 0); if ($reminderType === 0) { // 仕様書:毎日 $executionFlag = 1; } elseif ($reminderType === 1) { // 仕様書:1日おき(経過日数が偶数の場合) $executionFlag = ($elapsedDays % 2 === 0) ? 1 : 0; } elseif ($reminderType === 2) { // 仕様書:2日おき(経過日数を3で割った余りが0の場合) $executionFlag = ($elapsedDays % 3 === 0) ? 1 : 0; } else { // あり得ない $executionFlag = 0; } } $shouldExecute = ($executionFlag === 1); Log::info('実行タイミングチェック完了', [ 'park_id' => $park->park_id, 'update_pattern' => $updatePattern, 'elapsed_days' => $elapsedDays, 'reminder_type' => $park->reminder_type, 'execution_flag' => $executionFlag, 'should_execute' => $shouldExecute ]); return [ 'should_execute' => $shouldExecute, 'reason' => $shouldExecute ? '実行対象' : "実行フラグ=0(経過日数:{$elapsedDays}, リマインダー種別:{$park->reminder_type})", 'update_pattern' => $updatePattern, 'elapsed_days' => $elapsedDays, 'execution_flag' => $executionFlag ]; } catch (\Exception $e) { Log::error('実行タイミングチェックエラー', [ 'park_id' => $park->park_id ?? 'unknown', 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); throw $e; } } /** * 【処理2】定期更新対象者を取得する * * 仕様書に基づくSQLクエリ: * 定期契約マスタ T1 と 利用者マスタ T2 を結合して更新対象者の情報を取得する * * WHERE条件: * - T1.駐輪場ID = 処理0.駐輪場ID * - T1.更新可能日 <= 本日の日付 * - T1.解約フラグ = 0 * - T2.退会フラグ = 0 * - T1.授受フラグ = 1 * - T1.更新済フラグ is null * - 更新パターンによる有効期間Eの判定 * * @param object $park 駐輪場情報 * @param string $updatePattern 更新パターン("A" or "B") * @return array 定期更新対象者情報 */ private function getRegularUpdateTargetUsers($park, string $updatePattern): array { try { $now = Carbon::now(); $currentDate = $now->format('Y-m-d'); $todayDay = (int)$now->format('d'); // 本日の日(1-31) // DBから返る値は文字列なので、型変換して使用 $startDay = (int)$park->update_grace_period_start_date; // 例:"20" → 20 $endDay = (int)$park->update_grace_period_end_date; // 例:"6" → 6 // 有効期間E(契約終了日)の判定 $thisMonthEnd = $now->copy()->endOfMonth()->format('Y-m-d'); $lastMonthEnd = $now->copy()->subMonth()->endOfMonth()->format('Y-m-d'); $query = DB::table('regular_contract as T1') ->select([ 'T1.contract_id as 定期契約ID', 'T1.park_id as 駐輪場ID', 'T2.user_seq as 利用者ID', // user_seqが主キー '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_seq') // user_seqに結合 ->where('T1.park_id', $park->park_id) // 駐輪場ID ->where('T1.contract_updated_at', '<=', $currentDate) // 更新可能日 ->where('T1.contract_cancel_flag', 0) // 解約フラグ = 0 ->where('T2.user_quit_flag', 0) // 退会フラグ = 0 ->where('T1.contract_flag', 1) // 授受フラグ = 1 ->whereNull('T1.contract_renewal'); // 更新済フラグ is null // 仕様書:更新パターンによる有効期間Eの判定 if ($updatePattern === 'A') { // パターンA の場合: 有効期間E = 今月末 $query->where('T1.contract_periode', '=', $thisMonthEnd); } else { // パターンB の場合 if ($startDay <= $todayDay) { // 処理0.更新期間開始日 <= [本日の日付]の日 の場合 $query->where('T1.contract_periode', '=', $thisMonthEnd); } elseif ($endDay >= $todayDay) { // 処理0.更新期間終了日 >= [本日の日付]の日 の場合 $query->where('T1.contract_periode', '=', $lastMonthEnd); } } $targetUsers = $query->get()->toArray(); Log::info('定期更新対象者取得完了', [ 'park_id' => $park->park_id, 'update_pattern' => $updatePattern, 'this_month_end' => $thisMonthEnd, 'last_month_end' => $lastMonthEnd, 'target_users_count' => count($targetUsers) ]); return $targetUsers; } catch (\Exception $e) { Log::error('定期更新対象者取得エラー', [ 'park_id' => $park->park_id ?? 'unknown', 'update_pattern' => $updatePattern ?? 'unknown', 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); throw $e; } } /** * 【処理3】対象者の処理実行 * * 手動登録フラグによって処理を分岐: * - = 0 (ウェブ申込み): SHJ-7メール送信を呼び出し * - その他: オペレーターキュー追加処理 * * @param object $targetUser 対象者情報 * @param object $park 駐輪場情報 * @return array 処理結果 */ private function processTargetUser($targetUser, $park): array { try { $manualRegistFlag = $targetUser->手動登録フラグ ?? 1; if ($manualRegistFlag == 0) { // 仕様書:手動登録フラグ = 0(ウェブ申込み)の場合 // SHJ-7メール送信処理を呼び出し return $this->sendReminderMail($targetUser); } else { // 仕様書:手動登録フラグ <> 0 の場合 // オペレーターキュー追加処理 // ※文書には詳細仕様なし。他のService実装を参考に実装 return $this->addToOperatorQueue($targetUser, $park); } } catch (\Exception $e) { Log::error('対象者処理エラー', [ 'user_id' => $targetUser->利用者ID ?? 'unknown', 'contract_id' => $targetUser->定期契約ID ?? 'unknown', 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); 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 = 200 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 ); // SHJ-7仕様準拠: result === 0 が正常、それ以外は異常 if (($mailResult['result'] ?? 1) === 0) { // 仕様書:処理結果 = 0(正常)の場合 Log::info('メール送信成功', [ 'user_id' => $targetUser->利用者ID, 'contract_id' => $targetUser->定期契約ID ]); return [ 'type' => 'mail_success', 'success' => true, 'message' => 'メール送信成功', 'error_info' => null ]; } else { // 仕様書:その他の場合(異常) // バッチコメントに「処理2.定期契約ID」+「SHJ-7 メール送信.異常情報」を設定する(後ろに足す) // 仕様準拠: error_info を使用 $shjSevenErrorInfo = $mailResult['error_info'] ?? 'メール送信失敗'; $errorInfo = "定期契約ID:{$targetUser->定期契約ID} / SHJ-7 メール送信.異常情報:{$shjSevenErrorInfo}"; Log::warning('メール送信失敗', [ 'user_id' => $targetUser->利用者ID, 'contract_id' => $targetUser->定期契約ID, 'error_info' => $shjSevenErrorInfo ]); return [ 'type' => 'mail_error', 'success' => false, 'message' => 'メール送信失敗', 'error_info' => $errorInfo ]; } } catch (\Exception $e) { Log::error('リマインダーメール送信エラー', [ 'user_id' => $targetUser->利用者ID ?? 'unknown', 'contract_id' => $targetUser->定期契約ID ?? 'unknown', 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); // 仕様書準拠のエラー情報フォーマット $errorInfo = "定期契約ID:{$targetUser->定期契約ID} / SHJ-7 メール送信.異常情報:例外エラー - {$e->getMessage()}"; return [ 'type' => 'mail_error', 'success' => false, 'message' => 'メール送信例外エラー', 'error_info' => $errorInfo ]; } } /** * オペレーターキュー追加処理 * * 仕様書には詳細記載なし。 * 他のService(ShjOneService、ShjSixService)の実装を参考に実装。 * * @param object $targetUser 対象者情報 * @param object $park 駐輪場情報 * @return array 追加結果 */ private function addToOperatorQueue($targetUser, $park): array { try { // operator_queテーブルに登録 $operatorQue = OperatorQue::create([ 'que_class' => 5, // 定期更新通知(OperatorQueモデルの定数参照) 'user_id' => $targetUser->利用者ID, 'contract_id' => $targetUser->定期契約ID, 'park_id' => $targetUser->駐輪場ID, 'que_comment' => sprintf( '定期更新通知 / 契約ID:%s / 利用者:%s / 駐輪場:%s', $targetUser->定期契約ID, $targetUser->氏名 ?? '', $park->park_name ?? '' ), 'que_status' => 1, // キュー発生 'que_status_comment' => '', 'work_instructions' => '', 'operator_id' => 9999999, // 仕様書準拠:固定値(他Serviceと同様) 'created_at' => now(), 'updated_at' => now() ]); Log::info('オペレーターキュー追加成功', [ 'que_id' => $operatorQue->que_id, 'que_class' => 5, 'user_id' => $targetUser->利用者ID, 'contract_id' => $targetUser->定期契約ID, 'park_id' => $targetUser->駐輪場ID ]); return [ 'type' => 'queue_success', 'success' => true, 'message' => 'オペレーターキュー追加成功', 'que_id' => $operatorQue->que_id ]; } catch (\Exception $e) { Log::error('オペレーターキュー追加エラー', [ 'user_id' => $targetUser->利用者ID ?? 'unknown', 'contract_id' => $targetUser->定期契約ID ?? 'unknown', 'park_id' => $targetUser->駐輪場ID ?? 'unknown', 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'type' => 'queue_error', 'success' => false, 'message' => 'オペレーターキュー追加エラー: ' . $e->getMessage() ]; } } /** * 【処理4】SHJ-8バッチ処理ログ作成 * * 仕様書に基づくSHJ-8共通処理呼び出し * ※各駐輪場ごとに1回実行される * * @param object $park 駐輪場情報 * @param string $batchComment バッチコメント * @param int $mailSuccessCount メール正常終了件数 * @param int $mailErrorCount メール異常終了件数 * @param int $queueSuccessCount キュー登録正常終了件数 * @param int $queueErrorCount キュー登録異常終了件数 * @return void */ private function createShjBatchLog( $park, string $batchComment, int $mailSuccessCount, int $mailErrorCount, int $queueSuccessCount, int $queueErrorCount ): void { try { $device = Device::orderBy('device_id')->first(); $deviceId = $device ? $device->device_id : 1; // 仕様書:ステータスコメント生成 // 「内部変数.バッチコメント」+ "/" + 「処理1.駐輪場名」 // + ":メール正常終了件数" + 「内部変数.メール正常終了件数」 // + "、メール異常終了件数" + 「内部変数.メール異常終了件数」 // + "、キュー登録正常終了件数" + 「内部変数.キュー登録正常終了件数」 // + "、キュー登録異常終了件数" + 「内部変数.キュー登録異常終了件数」 $statusComment = ($batchComment ? $batchComment . ' / ' : '') . "{$park->park_name}:" . "メール正常終了件数={$mailSuccessCount}、" . "メール異常終了件数={$mailErrorCount}、" . "キュー登録正常終了件数={$queueSuccessCount}、" . "キュー登録異常終了件数={$queueErrorCount}"; $today = now()->format('Y/m/d'); Log::info('SHJ-8バッチ処理ログ作成', [ 'park_id' => $park->park_id, 'park_name' => $park->park_name, 'status_comment' => $statusComment ]); // SHJ-8サービスを呼び出し $this->shjEightService->execute( $deviceId, 'SHJ-3', 'SHJ-3定期更新リマインダー', 'success', $statusComment, $today, $today ); } catch (\Exception $e) { Log::error('SHJ-8バッチ処理ログ作成エラー', [ 'park_id' => $park->park_id ?? 'unknown', 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); // 仕様書:SHJ-8でエラーが発生してもメイン処理は継続 // エラーログのみ出力 } } /** * 全体の実行ログを記録する * * 駐輪場が0件の場合でも実行記録を残すための全体サマリーログ * * @param int $processedParksCount 処理した駐輪場数 * @param int $totalTargetUsers 対象者総数 * @param int $mailSuccessCount メール成功件数 * @param int $mailErrorCount メール失敗件数 * @param int $queueSuccessCount キュー成功件数 * @param int $queueErrorCount キュー失敗件数 * @return void */ private function createOverallBatchLog( int $processedParksCount, int $totalTargetUsers, int $mailSuccessCount, int $mailErrorCount, int $queueSuccessCount, int $queueErrorCount ): void { try { $device = Device::orderBy('device_id')->first(); $deviceId = $device ? $device->device_id : 1; // 全体サマリーのステータスコメント $statusComment = sprintf( '処理駐輪場数:%d、対象者総数:%d、メール成功:%d、メール失敗:%d、キュー追加:%d', $processedParksCount, $totalTargetUsers, $mailSuccessCount, $mailErrorCount, $queueSuccessCount + $queueErrorCount ); $today = now()->format('Y/m/d'); Log::info('SHJ-3 全体実行ログ作成', [ 'status_comment' => $statusComment ]); // SHJ-8サービスを呼び出し $this->shjEightService->execute( $deviceId, 'SHJ-3', 'SHJ-3定期更新リマインダー', 'success', $statusComment, $today, $today ); } catch (\Exception $e) { Log::error('SHJ-3 全体実行ログ作成エラー', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); } } }