694 lines
31 KiB
PHP
694 lines
31 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(SQL-1):
|
||
* - 「駐輪場マスタ」と「ゾーンマスタ」より空き状況を取得する
|
||
* - zone表から zone_number(現在契約台数)、zone_tolerance(限界収容台数)を取得
|
||
* - 空き台数 = 限界収容台数 - 現在契約台数
|
||
*
|
||
* @return array 駐輪場空き状況リスト
|
||
*/
|
||
private function getParkVacancyStatus(): array
|
||
{
|
||
try {
|
||
// 仕様書SQL-1に基づくクエリ:park + zone + ptype + psection
|
||
$vacancyList = DB::table('park as T1')
|
||
->select([
|
||
'T1.park_id',
|
||
'T1.park_name',
|
||
'T1.park_ruby',
|
||
'T2.ptype_id',
|
||
'T3.ptype_subject',
|
||
'T2.psection_id',
|
||
'T4.psection_subject',
|
||
DB::raw('sum(T2.zone_number) as sum_zone_number'), // 現在契約台数
|
||
DB::raw('sum(T2.zone_standard) as sum_zone_standard'), // 標準収容台数
|
||
DB::raw('sum(T2.zone_tolerance) as sum_zone_tolerance') // 限界収容台数
|
||
])
|
||
->join('zone as T2', 'T1.park_id', '=', 'T2.park_id')
|
||
->join('ptype as T3', 'T2.ptype_id', '=', 'T3.ptype_id')
|
||
->join('psection as T4', 'T2.psection_id', '=', 'T4.psection_id')
|
||
->where([
|
||
['T1.park_close_flag', '=', 0], // 駐輪場開設
|
||
['T2.delete_flag', '=', 0], // ゾーン有効
|
||
])
|
||
->groupBy(['T1.park_id', 'T2.ptype_id', 'T2.psection_id'])
|
||
->orderBy('T1.park_ruby')
|
||
->orderBy('T3.floor_sort')
|
||
->orderBy('T2.psection_id')
|
||
->get()
|
||
->map(function($record) {
|
||
// 【JOB1-STEP1】空き台数 = 限界収容台数 - 現在契約台数
|
||
$vacant_count = max(0, $record->sum_zone_tolerance - $record->sum_zone_number);
|
||
|
||
return (object)[
|
||
'park_id' => $record->park_id,
|
||
'park_name' => $record->park_name,
|
||
'park_ruby' => $record->park_ruby,
|
||
'ptype_id' => $record->ptype_id,
|
||
'ptype_subject' => $record->ptype_subject,
|
||
'psection_id' => $record->psection_id,
|
||
'psection_subject' => $record->psection_subject,
|
||
'sum_zone_number' => $record->sum_zone_number, // JOB1 現在契約台数
|
||
'sum_zone_standard' => $record->sum_zone_standard, // JOB1 標準収容台数
|
||
'sum_zone_tolerance' => $record->sum_zone_tolerance, // JOB1 限界収容台数
|
||
'vacant_count' => $vacant_count, // 内部変数.空き台数
|
||
];
|
||
})
|
||
->filter(function($zone) {
|
||
// 【判断1】空き状況判定:空きがあるもののみ
|
||
return $zone->vacant_count > 0;
|
||
})
|
||
->values();
|
||
|
||
Log::info('駐輪場空き状況取得完了(仕様書SQL-1準拠)', [
|
||
'total_records' => count($vacancyList),
|
||
'vacant_records' => $vacancyList->filter(function($v) {
|
||
return $v->vacant_count > 0;
|
||
})->count()
|
||
]);
|
||
|
||
return $vacancyList->toArray();
|
||
|
||
} catch (Exception $e) {
|
||
Log::error('駐輪場空き状況取得エラー', [
|
||
'error' => $e->getMessage()
|
||
]);
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 【処理2】空き待ち者の情報を取得する
|
||
*
|
||
* 仕様書JOB2に基づくSQL:
|
||
* - 空きが発生している「駐輪場ID」「駐輪分類ID」「車種区分ID」で空き待ちしている利用者を抽出する
|
||
* - reserve表 + user表のみ(仕様書準拠)
|
||
* - JOIN条件:T1.user_id = T2.user_seq(重要!)
|
||
*
|
||
* @param int $parkId 駐輪場ID(JOB1.駐輪場ID)
|
||
* @param int $psectionId 車種区分ID(JOB1.車種区分ID)
|
||
* @param int $ptypeId 駐輪分類ID(JOB1.駐輪分類ID)
|
||
* @return array 空き待ち者情報リスト
|
||
*/
|
||
private function getWaitingUsersInfo(int $parkId, int $psectionId, int $ptypeId): array
|
||
{
|
||
try {
|
||
// 仕様書JOB2 SQL準拠:reserve + user のみ
|
||
$waitingUsers = DB::table('reserve as T1')
|
||
->select([
|
||
'T1.user_id', // 利用者ID
|
||
'T1.reserve_id', // 定期予約ID
|
||
'T2.user_name', // 利用者名
|
||
'T2.user_manual_regist_flag', // 手動登録フラグ
|
||
'T2.user_primemail', // メールアドレス
|
||
'T2.user_submail', // 予備メールアドレス
|
||
'T1.reserve_manual', // 手動通知
|
||
// 以下は処理に必要な追加フィールド
|
||
'T1.park_id',
|
||
'T1.psection_id',
|
||
'T1.ptype_id',
|
||
'T1.reserve_date',
|
||
])
|
||
// 仕様書準拠:T1.user_id = T2.user_seq(user表のPK)
|
||
->join('user as T2', 'T1.user_id', '=', 'T2.user_seq')
|
||
->where([
|
||
['T1.park_id', '=', $parkId], // JOB1.駐輪場ID
|
||
['T1.psection_id', '=', $psectionId], // JOB1.車種区分ID
|
||
['T1.ptype_id', '=', $ptypeId], // JOB1.駐輪分類ID
|
||
['T1.valid_flag', '=', 1], // 有効フラグ = 1
|
||
['T2.user_quit_flag', '<>', 1] // 退会フラグ <> 1
|
||
])
|
||
->whereNull('T1.contract_id') // 定期契約 is null
|
||
->orderBy('T1.reserve_date', 'asc') // 予約日時順
|
||
->get()
|
||
->toArray();
|
||
|
||
Log::info('空き待ち者情報取得完了(仕様書JOB2準拠)', [
|
||
'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;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 空き待ち通知メールを送信
|
||
*
|
||
* 仕様書JOB3に基づくSHJ-7呼び出し:
|
||
* - パラメータ1: JOB1.メールアドレス(user_primemail)
|
||
* - パラメータ2: JOB1.予備メールアドレス(user_submail)
|
||
* - パラメータ3: メールID = 201
|
||
* - 追加: reserve_id=%reserve_id%&expiry=%expiry%(予約ID と 無効日)
|
||
*
|
||
* @param object $waitingUser 空き待ち者情報
|
||
* @param object $parkVacancy 駐輪場空き情報
|
||
* @return array 送信結果
|
||
*/
|
||
private function sendVacancyNotificationMail(object $waitingUser, object $parkVacancy): array
|
||
{
|
||
try {
|
||
// ShjMailSendServiceを利用してメール送信
|
||
$mailService = app(ShjMailSendService::class);
|
||
|
||
// 仕様書JOB3準拠:メールID = 201
|
||
$mailTemplateId = 201;
|
||
|
||
// 仕様書No1/No2に基づく主メール・副メール設定
|
||
$mainEmail = $waitingUser->user_primemail ?? '';
|
||
$subEmail = $waitingUser->user_submail ?? '';
|
||
|
||
// 仕様書準拠:reserve_id と expiry(当月末日、休日考慮しない)を追加
|
||
$expiry = now()->endOfMonth()->format('Y-m-d'); // 当月末日
|
||
$additionalParams = [
|
||
'reserve_id' => $waitingUser->reserve_id,
|
||
'expiry' => $expiry
|
||
];
|
||
|
||
// メール送信実行(仕様書JOB3準拠)
|
||
$mailResult = $mailService->executeMailSend(
|
||
$mainEmail,
|
||
$subEmail,
|
||
$mailTemplateId,
|
||
$additionalParams
|
||
);
|
||
|
||
// 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',
|
||
$parkVacancy->park_name ?? '', // JOB1から取得
|
||
$parkVacancy->ptype_subject ?? '', // 駐輪分類名(JOB1から取得)
|
||
$parkVacancy->psection_subject ?? '', // 車種区分名(JOB1から取得)
|
||
$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()
|
||
];
|
||
}
|
||
}
|
||
}
|