700 lines
30 KiB
PHP
700 lines
30 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Log;
|
||
use App\Models\OperatorQue;
|
||
use App\Models\Device;
|
||
use Exception;
|
||
|
||
/**
|
||
* SHJ-5 空き待ち通知処理サービス
|
||
*
|
||
* 駐輪場の空き状況を確認し、空き待ち予約者への通知処理を実行する
|
||
* 仕様書に基づくバックグラウンド定期バッチ処理
|
||
*/
|
||
class ShjFiveService
|
||
{
|
||
/**
|
||
* ShjEightService
|
||
*
|
||
* @var ShjEightService
|
||
*/
|
||
protected $shjEightService;
|
||
|
||
/**
|
||
* コンストラクタ
|
||
*
|
||
* @param ShjEightService $shjEightService
|
||
*/
|
||
public function __construct(ShjEightService $shjEightService)
|
||
{
|
||
$this->shjEightService = $shjEightService;
|
||
}
|
||
/**
|
||
* SHJ-5 メイン処理を実行
|
||
*
|
||
* 処理フロー:
|
||
* 1. 駐輪場の空き状況を取得する
|
||
* 2. 空き状況判定
|
||
* 3. 空き待ち者の情報を取得する
|
||
* 4. 取得件数判定
|
||
* 5. 空き待ち者への通知、またはオペレーターキュー追加処理
|
||
* 6. バッチ処理ログを作成する
|
||
*
|
||
* @return array 処理結果
|
||
*/
|
||
public function executeParkVacancyNotification(): array
|
||
{
|
||
try {
|
||
$startTime = now();
|
||
Log::info('SHJ-5 空き待ち通知処理開始');
|
||
|
||
// 処理統計
|
||
$processedParksCount = 0;
|
||
$vacantParksCount = 0;
|
||
$totalWaitingUsers = 0;
|
||
$notificationSuccessCount = 0;
|
||
$operatorQueueCount = 0;
|
||
$mailErrors = []; // メール異常終了件数専用
|
||
$errors = []; // 全体エラー収集用
|
||
$allQueueItems = []; // 全オペレーターキュー作成用データ
|
||
|
||
// 【処理1】駐輪場の空き状況を取得する
|
||
$parkVacancyList = $this->getParkVacancyStatus();
|
||
Log::info('駐輪場空き状況取得完了', [
|
||
'total_parks' => count($parkVacancyList)
|
||
]);
|
||
|
||
// 各駐輪場に対する処理
|
||
foreach ($parkVacancyList as $parkVacancyData) {
|
||
// 配列をオブジェクトに変換
|
||
$parkVacancy = (object) $parkVacancyData;
|
||
$processedParksCount++;
|
||
|
||
Log::info('駐輪場処理開始', [
|
||
'park_id' => $parkVacancy->park_id,
|
||
'park_name' => $parkVacancy->park_name,
|
||
'psection_id' => $parkVacancy->psection_id,
|
||
'ptype_id' => $parkVacancy->ptype_id,
|
||
'vacant_count' => $parkVacancy->vacant_count
|
||
]);
|
||
|
||
// 【判断1】空き状況判定
|
||
if ($parkVacancy->vacant_count < 1) {
|
||
Log::info('空きなし - 処理スキップ', [
|
||
'park_id' => $parkVacancy->park_id,
|
||
'vacant_count' => $parkVacancy->vacant_count
|
||
]);
|
||
continue;
|
||
}
|
||
|
||
$vacantParksCount++;
|
||
|
||
// 【処理2】空き待ち者の情報を取得する
|
||
$waitingUsers = $this->getWaitingUsersInfo(
|
||
$parkVacancy->park_id,
|
||
$parkVacancy->psection_id,
|
||
$parkVacancy->ptype_id
|
||
);
|
||
|
||
// 【判断2】取得件数判定
|
||
if (empty($waitingUsers)) {
|
||
Log::info('空き待ち者なし', [
|
||
'park_id' => $parkVacancy->park_id
|
||
]);
|
||
continue;
|
||
}
|
||
|
||
$totalWaitingUsers += count($waitingUsers);
|
||
Log::info('空き待ち者情報取得完了', [
|
||
'park_id' => $parkVacancy->park_id,
|
||
'waiting_users_count' => count($waitingUsers)
|
||
]);
|
||
|
||
// 【処理3】空き待ち者への通知、またはオペレーターキュー追加処理
|
||
$notificationResult = $this->processWaitingUsersNotification(
|
||
$waitingUsers,
|
||
$parkVacancy
|
||
);
|
||
|
||
$notificationSuccessCount += $notificationResult['notification_success_count'];
|
||
$operatorQueueCount += $notificationResult['operator_queue_count'];
|
||
|
||
if (!empty($notificationResult['errors'])) {
|
||
$mailErrors = array_merge($mailErrors, $notificationResult['errors']);
|
||
$errors = array_merge($errors, $notificationResult['errors']);
|
||
}
|
||
|
||
// オペレーターキュー作成用データを収集
|
||
if (!empty($notificationResult['queue_items'])) {
|
||
$allQueueItems = array_merge($allQueueItems ?? [], $notificationResult['queue_items']);
|
||
}
|
||
}
|
||
|
||
// 【処理4】仕様書準拠:先に呼び出し、成功時のみ内部変数を更新
|
||
$queueErrorCount = 0; // キュー登録異常終了件数(累計)
|
||
$queueSuccessCount = 0; // キュー登録正常終了件数(累計)
|
||
|
||
foreach ($allQueueItems as $queueItem) {
|
||
// 仕様書準拠:在呼叫前先計算"如果這次成功會是第幾件",確保記錄反映最新件數
|
||
$predictedSuccessCount = $queueSuccessCount + 1;
|
||
$predictedErrorCount = $queueErrorCount; // 暂时保持当前错误计数
|
||
|
||
$queueResult = $this->addToOperatorQueue(
|
||
$queueItem['waiting_user'],
|
||
$queueItem['park_vacancy'],
|
||
$queueItem['batch_comment'],
|
||
$notificationSuccessCount, // 最終メール正常終了件数
|
||
$predictedSuccessCount, // 預測成功時的件數(包含本次)
|
||
count($mailErrors), // 現在のメール異常終了件数(動態計算)
|
||
$predictedErrorCount // 現在のキュー登録異常終了件数
|
||
);
|
||
|
||
// 仕様書:根据实际结果决定是否采用预测值
|
||
if ($queueResult['success']) {
|
||
$queueSuccessCount = $predictedSuccessCount; // 采用预测的成功计数
|
||
} else {
|
||
$queueErrorCount++; // 失败时递增错误计数
|
||
|
||
// 仕様書:包含具体错误消息,满足"エラーメッセージ/スタックトレースを保持"要求
|
||
$errorDetail = $queueResult['error'] ?? 'Unknown error';
|
||
$queueErrorInfo = sprintf('キュー登録失敗:予約ID:%d - %s',
|
||
$queueItem['waiting_user']->reserve_id ?? 0,
|
||
$errorDetail
|
||
);
|
||
$errors[] = $queueErrorInfo; // 加入总错误统计(包含具体原因)
|
||
|
||
Log::error('オペレーターキュー作成失敗', [
|
||
'user_id' => $queueItem['waiting_user']->user_id,
|
||
'reserve_id' => $queueItem['waiting_user']->reserve_id ?? 0,
|
||
'error' => $errorDetail
|
||
]);
|
||
}
|
||
}
|
||
|
||
$endTime = now();
|
||
$duration = $startTime->diffInSeconds($endTime);
|
||
|
||
Log::info('SHJ-5 空き待ち通知処理完了', [
|
||
'duration_seconds' => $duration,
|
||
'processed_parks_count' => $processedParksCount,
|
||
'vacant_parks_count' => $vacantParksCount,
|
||
'total_waiting_users' => $totalWaitingUsers,
|
||
'notification_success_count' => $notificationSuccessCount,
|
||
'operator_queue_success_count' => $queueSuccessCount, // 仕様書:正常完了件数
|
||
'queue_error_count' => $queueErrorCount,
|
||
'mail_error_count' => count($mailErrors), // メール異常終了件数(分離)
|
||
'total_error_count' => count($errors) // 全体エラー件数
|
||
]);
|
||
|
||
// 仕様書に基づく内部変数.ステータスコメント生成
|
||
$statusComment = sprintf(
|
||
'メール正常終了件数:%d/メール異常終了件数:%d/キュー登録正常終了件数:%d/キュー登録異常終了件数:%d',
|
||
$notificationSuccessCount,
|
||
count($mailErrors), // メール異常終了件数(キュー失敗を除外)
|
||
$queueSuccessCount ?? 0, // 実際のキュー登録成功件数
|
||
$queueErrorCount ?? 0 // 実際のキュー登録失敗件数
|
||
);
|
||
|
||
// SHJ-8 バッチ処理ログ作成
|
||
try {
|
||
$device = Device::orderBy('device_id')->first();
|
||
$deviceId = $device ? $device->device_id : 1;
|
||
$today = now()->format('Y/m/d');
|
||
|
||
$this->shjEightService->execute(
|
||
$deviceId,
|
||
'SHJ-5',
|
||
'SHJ-5空き待ち通知',
|
||
'success',
|
||
$statusComment,
|
||
$today,
|
||
$today
|
||
);
|
||
|
||
Log::info('SHJ-8 バッチ処理ログ作成完了');
|
||
} catch (Exception $e) {
|
||
Log::error('SHJ-8 バッチ処理ログ作成エラー', [
|
||
'error' => $e->getMessage()
|
||
]);
|
||
}
|
||
|
||
return [
|
||
'success' => true,
|
||
'message' => 'SHJ-5 空き待ち通知処理が正常に完了しました',
|
||
'processed_parks_count' => $processedParksCount,
|
||
'vacant_parks_count' => $vacantParksCount,
|
||
'total_waiting_users' => $totalWaitingUsers,
|
||
'notification_success_count' => $notificationSuccessCount,
|
||
'operator_queue_count' => $queueSuccessCount ?? 0, // 仕様書:正常完了件数を使用
|
||
'error_count' => count($errors),
|
||
'errors' => $errors,
|
||
'duration_seconds' => $duration,
|
||
'status_comment' => $statusComment // SHJ-8用の完全なステータスコメント
|
||
];
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('SHJ-5 空き待ち通知処理でエラーが発生', [
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString()
|
||
]);
|
||
|
||
return [
|
||
'success' => false,
|
||
'message' => 'SHJ-5 空き待ち通知処理でエラーが発生: ' . $e->getMessage(),
|
||
'error_details' => $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 【処理1】駐輪場の空き状況を取得する
|
||
*
|
||
* 仕様書に基づくSQL:
|
||
* - zone表から標準台数と現在の契約台数を比較
|
||
* - 空きがある駐輪場の情報を取得
|
||
*
|
||
* @return array 駐輪場空き状況リスト
|
||
*/
|
||
private function getParkVacancyStatus(): array
|
||
{
|
||
try {
|
||
// ゾーン毎の契約台数を取得
|
||
$contractCounts = DB::table('regular_contract as T1')
|
||
->select([
|
||
'T1.park_id',
|
||
'T1.psection_id',
|
||
'T5.ptype_id',
|
||
DB::raw('count(T1.contract_id) as contract_count')
|
||
])
|
||
->join('park as T2', 'T1.park_id', '=', 'T2.park_id')
|
||
->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');
|
||
})
|
||
->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', 'T1.psection_id', 'T5.ptype_id'])
|
||
->get()
|
||
->keyBy(function($item) {
|
||
return $item->park_id . '_' . $item->psection_id . '_' . $item->ptype_id;
|
||
});
|
||
|
||
// ゾーン情報と照合して空き状況を算出
|
||
$vacancyList = DB::table('zone as T1')
|
||
->select([
|
||
'T1.park_id',
|
||
'T2.park_name',
|
||
'T1.psection_id',
|
||
'T1.ptype_id',
|
||
'T1.zone_standard',
|
||
'T3.psection_subject',
|
||
'T4.ptype_subject'
|
||
])
|
||
->join('park as T2', 'T1.park_id', '=', 'T2.park_id')
|
||
->join('psection as T3', 'T1.psection_id', '=', 'T3.psection_id')
|
||
->join('ptype as T4', 'T1.ptype_id', '=', 'T4.ptype_id')
|
||
->where([
|
||
['T1.delete_flag', '=', 0], // ゾーン有効
|
||
['T2.park_close_flag', '=', 0], // 駐輪場開設
|
||
])
|
||
->get()
|
||
->map(function($zone) use ($contractCounts) {
|
||
$key = $zone->park_id . '_' . $zone->psection_id . '_' . $zone->ptype_id;
|
||
$contractCount = isset($contractCounts[$key]) ? $contractCounts[$key]->contract_count : 0;
|
||
|
||
$zone->contract_count = $contractCount;
|
||
$zone->vacant_count = max(0, $zone->zone_standard - $contractCount);
|
||
|
||
return $zone;
|
||
})
|
||
->filter(function($zone) {
|
||
return $zone->vacant_count > 0; // 空きがあるもののみ
|
||
})
|
||
->values();
|
||
|
||
Log::info('駐輪場空き状況算出完了', [
|
||
'total_zones' => count($vacancyList),
|
||
'vacant_zones' => $vacancyList->filter(function($v) {
|
||
return $v->vacant_count > 0;
|
||
})->count()
|
||
]);
|
||
|
||
return $vacancyList->toArray();
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('駐輪場空き状況取得エラー', [
|
||
'error' => $e->getMessage()
|
||
]);
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 【処理2】空き待ち者の情報を取得する
|
||
*
|
||
* 仕様書に基づく取得条件:
|
||
* - 契約未紐付(contract_id IS NULL)
|
||
* - 退会でない(user_quit_flag <> 1)
|
||
* - 有効な予約(valid_flag = 1)
|
||
* - 予約日時順で取得(reserve_date昇順)
|
||
*
|
||
* @param int $parkId 駐輪場ID
|
||
* @param int $psectionId 車種区分ID
|
||
* @param int $ptypeId 駐輪分類ID
|
||
* @return array 空き待ち者情報リスト
|
||
*/
|
||
private function getWaitingUsersInfo(int $parkId, int $psectionId, int $ptypeId): array
|
||
{
|
||
try {
|
||
$waitingUsers = DB::table('reserve as T1')
|
||
->select([
|
||
'T1.reserve_id',
|
||
'T1.user_id',
|
||
'T1.park_id',
|
||
'T1.psection_id',
|
||
'T1.ptype_id',
|
||
'T1.reserve_order',
|
||
'T1.reserve_date',
|
||
'T1.reserve_manual', // 手動通知フラグ
|
||
'T1.contract_id', // 契約紐付確認用
|
||
'T2.user_name',
|
||
'T2.user_primemail',
|
||
'T2.user_submail', // 副メールアドレス
|
||
'T2.user_manual_regist_flag', // 手動登録フラグ
|
||
'T2.user_quit_flag', // 退会フラグ
|
||
'T3.park_name',
|
||
'T4.psection_subject',
|
||
'T5.ptype_subject'
|
||
])
|
||
->join('user as T2', 'T1.user_id', '=', 'T2.user_id')
|
||
->join('park as T3', 'T1.park_id', '=', 'T3.park_id')
|
||
->join('psection as T4', 'T1.psection_id', '=', 'T4.psection_id')
|
||
->join('ptype as T5', 'T1.ptype_id', '=', 'T5.ptype_id')
|
||
->where([
|
||
['T1.park_id', '=', $parkId],
|
||
['T1.psection_id', '=', $psectionId],
|
||
['T1.ptype_id', '=', $ptypeId],
|
||
['T1.valid_flag', '=', 1], // 有効な予約
|
||
['T2.user_quit_flag', '<>', 1] // 退会でない
|
||
])
|
||
->whereNull('T1.contract_id') // 契約未紐付
|
||
->orderBy('T1.reserve_date', 'asc') // 仕様書に基づく予約日時順
|
||
->get()
|
||
->toArray();
|
||
|
||
Log::info('空き待ち者情報取得完了', [
|
||
'park_id' => $parkId,
|
||
'psection_id' => $psectionId,
|
||
'ptype_id' => $ptypeId,
|
||
'waiting_users_count' => count($waitingUsers)
|
||
]);
|
||
|
||
return $waitingUsers;
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('空き待ち者情報取得エラー', [
|
||
'park_id' => $parkId,
|
||
'psection_id' => $psectionId,
|
||
'ptype_id' => $ptypeId,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 【処理3】空き待ち者への通知、またはオペレーターキュー追加処理
|
||
*
|
||
* 仕様書に基づく分岐処理:
|
||
* - 手動通知フラグ判定(reserve_manual)
|
||
* - メール送信成功時のreserve.sent_date更新
|
||
* - 失敗時のオペレーターキュー追加(最終統計で処理)
|
||
*
|
||
* @param array $waitingUsers 空き待ち者リスト
|
||
* @param object $parkVacancy 駐輪場空き情報
|
||
* @return array 通知処理結果
|
||
*/
|
||
private function processWaitingUsersNotification(array $waitingUsers, object $parkVacancy): array
|
||
{
|
||
$notificationSuccessCount = 0;
|
||
$operatorQueueCount = 0;
|
||
$errors = [];
|
||
$queueItems = []; // オペレーターキュー作成用データ収集
|
||
|
||
try {
|
||
// 空きがある分だけ処理(先着順)
|
||
$availableSpots = min($parkVacancy->vacant_count, count($waitingUsers));
|
||
|
||
for ($i = 0; $i < $availableSpots; $i++) {
|
||
$waitingUserData = $waitingUsers[$i];
|
||
// 配列をオブジェクトに変換
|
||
$waitingUser = (object) $waitingUserData;
|
||
|
||
try {
|
||
// 【仕様判断】手動通知フラグチェック
|
||
if ($waitingUser->reserve_manual == 1) {
|
||
// 手動通知 → オペレーターキュー作成データ収集
|
||
$batchComment = '手動通知フラグ設定のため予約ID:' . $waitingUser->reserve_id;
|
||
$queueItems[] = [
|
||
'waiting_user' => $waitingUser,
|
||
'park_vacancy' => $parkVacancy,
|
||
'batch_comment' => $batchComment
|
||
];
|
||
$operatorQueueCount++;
|
||
|
||
Log::info('手動通知フラグによりオペレーターキュー登録予定', [
|
||
'user_id' => $waitingUser->user_id,
|
||
'reserve_id' => $waitingUser->reserve_id
|
||
]);
|
||
} else {
|
||
// 自動通知 → メール送信を試行
|
||
$mailResult = $this->sendVacancyNotificationMail($waitingUser, $parkVacancy);
|
||
|
||
if ($mailResult['success']) {
|
||
// メール送信成功 → reserve.sent_date更新
|
||
$this->updateReserveSentDate($waitingUser->reserve_id);
|
||
$notificationSuccessCount++;
|
||
|
||
Log::info('空き待ち通知メール送信成功', [
|
||
'user_id' => $waitingUser->user_id,
|
||
'reserve_id' => $waitingUser->reserve_id,
|
||
'park_id' => $parkVacancy->park_id
|
||
]);
|
||
} else {
|
||
// メール送信失敗 → オペレーターキュー作成データ収集
|
||
$shjSevenError = $mailResult['error'] ?? $mailResult['message'] ?? 'SHJ-7メール送信エラー';
|
||
$batchComment = $shjSevenError . '予約ID:' . $waitingUser->reserve_id;
|
||
$queueItems[] = [
|
||
'waiting_user' => $waitingUser,
|
||
'park_vacancy' => $parkVacancy,
|
||
'batch_comment' => $batchComment
|
||
];
|
||
$operatorQueueCount++;
|
||
$errors[] = $shjSevenError;
|
||
}
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('空き待ち者通知処理エラー', [
|
||
'user_id' => $waitingUser->user_id,
|
||
'reserve_id' => $waitingUser->reserve_id,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
|
||
// エラー発生時もオペレーターキュー作成データ収集
|
||
$batchComment = 'システムエラー:' . $e->getMessage() . '予約ID:' . $waitingUser->reserve_id;
|
||
$queueItems[] = [
|
||
'waiting_user' => $waitingUser,
|
||
'park_vacancy' => $parkVacancy,
|
||
'batch_comment' => $batchComment
|
||
];
|
||
$operatorQueueCount++;
|
||
$errors[] = $e->getMessage();
|
||
}
|
||
}
|
||
|
||
return [
|
||
'notification_success_count' => $notificationSuccessCount,
|
||
'operator_queue_count' => $operatorQueueCount,
|
||
'errors' => $errors,
|
||
'queue_items' => $queueItems // 後でキュー作成用
|
||
];
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('空き待ち者通知処理全体エラー', [
|
||
'park_id' => $parkVacancy->park_id,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 空き待ち通知メールを送信
|
||
*
|
||
* 仕様書に基づくSHJ-7呼び出し:
|
||
* - 主メールアドレス・副メールアドレスを正しく渡す
|
||
* - 必要なパラメータを全て設定
|
||
*
|
||
* @param object $waitingUser 空き待ち者情報
|
||
* @param object $parkVacancy 駐輪場空き情報
|
||
* @return array 送信結果
|
||
*/
|
||
private function sendVacancyNotificationMail(object $waitingUser, object $parkVacancy): array
|
||
{
|
||
try {
|
||
// ShjMailSendServiceを利用してメール送信
|
||
$mailService = app(ShjMailSendService::class);
|
||
|
||
// 空き待ち通知用のメールテンプレートID(予約告知通知)
|
||
// OperatorQueの定数と合わせて4番を使用
|
||
$mailTemplateId = 4; // 予約告知通知のテンプレートID
|
||
|
||
// 仕様書No1/No2に基づく主メール・副メール設定
|
||
$mainEmail = $waitingUser->user_primemail ?? '';
|
||
$subEmail = $waitingUser->user_submail ?? '';
|
||
|
||
// メール送信実行(仕様書準拠)
|
||
$mailResult = $mailService->executeMailSend(
|
||
$mainEmail,
|
||
$subEmail,
|
||
$mailTemplateId
|
||
);
|
||
|
||
// SHJ-7の結果を標準形式に変換(result: 0=成功, 1=失敗)
|
||
$success = ($mailResult['result'] ?? 1) === 0;
|
||
|
||
Log::info('空き待ち通知メール送信試行完了', [
|
||
'user_id' => $waitingUser->user_id,
|
||
'main_email' => $mainEmail,
|
||
'sub_email' => $subEmail,
|
||
'mail_template_id' => $mailTemplateId,
|
||
'result' => $mailResult['result'] ?? 1,
|
||
'success' => $success
|
||
]);
|
||
|
||
return [
|
||
'success' => $success,
|
||
'result' => $mailResult['result'] ?? 1,
|
||
'error' => $mailResult['error_info'] ?? null,
|
||
'message' => $success ? 'メール送信成功' : ($mailResult['error_info'] ?? 'メール送信失敗')
|
||
];
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('空き待ち通知メール送信エラー', [
|
||
'user_id' => $waitingUser->user_id,
|
||
'main_email' => $waitingUser->user_primemail ?? '',
|
||
'sub_email' => $waitingUser->user_submail ?? '',
|
||
'error' => $e->getMessage()
|
||
]);
|
||
|
||
return [
|
||
'success' => false,
|
||
'error' => $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* reserve.sent_date及びvalid_flag更新
|
||
*
|
||
* 仕様書準拠:メール送信成功時にreserve.sent_dateとvalid_flag=0を同時更新
|
||
* 重複通知を防ぎ、処理済みマークを設定
|
||
*
|
||
* @param int $reserveId 予約ID
|
||
* @return void
|
||
*/
|
||
private function updateReserveSentDate(int $reserveId): void
|
||
{
|
||
try {
|
||
DB::table('reserve')
|
||
->where('reserve_id', $reserveId)
|
||
->update([
|
||
'sent_date' => now()->format('Y-m-d H:i:s'),
|
||
'valid_flag' => 0, // 仕様書:メール送信成功時に0に更新
|
||
'updated_at' => now()
|
||
]);
|
||
|
||
Log::info('reserve.sent_date及びvalid_flag更新完了', [
|
||
'reserve_id' => $reserveId,
|
||
'sent_date' => now()->format('Y-m-d H:i:s'),
|
||
'valid_flag' => 0
|
||
]);
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('reserve.sent_date及びvalid_flag更新エラー', [
|
||
'reserve_id' => $reserveId,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* オペレーターキューに追加
|
||
*
|
||
* 仕様書に基づくキュー登録:
|
||
* - que_comment: 空文字列
|
||
* - que_status_comment: 仕様書完全準拠形式(統計情報含む)
|
||
* - operator_id: 9999999固定
|
||
*
|
||
* @param object $waitingUser 空き待ち者情報
|
||
* @param object $parkVacancy 駐輪場空き情報
|
||
* @param string $batchComment 内部変数.バッチコメント
|
||
* @param int $mailSuccessCount メール正常終了件数
|
||
* @param int $queueSuccessCount キュー登録正常終了件数
|
||
* @param int $mailErrorCount メール異常終了件数
|
||
* @param int $queueErrorCount キュー登録異常終了件数
|
||
* @return array 追加結果
|
||
*/
|
||
private function addToOperatorQueue(object $waitingUser, object $parkVacancy, string $batchComment, int $mailSuccessCount, int $queueSuccessCount, int $mailErrorCount, int $queueErrorCount): array
|
||
{
|
||
try {
|
||
// 仕様書完全準拠:駐輪場名/駐輪分類名/車種区分名/空き台数…/対象予約ID…/内部変数.バッチコメント/内部変数.メール正常終了件数…メール異常終了件数…キュー登録正常終了件数…キュー登録異常終了件数…
|
||
$statusComment = sprintf(
|
||
'%s/%s/%s/空き台数:%d台/対象予約ID:%d/%s/メール正常終了件数:%d/メール異常終了件数:%d/キュー登録正常終了件数:%d/キュー登録異常終了件数:%d',
|
||
$waitingUser->park_name ?? '',
|
||
$waitingUser->ptype_subject ?? '', // 駐輪分類名
|
||
$waitingUser->psection_subject ?? '', // 車種区分名
|
||
$parkVacancy->vacant_count ?? 0,
|
||
$waitingUser->reserve_id ?? 0,
|
||
$batchComment, // 内部変数.バッチコメント
|
||
$mailSuccessCount, // 内部変数.メール正常終了件数
|
||
$mailErrorCount,
|
||
$queueSuccessCount,
|
||
$queueErrorCount
|
||
);
|
||
|
||
OperatorQue::create([
|
||
'que_class' => 4, // 予約告知通知
|
||
'user_id' => $waitingUser->user_id,
|
||
'contract_id' => null,
|
||
'park_id' => $waitingUser->park_id,
|
||
'que_comment' => '', // 仕様書:空文字列
|
||
'que_status' => 1, // キュー発生
|
||
'que_status_comment' => $statusComment, // 仕様書:完全準拠形式
|
||
'work_instructions' => '空き待ち者への連絡をお願いします。',
|
||
'operator_id' => 9999999, // 仕様書:固定値9999999
|
||
]);
|
||
|
||
Log::info('オペレーターキュー追加成功', [
|
||
'user_id' => $waitingUser->user_id,
|
||
'park_id' => $waitingUser->park_id,
|
||
'reserve_id' => $waitingUser->reserve_id,
|
||
'que_class' => 4,
|
||
'operator_id' => 9999999,
|
||
'batch_comment' => $batchComment,
|
||
'mail_success_count' => $mailSuccessCount,
|
||
'mail_error_count' => $mailErrorCount,
|
||
'queue_success_count' => $queueSuccessCount,
|
||
'queue_error_count' => $queueErrorCount,
|
||
'status_comment' => $statusComment
|
||
]);
|
||
|
||
return ['success' => true];
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('オペレーターキュー追加エラー', [
|
||
'user_id' => $waitingUser->user_id,
|
||
'park_id' => $waitingUser->park_id,
|
||
'reserve_id' => $waitingUser->reserve_id ?? null,
|
||
'batch_comment' => $batchComment,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
|
||
return [
|
||
'success' => false,
|
||
'error' => $e->getMessage()
|
||
];
|
||
}
|
||
}
|
||
}
|