select([ 'T1.park_id', // 駐輪場ID 'T2.park_name', // 駐輪場名 'T5.psection_id', // 車種区分ID 'T4.psection_subject', // 車種区分名 'T5.ptype_id', // 駐輪分類ID 'T3.ptype_subject', // 駐輪分類名 'T1.zone_id', // ゾーンID DB::raw('count(T1.contract_id) as cnt') // 契約台数 ]) // park テーブルとの JOIN ->join('park as T2', 'T1.park_id', '=', 'T2.park_id') // psection テーブルとの JOIN ->join('psection as T4', 'T1.psection_id', '=', 'T4.psection_id') // price_a テーブルとの複合条件 JOIN ->join('price_a as T5', function($join) { $join->on('T1.park_id', '=', 'T5.park_id') ->on('T1.price_parkplaceid', '=', 'T5.price_parkplaceid') ->on('T1.psection_id', '=', 'T5.psection_id'); }) // ptype テーブルとの JOIN ->join('ptype as T3', 'T5.ptype_id', '=', 'T3.ptype_id') ->where([ ['T1.contract_flag', '=', 1], // 有効契約 ['T2.park_close_flag', '=', 0], // 駐輪場未閉鎖 ]) // 契約有効期間内の条件 ->whereRaw("date_format(now(), '%y %m %d') BETWEEN T1.contract_periods AND T1.contract_periode") ->groupBy([ 'T1.park_id', 'T2.park_name', 'T5.psection_id', 'T4.psection_subject', 'T5.ptype_id', 'T3.ptype_subject', 'T1.zone_id' ]) ->get(); Log::info('SHJ-11 契約台数算出完了', [ 'count' => $query->count(), 'sql_conditions' => [ 'contract_flag' => 1, 'park_close_flag' => 0, 'contract_period_check' => 'BETWEEN contract_periods AND contract_periode' ] ]); return $query->toArray(); } catch (\Exception $e) { Log::error('SHJ-11 契約台数算出エラー', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); throw $e; } } /** * 【処理2・3】ゾーンマスタ管理処理 * * 処理フロー: * 1. ゾーンマスタを取得する * 2. 取得判定 → 存在しない場合は新規登録 * 3. 契約台数チェック(限界台数超過判定) * 4. 契約台数を反映する(ゾーンマスタ更新) * * @param array $contractCounts 契約台数集計結果 * @return array 処理結果 */ public function processZoneManagement(array $contractCounts): array { $createdZones = 0; $updatedZones = 0; $overCapacityCount = 0; $errors = []; $processParameters = []; try { DB::beginTransaction(); foreach ($contractCounts as $contractData) { try { // 【処理2】ゾーンマスタを取得する $zoneData = $this->getZoneData($contractData); if (!$zoneData) { // 【判断2】ゾーンマスタが存在しない場合 → 新規登録 $createResult = $this->createZoneData($contractData); if ($createResult['success']) { $createdZones++; } $zoneData = $createResult['zone_data']; } // 【判断3】契約台数チェック(限界台数超過判定) $isOverCapacity = $this->checkCapacityLimit($contractData, $zoneData); if ($isOverCapacity) { $overCapacityCount++; Log::warning('SHJ-11 限界台数超過検出', [ 'park_id' => $contractData->park_id, 'zone_id' => $contractData->zone_id, 'current_count' => $contractData->cnt, 'limit_capacity' => $zoneData->zone_tolerance ?? 0 ]); } // 【処理3】契約台数を反映する(ゾーンマスタ更新) $updateResult = $this->updateZoneContractCount($contractData); if ($updateResult['success']) { $updatedZones++; } // 処理パラメータ記録 $processParameters[] = [ 'park_id' => $contractData->park_id, 'psection_id' => $contractData->psection_id, 'ptype_id' => $contractData->ptype_id, 'zone_id' => $contractData->zone_id, 'contract_count' => $contractData->cnt, 'is_over_capacity' => $isOverCapacity, 'zone_created' => !$zoneData && $createResult['success'] ?? false, 'zone_updated' => $updateResult['success'] ?? false ]; } catch (\Exception $e) { $errors[] = [ 'park_id' => $contractData->park_id ?? null, 'zone_id' => $contractData->zone_id ?? null, 'error' => $e->getMessage() ]; Log::warning('SHJ-11 個別処理エラー', [ 'park_id' => $contractData->park_id ?? null, 'zone_id' => $contractData->zone_id ?? null, 'error' => $e->getMessage() ]); } } DB::commit(); return [ 'success' => true, 'created_zones' => $createdZones, 'updated_zones' => $updatedZones, 'over_capacity_count' => $overCapacityCount, 'parameters' => $processParameters, 'errors' => $errors, 'message' => '現在契約台数集計処理完了' ]; } catch (\Exception $e) { DB::rollBack(); Log::error('SHJ-11 ゾーンマスタ管理処理全体エラー', [ 'error' => $e->getMessage(), 'processed_count' => count($processParameters) ]); return [ 'success' => false, 'created_zones' => $createdZones, 'updated_zones' => $updatedZones, 'over_capacity_count' => $overCapacityCount, 'parameters' => $processParameters, 'errors' => $errors, 'message' => 'ゾーンマスタ管理処理エラー: ' . $e->getMessage(), 'details' => $e->getTraceAsString() ]; } } /** * ゾーンマスタデータ取得 * * 集計単位に対応するゾーンマスタを取得 * * @param object $contractData 契約台数集計データ * @return object|null ゾーンマスタデータ */ private function getZoneData($contractData) { try { return DB::table('zone') ->select([ 'zone_id', 'park_id', 'ptype_id', 'psection_id', 'zone_name', 'zone_number', // 現在契約台数 'zone_standard', // 標準収容台数 'zone_tolerance' // 限界収容台数 ]) ->where([ ['park_id', '=', $contractData->park_id], ['psection_id', '=', $contractData->psection_id], ['ptype_id', '=', $contractData->ptype_id], ['zone_id', '=', $contractData->zone_id] ]) ->first(); } catch (\Exception $e) { Log::error('SHJ-11 ゾーンマスタ取得エラー', [ 'park_id' => $contractData->park_id, 'zone_id' => $contractData->zone_id, 'error' => $e->getMessage() ]); throw $e; } } /** * ゾーンマスタ新規作成 * * 仕様書に基づくINSERT処理 * * @param object $contractData 契約台数集計データ * @return array 作成結果 */ private function createZoneData($contractData): array { try { // 新規ゾーンマスタのデフォルト値設定 $newZoneData = [ 'zone_id' => $contractData->zone_id, 'park_id' => $contractData->park_id, 'ptype_id' => $contractData->ptype_id, 'psection_id' => $contractData->psection_id, 'zone_name' => null, // デフォルトnull 'zone_number' => $contractData->cnt, // 算出した契約台数 'zone_standard' => null, // デフォルトnull 'zone_tolerance' => null, // デフォルトnull 'zone_sort' => null, // デフォルトnull 'delete_flag' => 0, // 削除フラグOFF 'created_at' => now(), 'updated_at' => now(), 'ope_id' => 9999999 // 仕様書指定値 ]; DB::table('zone')->insert($newZoneData); Log::info('SHJ-11 ゾーンマスタ新規作成完了', [ 'zone_id' => $contractData->zone_id, 'park_id' => $contractData->park_id, 'contract_count' => $contractData->cnt ]); return [ 'success' => true, 'zone_data' => (object) $newZoneData, 'message' => 'ゾーンマスタを新規作成しました' ]; } catch (\Exception $e) { Log::error('SHJ-11 ゾーンマスタ新規作成エラー', [ 'zone_id' => $contractData->zone_id, 'park_id' => $contractData->park_id, 'error' => $e->getMessage() ]); return [ 'success' => false, 'zone_data' => null, 'message' => 'ゾーンマスタ新規作成エラー: ' . $e->getMessage() ]; } } /** * 契約台数限界チェック * * 【判断3】契約台数 > 限界収容台数の判定 * * @param object $contractData 契約台数集計データ * @param object|null $zoneData ゾーンマスタデータ * @return bool 限界台数超過フラグ */ private function checkCapacityLimit($contractData, $zoneData = null): bool { if (!$zoneData || is_null($zoneData->zone_tolerance)) { // ゾーンデータが存在しないか、限界収容台数が未設定の場合は超過判定しない return false; } // 契約台数 > 限界収容台数の判定 return $contractData->cnt > $zoneData->zone_tolerance; } /** * ゾーンマスタ契約台数更新 * * 【処理3】現在契約台数をゾーンマスタに反映 * * @param object $contractData 契約台数集計データ * @return array 更新結果 */ private function updateZoneContractCount($contractData): array { try { $updateData = [ 'zone_number' => $contractData->cnt, // 現在契約台数を更新 'updated_at' => now(), // 更新日時 'ope_id' => 'SHJ-11' // 更新オペレータID ]; $updated = DB::table('zone') ->where([ ['park_id', '=', $contractData->park_id], ['psection_id', '=', $contractData->psection_id], ['ptype_id', '=', $contractData->ptype_id], ['zone_id', '=', $contractData->zone_id] ]) ->update($updateData); if ($updated > 0) { Log::info('SHJ-11 ゾーンマスタ更新完了', [ 'zone_id' => $contractData->zone_id, 'park_id' => $contractData->park_id, 'new_contract_count' => $contractData->cnt ]); return [ 'success' => true, 'message' => 'ゾーンマスタ契約台数を更新しました' ]; } else { return [ 'success' => false, 'message' => 'ゾーンマスタ更新対象が見つかりません' ]; } } catch (\Exception $e) { Log::error('SHJ-11 ゾーンマスタ更新エラー', [ 'zone_id' => $contractData->zone_id, 'park_id' => $contractData->park_id, 'error' => $e->getMessage() ]); return [ 'success' => false, 'message' => 'ゾーンマスタ更新エラー: ' . $e->getMessage() ]; } } /** * 【処理4】バッチ処理ログを作成する * * 統一BatchLogシステムを使用してSHJ-11の実行ログを記録 * * @param string $status ステータス * @param array $parameters パラメータ * @param string $message メッセージ * @param int $executionCount 実行回数 * @param int $successCount 成功回数 * @param int $errorCount エラー回数 * @return void */ public function createBatchLog( string $status, array $parameters, string $message, int $executionCount = 0, int $successCount = 0, int $errorCount = 0 ): void { try { BatchLog::createBatchLog( 'SHJ-11', $status, $parameters, $message, [ 'execution_count' => $executionCount, 'success_count' => $successCount, 'error_count' => $errorCount, 'process_type' => '現在契約台数集計', 'executed_at' => now()->toISOString() ] ); } catch (\Exception $e) { Log::error('SHJ-11 バッチログ作成エラー', [ 'error' => $e->getMessage(), 'status' => $status, 'message' => $message ]); } } }