shj10 shj11 修正
All checks were successful
Deploy api / deploy (push) Successful in 22s

This commit is contained in:
go.unhi 2026-02-27 18:54:30 +09:00 committed by unhi.go
parent e1073e2577
commit 467223e094
9 changed files with 200 additions and 156 deletions

View File

@ -9,7 +9,7 @@ use App\Services\ShjElevenService;
/** /**
* SHJ-11 現在契約台数集計コマンド * SHJ-11 現在契約台数集計コマンド
* *
* 集計単位每个の契約台数を算出し、ゾーンマスタとの管理処理を実行する * 集計単位の契約台数を算出し、ゾーンマスタとの管理処理を実行する
* バックグラウンドで実行される定期バッチ処理 * バックグラウンドで実行される定期バッチ処理
*/ */
class ShjElevenCommand extends Command class ShjElevenCommand extends Command
@ -29,7 +29,7 @@ class ShjElevenCommand extends Command
* *
* @var string * @var string
*/ */
protected $description = 'SHJ-11 現在契約台数集計 - 集計単位每个契約台数を算出しゾーンマスタ管理を実行'; protected $description = 'SHJ-11 現在契約台数集計 - 集計単位契約台数を算出しゾーンマスタ管理を実行';
/** /**
* SHJ-11サービスクラス * SHJ-11サービスクラス
@ -53,7 +53,7 @@ class ShjElevenCommand extends Command
* コンソールコマンドを実行 * コンソールコマンドを実行
* *
* 処理フロー(仕様書準拠): * 処理フロー(仕様書準拠):
* 【処理1】集計単位每个の契約台数を算出する * 【処理1】集計単位の契約台数を算出する
* 【判断1】取得件数判定 * 【判断1】取得件数判定
* - 取得件数 = 0 【処理4】バッチログ作成「全駐輪場契約なし」 終了 * - 取得件数 = 0 【処理4】バッチログ作成「全駐輪場契約なし」 終了
* - 取得件数 1 【処理2】ゾーンマスタ処理循環 終了 * - 取得件数 1 【処理2】ゾーンマスタ処理循環 終了
@ -72,8 +72,8 @@ class ShjElevenCommand extends Command
'start_time' => $startTime 'start_time' => $startTime
]); ]);
// 【処理1】集計単位每个の契約台数を算出する // 【処理1】集計単位の契約台数を算出する
$this->info('【処理1】集計単位每个の契約台数を算出しています...'); $this->info('【処理1】集計単位の契約台数を算出しています...');
$contractCounts = $this->shjElevenService->calculateContractCounts(); $contractCounts = $this->shjElevenService->calculateContractCounts();
// 【判断1】取得件数判定 // 【判断1】取得件数判定

View File

@ -62,7 +62,7 @@ class ShjNineCommand extends Command
* *
* @return int * @return int
*/ */
public function handle() public function handle(): int
{ {
// 開始ログ出力 // 開始ログ出力
$startTime = now(); $startTime = now();

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Console\Commands; namespace App\Console\Commands;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@ -64,7 +66,7 @@ class ShjTenCommand extends Command
* *
* @return int * @return int
*/ */
public function handle() public function handle(): int
{ {
try { try {
// 開始ログ出力 // 開始ログ出力
@ -90,6 +92,8 @@ class ShjTenCommand extends Command
// パラメータ検証 // パラメータ検証
if (!$this->validateParameters($type, $target)) { if (!$this->validateParameters($type, $target)) {
$this->error('パラメータが不正です。'); $this->error('パラメータが不正です。');
// パラメーター不正時もJOB5でバッチ処理ログを作成する
$this->shjTenService->logValidationError($type);
return self::FAILURE; return self::FAILURE;
} }
@ -141,7 +145,6 @@ class ShjTenCommand extends Command
/** /**
* パラメーター指定なしの場合のデフォルト値を取得 * パラメーター指定なしの場合のデフォルト値を取得
* *
* 仕様書:
* - 年次の場合前期財政年度4月開始 * - 年次の場合前期財政年度4月開始
* - 月次の場合本日の1ヶ月前 * - 月次の場合本日の1ヶ月前
* *
@ -150,7 +153,7 @@ class ShjTenCommand extends Command
*/ */
private function getDefaultTarget(string $type): string private function getDefaultTarget(string $type): string
{ {
$fiscalStartMonth = 4; // 財政年度開始月4月 $fiscalStartMonth = (int) config('shj10.fiscal_start_month', 4);
if ($type === 'yearly') { if ($type === 'yearly') {
// 前期を計算 // 前期を計算
@ -225,9 +228,8 @@ class ShjTenCommand extends Command
* - yearly 2019: 2019年4月1日 2020年3月31日 * - yearly 2019: 2019年4月1日 2020年3月31日
* - monthly 2019/01: 2019年1月1日 2019年1月31日 * - monthly 2019/01: 2019年1月1日 2019年1月31日
* *
* 仕様書: * - yearly: 売上日付 = 年度の1月1日で表現
* - yearly: 売上日付 = パラメーター.集計対象年(期) 年度の1月1日で表現 * - monthly: 売上日付 = 該当月の1日で表現
* - monthly: 売上日付 = パラメーター.集計対象月 該当月の1日で表現
* *
* @param string $type 集計種別 * @param string $type 集計種別
* @param string $target 集計対象 * @param string $target 集計対象
@ -235,7 +237,7 @@ class ShjTenCommand extends Command
*/ */
private function determineFiscalPeriod(string $type, string $target): array private function determineFiscalPeriod(string $type, string $target): array
{ {
$fiscalStartMonth = 4; // 財政年度開始月4月 $fiscalStartMonth = (int) config('shj10.fiscal_start_month', 4);
if ($type === 'yearly') { if ($type === 'yearly') {
$year = (int)$target; $year = (int)$target;
@ -245,7 +247,7 @@ class ShjTenCommand extends Command
$endDate = sprintf('%04d-%02d-%02d', $year + 1, $fiscalStartMonth - 1, $endDate = sprintf('%04d-%02d-%02d', $year + 1, $fiscalStartMonth - 1,
date('t', strtotime(sprintf('%04d-%02d-01', $year + 1, $fiscalStartMonth - 1)))); date('t', strtotime(sprintf('%04d-%02d-01', $year + 1, $fiscalStartMonth - 1))));
// 売上日付: 仕様書では年度(例:2019)、DBはDATE型なので年度の1月1日で表現 // 売上日付: DBはDATE型のため年度の1月1日で表現
$earningsDate = sprintf('%04d-01-01', $year); $earningsDate = sprintf('%04d-01-01', $year);
return [ return [

View File

@ -26,7 +26,7 @@ class ShjEightService
* SHJ-8 メイン処理実行 * SHJ-8 メイン処理実行
* *
* 修正版7項目入力status_comment追加 * 修正版7項目入力status_comment追加
* @param int $deviceId デバイスID (必須) * @param int|null $deviceId デバイスID (任意・NULL可)
* @param string|null $processName プロセス名 * @param string|null $processName プロセス名
* @param string|null $jobName ジョブ名 * @param string|null $jobName ジョブ名
* @param string $status ステータス * @param string $status ステータス
@ -36,7 +36,7 @@ class ShjEightService
* @return array 処理結果 ['result' => 0|1, 'error_message' => string|null] * @return array 処理結果 ['result' => 0|1, 'error_message' => string|null]
*/ */
public function execute( public function execute(
int $deviceId, ?int $deviceId,
?string $processName, ?string $processName,
?string $jobName, ?string $jobName,
string $status, string $status,
@ -125,7 +125,7 @@ class ShjEightService
* 【処理1】入力パラメーターをチェックする * 【処理1】入力パラメーターをチェックする
* *
* 修正版7項目チェックstatus_comment追加 * 修正版7項目チェックstatus_comment追加
* 1. デバイスID: 必須、device表に存在チェック * 1. デバイスID: 任意、指定時はdevice表に存在チェック
* 2. プロセス名: 「プロセス名」「ジョブ名」いずれか必須 * 2. プロセス名: 「プロセス名」「ジョブ名」いずれか必須
* 3. ジョブ名: 「プロセス名」「ジョブ名」いずれか必須 * 3. ジョブ名: 「プロセス名」「ジョブ名」いずれか必須
* 4. ステータス: 必須 * 4. ステータス: 必須
@ -133,7 +133,7 @@ class ShjEightService
* 6. 登録日時: 日付型(yyyy/mm/dd形式) * 6. 登録日時: 日付型(yyyy/mm/dd形式)
* 7. 更新日時: 日付型(yyyy/mm/dd形式) * 7. 更新日時: 日付型(yyyy/mm/dd形式)
* *
* @param int $deviceId デバイスID * @param int|null $deviceId デバイスID
* @param string|null $processName プロセス名 * @param string|null $processName プロセス名
* @param string|null $jobName ジョブ名 * @param string|null $jobName ジョブ名
* @param string $status ステータス * @param string $status ステータス
@ -143,7 +143,7 @@ class ShjEightService
* @return array 検証結果 ['valid' => bool, 'error_message' => string|null] * @return array 検証結果 ['valid' => bool, 'error_message' => string|null]
*/ */
private function validateParameters( private function validateParameters(
int $deviceId, ?int $deviceId,
?string $processName, ?string $processName,
?string $jobName, ?string $jobName,
string $status, string $status,
@ -153,12 +153,14 @@ class ShjEightService
): array { ): array {
$errors = []; $errors = [];
// 1. デバイスIDチェック (必須、存在チェック) // 1. デバイスIDチェック (任意、指定時のみ存在チェック)
if (!is_null($deviceId)) {
if ($deviceId <= 0) { if ($deviceId <= 0) {
$errors[] = "パラメーターNGデバイスID/{$deviceId}"; $errors[] = "パラメーターNGデバイスID/{$deviceId}";
} elseif (!Device::where('device_id', $deviceId)->exists()) { } elseif (!Device::where('device_id', $deviceId)->exists()) {
$errors[] = "パラメーターNGデバイスID/{$deviceId}"; $errors[] = "パラメーターNGデバイスID/{$deviceId}";
} }
}
// 2. プロセス名とジョブ名のいずれか必須チェック // 2. プロセス名とジョブ名のいずれか必須チェック
if (empty($processName) && empty($jobName)) { if (empty($processName) && empty($jobName)) {
@ -232,7 +234,7 @@ class ShjEightService
* bat_job_logテーブルにINSERT * bat_job_logテーブルにINSERT
* 修正版:ステータスコメントは呼び出し元から受け取る(固定値廃止) * 修正版:ステータスコメントは呼び出し元から受け取る(固定値廃止)
* *
* @param int $deviceId デバイスID * @param int|null $deviceId デバイスID
* @param string|null $processName プロセス名 * @param string|null $processName プロセス名
* @param string|null $jobName ジョブ名 * @param string|null $jobName ジョブ名
* @param string $status ステータス * @param string $status ステータス
@ -242,7 +244,7 @@ class ShjEightService
* @return BatJobLog 作成されたバッチジョブログ * @return BatJobLog 作成されたバッチジョブログ
*/ */
private function createBatchJobLog( private function createBatchJobLog(
int $deviceId, ?int $deviceId,
?string $processName, ?string $processName,
?string $jobName, ?string $jobName,
string $status, string $status,

View File

@ -101,7 +101,7 @@ class ShjElevenService
} }
/** /**
* 【処理1】集計単位每个の契約台数を算出する * 【処理1】集計単位の契約台数を算出する
* *
* 集計単位: 駐輪場ID + 車種区分ID + 駐輪分類ID + ゾーンID * 集計単位: 駐輪場ID + 車種区分ID + 駐輪分類ID + ゾーンID
* *
@ -621,7 +621,7 @@ class ShjElevenService
. $contractData->ptype_subject . '' . $contractData->ptype_subject . ''
. $contractData->psection_subject . '' . $contractData->psection_subject . ''
. $contractData->zone_id . '/契約台数' . $contractData->zone_id . '/契約台数'
. $contractData->cnt . ': マスタなしのため登録'; . $contractData->cnt . 'マスタなしのため登録';
} }
/** /**
@ -647,7 +647,7 @@ class ShjElevenService
$comment = $contractData->park_name . '' $comment = $contractData->park_name . ''
. $contractData->ptype_subject . '' . $contractData->ptype_subject . ''
. $contractData->psection_subject . '' . $contractData->psection_subject . ''
. $contractData->zone_id . ($zoneData->zone_name ?? $contractData->zone_id)
. '/限界収容台数:' . ($zoneData->zone_tolerance ?? 0) . '/限界収容台数:' . ($zoneData->zone_tolerance ?? 0)
. '/現在契約台数(更新前):' . ($zoneData->zone_number ?? 0) . '/現在契約台数(更新前):' . ($zoneData->zone_number ?? 0)
. '/現在契約台数(更新後):' . $contractData->cnt . ''; . '/現在契約台数(更新後):' . $contractData->cnt . '';
@ -701,8 +701,8 @@ class ShjElevenService
'zone_id' => $contractData->zone_id 'zone_id' => $contractData->zone_id
]); ]);
// SHJ-8サービスを呼び出し // SHJ-8サービスを呼び出し(仕様書:処理結果の判定を行う)
$this->shjEightService->execute( $result = $this->shjEightService->execute(
$deviceId, $deviceId,
$processName, $processName,
$jobName, $jobName,
@ -712,6 +712,22 @@ class ShjElevenService
$today $today
); );
// 仕様書「SHJ-8 バッチ処理ログ作成.処理結果」の判定
// result=0正常、その他異常いずれも次の繰り返し処理へ
if (($result['result'] ?? 1) !== 0) {
Log::warning('SHJ-8 バッチ処理ログ作成 処理結果異常', [
'result' => $result,
'park_id' => $contractData->park_id,
'zone_id' => $contractData->zone_id,
'error_message' => $result['error_message'] ?? null
]);
return [
'success' => false,
'error_message' => $result['error_message'] ?? 'SHJ-8処理結果異常'
];
}
Log::info('SHJ-8バッチ処理ログ作成完了', [ Log::info('SHJ-8バッチ処理ログ作成完了', [
'park_id' => $contractData->park_id, 'park_id' => $contractData->park_id,
'zone_id' => $contractData->zone_id 'zone_id' => $contractData->zone_id
@ -774,8 +790,8 @@ class ShjElevenService
'status_comment' => $statusComment 'status_comment' => $statusComment
]); ]);
// SHJ-8サービスを呼び出し // SHJ-8サービスを呼び出し(仕様書:処理結果の判定を行う)
$this->shjEightService->execute( $result = $this->shjEightService->execute(
$deviceId, $deviceId,
$processName, $processName,
$jobName, $jobName,
@ -785,6 +801,19 @@ class ShjElevenService
$today $today
); );
// 仕様書「SHJ-8 バッチ処理ログ作成.処理結果」の判定
if (($result['result'] ?? 1) !== 0) {
Log::warning('SHJ-8 バッチ処理ログ作成 処理結果異常(対象なし)', [
'result' => $result,
'error_message' => $result['error_message'] ?? null
]);
return [
'success' => false,
'error_message' => $result['error_message'] ?? 'SHJ-8処理結果異常'
];
}
Log::info('SHJ-8バッチ処理ログ作成完了対象なし'); Log::info('SHJ-8バッチ処理ログ作成完了対象なし');
return [ return [

View File

@ -6,7 +6,6 @@ use App\Models\Park;
use App\Models\EarningsSummary; use App\Models\EarningsSummary;
use App\Models\Psection; use App\Models\Psection;
use App\Models\OperatorQue; use App\Models\OperatorQue;
use App\Models\Device;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Carbon\Carbon; use Carbon\Carbon;
@ -54,7 +53,7 @@ class ShjNineService
/** /**
* SHJ-9 売上集計処理メイン実行(日次のみ) * SHJ-9 売上集計処理メイン実行(日次のみ)
* *
* 処理フロー (todo/SHJ-9/SHJ-9.txt): * 処理フロー:
* 【処理1】集計対象を設定する * 【処理1】集計対象を設定する
* 【処理2】駐輪場マスタを取得する * 【処理2】駐輪場マスタを取得する
* 【判断1】取得件数判定 * 【判断1】取得件数判定
@ -346,8 +345,6 @@ class ShjNineService
/** /**
* 0. 情報不備チェック * 0. 情報不備チェック
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:44-68
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $targetDate 集計対象日YYYY-MM-DD * @param string $targetDate 集計対象日YYYY-MM-DD
* @return string 情報不備メッセージ(仕様フォーマット:"情報不備xxx" or "情報不備:なし" * @return string 情報不備メッセージ(仕様フォーマット:"情報不備xxx" or "情報不備:なし"
@ -390,7 +387,6 @@ class ShjNineService
/** /**
* 定期契約データ取得(車種区分・分類名1・定期有効月数毎) * 定期契約データ取得(車種区分・分類名1・定期有効月数毎)
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:70-95
* SQL定義減免措置・継続フラグ・車種区分・分類名・有効月数でグループ化し、 * SQL定義減免措置・継続フラグ・車種区分・分類名・有効月数でグループ化し、
* 授受金額の合計と件数を算出する * 授受金額の合計と件数を算出する
* *
@ -432,8 +428,6 @@ class ShjNineService
/** /**
* 一時金データ取得(車種毎) * 一時金データ取得(車種毎)
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:114-125
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $targetDate 集計対象日YYYY-MM-DD * @param string $targetDate 集計対象日YYYY-MM-DD
* @return array * @return array
@ -457,8 +451,6 @@ class ShjNineService
/** /**
* 解約返戻金データ取得(車種区分毎) * 解約返戻金データ取得(車種区分毎)
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:126-137
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $targetDate 集計対象日YYYY-MM-DD * @param string $targetDate 集計対象日YYYY-MM-DD
* @return array * @return array
@ -482,8 +474,6 @@ class ShjNineService
/** /**
* 再発行データ取得(車種区分毎) * 再発行データ取得(車種区分毎)
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:138-149
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $targetDate 集計対象日YYYY-MM-DD * @param string $targetDate 集計対象日YYYY-MM-DD
* @return array * @return array
@ -512,8 +502,6 @@ class ShjNineService
* ここで park_id + psection_id + usertype_subject1 + enable_months をキーに統合し、 * ここで park_id + psection_id + usertype_subject1 + enable_months をキーに統合し、
* 新規/更新 × 減免/通常 の各件数・金額を1つのオブジェクトに集約する。 * 新規/更新 × 減免/通常 の各件数・金額を1つのオブジェクトに集約する。
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:96-113
*
* @param array $regularData calculateRegularEarnings()の結果 * @param array $regularData calculateRegularEarnings()の結果
* @return array キーpsection_id|usertype|months、値統合されたデータオブジェクト * @return array キーpsection_id|usertype|months、値統合されたデータオブジェクト
*/ */
@ -788,7 +776,6 @@ class ShjNineService
/** /**
* 【処理5】オペレータキュー作成駐輪場単位・情報不備がある場合のみ * 【処理5】オペレータキュー作成駐輪場単位・情報不備がある場合のみ
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:253-280
* - que_class: 14(集計対象エラー) * - que_class: 14(集計対象エラー)
* - que_comment: 空文字("" * - que_comment: 空文字(""
* - que_status: 1(キュー発生) * - que_status: 1(キュー発生)
@ -837,7 +824,6 @@ class ShjNineService
/** /**
* SHJ-8 バッチ処理ログ作成 * SHJ-8 バッチ処理ログ作成
* *
* 仕様 todo/SHJ-9/SHJ-9.txt:289-300
* 共通処理「SHJ-8 バッチ処理ログ作成」を呼び出す * 共通処理「SHJ-8 バッチ処理ログ作成」を呼び出す
* *
* @param string $jobName ジョブ名 * @param string $jobName ジョブ名
@ -848,13 +834,11 @@ class ShjNineService
private function callShjEight(string $jobName, string $status, string $statusComment): array private function callShjEight(string $jobName, string $status, string $statusComment): array
{ {
try { try {
$device = Device::orderBy('device_id')->first(); // 仕様書: SHJ-9パラメーター仕様 デバイスID = (空)
$deviceId = $device ? $device->device_id : 1;
$today = now()->format('Y/m/d'); $today = now()->format('Y/m/d');
$result = $this->shjEightService->execute( $result = $this->shjEightService->execute(
$deviceId, null,
'SHJ-9', 'SHJ-9',
$jobName, $jobName,
$status, $status,

View File

@ -201,8 +201,34 @@ class ShjSixService
} }
// 【処理5】バッチ処理ログを作成する - SHJ-8呼び出し // 【処理5】バッチ処理ログを作成する - SHJ-8呼び出し
// 仕様書準拠:ステータスコメント = バッチコメント + 各件数 // 仕様書準拠JOB5 は常に実行するJOB4 の結果に関わらず)
// 注bat_job_log.device_id は int unsigned のため連結文字列は格納不可
// 先頭デバイスIDを使用。デバイスなしの場合は 0
// SHJ-8 はエラー返却するが、式様書上 result≠0 でも「処理を終了する」のため問題なし)
$deviceIds = $devices->pluck('device_id')->toArray();
$deviceId = !empty($deviceIds) ? (int)$deviceIds[0] : 0;
// デバイスが0件の場合はバッチコメントに明記JOB3がスキップされた理由を記録
if (empty($deviceIds)) {
$accumulatedBatchComment .= ($accumulatedBatchComment ? '、' : '')
. 'デバイステーブル空JOB3スキップ';
}
// JOB4 監視対象ログ情報を整形varchar(255)超過防止のため最大5件ID表示
$monitoredIds = $printerResult['monitored_log_ids'] ?? [];
$monitoredCount = count($monitoredIds);
if ($monitoredCount === 0) {
$job4Summary = 'JOB4監視:0件';
} elseif ($monitoredCount <= 5) {
$job4Summary = 'JOB4監視:' . $monitoredCount . '件[ID:' . implode(',', $monitoredIds) . ']';
} else {
$shownIds = array_slice($monitoredIds, 0, 5);
$job4Summary = 'JOB4監視:' . $monitoredCount . '件[ID:' . implode(',', $shownIds) . '...]';
}
// ステータスコメント = バッチコメント + JOB4監視情報 + 各件数
$statusComment = $accumulatedBatchComment $statusComment = $accumulatedBatchComment
. '、' . $job4Summary
. ':メール正常終了件数' . $totalMailSuccessCount . ':メール正常終了件数' . $totalMailSuccessCount
. '、メール異常終了件数' . $totalMailErrorCount . '、メール異常終了件数' . $totalMailErrorCount
. '、キュー登録正常終了件数' . $totalQueueSuccessCount . '、キュー登録正常終了件数' . $totalQueueSuccessCount
@ -213,13 +239,6 @@ class ShjSixService
'SHJ-6 サーバ死活監視処理正常完了' : 'SHJ-6 サーバ死活監視処理正常完了' :
'SHJ-6 サーバ死活監視処理完了(警告あり)'; 'SHJ-6 サーバ死活監視処理完了(警告あり)';
// 仕様書準拠JOB5 は常に実行するJOB4 の結果に関わらず)
// 注bat_job_log.device_id は int unsigned のため連結文字列は格納不可
// 先頭デバイスIDを使用。デバイスなしの場合は 0
// SHJ-8 はエラー返却するが、式様書上 result≠0 でも「処理を終了する」のため問題なし)
$deviceIds = $devices->pluck('device_id')->toArray();
$deviceId = !empty($deviceIds) ? (int)$deviceIds[0] : 0;
// SHJ-8 バッチ処理ログ作成 // SHJ-8 バッチ処理ログ作成
$shj8Result = $this->createShjBatchLog( $shj8Result = $this->createShjBatchLog(
$deviceId, $deviceId,
@ -483,6 +502,10 @@ class ShjSixService
// 仕様書: ステータス >= 100 // 仕様書: ステータス >= 100
// status は varchar型のため CAST で数値変換して比較 // status は varchar型のため CAST で数値変換して比較
$errorLogs = DB::table('print_job_log') $errorLogs = DB::table('print_job_log')
->select([
'job_log_id', 'park_id', 'user_id', 'contract_id',
'process_name', 'job_name', 'status', 'error_code', 'status_comment',
])
->where('created_at', '>=', $fifteenMinutesAgo) ->where('created_at', '>=', $fifteenMinutesAgo)
->where('created_at', '<=', now()) ->where('created_at', '<=', now())
->whereRaw('CAST(status AS SIGNED) >= 100') ->whereRaw('CAST(status AS SIGNED) >= 100')
@ -575,6 +598,7 @@ class ShjSixService
return [ return [
'success' => true, 'success' => true,
'error_count' => $errorLogs->count(), 'error_count' => $errorLogs->count(),
'monitored_log_ids' => $errorLogs->pluck('job_log_id')->toArray(), // JOB4監視対象ログID一覧
'mail_success_count' => $mailSuccessCount, 'mail_success_count' => $mailSuccessCount,
'mail_error_count' => $mailErrorCount, 'mail_error_count' => $mailErrorCount,
'queue_success_count' => $queueSuccessCount, // 仕様書準拠 'queue_success_count' => $queueSuccessCount, // 仕様書準拠

View File

@ -1,12 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace App\Services; namespace App\Services;
use App\Models\Park; use App\Models\Park;
use App\Models\EarningsSummary; use App\Models\EarningsSummary;
use App\Models\Psection; use App\Models\Psection;
use App\Models\OperatorQue; use App\Models\OperatorQue;
use App\Models\Device;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Carbon\Carbon; use Carbon\Carbon;
@ -19,13 +20,6 @@ use Carbon\Carbon;
*/ */
class ShjTenService class ShjTenService
{ {
/**
* 財政年度開始月
*
* @var int
*/
const FISCAL_START_MONTH = 4;
/** /**
* バッチ実行者の固定オペレータID * バッチ実行者の固定オペレータID
*/ */
@ -58,10 +52,25 @@ class ShjTenService
$this->shjEightService = $shjEightService; $this->shjEightService = $shjEightService;
} }
/**
* パラメーター不正時のバッチ処理ログ作成JOB1→JOB5パス
* パラメーター.集計対象年月日が日付形式ではない場合 ステータスコメント設定 JOB5へ
* JOB5ではバッチ処理ログを必ず作成する
*
* @param string $type 集計種別yearly/monthly
* @return void
*/
public function logValidationError(string $type): void
{
$typeLabel = $this->getTypeLabel($type);
$statusComment = "売上集計{$typeLabel}:パラメーターが不正です。(日付形式ではありません)";
$this->callShjEight('SHJ-10売上集計年次・月次', 'success', $statusComment);
}
/** /**
* SHJ-10 財政年度売上集計処理メイン実行 * SHJ-10 財政年度売上集計処理メイン実行
* *
* 処理フロー (todo/SHJ-10/SHJ-10.txt): * 処理フロー:
* 【処理1】集計対象を設定する * 【処理1】集計対象を設定する
* 【処理2】駐輪場マスタを取得する * 【処理2】駐輪場マスタを取得する
* 【判断1】取得件数判定 * 【判断1】取得件数判定
@ -100,9 +109,6 @@ class ShjTenService
$statusComment = "売上集計{$typeLabel}:駐輪場マスタが存在していません。"; $statusComment = "売上集計{$typeLabel}:駐輪場マスタが存在していません。";
$statusComments[] = $statusComment; $statusComments[] = $statusComment;
// 【処理5】オペレータキュー作成
$this->createOperatorQueue($statusComment, null);
// SHJ-8 バッチ処理ログ作成 // SHJ-8 バッチ処理ログ作成
$this->callShjEight('SHJ-10売上集計年次・月次', 'success', $statusComment); $this->callShjEight('SHJ-10売上集計年次・月次', 'success', $statusComment);
@ -135,12 +141,8 @@ class ShjTenService
} }
} }
// 最終ステータスコメント生成 // 最終ステータスコメント生成(仕様 JOB5ステータスコメント情報不備
$typeLabel = $this->getTypeLabel($type); $finalStatusComment = implode('', $statusComments) . implode('', $dataIntegrityIssues);
$finalStatusComment = "売上集計{$typeLabel}:対象={$fiscalPeriod['target_label']}、駐輪場数={$processedParks}、集計レコード数={$summaryRecords}";
if (!empty($dataIntegrityIssues)) {
$finalStatusComment .= "、情報不備=" . implode('、', $dataIntegrityIssues);
}
// 【処理5】オペレータキュー作成 // 【処理5】オペレータキュー作成
// ※ 駐輪場単位で既に作成済みprocessFiscalEarningsForPark内で情報不備検出時に実施 // ※ 駐輪場単位で既に作成済みprocessFiscalEarningsForPark内で情報不備検出時に実施
@ -258,7 +260,7 @@ class ShjTenService
// 0. 情報不備チェック // 0. 情報不備チェック
$dataIntegrityIssue = $this->checkDataIntegrity($park->park_id, $startDate, $endDate); $dataIntegrityIssue = $this->checkDataIntegrity($park->park_id, $startDate, $endDate);
// 情報不備がある場合、駐輪場単位でオペレータキュー作成(仕様 todo/SHJ-10/SHJ-10.txt:289-299 // 情報不備がある場合、駐輪場単位でオペレータキューを作成する
if ($dataIntegrityIssue !== '情報不備:なし') { if ($dataIntegrityIssue !== '情報不備:なし') {
$this->createOperatorQueue($dataIntegrityIssue, $park->park_id); $this->createOperatorQueue($dataIntegrityIssue, $park->park_id);
} }
@ -277,7 +279,7 @@ class ShjTenService
// 【判断2】データがいずれかあれば【処理4】へ // 【判断2】データがいずれかあれば【処理4】へ
if (empty($regularData) && empty($lumpsumData) && empty($refundData) && empty($reissueData)) { if (empty($regularData) && empty($lumpsumData) && empty($refundData) && empty($reissueData)) {
// 対象データなし - 仕様 todo/SHJ-10/SHJ-10.txt:209-211 // 対象データなし
$typeLabel = $this->getTypeLabel($aggregationTarget['type']); $typeLabel = $this->getTypeLabel($aggregationTarget['type']);
$noDataMessage = "売上集計{$typeLabel}{$startDate}{$endDate}/駐輪場:{$park->park_name}:売上データが存在しません。"; $noDataMessage = "売上集計{$typeLabel}{$startDate}{$endDate}/駐輪場:{$park->park_name}:売上データが存在しません。";
@ -331,8 +333,6 @@ class ShjTenService
/** /**
* 0. 情報不備チェック(期間集計版) * 0. 情報不備チェック(期間集計版)
* *
* 仕様 todo/SHJ-10/SHJ-10.txt:77-101
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $startDate 集計開始日YYYY-MM-DD * @param string $startDate 集計開始日YYYY-MM-DD
* @param string $endDate 集計終了日YYYY-MM-DD * @param string $endDate 集計終了日YYYY-MM-DD
@ -363,19 +363,7 @@ class ShjTenService
/** /**
* 定期契約データ取得(車種区分・分類名1・定期有効月数毎) * 定期契約データ取得(車種区分・分類名1・定期有効月数毎)
* 金額・件数は全て0固定だが、分類や月数の組み合わせごとにレコードが必要
* *
* 仕様 todo/SHJ-10/SHJ-10.txt:104-128
*
* @param int $parkId 駐輪場ID
* @param string $startDate 集計開始日YYYY-MM-DD
* @param string $endDate 集計終了日YYYY-MM-DD
* @return array
*/
/**
* 定期契約データ取得(車種区分・分類名1・定期有効月数毎)
*
* 仕様 todo/SHJ-10/SHJ-10.txt:104-129
* SQL定義減免措置・継続フラグ・車種区分・分類名・有効月数でグループ化し、 * SQL定義減免措置・継続フラグ・車種区分・分類名・有効月数でグループ化し、
* 授受金額の合計と件数を算出する * 授受金額の合計と件数を算出する
* *
@ -418,8 +406,6 @@ class ShjTenService
/** /**
* 一時金データ取得(車種毎) * 一時金データ取得(車種毎)
* *
* 仕様 todo/SHJ-10/SHJ-10.txt:148-159
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $startDate 集計開始日YYYY-MM-DD * @param string $startDate 集計開始日YYYY-MM-DD
* @param string $endDate 集計終了日YYYY-MM-DD * @param string $endDate 集計終了日YYYY-MM-DD
@ -444,8 +430,6 @@ class ShjTenService
/** /**
* 解約返戻金データ取得(車種区分毎) * 解約返戻金データ取得(車種区分毎)
* *
* 仕様 todo/SHJ-10/SHJ-10.txt:160-171
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $startDate 集計開始日YYYY-MM-DD * @param string $startDate 集計開始日YYYY-MM-DD
* @param string $endDate 集計終了日YYYY-MM-DD * @param string $endDate 集計終了日YYYY-MM-DD
@ -470,8 +454,6 @@ class ShjTenService
/** /**
* 再発行データ取得(車種区分毎) * 再発行データ取得(車種区分毎)
* *
* 仕様 todo/SHJ-10/SHJ-10.txt:172-183
*
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param string $startDate 集計開始日YYYY-MM-DD * @param string $startDate 集計開始日YYYY-MM-DD
* @param string $endDate 集計終了日YYYY-MM-DD * @param string $endDate 集計終了日YYYY-MM-DD
@ -501,8 +483,6 @@ class ShjTenService
* ここで park_id + psection_id + usertype_subject1 + enable_months をキーに統合し、 * ここで park_id + psection_id + usertype_subject1 + enable_months をキーに統合し、
* 新規/更新 × 減免/通常 の各件数・金額を1つのオブジェクトに集約する。 * 新規/更新 × 減免/通常 の各件数・金額を1つのオブジェクトに集約する。
* *
* 仕様 todo/SHJ-10/SHJ-10.txt:130-147
*
* @param array $regularData calculateRegularEarnings()の結果 * @param array $regularData calculateRegularEarnings()の結果
* @return array キーpsection_id|usertype|months、値統合されたデータオブジェクト * @return array キーpsection_id|usertype|months、値統合されたデータオブジェクト
*/ */
@ -652,12 +632,18 @@ class ShjTenService
?string $usertypeSubject1, ?string $usertypeSubject1,
int $enableMonths int $enableMonths
): void { ): void {
// 仕様書どおり、同一キーの組み合わせで削除 // 同一キーのレコードを先に削除してから登録する
$query = DB::table('earnings_summary') $query = DB::table('earnings_summary')
->where('park_id', $parkId) ->where('park_id', $parkId)
->where('summary_type', $aggregationTarget['summary_type']) ->where('summary_type', $aggregationTarget['summary_type'])
->whereNull('summary_start_date') ->where(function ($q) use ($aggregationTarget) {
->whereNull('summary_end_date') $q->whereNull('summary_start_date')
->orWhere('summary_start_date', $aggregationTarget['start_date']);
})
->where(function ($q) use ($aggregationTarget) {
$q->whereNull('summary_end_date')
->orWhere('summary_end_date', $aggregationTarget['end_date']);
})
->where('earnings_date', $aggregationTarget['earnings_date']) ->where('earnings_date', $aggregationTarget['earnings_date'])
->where('psection_id', $psectionId) ->where('psection_id', $psectionId)
->where('enable_months', $enableMonths); ->where('enable_months', $enableMonths);
@ -724,7 +710,7 @@ class ShjTenService
if ($dataType === 'regular') { if ($dataType === 'regular') {
// 定期契約データの場合mergeRegularDataByGroup()で既に統合済み // 定期契約データの場合mergeRegularDataByGroup()で既に統合済み
// 新規/更新 × 減免/通常 の各件数・金額がすべて含まれている (仕様line 130-147) // 新規/更新 × 減免/通常 の各件数・金額がすべて含まれている
$insertData = array_merge($insertData, [ $insertData = array_merge($insertData, [
'regular_new_count' => $data->regular_new_count ?? 0, 'regular_new_count' => $data->regular_new_count ?? 0,
'regular_new_amount' => $data->regular_new_amount ?? 0, 'regular_new_amount' => $data->regular_new_amount ?? 0,
@ -734,32 +720,32 @@ class ShjTenService
'regular_update_amount' => $data->regular_update_amount ?? 0, 'regular_update_amount' => $data->regular_update_amount ?? 0,
'regular_update_reduction_count' => $data->regular_update_reduction_count ?? 0, 'regular_update_reduction_count' => $data->regular_update_reduction_count ?? 0,
'regular_update_reduction_amount' => $data->regular_update_reduction_amount ?? 0, 'regular_update_reduction_amount' => $data->regular_update_reduction_amount ?? 0,
'lumpsum_count' => 0, // 仕様line 140 'lumpsum_count' => 0,
'lumpsum' => 0, // 仕様line 141 'lumpsum' => 0,
'refunds' => 0, // 仕様line 142 'refunds' => 0,
'other_income' => 0, // 仕様line 143 'other_income' => 0,
'other_spending' => 0, // 仕様line 144 'other_spending' => 0,
'reissue_count' => 0, // 仕様line 145 'reissue_count' => 0,
'reissue_amount' => 0 // 仕様line 146 'reissue_amount' => 0
]); ]);
} else { } else {
// 一時金・解約・再発行データの場合定期フィールドは0固定 (仕様line 186-202) // 一時金・解約・再発行データの場合定期フィールドは0固定
$insertData = array_merge($insertData, [ $insertData = array_merge($insertData, [
'regular_new_count' => 0, // 仕様line 186 'regular_new_count' => 0,
'regular_new_amount' => 0, // 仕様line 187 'regular_new_amount' => 0,
'regular_new_reduction_count' => 0, // 仕様line 188 'regular_new_reduction_count' => 0,
'regular_new_reduction_amount' => 0, // 仕様line 189 'regular_new_reduction_amount' => 0,
'regular_update_count' => 0, // 仕様line 190 'regular_update_count' => 0,
'regular_update_amount' => 0, // 仕様line 191 'regular_update_amount' => 0,
'regular_update_reduction_count' => 0, // 仕様line 192 'regular_update_reduction_count' => 0,
'regular_update_reduction_amount' => 0, // 仕様line 193 'regular_update_reduction_amount' => 0,
'lumpsum_count' => $data->lumpsum_count ?? 0, // 仕様line 194 'lumpsum_count' => $data->lumpsum_count ?? 0,
'lumpsum' => $data->lumpsum ?? 0, // 仕様line 195 'lumpsum' => $data->lumpsum ?? 0,
'refunds' => $data->refunds ?? 0, // 仕様line 196 'refunds' => $data->refunds ?? 0,
'other_income' => 0, // 仕様line 197 'other_income' => 0,
'other_spending' => 0, // 仕様line 198 'other_spending' => 0,
'reissue_count' => $data->reissue_count ?? 0, // 仕様line 199 'reissue_count' => $data->reissue_count ?? 0,
'reissue_amount' => 0 // 仕様line 200: 0固定 'reissue_amount' => 0
]); ]);
} }
@ -776,13 +762,12 @@ class ShjTenService
/** /**
* 【処理5】オペレータキュー作成駐輪場単位・情報不備がある場合のみ * 【処理5】オペレータキュー作成駐輪場単位・情報不備がある場合のみ
* *
* 仕様 todo/SHJ-10/SHJ-10.txt:289-317
* - que_class: 14(集計対象エラー) * - que_class: 14(集計対象エラー)
* - que_comment: 仕様書line 297 * - que_comment:
* - que_status: 1(キュー発生) * - que_status: 1(キュー発生)
* - que_status_comment: 仕様書line 299 * - que_status_comment:
* - work_instructions: 情報不備メッセージ仕様書line 300 * - work_instructions: 情報不備メッセージ
* - park_id: 駐輪場ID(仕様 "処理1.駐輪場ID"、パラメータエラー時はnull * - park_id: 駐輪場ID
* - operator_id: 9999999(バッチ処理固定値) * - operator_id: 9999999(バッチ処理固定値)
* *
* @param string $message 情報不備メッセージ * @param string $message 情報不備メッセージ
@ -835,13 +820,11 @@ class ShjTenService
private function callShjEight(string $jobName, string $status, string $statusComment): void private function callShjEight(string $jobName, string $status, string $statusComment): void
{ {
try { try {
$device = Device::orderBy('device_id')->first(); // デバイスIDは空nullで固定
$deviceId = $device ? $device->device_id : 1;
$today = now()->format('Y/m/d'); $today = now()->format('Y/m/d');
$this->shjEightService->execute( $this->shjEightService->execute(
$deviceId, null,
'SHJ-10', 'SHJ-10',
$jobName, $jobName,
$status, $status,

20
config/shj10.php Normal file
View File

@ -0,0 +1,20 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| SHJ-10 売上集計処理 Configuration
|--------------------------------------------------------------------------
| SHJ-10バッチ処理の設定ファイル
|
*/
/*
|--------------------------------------------------------------------------
| 財政年度開始月
|--------------------------------------------------------------------------
| 仕様:開始月は Config 等で定義し変更可能とする
| 環境変数 SHJ10_FISCAL_START_MONTH で上書き可能
*/
'fiscal_start_month' => env('SHJ10_FISCAL_START_MONTH', 4),
];