shjEightService = $shjEightService; } /** * SHJ-9 売上集計処理メイン実行(日次のみ) * * 処理フロー (todo/SHJ-9/SHJ-9.txt): * 【処理1】集計対象を設定する * 【処理2】駐輪場マスタを取得する * 【判断1】取得件数判定 * 【処理3】車種区分毎に算出する * 【判断2】取得判定 * 【処理4】売上集計結果を削除→登録する * 【処理5】オペレータキュー作成およびバッチ処理ログを作成する * * @param string $type 集計種別(daily 固定) * @param string $aggregationDate 集計対象日(YYYY-MM-DD) * @return array 処理結果 */ public function executeEarningsAggregation(string $type, string $aggregationDate): array { $statusComments = []; // 内部変数.ステータスコメント $allDataIntegrity = []; // 内部変数.情報不備(なし含む全件) $dataIntegrityIssues = []; // オペレータキュー作成用(NULL以外) try { // 【処理1】集計対象を設定する // パラメーター検証(日付形式チェック) if (!$this->isValidDateFormat($aggregationDate)) { // 日付形式エラー時は【処理5】へ(仕様JOB1:ステータスコメント設定→JOB5) $statusComment = "売上集計(日次):パラメーターが不正です。(日付形式ではありません)"; // 仕様JOB5:情報不備がNULL→オペレータキュー作成しない(日付エラーは情報不備ではない) // SHJ-8 バッチ処理ログ作成(仕様JOB5:ステータスは常にsuccess) $shjEightResult = $this->callShjEight('SHJ-9売上集計(日次)', 'success', $statusComment); $this->evaluateShjEightResult($shjEightResult); return [ 'success' => true, // 仕様上はwarningで成功扱い 'message' => $statusComment, 'processed_parks' => 0, 'summary_records' => 0 ]; } $targetDate = Carbon::parse($aggregationDate)->format('Y-m-d'); Log::info('SHJ-9 売上集計処理開始', [ 'type' => $type, 'target_date' => $targetDate ]); // 【処理2】駐輪場マスタを取得する $parkInfo = $this->getParkInformation(); // 【判断1】取得件数判定 if (empty($parkInfo)) { $statusComment = '売上集計(日次):駐輪場マスタが存在していません。'; // 仕様JOB2-STEP1:情報不備がNULL→オペレータキュー作成しない // SHJ-8 バッチ処理ログ作成(仕様JOB5:ステータスは常にsuccess) $shjEightResult = $this->callShjEight('SHJ-9売上集計(日次)', 'success', $statusComment); $this->evaluateShjEightResult($shjEightResult); return [ 'success' => true, 'message' => $statusComment, 'processed_parks' => 0, 'summary_records' => 0 ]; } // 仕様JOB3/JOB4:車種区分毎に算出→売上集計結果を登録 $summaryRecords = 0; $processedParks = 0; foreach ($parkInfo as $park) { $result = $this->processEarningsForPark($park, $targetDate); $processedParks++; $summaryRecords += $result['summary_records']; // 仕様JOB4:レコード毎のステータスコメントを収集 if (!empty($result['status_comments'])) { $statusComments = array_merge($statusComments, $result['status_comments']); } // 仕様JOB3-STEP1:対象データなしの場合のステータスコメント if (!empty($result['no_data_message'])) { $statusComments[] = $result['no_data_message']; } // 仕様JOB5:全parkの情報不備を収集(なし含む) $allDataIntegrity[] = $result['data_integrity_issue']; // 仕様JOB5:NULL以外の場合にオペレータキューを登録 if ($result['data_integrity_issue'] !== null) { $dataIntegrityIssues[] = [ 'park_id' => $park->park_id, 'message' => $result['data_integrity_issue'] ]; } } // 仕様JOB5:情報不備がNULL以外の場合、オペレータキューを登録 foreach ($dataIntegrityIssues as $issue) { $this->createOperatorQueue($issue['message'], $issue['park_id']); } if (!empty($dataIntegrityIssues)) { Log::warning('SHJ-9 情報不備検出', [ 'issues' => $dataIntegrityIssues ]); } // 仕様JOB5:ステータスコメント = 内部変数.ステータスコメント + 内部変数.情報不備(なし含む全件) $allParts = array_merge($statusComments, $allDataIntegrity); $finalStatusComment = implode("\n", $allParts); Log::info('SHJ-9 完全ステータスコメント', ['status_comment' => $finalStatusComment]); // 仕様JOB5:SHJ-8 バッチ処理ログ作成(ステータスは常にsuccess) $shjEightResult = $this->callShjEight('SHJ-9売上集計(日次)', 'success', $finalStatusComment); $this->evaluateShjEightResult($shjEightResult); Log::info('SHJ-9 売上集計処理完了', [ 'processed_parks' => $processedParks, 'summary_records' => $summaryRecords, 'data_integrity_issues' => count($dataIntegrityIssues) ]); return [ 'success' => true, 'message' => 'SHJ-9 売上集計処理が正常に完了しました', 'processed_parks' => $processedParks, 'summary_records' => $summaryRecords, 'data_integrity_issues' => count($dataIntegrityIssues) ]; } catch (\Exception $e) { $errorMessage = '売上集計(日次):エラー発生 - ' . $e->getMessage(); // SHJ-8 バッチ処理ログ作成(エラー時も作成) try { $shjEightResult = $this->callShjEight('SHJ-9売上集計(日次)', 'success', $errorMessage); $this->evaluateShjEightResult($shjEightResult); } catch (\Exception $shjException) { Log::error('SHJ-8呼び出しエラー', ['error' => $shjException->getMessage()]); } Log::error('SHJ-9 売上集計処理エラー', [ 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => $errorMessage, 'details' => $e->getMessage() ]; } } /** * 日付形式の検証(厳格:YYYY-MM-DD形式のみ許可) * * @param string $date 日付文字列 * @return bool 有効な日付形式かどうか */ private function isValidDateFormat(string $date): bool { // YYYY-MM-DD形式の正規表現チェック if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) { return false; } // 実際の日付として有効かチェック $dateParts = explode('-', $date); return checkdate((int)$dateParts[1], (int)$dateParts[2], (int)$dateParts[0]); } /** * 【処理2】駐輪場マスタを取得する * * @return array 駐輪場情報 */ private function getParkInformation(): array { try { $parkInfo = DB::table('park') ->select(['park_id', 'park_name']) ->where('park_close_flag', '<>', 1) ->orderBy('park_ruby') ->get() ->toArray(); Log::info('駐輪場マスタ取得完了', [ 'park_count' => count($parkInfo) ]); return $parkInfo; } catch (\Exception $e) { Log::error('駐輪場マスタ取得エラー', [ 'error' => $e->getMessage() ]); throw $e; } } /** * 駐輪場毎の売上集計処理 * * @param object $park 駐輪場情報 * @param string $targetDate 集計対象日(YYYY-MM-DD) * @return array 処理結果 */ private function processEarningsForPark($park, string $targetDate): array { try { // 仕様JOB3-0:情報不備チェック(SQL-2) $dataIntegrityIssue = $this->checkDataIntegrity($park->park_id, $targetDate); // 仕様JOB3-①:定期契約データ取得(車種区分・分類名1・定期有効月数毎) $regularData = $this->calculateRegularEarnings($park->park_id, $targetDate); // 仕様JOB3-②:一時金データ取得(車種毎) $lumpsumData = $this->calculateLumpsumEarnings($park->park_id, $targetDate); // 仕様JOB3-③:解約返戻金データ取得(車種区分毎) $refundData = $this->calculateRefundEarnings($park->park_id, $targetDate); // 仕様JOB3-④:再発行データ取得(車種区分毎) $reissueData = $this->calculateReissueCount($park->park_id, $targetDate); // 仕様JOB3-STEP1:①②③④のデータがいずれかあれば→JOB4へ if (empty($regularData) && empty($lumpsumData) && empty($refundData) && empty($reissueData)) { // 仕様JOB3-STEP1:対象データなし $noDataMessage = "売上集計(日次):対象日:{$targetDate}/駐輪場:{$park->park_name}:売上データが存在しません。"; return [ 'summary_records' => 0, 'data_integrity_issue' => $dataIntegrityIssue, 'no_data_message' => $noDataMessage, 'status_comments' => [] ]; } // 仕様JOB4:売上集計結果を登録(同一キーの既存レコードは各insert前に削除) $summaryRecords = 0; $statusComments = []; // ① 定期契約データ:同じ組合せ(psection×usertype×months)を統合 $mergedRegularData = $this->mergeRegularDataByGroup($regularData); foreach ($mergedRegularData as $key => $mergedRow) { $sc = $this->createEarningsSummary($park, $mergedRow, $targetDate, 'regular', $dataIntegrityIssue); $statusComments[] = $sc; $summaryRecords++; } // ②③④ 一時金・解約・再発行データ(車種区分毎に集約) $otherDataByPsection = $this->mergeOtherEarningsData($lumpsumData, $refundData, $reissueData); foreach ($otherDataByPsection as $psectionId => $data) { $sc = $this->createEarningsSummary($park, $data, $targetDate, 'other', null); $statusComments[] = $sc; $summaryRecords++; } Log::info('駐輪場売上集計完了', [ 'park_id' => $park->park_id, 'park_name' => $park->park_name, 'summary_records' => $summaryRecords, 'data_integrity_issue' => $dataIntegrityIssue ]); return [ 'summary_records' => $summaryRecords, 'data_integrity_issue' => $dataIntegrityIssue, 'no_data_message' => null, 'status_comments' => $statusComments ]; } catch (\Exception $e) { Log::error('駐輪場売上集計エラー', [ 'park_id' => $park->park_id, 'error' => $e->getMessage() ]); throw $e; } } /** * 0. 情報不備チェック * * 仕様 todo/SHJ-9/SHJ-9.txt:44-68 * * @param int $parkId 駐輪場ID * @param string $targetDate 集計対象日(YYYY-MM-DD) * @return string 情報不備メッセージ(仕様フォーマット:"情報不備:xxx" or "情報不備:なし") */ private function checkDataIntegrity(int $parkId, string $targetDate): string { // 仕様SQL-2:情報不備チェック(ログ吐き出し) $incompleteContracts = DB::table('regular_contract') ->select(['contract_id', 'contract_reduction', 'update_flag', 'psection_id', 'enable_months']) ->where('park_id', $parkId) ->where('contract_flag', 1) ->whereDate('contract_payment_day', '=', $targetDate) ->where(function($query) { $query->whereNull('update_flag') ->orWhereNull('psection_id') ->orWhereNull('enable_months'); }) ->get() ->toArray(); if (empty($incompleteContracts)) { return self::DATA_INTEGRITY_NONE; } // 仕様SQL-2:ログ吐き出し(詳細情報を出力) Log::warning('SHJ-9 情報不備契約詳細', [ 'park_id' => $parkId, 'target_date' => $targetDate, 'contracts' => $incompleteContracts ]); // 仕様フォーマット:" 情報不備:" + 契約IDカンマ区切り(全角スペース付き) $contractIds = array_map(function($c) { return is_object($c) ? $c->contract_id : $c['contract_id']; }, $incompleteContracts); return ' 情報不備:' . implode(',', $contractIds); } /** * ① 定期契約データ取得(車種区分・分類名1・定期有効月数毎) * * 仕様 todo/SHJ-9/SHJ-9.txt:70-95 * SQL定義:減免措置・継続フラグ・車種区分・分類名・有効月数でグループ化し、 * 授受金額の合計と件数を算出する * * @param int $parkId 駐輪場ID * @param string $targetDate 集計対象日(YYYY-MM-DD) * @return array */ private function calculateRegularEarnings(int $parkId, string $targetDate): array { $results = DB::table('regular_contract as T1') ->join('usertype as T3', 'T1.user_categoryid', '=', 'T3.user_categoryid') ->select([ DB::raw('IFNULL(T1.contract_reduction, 0) as contract_reduction'), 'T1.update_flag', 'T1.psection_id', 'T3.usertype_subject1', 'T1.enable_months', DB::raw('SUM(T1.contract_money) as total_amount'), // 仕様line 77: 授受金額の合計 DB::raw('COUNT(T1.contract_money) as contract_count') // 仕様line 78: 授受件数 ]) ->where('T1.park_id', $parkId) ->where('T1.contract_flag', 1) ->whereDate('T1.contract_payment_day', '=', $targetDate) ->whereNotNull('T1.update_flag') ->whereNotNull('T1.psection_id') ->whereNotNull('T1.enable_months') ->groupBy([ DB::raw('IFNULL(T1.contract_reduction, 0)'), 'T1.update_flag', 'T1.psection_id', 'T3.usertype_subject1', 'T1.enable_months' ]) ->get(); return $results->toArray(); } /** * ② 一時金データ取得(車種毎) * * 仕様 todo/SHJ-9/SHJ-9.txt:114-125 * * @param int $parkId 駐輪場ID * @param string $targetDate 集計対象日(YYYY-MM-DD) * @return array */ private function calculateLumpsumEarnings(int $parkId, string $targetDate): array { $results = DB::table('lumpsum_transaction') ->select([ 'type_class as psection_id', DB::raw('COUNT(*) as lumpsum_count'), DB::raw('COALESCE(SUM(deposit_amount), 0) as lumpsum') ]) ->where('park_id', $parkId) ->whereDate('pay_date', '=', $targetDate) ->groupBy('type_class') ->get(); return $results->toArray(); } /** * ③ 解約返戻金データ取得(車種区分毎) * * 仕様 todo/SHJ-9/SHJ-9.txt:126-137 * * @param int $parkId 駐輪場ID * @param string $targetDate 集計対象日(YYYY-MM-DD) * @return array */ private function calculateRefundEarnings(int $parkId, string $targetDate): array { $results = DB::table('regular_contract') ->select([ 'psection_id', DB::raw('COALESCE(SUM(refunds), 0) as refunds') ]) ->where('park_id', $parkId) ->where('contract_cancel_flag', 1) ->whereDate('repayment_at', '=', $targetDate) ->groupBy('psection_id') ->get(); return $results->toArray(); } /** * ④ 再発行データ取得(車種区分毎) * * 仕様 todo/SHJ-9/SHJ-9.txt:138-149 * * @param int $parkId 駐輪場ID * @param string $targetDate 集計対象日(YYYY-MM-DD) * @return array */ private function calculateReissueCount(int $parkId, string $targetDate): array { $results = DB::table('seal') ->select([ 'psection_id', DB::raw('COUNT(contract_id) as reissue_count') ]) ->where('park_id', $parkId) ->where('contract_seal_issue', '>=', 2) ->whereDate('seal_day', '=', $targetDate) ->groupBy('psection_id') ->get(); return $results->toArray(); } /** * 定期契約データを組合せ毎に統合 * * SQLは contract_reduction × update_flag で分組しているため、 * 同じ psection × usertype × months の組合せで複数行が返る場合がある。 * ここで park_id + psection_id + usertype_subject1 + enable_months をキーに統合し、 * 新規/更新 × 減免/通常 の各件数・金額を1つのオブジェクトに集約する。 * * 仕様 todo/SHJ-9/SHJ-9.txt:96-113 * * @param array $regularData calculateRegularEarnings()の結果 * @return array キー:psection_id|usertype|months、値:統合されたデータオブジェクト */ private function mergeRegularDataByGroup(array $regularData): array { $merged = []; foreach ($regularData as $row) { // 統合キー:psection_id|usertype_subject1|enable_months $key = $row->psection_id . '|' . $row->usertype_subject1 . '|' . $row->enable_months; // 初回作成 if (!isset($merged[$key])) { $merged[$key] = (object)[ 'psection_id' => $row->psection_id, 'usertype_subject1' => $row->usertype_subject1, 'enable_months' => $row->enable_months, // 新規・通常 'regular_new_count' => 0, 'regular_new_amount' => 0, // 新規・減免 'regular_new_reduction_count' => 0, 'regular_new_reduction_amount' => 0, // 更新・通常 'regular_update_count' => 0, 'regular_update_amount' => 0, // 更新・減免 'regular_update_reduction_count' => 0, 'regular_update_reduction_amount' => 0 ]; } // 区分判定 $isNew = in_array($row->update_flag, [2, null]); // 新規 $isReduction = ($row->contract_reduction == 1); // 減免 $count = $row->contract_count ?? 0; $amount = $row->total_amount ?? 0; // 対応するフィールドに累加 if ($isNew && !$isReduction) { // 新規・通常 $merged[$key]->regular_new_count += $count; $merged[$key]->regular_new_amount += $amount; } elseif ($isNew && $isReduction) { // 新規・減免 $merged[$key]->regular_new_reduction_count += $count; $merged[$key]->regular_new_reduction_amount += $amount; } elseif (!$isNew && !$isReduction) { // 更新・通常 $merged[$key]->regular_update_count += $count; $merged[$key]->regular_update_amount += $amount; } elseif (!$isNew && $isReduction) { // 更新・減免 $merged[$key]->regular_update_reduction_count += $count; $merged[$key]->regular_update_reduction_amount += $amount; } } return $merged; } /** * 一時金・解約・再発行データを車種区分毎に統合 * * @param array $lumpsumData * @param array $refundData * @param array $reissueData * @return array */ private function mergeOtherEarningsData(array $lumpsumData, array $refundData, array $reissueData): array { $merged = []; // 一時金 foreach ($lumpsumData as $row) { $psectionId = $row->psection_id; if (!isset($merged[$psectionId])) { $merged[$psectionId] = (object)[ 'psection_id' => $psectionId, 'usertype_subject1' => null, 'enable_months' => 0, 'lumpsum_count' => 0, 'lumpsum' => 0, 'refunds' => 0, 'reissue_count' => 0 ]; } $merged[$psectionId]->lumpsum_count = $row->lumpsum_count; $merged[$psectionId]->lumpsum = $row->lumpsum; } // 解約返戻金 foreach ($refundData as $row) { $psectionId = $row->psection_id; if (!isset($merged[$psectionId])) { $merged[$psectionId] = (object)[ 'psection_id' => $psectionId, 'usertype_subject1' => null, 'enable_months' => 0, 'lumpsum_count' => 0, 'lumpsum' => 0, 'refunds' => 0, 'reissue_count' => 0 ]; } $merged[$psectionId]->refunds = $row->refunds; } // 再発行 foreach ($reissueData as $row) { $psectionId = $row->psection_id; if (!isset($merged[$psectionId])) { $merged[$psectionId] = (object)[ 'psection_id' => $psectionId, 'usertype_subject1' => null, 'enable_months' => 0, 'lumpsum_count' => 0, 'lumpsum' => 0, 'refunds' => 0, 'reissue_count' => 0 ]; } $merged[$psectionId]->reissue_count = $row->reissue_count; } return $merged; } /** * 車種区分名を取得 * * @param int|null $psectionId 車種区分ID * @return string 車種区分名 */ private function getPsectionName(?int $psectionId): string { if ($psectionId === null) { return ''; } $name = DB::table('psection') ->where('psection_id', $psectionId) ->value('psection_subject'); return $name ?? ''; } /** * 仕様JOB4:売上集計結果を削除→登録 * * 同一キー(駐車場ID,集計種別,集計開始日,集計終了日,売上日付,車種区分,分類名1,定期有効月数) * が既に登録済みの場合削除した上で、新規レコードを登録する。 * * @param object $park 駐輪場情報 * @param object $data 売上データ * @param string $targetDate 集計対象日(YYYY-MM-DD) * @param string $dataType データ種別(regular or other) * @param string|null $dataIntegrityIssue 情報不備メッセージ(regularのみ使用) * @return string 仕様JOB4形式のステータスコメント */ private function createEarningsSummary($park, $data, string $targetDate, string $dataType, ?string $dataIntegrityIssue = null): string { $usertypeSubject1 = $data->usertype_subject1 ?? null; $enableMonths = $data->enable_months ?? 0; // 仕様JOB4:同一キーの既存レコードを削除 $deleteQuery = DB::table('earnings_summary') ->where('park_id', $park->park_id) ->where('summary_type', self::SUMMARY_TYPE_DAILY) ->whereNull('summary_start_date') ->whereNull('summary_end_date') ->where('earnings_date', $targetDate); // NULL値対応:psection_idがnullの場合はwhereNull if ($data->psection_id === null) { $deleteQuery->whereNull('psection_id'); } else { $deleteQuery->where('psection_id', $data->psection_id); } // NULL値対応:usertype_subject1がnullの場合はwhereNull if ($usertypeSubject1 === null) { $deleteQuery->whereNull('usertype_subject1'); } else { $deleteQuery->where('usertype_subject1', $usertypeSubject1); } $deleteQuery->where('enable_months', $enableMonths); $deleteQuery->delete(); // 仕様:集計備考の生成 if ($dataType === 'regular' && $dataIntegrityIssue !== null) { // 仕様JOB3-①:定期データのsummary_noteには情報不備を含める $summaryNote = "SHJ-9:{$targetDate}{$dataIntegrityIssue}"; } else { // 仕様JOB3-②③④:otherデータのsummary_note $summaryNote = "SHJ-9:{$targetDate}"; } $insertData = [ 'park_id' => $park->park_id, 'summary_type' => self::SUMMARY_TYPE_DAILY, 'summary_start_date' => null, 'summary_end_date' => null, 'earnings_date' => $targetDate, 'psection_id' => $data->psection_id, 'usertype_subject1' => $usertypeSubject1, 'enable_months' => $enableMonths, 'summary_note' => $summaryNote, 'created_at' => now(), 'updated_at' => now(), 'operator_id' => self::BATCH_OPERATOR_ID ]; if ($dataType === 'regular') { // 仕様JOB3-①:定期契約データ $insertData = array_merge($insertData, [ 'regular_new_count' => $data->regular_new_count ?? 0, 'regular_new_amount' => $data->regular_new_amount ?? 0, 'regular_new_reduction_count' => $data->regular_new_reduction_count ?? 0, 'regular_new_reduction_amount' => $data->regular_new_reduction_amount ?? 0, 'regular_update_count' => $data->regular_update_count ?? 0, 'regular_update_amount' => $data->regular_update_amount ?? 0, 'regular_update_reduction_count' => $data->regular_update_reduction_count ?? 0, 'regular_update_reduction_amount' => $data->regular_update_reduction_amount ?? 0, 'lumpsum_count' => 0, 'lumpsum' => 0, 'refunds' => 0, 'other_income' => 0, 'other_spending' => 0, 'reissue_count' => 0, 'reissue_amount' => 0 ]); } else { // 仕様JOB3-②③④:一時金・解約・再発行データ(定期フィールドは0固定) $insertData = array_merge($insertData, [ 'regular_new_count' => 0, 'regular_new_amount' => 0, 'regular_new_reduction_count' => 0, 'regular_new_reduction_amount' => 0, 'regular_update_count' => 0, 'regular_update_amount' => 0, 'regular_update_reduction_count' => 0, 'regular_update_reduction_amount' => 0, 'lumpsum_count' => $data->lumpsum_count ?? 0, 'lumpsum' => $data->lumpsum ?? 0, 'refunds' => $data->refunds ?? 0, 'other_income' => 0, 'other_spending' => 0, 'reissue_count' => $data->reissue_count ?? 0, 'reissue_amount' => 0 ]); } DB::table('earnings_summary')->insert($insertData); // 仕様JOB4:レコード毎のステータスコメント生成(全データ型共通フォーマット) $psectionName = $this->getPsectionName($data->psection_id); $displayUsertype = $usertypeSubject1 ?? ''; $statusComment = "売上集計(日次):対象日:{$targetDate}/駐輪場:{$park->park_name}/車種区分:{$psectionName}/分類名1:{$displayUsertype}/定期有効月数:{$enableMonths}"; Log::debug('売上集計結果登録', [ 'park_id' => $park->park_id, 'psection_id' => $data->psection_id, 'data_type' => $dataType, 'target_date' => $targetDate ]); return $statusComment; } /** * 【処理5】オペレータキュー作成(駐輪場単位・情報不備がある場合のみ) * * 仕様 todo/SHJ-9/SHJ-9.txt:253-280 * - que_class: 14(集計対象エラー) * - que_comment: 空文字("") * - que_status: 1(キュー発生) * - que_status_comment: 空文字("") * - work_instructions: 情報不備メッセージ * - park_id: 駐輪場ID(仕様 "処理1.駐輪場ID"、パラメータエラー時はnull) * - operator_id: 9999999(バッチ処理固定値) * * @param string $message 情報不備メッセージ * @param int|null $parkId 駐輪場ID(パラメータエラー時はnull) * @return void */ private function createOperatorQueue(string $message, ?int $parkId = null): void { try { DB::table('operator_que')->insert([ 'que_class' => 14, // 集計対象エラー 'user_id' => null, 'contract_id' => null, 'park_id' => $parkId, // 仕様:処理1.駐輪場ID 'que_comment' => '', // 仕様line 260: "" 'que_status' => 1, // キュー発生 'que_status_comment' => '', // 仕様line 262: "" 'work_instructions' => $message, // 仕様line 263: 情報不備 'operator_id' => self::BATCH_OPERATOR_ID, // 9999999 'created_at' => now(), 'updated_at' => now() ]); Log::info('オペレータキュー作成完了', [ 'park_id' => $parkId, 'que_class' => 14, 'que_status' => 1, 'operator_id' => self::BATCH_OPERATOR_ID, 'work_instructions' => $message ]); } catch (\Exception $e) { Log::error('オペレータキュー作成エラー', [ 'park_id' => $parkId, 'error' => $e->getMessage() ]); } } /** * SHJ-8 バッチ処理ログ作成 * * 仕様 todo/SHJ-9/SHJ-9.txt:289-300 * 共通処理「SHJ-8 バッチ処理ログ作成」を呼び出す * * @param string $jobName ジョブ名 * @param string $status ステータス (success/error) * @param string $statusComment 業務固有のステータスコメント * @return array SHJ-8実行結果 */ private function callShjEight(string $jobName, string $status, string $statusComment): array { try { $device = Device::orderBy('device_id')->first(); $deviceId = $device ? $device->device_id : 1; $today = now()->format('Y/m/d'); $result = $this->shjEightService->execute( $deviceId, 'SHJ-9', $jobName, $status, $statusComment, $today, $today ); Log::info('SHJ-8 バッチ処理ログ作成完了', [ 'job_name' => $jobName, 'status' => $status, 'shj8_result' => $result['result'] ?? null ]); return $result; } catch (\Exception $e) { Log::error('SHJ-8 バッチ処理ログ作成エラー', [ 'error' => $e->getMessage(), 'job_name' => $jobName, 'status_comment' => $statusComment ]); throw $e; } } /** * SHJ-8実行結果の判定 * * 仕様JOB5の判定(処理結果=0/その他)をログで明示する。 * * @param array $shjEightResult SHJ-8返却値 * @return void */ private function evaluateShjEightResult(array $shjEightResult): void { if ((int)($shjEightResult['result'] ?? 1) === 0) { Log::info('SHJ-9 SHJ-8処理結果判定: 0(正常)'); return; } Log::warning('SHJ-9 SHJ-8処理結果判定: 0以外(異常)', [ 'shj8_result' => $shjEightResult ]); } }