386 lines
13 KiB
PHP
386 lines
13 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Log;
|
||
use App\Models\Device;
|
||
use Carbon\Carbon;
|
||
|
||
/**
|
||
* SHJ-13 契約台数追加処理サービス
|
||
*
|
||
* 新規契約時の契約台数を park_number・zone テーブルに反映する処理
|
||
* SHJ-4B の副作用処理として実行される
|
||
*/
|
||
class ShjThirteenService
|
||
{
|
||
/**
|
||
* ShjEightService
|
||
*
|
||
* @var ShjEightService
|
||
*/
|
||
protected $shjEightService;
|
||
|
||
/**
|
||
* コンストラクタ
|
||
*
|
||
* @param ShjEightService $shjEightService
|
||
*/
|
||
public function __construct(ShjEightService $shjEightService)
|
||
{
|
||
$this->shjEightService = $shjEightService;
|
||
}
|
||
/**
|
||
* SHJ-13 契約台数追加処理実行
|
||
*
|
||
* 【処理1】契約台数を反映する - park_number・zone テーブルの契約台数を+1更新
|
||
* 【処理2】バッチ処理ログを作成する - SHJ-8共通仕様でログ登録
|
||
*
|
||
* @param array $contractData 契約データ
|
||
* @return array 処理結果
|
||
*/
|
||
public function execute(array $contractData): array
|
||
{
|
||
$startTime = now();
|
||
|
||
Log::info('SHJ-13 契約台数追加処理開始', [
|
||
'contract_id' => $contractData['contract_id'] ?? null,
|
||
'park_id' => $contractData['park_id'] ?? null,
|
||
'psection_id' => $contractData['psection_id'] ?? null,
|
||
'ptype_id' => $contractData['ptype_id'] ?? null,
|
||
'zone_id' => $contractData['zone_id'] ?? null,
|
||
]);
|
||
|
||
try {
|
||
// パラメータ検証
|
||
$validationResult = $this->validateParameters($contractData);
|
||
if (!$validationResult['valid']) {
|
||
return $this->createErrorResult(
|
||
1001,
|
||
'パラメータエラー: ' . $validationResult['message']
|
||
);
|
||
}
|
||
|
||
// 【処理1・2】契約台数反映とバッチログ作成を一体で実行
|
||
$processResult = $this->executeProcessWithLogging($contractData);
|
||
if (!$processResult['success']) {
|
||
return $this->createErrorResult(
|
||
$processResult['error_code'],
|
||
$processResult['error_message'],
|
||
$processResult['stack_trace'] ?? ''
|
||
);
|
||
}
|
||
|
||
$statusComment = $processResult['status_comment'];
|
||
|
||
$endTime = now();
|
||
Log::info('SHJ-13 契約台数追加処理完了', [
|
||
'contract_id' => $contractData['contract_id'],
|
||
'execution_time' => $startTime->diffInSeconds($endTime),
|
||
'updated_count' => $processResult['updated_count'],
|
||
'status_comment' => $statusComment,
|
||
]);
|
||
|
||
return ['result' => 0];
|
||
|
||
} catch (\Throwable $e) {
|
||
Log::error('SHJ-13 契約台数追加処理例外エラー', [
|
||
'contract_data' => $contractData,
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString(),
|
||
]);
|
||
|
||
return $this->createErrorResult(
|
||
$e->getCode() ?: 1999,
|
||
$e->getMessage(),
|
||
$e->getTraceAsString()
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* パラメータ検証
|
||
*
|
||
* @param array $contractData
|
||
* @return array
|
||
*/
|
||
private function validateParameters(array $contractData): array
|
||
{
|
||
$errors = [];
|
||
|
||
if (empty($contractData['park_id'])) {
|
||
$errors[] = '駐輪場IDが設定されていません';
|
||
}
|
||
|
||
if (empty($contractData['psection_id'])) {
|
||
$errors[] = '車種区分IDが設定されていません';
|
||
}
|
||
|
||
if (empty($contractData['ptype_id'])) {
|
||
$errors[] = '駐輪分類IDが設定されていません';
|
||
}
|
||
|
||
if (empty($contractData['zone_id'])) {
|
||
$errors[] = 'ゾーンIDが設定されていません';
|
||
}
|
||
|
||
if (!empty($errors)) {
|
||
return [
|
||
'valid' => false,
|
||
'message' => implode(', ', $errors),
|
||
'details' => $errors,
|
||
];
|
||
}
|
||
|
||
return ['valid' => true];
|
||
}
|
||
|
||
/**
|
||
* 契約台数反映とバッチログ作成の一体処理
|
||
*
|
||
* park_number・zone テーブルの契約台数を+1更新し、バッチログを作成
|
||
* 全てを1つのトランザクション内で実行
|
||
*
|
||
* @param array $contractData
|
||
* @return array
|
||
*/
|
||
private function executeProcessWithLogging(array $contractData): array
|
||
{
|
||
try {
|
||
return DB::transaction(function() use ($contractData) {
|
||
// 各テーブルの名称取得
|
||
$names = $this->getTableNames($contractData);
|
||
if (!$names['success']) {
|
||
throw new \Exception('名称取得エラー: ' . $names['message'], 1002);
|
||
}
|
||
|
||
// park_number テーブル更新
|
||
$parkNumberUpdated = DB::table('park_number')
|
||
->where('park_id', $contractData['park_id'])
|
||
->where('psection_id', $contractData['psection_id'])
|
||
->where('ptype_id', $contractData['ptype_id'])
|
||
->increment('park_number', 1, [
|
||
'updated_at' => now(),
|
||
]);
|
||
|
||
if ($parkNumberUpdated === 0) {
|
||
throw new \Exception('park_numberテーブルの対象レコードが存在しません', 1011);
|
||
}
|
||
|
||
// zone テーブル更新
|
||
$zoneUpdated = DB::table('zone')
|
||
->where('zone_id', $contractData['zone_id'])
|
||
->increment('zone_number', 1, [
|
||
'updated_at' => now(),
|
||
]);
|
||
|
||
if ($zoneUpdated === 0) {
|
||
throw new \Exception('zoneテーブルの対象レコードが存在しません', 1012);
|
||
}
|
||
|
||
// 更新後の契約台数取得
|
||
$updatedZone = DB::table('zone')
|
||
->where('zone_id', $contractData['zone_id'])
|
||
->first(['zone_number']);
|
||
|
||
// ステータスコメント構築
|
||
$statusComment = $this->buildStatusComment($names['names'], $updatedZone->zone_number);
|
||
|
||
// バッチ処理ログ作成(同一トランザクション内)
|
||
// SHJ-8サービスを呼び出し
|
||
$device = Device::orderBy('device_id')->first();
|
||
$deviceId = $device ? $device->device_id : 1;
|
||
$today = now()->format('Y/m/d');
|
||
|
||
$this->shjEightService->execute(
|
||
$deviceId,
|
||
'SHJ-13',
|
||
'SHJ-13契約台数追加',
|
||
'success',
|
||
$statusComment,
|
||
$today,
|
||
$today
|
||
);
|
||
|
||
Log::info('SHJ-13 契約台数更新・ログ作成完了', [
|
||
'contract_id' => $contractData['contract_id'],
|
||
'park_number_updated' => $parkNumberUpdated,
|
||
'zone_updated' => $zoneUpdated,
|
||
'updated_count' => $updatedZone->zone_number,
|
||
'status_comment' => $statusComment,
|
||
]);
|
||
|
||
return [
|
||
'success' => true,
|
||
'updated_count' => $updatedZone->zone_number,
|
||
'status_comment' => $statusComment,
|
||
];
|
||
});
|
||
|
||
} catch (\Throwable $e) {
|
||
Log::error('SHJ-13 契約台数更新・ログ作成エラー', [
|
||
'contract_data' => $contractData,
|
||
'error_code' => $e->getCode(),
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString(),
|
||
]);
|
||
|
||
return [
|
||
'success' => false,
|
||
'error_code' => $e->getCode() ?: 1010,
|
||
'error_message' => $e->getMessage(),
|
||
'stack_trace' => $e->getTraceAsString(),
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* テーブル名称取得
|
||
*
|
||
* @param array $contractData
|
||
* @return array
|
||
*/
|
||
private function getTableNames(array $contractData): array
|
||
{
|
||
try {
|
||
// 駐輪場名取得
|
||
$park = DB::table('park')
|
||
->where('park_id', $contractData['park_id'])
|
||
->first(['park_name']);
|
||
|
||
if (!$park) {
|
||
return [
|
||
'success' => false,
|
||
'message' => "駐輪場が見つかりません: park_id={$contractData['park_id']}",
|
||
];
|
||
}
|
||
|
||
// 駐輪分類名取得
|
||
$ptype = DB::table('ptype')
|
||
->where('ptype_id', $contractData['ptype_id'])
|
||
->first(['ptype_subject']);
|
||
|
||
if (!$ptype) {
|
||
return [
|
||
'success' => false,
|
||
'message' => "駐輪分類が見つかりません: ptype_id={$contractData['ptype_id']}",
|
||
];
|
||
}
|
||
|
||
// 車種区分名取得
|
||
$psection = DB::table('psection')
|
||
->where('psection_id', $contractData['psection_id'])
|
||
->first(['psection_subject']);
|
||
|
||
if (!$psection) {
|
||
return [
|
||
'success' => false,
|
||
'message' => "車種区分が見つかりません: psection_id={$contractData['psection_id']}",
|
||
];
|
||
}
|
||
|
||
// ゾーン名取得
|
||
$zone = DB::table('zone')
|
||
->where('zone_id', $contractData['zone_id'])
|
||
->first(['zone_name']);
|
||
|
||
if (!$zone) {
|
||
return [
|
||
'success' => false,
|
||
'message' => "ゾーンが見つかりません: zone_id={$contractData['zone_id']}",
|
||
];
|
||
}
|
||
|
||
return [
|
||
'success' => true,
|
||
'names' => [
|
||
'park_name' => $park->park_name,
|
||
'ptype_subject' => $ptype->ptype_subject,
|
||
'psection_subject' => $psection->psection_subject,
|
||
'zone_name' => $zone->zone_name,
|
||
],
|
||
];
|
||
|
||
} catch (\Throwable $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => 'テーブル名称取得エラー: ' . $e->getMessage(),
|
||
'details' => $e->getTraceAsString(),
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ステータスコメント構築
|
||
*
|
||
* 形式:駐輪場名/駐輪分類名/車種区分名/ゾーン名/現在契約台数(更新後):{数値}/
|
||
*
|
||
* @param array $names
|
||
* @param int $updatedCount
|
||
* @return string
|
||
*/
|
||
private function buildStatusComment(array $names, int $updatedCount): string
|
||
{
|
||
return sprintf(
|
||
'%s/%s/%s/%s/現在契約台数(更新後):%d/',
|
||
$names['park_name'],
|
||
$names['ptype_subject'],
|
||
$names['psection_subject'],
|
||
$names['zone_name'],
|
||
$updatedCount
|
||
);
|
||
}
|
||
|
||
|
||
/**
|
||
* エラー結果作成(SHJ-8ログも作成)
|
||
*
|
||
* @param int $errorCode
|
||
* @param string $errorMessage
|
||
* @param string $stackTrace
|
||
* @return array
|
||
*/
|
||
private function createErrorResult(int $errorCode, string $errorMessage, string $stackTrace = ''): array
|
||
{
|
||
// エラー時もSHJ-8でバッチログを作成
|
||
try {
|
||
$device = Device::orderBy('device_id')->first();
|
||
$deviceId = $device ? $device->device_id : 1;
|
||
$today = now()->format('Y/m/d');
|
||
|
||
$statusComment = sprintf(
|
||
'エラーコード:%d/エラーメッセージ:%s',
|
||
$errorCode,
|
||
$errorMessage
|
||
);
|
||
|
||
$this->shjEightService->execute(
|
||
$deviceId,
|
||
'SHJ-13',
|
||
'SHJ-13契約台数追加',
|
||
'success', // 仕様書:エラー時も"success"で記録
|
||
$statusComment,
|
||
$today,
|
||
$today
|
||
);
|
||
|
||
Log::info('SHJ-13 エラー時バッチログ作成完了', [
|
||
'error_code' => $errorCode,
|
||
'status_comment' => $statusComment
|
||
]);
|
||
} catch (\Exception $e) {
|
||
Log::error('SHJ-13 エラー時バッチログ作成失敗', [
|
||
'error' => $e->getMessage()
|
||
]);
|
||
}
|
||
|
||
return [
|
||
'result' => 1,
|
||
'error_code' => $errorCode,
|
||
'error_message' => $errorMessage,
|
||
'stack_trace' => $stackTrace,
|
||
];
|
||
}
|
||
}
|