Merge pull request 'main_go' (#8) from main_go into main
All checks were successful
Deploy main / deploy (push) Successful in 22s
All checks were successful
Deploy main / deploy (push) Successful in 22s
Reviewed-on: #8
This commit is contained in:
commit
20d99f2102
20
.gitea/workflows/deploy-preview.yml
Normal file
20
.gitea/workflows/deploy-preview.yml
Normal file
@ -0,0 +1,20 @@
|
||||
name: Deploy preview (main_go)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main_go"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: deploy-main_go
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ["native"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Deploy to preview (main_go)
|
||||
env:
|
||||
BRANCH: main_go
|
||||
run: /usr/local/bin/deploy_branch_simple.sh
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@ yarn-error.log
|
||||
/.nova
|
||||
/.vscode
|
||||
/.zed
|
||||
/docs
|
||||
|
||||
206
app/Console/Commands/ShjNineCommand.php
Normal file
206
app/Console/Commands/ShjNineCommand.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Services\ShjNineService;
|
||||
|
||||
/**
|
||||
* SHJ-9 売上集計処理コマンド
|
||||
*
|
||||
* 駐輪場の売上データを日次・月次・年次で集計する処理を実行する
|
||||
* バックグラウンドで実行される定期バッチ処理
|
||||
*/
|
||||
class ShjNineCommand extends Command
|
||||
{
|
||||
/**
|
||||
* コンソールコマンドの名前とシグネチャ
|
||||
*
|
||||
* 引数:
|
||||
* - type: 集計種別 (daily/monthly/yearly) (必須)
|
||||
* - target_date: 集計対象日 (オプション、YYYY-MM-DD形式)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'shj:9 {type : 集計種別(daily/monthly/yearly)} {target_date? : 集計対象日(YYYY-MM-DD)}';
|
||||
|
||||
/**
|
||||
* コンソールコマンドの説明
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'SHJ-9 売上集計処理 - 日次/月次/年次売上データ集計を実行';
|
||||
|
||||
/**
|
||||
* SHJ-9サービスクラス
|
||||
*
|
||||
* @var ShjNineService
|
||||
*/
|
||||
protected $shjNineService;
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*
|
||||
* @param ShjNineService $shjNineService
|
||||
*/
|
||||
public function __construct(ShjNineService $shjNineService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->shjNineService = $shjNineService;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンソールコマンドを実行
|
||||
*
|
||||
* 処理フロー:
|
||||
* 1. パラメータ取得と検証
|
||||
* 2. 集計対象日設定
|
||||
* 3. 売上集計処理実行
|
||||
* 4. バッチログ作成
|
||||
* 5. 処理結果返却
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
// 開始ログ出力
|
||||
$startTime = now();
|
||||
$this->info('SHJ-9 売上集計処理を開始します。');
|
||||
|
||||
// 引数取得
|
||||
$type = $this->argument('type');
|
||||
$targetDate = $this->argument('target_date');
|
||||
|
||||
Log::info('SHJ-9 売上集計処理開始', [
|
||||
'start_time' => $startTime,
|
||||
'type' => $type,
|
||||
'target_date' => $targetDate
|
||||
]);
|
||||
|
||||
// パラメータ検証
|
||||
if (!$this->validateParameters($type, $targetDate)) {
|
||||
$this->error('パラメータが不正です。');
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
// 集計対象日設定
|
||||
$aggregationDate = $this->determineAggregationDate($type, $targetDate);
|
||||
|
||||
$this->info("集計種別: {$type}");
|
||||
$this->info("集計対象日: {$aggregationDate}");
|
||||
|
||||
// SHJ-9処理実行
|
||||
$result = $this->shjNineService->executeEarningsAggregation($type, $aggregationDate);
|
||||
|
||||
// 処理結果確認
|
||||
if ($result['success']) {
|
||||
$endTime = now();
|
||||
$this->info('SHJ-9 売上集計処理が正常に完了しました。');
|
||||
$this->info("処理時間: {$startTime->diffInSeconds($endTime)}秒");
|
||||
$this->info("処理結果: 駐輪場数 {$result['processed_parks']}, 集計レコード数 {$result['summary_records']}");
|
||||
|
||||
Log::info('SHJ-9 売上集計処理完了', [
|
||||
'end_time' => $endTime,
|
||||
'duration_seconds' => $startTime->diffInSeconds($endTime),
|
||||
'result' => $result
|
||||
]);
|
||||
|
||||
return self::SUCCESS;
|
||||
} else {
|
||||
$this->error('SHJ-9 売上集計処理でエラーが発生しました: ' . $result['message']);
|
||||
Log::error('SHJ-9 売上集計処理エラー', [
|
||||
'error' => $result['message'],
|
||||
'details' => $result['details'] ?? null
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->error('SHJ-9 売上集計処理で予期しないエラーが発生しました: ' . $e->getMessage());
|
||||
Log::error('SHJ-9 売上集計処理例外エラー', [
|
||||
'exception' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パラメータの妥当性を検証
|
||||
*
|
||||
* @param string $type 集計種別
|
||||
* @param string|null $targetDate 対象日
|
||||
* @return bool 検証結果
|
||||
*/
|
||||
private function validateParameters(string $type, ?string $targetDate): bool
|
||||
{
|
||||
// 集計種別チェック
|
||||
$allowedTypes = ['daily', 'monthly', 'yearly'];
|
||||
if (!in_array($type, $allowedTypes)) {
|
||||
$this->error('集計種別は daily, monthly, yearly のいずれかを指定してください。');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 対象日形式チェック(指定されている場合)
|
||||
if ($targetDate && !$this->isValidDateFormat($targetDate)) {
|
||||
$this->error('対象日の形式が正しくありません(YYYY-MM-DD形式で指定してください)。');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 集計対象日を決定
|
||||
*
|
||||
* @param string $type 集計種別
|
||||
* @param string|null $targetDate 指定日
|
||||
* @return string 集計対象日
|
||||
*/
|
||||
private function determineAggregationDate(string $type, ?string $targetDate): string
|
||||
{
|
||||
if ($targetDate) {
|
||||
return $targetDate;
|
||||
}
|
||||
|
||||
// パラメータ指定がない場合のデフォルト設定
|
||||
switch ($type) {
|
||||
case 'daily':
|
||||
// 日次:昨日(本日の1日前)
|
||||
return now()->subDay()->format('Y-m-d');
|
||||
|
||||
case 'monthly':
|
||||
// 月次:前月の最終日
|
||||
return now()->subMonth()->endOfMonth()->format('Y-m-d');
|
||||
|
||||
case 'yearly':
|
||||
// 年次:前年の最終日
|
||||
return now()->subYear()->endOfYear()->format('Y-m-d');
|
||||
|
||||
default:
|
||||
return now()->subDay()->format('Y-m-d');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日付形式の検証
|
||||
*
|
||||
* @param string $date 日付文字列
|
||||
* @return bool 有効な日付形式かどうか
|
||||
*/
|
||||
private function isValidDateFormat(string $date): bool
|
||||
{
|
||||
// YYYY-MM-DD形式の正規表現チェック
|
||||
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 実際の日付として有効かチェック
|
||||
$dateParts = explode('-', $date);
|
||||
return checkdate((int)$dateParts[1], (int)$dateParts[2], (int)$dateParts[0]);
|
||||
}
|
||||
}
|
||||
129
app/Console/Commands/ShjSixCommand.php
Normal file
129
app/Console/Commands/ShjSixCommand.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Services\ShjSixService;
|
||||
|
||||
/**
|
||||
* SHJ-6 サーバ死活監視処理コマンド
|
||||
*
|
||||
* サーバとデバイスの死活監視を行い、異常時にはメール通知を実行する
|
||||
* 定期実行またはオンデマンド実行のバックグラウンドバッチ処理
|
||||
*/
|
||||
class ShjSixCommand extends Command
|
||||
{
|
||||
/**
|
||||
* コンソールコマンドの名前とシグネチャ
|
||||
*
|
||||
* パラメータなしで実行
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'shj:6';
|
||||
|
||||
/**
|
||||
* コンソールコマンドの説明
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'SHJ-6 サーバ死活監視処理 - サーバ・デバイス監視とアラート通知を実行';
|
||||
|
||||
/**
|
||||
* SHJ-6サービスクラス
|
||||
*
|
||||
* @var ShjSixService
|
||||
*/
|
||||
protected $shjSixService;
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*
|
||||
* @param ShjSixService $shjSixService
|
||||
*/
|
||||
public function __construct(ShjSixService $shjSixService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->shjSixService = $shjSixService;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンソールコマンドを実行
|
||||
*
|
||||
* 処理フロー:
|
||||
* 1. サーバ死活監視(DBアクセス)
|
||||
* 2. デバイス管理マスタを取得する
|
||||
* 3. デバイス毎のハードウェア状態を取得する
|
||||
* 4. プリンタ制御プログラムログを取得する
|
||||
* 5. バッチ処理ログを作成する
|
||||
* ※ 異常検出時は共通A処理(メール通知)を実行
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
// 開始ログ出力
|
||||
$startTime = now();
|
||||
$this->info('SHJ-6 サーバ死活監視処理を開始します。');
|
||||
|
||||
Log::info('SHJ-6 サーバ死活監視処理開始', [
|
||||
'start_time' => $startTime
|
||||
]);
|
||||
|
||||
// SHJ-6監視処理実行
|
||||
$result = $this->shjSixService->executeServerMonitoring();
|
||||
|
||||
// 処理結果確認
|
||||
if ($result['success']) {
|
||||
$endTime = now();
|
||||
$this->info('SHJ-6 サーバ死活監視処理が正常に完了しました。');
|
||||
$this->info("処理時間: {$startTime->diffInSeconds($endTime)}秒");
|
||||
$this->info("監視結果: {$result['monitoring_summary']}");
|
||||
|
||||
// 警告がある場合は表示
|
||||
if (!empty($result['warnings'])) {
|
||||
$this->warn('警告が検出されました:');
|
||||
foreach ($result['warnings'] as $warning) {
|
||||
$this->warn("- {$warning}");
|
||||
}
|
||||
}
|
||||
|
||||
Log::info('SHJ-6 サーバ死活監視処理完了', [
|
||||
'end_time' => $endTime,
|
||||
'duration_seconds' => $startTime->diffInSeconds($endTime),
|
||||
'result' => $result
|
||||
]);
|
||||
|
||||
return self::SUCCESS;
|
||||
} else {
|
||||
$this->error('SHJ-6 サーバ死活監視処理でエラーが発生しました: ' . $result['message']);
|
||||
|
||||
// エラー詳細があれば表示
|
||||
if (!empty($result['error_details'])) {
|
||||
$this->error('エラー詳細:');
|
||||
foreach ($result['error_details'] as $detail) {
|
||||
$this->error("- {$detail}");
|
||||
}
|
||||
}
|
||||
|
||||
Log::error('SHJ-6 サーバ死活監視処理エラー', [
|
||||
'error' => $result['message'],
|
||||
'details' => $result['error_details'] ?? null
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->error('SHJ-6 サーバ死活監視処理で予期しないエラーが発生しました: ' . $e->getMessage());
|
||||
Log::error('SHJ-6 サーバ死活監視処理例外エラー', [
|
||||
'exception' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
236
app/Console/Commands/ShjTenCommand.php
Normal file
236
app/Console/Commands/ShjTenCommand.php
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Services\ShjTenService;
|
||||
|
||||
/**
|
||||
* SHJ-10 売上集計処理コマンド
|
||||
*
|
||||
* 駐輪場の売上データを財政年度ベースで年次・月次集計する処理を実行する
|
||||
* 4月開始の財政年度期間で計算するバックグラウンドバッチ処理
|
||||
*/
|
||||
class ShjTenCommand extends Command
|
||||
{
|
||||
/**
|
||||
* コンソールコマンドの名前とシグネチャ
|
||||
*
|
||||
* 引数:
|
||||
* - type: 集計種別 (yearly/monthly) (必須)
|
||||
* - target: 集計対象 (必須)
|
||||
* - yearly: 年度 (例: 2019)
|
||||
* - monthly: 年月 (例: 2019/01)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'shj:10 {type : 集計種別(yearly/monthly)} {target : 集計対象(yearly:年度, monthly:年月)}';
|
||||
|
||||
/**
|
||||
* コンソールコマンドの説明
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'SHJ-10 売上集計処理 - 財政年度ベース年次/月次売上データ集計を実行';
|
||||
|
||||
/**
|
||||
* SHJ-10サービスクラス
|
||||
*
|
||||
* @var ShjTenService
|
||||
*/
|
||||
protected $shjTenService;
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*
|
||||
* @param ShjTenService $shjTenService
|
||||
*/
|
||||
public function __construct(ShjTenService $shjTenService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->shjTenService = $shjTenService;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンソールコマンドを実行
|
||||
*
|
||||
* 処理フロー:
|
||||
* 1. パラメータ取得と検証
|
||||
* 2. 財政年度期間設定
|
||||
* 3. 売上集計処理実行
|
||||
* 4. バッチログ作成
|
||||
* 5. 処理結果返却
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
// 開始ログ出力
|
||||
$startTime = now();
|
||||
$this->info('SHJ-10 売上集計処理を開始します。');
|
||||
|
||||
// 引数取得
|
||||
$type = $this->argument('type');
|
||||
$target = $this->argument('target');
|
||||
|
||||
Log::info('SHJ-10 売上集計処理開始', [
|
||||
'start_time' => $startTime,
|
||||
'type' => $type,
|
||||
'target' => $target
|
||||
]);
|
||||
|
||||
// パラメータ検証
|
||||
if (!$this->validateParameters($type, $target)) {
|
||||
$this->error('パラメータが不正です。');
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
// 財政年度期間設定
|
||||
$fiscalPeriod = $this->determineFiscalPeriod($type, $target);
|
||||
|
||||
$this->info("集計種別: {$type}");
|
||||
$this->info("集計対象: {$target}");
|
||||
$this->info("財政期間: {$fiscalPeriod['start_date']} ~ {$fiscalPeriod['end_date']}");
|
||||
|
||||
// SHJ-10処理実行
|
||||
$result = $this->shjTenService->executeFiscalEarningsAggregation($type, $target, $fiscalPeriod);
|
||||
|
||||
// 処理結果確認
|
||||
if ($result['success']) {
|
||||
$endTime = now();
|
||||
$this->info('SHJ-10 売上集計処理が正常に完了しました。');
|
||||
$this->info("処理時間: {$startTime->diffInSeconds($endTime)}秒");
|
||||
$this->info("処理結果: 駐輪場数 {$result['processed_parks']}, 集計レコード数 {$result['summary_records']}");
|
||||
|
||||
Log::info('SHJ-10 売上集計処理完了', [
|
||||
'end_time' => $endTime,
|
||||
'duration_seconds' => $startTime->diffInSeconds($endTime),
|
||||
'result' => $result
|
||||
]);
|
||||
|
||||
return self::SUCCESS;
|
||||
} else {
|
||||
$this->error('SHJ-10 売上集計処理でエラーが発生しました: ' . $result['message']);
|
||||
Log::error('SHJ-10 売上集計処理エラー', [
|
||||
'error' => $result['message'],
|
||||
'details' => $result['details'] ?? null
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->error('SHJ-10 売上集計処理で予期しないエラーが発生しました: ' . $e->getMessage());
|
||||
Log::error('SHJ-10 売上集計処理例外エラー', [
|
||||
'exception' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パラメータの妥当性を検証
|
||||
*
|
||||
* @param string $type 集計種別
|
||||
* @param string $target 集計対象
|
||||
* @return bool 検証結果
|
||||
*/
|
||||
private function validateParameters(string $type, string $target): bool
|
||||
{
|
||||
// 集計種別チェック
|
||||
$allowedTypes = ['yearly', 'monthly'];
|
||||
if (!in_array($type, $allowedTypes)) {
|
||||
$this->error('集計種別は yearly, monthly のいずれかを指定してください。');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 集計対象形式チェック
|
||||
if ($type === 'yearly') {
|
||||
// 年度形式チェック (例: 2019)
|
||||
if (!preg_match('/^\d{4}$/', $target)) {
|
||||
$this->error('年次集計の場合、年度を4桁の数字で指定してください。(例: 2019)');
|
||||
return false;
|
||||
}
|
||||
} elseif ($type === 'monthly') {
|
||||
// 年月形式チェック (例: 2019/01)
|
||||
if (!preg_match('/^\d{4}\/\d{2}$/', $target)) {
|
||||
$this->error('月次集計の場合、年月をYYYY/MM形式で指定してください。(例: 2019/01)');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 月の範囲チェック (01-12)
|
||||
$parts = explode('/', $target);
|
||||
$month = (int)$parts[1];
|
||||
if ($month < 1 || $month > 12) {
|
||||
$this->error('月は01から12までの範囲で指定してください。');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 財政年度期間を決定
|
||||
*
|
||||
* 財政年度は4月開始(Config設定可能)
|
||||
* - yearly 2019: 2019年4月1日 ~ 2020年3月31日
|
||||
* - monthly 2019/01: 2019年1月1日 ~ 2019年1月31日
|
||||
*
|
||||
* @param string $type 集計種別
|
||||
* @param string $target 集計対象
|
||||
* @return array 財政期間情報
|
||||
*/
|
||||
private function determineFiscalPeriod(string $type, string $target): array
|
||||
{
|
||||
$fiscalStartMonth = 4; // 財政年度開始月(4月)
|
||||
|
||||
if ($type === 'yearly') {
|
||||
$year = (int)$target;
|
||||
|
||||
// 財政年度期間計算
|
||||
$startDate = sprintf('%04d-%02d-01', $year, $fiscalStartMonth);
|
||||
$endDate = sprintf('%04d-%02d-%02d', $year + 1, $fiscalStartMonth - 1,
|
||||
date('t', strtotime(sprintf('%04d-%02d-01', $year + 1, $fiscalStartMonth - 1))));
|
||||
|
||||
return [
|
||||
'type' => 'yearly',
|
||||
'fiscal_year' => $year,
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate,
|
||||
'summary_type' => 1, // 年次
|
||||
'target_label' => "{$year}年度"
|
||||
];
|
||||
|
||||
} elseif ($type === 'monthly') {
|
||||
$parts = explode('/', $target);
|
||||
$year = (int)$parts[0];
|
||||
$month = (int)$parts[1];
|
||||
|
||||
// 指定月の期間計算
|
||||
$startDate = sprintf('%04d-%02d-01', $year, $month);
|
||||
$endDate = sprintf('%04d-%02d-%02d', $year, $month,
|
||||
date('t', strtotime($startDate)));
|
||||
|
||||
// 該当する財政年度を計算
|
||||
$fiscalYear = $month >= $fiscalStartMonth ? $year : $year - 1;
|
||||
|
||||
return [
|
||||
'type' => 'monthly',
|
||||
'fiscal_year' => $fiscalYear,
|
||||
'target_year' => $year,
|
||||
'target_month' => $month,
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate,
|
||||
'summary_type' => 2, // 月次
|
||||
'target_label' => "{$year}年{$month}月"
|
||||
];
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("不正な集計種別: {$type}");
|
||||
}
|
||||
}
|
||||
@ -24,3 +24,5 @@ enum QueueClass: string
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -15,3 +15,5 @@ enum QueueStatus: string
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -85,3 +85,5 @@ class OperatorQue extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -56,3 +56,5 @@ class Park extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -112,3 +112,5 @@ class User extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -19,3 +19,4 @@ abstract class BaseModel extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -38,3 +38,5 @@ trait HasSortable
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
298
app/Models/EarningsSummary.php
Normal file
298
app/Models/EarningsSummary.php
Normal file
@ -0,0 +1,298 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* 売上集計結果モデル - earnings_summaryテーブル
|
||||
*
|
||||
* SHJ-9で作成される日次・月次・年次の売上集計データを管理
|
||||
*/
|
||||
class EarningsSummary extends Model
|
||||
{
|
||||
/**
|
||||
* テーブル名
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'earnings_summary';
|
||||
|
||||
/**
|
||||
* プライマリキー
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'earnings_summary_id';
|
||||
|
||||
/**
|
||||
* 一括代入可能な属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'park_id', // 駐輪場ID
|
||||
'summary_type', // 集計区分
|
||||
'summary_start_date', // 集計開始日
|
||||
'summary_end_date', // 集計終了日
|
||||
'earnings_date', // 売上日
|
||||
'psection_id', // 車種区分ID
|
||||
'usertype_subject1', // 規格
|
||||
'enable_months', // 期間(月数)
|
||||
'regular_new_count', // 期間件数
|
||||
'regular_new_amount', // 期間金額
|
||||
'regular_new_reduction_count', // 期間成免件数
|
||||
'regular_new_reduction_amount', // 期間成免金額
|
||||
'regular_update_count', // 更新件数
|
||||
'regular_update_amount', // 更新金額
|
||||
'regular_update_reduction_count', // 更新成免件数
|
||||
'regular_update_reduction_amount', // 更新成免金額
|
||||
'turnsum_count', // 残金件数
|
||||
'turnsum', // 残金
|
||||
'refunds', // 解時返戻金
|
||||
'other_income', // 分別収入
|
||||
'other_spending', // 分別支出
|
||||
'reissue_count', // 発行件数
|
||||
'reissue_amount', // 発行金額
|
||||
'summary_note', // 計備考
|
||||
'created_at', // 登録日時
|
||||
'updated_at', // 更新日時
|
||||
'operator_id' // 新法・ページID
|
||||
];
|
||||
|
||||
/**
|
||||
* キャストする属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'earnings_summary_id' => 'integer',
|
||||
'park_id' => 'integer',
|
||||
'psection_id' => 'integer',
|
||||
'enable_months' => 'integer',
|
||||
'regular_new_count' => 'integer',
|
||||
'regular_new_amount' => 'decimal:2',
|
||||
'regular_new_reduction_count' => 'integer',
|
||||
'regular_new_reduction_amount' => 'decimal:2',
|
||||
'regular_update_count' => 'integer',
|
||||
'regular_update_amount' => 'decimal:2',
|
||||
'regular_update_reduction_count' => 'integer',
|
||||
'regular_update_reduction_amount' => 'decimal:2',
|
||||
'turnsum_count' => 'integer',
|
||||
'turnsum' => 'decimal:2',
|
||||
'refunds' => 'decimal:2',
|
||||
'other_income' => 'decimal:2',
|
||||
'other_spending' => 'decimal:2',
|
||||
'reissue_count' => 'integer',
|
||||
'reissue_amount' => 'decimal:2',
|
||||
'operator_id' => 'integer',
|
||||
'summary_start_date' => 'date',
|
||||
'summary_end_date' => 'date',
|
||||
'earnings_date' => 'date',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime'
|
||||
];
|
||||
|
||||
/**
|
||||
* 日付属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = [
|
||||
'summary_start_date',
|
||||
'summary_end_date',
|
||||
'earnings_date',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* 集計タイプの定数
|
||||
*/
|
||||
const TYPE_DAILY = '日次';
|
||||
const TYPE_MONTHLY = '月次';
|
||||
const TYPE_YEARLY = '年次';
|
||||
|
||||
/**
|
||||
* 駐輪場との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function park()
|
||||
{
|
||||
return $this->belongsTo(Park::class, 'park_id', 'park_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 車種区分との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function psection()
|
||||
{
|
||||
return $this->belongsTo(Psection::class, 'psection_id', 'psection_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定期間の売上集計データを取得
|
||||
*
|
||||
* @param int $parkId 駐輪場ID
|
||||
* @param string $startDate 開始日
|
||||
* @param string $endDate 終了日
|
||||
* @param string|null $summaryType 集計タイプ
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getEarningsByPeriod(int $parkId, string $startDate, string $endDate, ?string $summaryType = null)
|
||||
{
|
||||
$query = self::where('park_id', $parkId)
|
||||
->whereBetween('earnings_date', [$startDate, $endDate]);
|
||||
|
||||
if ($summaryType) {
|
||||
$query->where('summary_type', $summaryType);
|
||||
}
|
||||
|
||||
return $query->with(['park', 'psection'])
|
||||
->orderBy('earnings_date')
|
||||
->orderBy('psection_id')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 駐輪場別の売上合計を取得
|
||||
*
|
||||
* @param int $parkId 駐輪場ID
|
||||
* @param string $startDate 開始日
|
||||
* @param string $endDate 終了日
|
||||
* @return array 売上合計データ
|
||||
*/
|
||||
public static function getEarningsTotalByPark(int $parkId, string $startDate, string $endDate): array
|
||||
{
|
||||
$result = self::where('park_id', $parkId)
|
||||
->whereBetween('earnings_date', [$startDate, $endDate])
|
||||
->selectRaw('
|
||||
SUM(regular_new_count) as total_new_count,
|
||||
SUM(regular_new_amount) as total_new_amount,
|
||||
SUM(regular_update_count) as total_update_count,
|
||||
SUM(regular_update_amount) as total_update_amount,
|
||||
SUM(turnsum_count) as total_turnsum_count,
|
||||
SUM(turnsum) as total_turnsum,
|
||||
SUM(refunds) as total_refunds,
|
||||
SUM(reissue_count) as total_reissue_count,
|
||||
SUM(reissue_amount) as total_reissue_amount
|
||||
')
|
||||
->first();
|
||||
|
||||
return $result ? $result->toArray() : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 最新の集計日を取得
|
||||
*
|
||||
* @param int|null $parkId 駐輪場ID(省略時は全体)
|
||||
* @param string|null $summaryType 集計タイプ
|
||||
* @return string|null 最新集計日
|
||||
*/
|
||||
public static function getLatestEarningsDate(?int $parkId = null, ?string $summaryType = null): ?string
|
||||
{
|
||||
$query = self::query();
|
||||
|
||||
if ($parkId) {
|
||||
$query->where('park_id', $parkId);
|
||||
}
|
||||
|
||||
if ($summaryType) {
|
||||
$query->where('summary_type', $summaryType);
|
||||
}
|
||||
|
||||
$latest = $query->max('earnings_date');
|
||||
|
||||
return $latest ? Carbon::parse($latest)->format('Y-m-d') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 期間の売上データを削除
|
||||
*
|
||||
* @param int $parkId 駐輪場ID
|
||||
* @param string $startDate 開始日
|
||||
* @param string $endDate 終了日
|
||||
* @param string|null $summaryType 集計タイプ
|
||||
* @return int 削除件数
|
||||
*/
|
||||
public static function deleteEarningsByPeriod(int $parkId, string $startDate, string $endDate, ?string $summaryType = null): int
|
||||
{
|
||||
$query = self::where('park_id', $parkId)
|
||||
->where('summary_start_date', $startDate)
|
||||
->where('summary_end_date', $endDate);
|
||||
|
||||
if ($summaryType) {
|
||||
$query->where('summary_type', $summaryType);
|
||||
}
|
||||
|
||||
return $query->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 売上集計データの作成
|
||||
*
|
||||
* @param array $data 売上データ
|
||||
* @return EarningsSummary 作成されたモデル
|
||||
*/
|
||||
public static function createEarningsSummary(array $data): EarningsSummary
|
||||
{
|
||||
$defaultData = [
|
||||
'regular_new_count' => 0,
|
||||
'regular_new_amount' => 0.00,
|
||||
'regular_new_reduction_count' => 0,
|
||||
'regular_new_reduction_amount' => 0.00,
|
||||
'regular_update_count' => 0,
|
||||
'regular_update_amount' => 0.00,
|
||||
'regular_update_reduction_count' => 0,
|
||||
'regular_update_reduction_amount' => 0.00,
|
||||
'turnsum_count' => 0,
|
||||
'turnsum' => 0.00,
|
||||
'refunds' => 0.00,
|
||||
'other_income' => 0.00,
|
||||
'other_spending' => 0.00,
|
||||
'reissue_count' => 0,
|
||||
'reissue_amount' => 0.00,
|
||||
'operator_id' => 0
|
||||
];
|
||||
|
||||
$mergedData = array_merge($defaultData, $data);
|
||||
|
||||
return self::create($mergedData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 売上合計の計算
|
||||
*
|
||||
* @return float 売上合計
|
||||
*/
|
||||
public function getTotalEarningsAttribute(): float
|
||||
{
|
||||
return $this->regular_new_amount +
|
||||
$this->regular_update_amount +
|
||||
$this->turnsum +
|
||||
$this->reissue_amount +
|
||||
$this->other_income -
|
||||
$this->other_spending -
|
||||
$this->refunds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字列表現
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'EarningsSummary[ID:%d, Park:%d, Type:%s, Date:%s]',
|
||||
$this->earnings_summary_id,
|
||||
$this->park_id,
|
||||
$this->summary_type,
|
||||
$this->earnings_date ? $this->earnings_date->format('Y-m-d') : 'N/A'
|
||||
);
|
||||
}
|
||||
}
|
||||
229
app/Models/HardwareCheckLog.php
Normal file
229
app/Models/HardwareCheckLog.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* ハードウェアチェックログモデル - hardware_check_logテーブル
|
||||
*
|
||||
* デバイスのハードウェア状態監視ログを管理
|
||||
*/
|
||||
class HardwareCheckLog extends Model
|
||||
{
|
||||
/**
|
||||
* テーブル名
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'hardware_check_log';
|
||||
|
||||
/**
|
||||
* プライマリキー
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'log_id';
|
||||
|
||||
/**
|
||||
* 一括代入可能な属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'device_id', // デバイスID
|
||||
'status', // ステータス
|
||||
'status_comment', // ステータスコメント
|
||||
'created_at', // 作成日時
|
||||
'updated_at', // 更新日時
|
||||
'operator_id' // オペレータID
|
||||
];
|
||||
|
||||
/**
|
||||
* キャストする属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'log_id' => 'integer',
|
||||
'device_id' => 'integer',
|
||||
'status' => 'integer',
|
||||
'operator_id' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime'
|
||||
];
|
||||
|
||||
/**
|
||||
* ステータスの定数
|
||||
*/
|
||||
const STATUS_NORMAL = 1; // 正常
|
||||
const STATUS_WARNING = 2; // 警告
|
||||
const STATUS_ERROR = 3; // エラー
|
||||
const STATUS_UNKNOWN = 0; // 不明
|
||||
|
||||
/**
|
||||
* デバイスとの関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function device()
|
||||
{
|
||||
return $this->belongsTo(Device::class, 'device_id', 'device_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定デバイスの最新ハードウェア状態を取得
|
||||
*
|
||||
* @param int $deviceId デバイスID
|
||||
* @return HardwareCheckLog|null 最新ログ
|
||||
*/
|
||||
public static function getLatestStatusByDevice(int $deviceId): ?HardwareCheckLog
|
||||
{
|
||||
return self::where('device_id', $deviceId)
|
||||
->orderBy('created_at', 'desc')
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 全デバイスの最新ハードウェア状態を取得
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getLatestStatusForAllDevices()
|
||||
{
|
||||
return self::select('device_id')
|
||||
->selectRaw('MAX(created_at) as latest_created_at')
|
||||
->groupBy('device_id')
|
||||
->with(['device'])
|
||||
->get()
|
||||
->map(function ($log) {
|
||||
return self::where('device_id', $log->device_id)
|
||||
->where('created_at', $log->latest_created_at)
|
||||
->with(['device'])
|
||||
->first();
|
||||
})
|
||||
->filter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 異常状態のデバイスを取得
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getAbnormalDevices()
|
||||
{
|
||||
$latestLogs = self::getLatestStatusForAllDevices();
|
||||
|
||||
return $latestLogs->filter(function ($log) {
|
||||
return $log->status !== self::STATUS_NORMAL;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定期間内のログを取得
|
||||
*
|
||||
* @param int $deviceId デバイスID
|
||||
* @param string $startTime 開始時刻
|
||||
* @param string $endTime 終了時刻
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getLogsByPeriod(int $deviceId, string $startTime, string $endTime)
|
||||
{
|
||||
return self::where('device_id', $deviceId)
|
||||
->whereBetween('created_at', [$startTime, $endTime])
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* ハードウェア状態ログを作成
|
||||
*
|
||||
* @param int $deviceId デバイスID
|
||||
* @param int $status ステータス
|
||||
* @param string $statusComment ステータスコメント
|
||||
* @param int|null $operatorId オペレータID
|
||||
* @return HardwareCheckLog 作成されたログ
|
||||
*/
|
||||
public static function createLog(
|
||||
int $deviceId,
|
||||
int $status,
|
||||
string $statusComment = '',
|
||||
?int $operatorId = null
|
||||
): HardwareCheckLog {
|
||||
return self::create([
|
||||
'device_id' => $deviceId,
|
||||
'status' => $status,
|
||||
'status_comment' => $statusComment,
|
||||
'operator_id' => $operatorId ?? 0
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* ステータス名を取得
|
||||
*
|
||||
* @param int $status ステータス
|
||||
* @return string ステータス名
|
||||
*/
|
||||
public static function getStatusName(int $status): string
|
||||
{
|
||||
switch ($status) {
|
||||
case self::STATUS_NORMAL:
|
||||
return '正常';
|
||||
case self::STATUS_WARNING:
|
||||
return '警告';
|
||||
case self::STATUS_ERROR:
|
||||
return 'エラー';
|
||||
case self::STATUS_UNKNOWN:
|
||||
return '不明';
|
||||
default:
|
||||
return "ステータス{$status}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 現在のステータス名を取得
|
||||
*
|
||||
* @return string ステータス名
|
||||
*/
|
||||
public function getStatusNameAttribute(): string
|
||||
{
|
||||
return self::getStatusName($this->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 正常状態かどうかを判定
|
||||
*
|
||||
* @return bool 正常状態かどうか
|
||||
*/
|
||||
public function isNormal(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 異常状態かどうかを判定
|
||||
*
|
||||
* @return bool 異常状態かどうか
|
||||
*/
|
||||
public function isAbnormal(): bool
|
||||
{
|
||||
return $this->status !== self::STATUS_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字列表現
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'HardwareCheckLog[ID:%d, Device:%d, Status:%s, Time:%s]',
|
||||
$this->log_id,
|
||||
$this->device_id,
|
||||
$this->getStatusNameAttribute(),
|
||||
$this->created_at ? $this->created_at->format('Y-m-d H:i:s') : 'N/A'
|
||||
);
|
||||
}
|
||||
}
|
||||
293
app/Models/OperatorQue.php
Normal file
293
app/Models/OperatorQue.php
Normal file
@ -0,0 +1,293 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* オペレータキューモデル - operator_queテーブル
|
||||
*
|
||||
* バッチ処理結果の通知や作業指示を管理
|
||||
*/
|
||||
class OperatorQue extends Model
|
||||
{
|
||||
/**
|
||||
* テーブル名
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'operator_que';
|
||||
|
||||
/**
|
||||
* プライマリキー
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'que_id';
|
||||
|
||||
/**
|
||||
* 一括代入可能な属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'que_class', // キュークラス
|
||||
'user_id', // ユーザーID
|
||||
'contract_id', // 契約ID
|
||||
'park_id', // 駐輪場ID
|
||||
'que_comment', // キューコメント
|
||||
'que_status', // キューステータス
|
||||
'que_status_comment', // キューステータスコメント
|
||||
'work_instructions', // 作業指示
|
||||
'created_at', // 作成日時
|
||||
'updated_at' // 更新日時
|
||||
];
|
||||
|
||||
/**
|
||||
* キャストする属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'que_id' => 'integer',
|
||||
'que_class' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'contract_id' => 'integer',
|
||||
'park_id' => 'integer',
|
||||
'que_status' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime'
|
||||
];
|
||||
|
||||
/**
|
||||
* キュークラスの定数
|
||||
*/
|
||||
const CLASS_SHJ4C = 4; // SHJ-4C室割当処理
|
||||
const CLASS_SHJ6 = 6; // SHJ-6サーバ死活監視処理
|
||||
const CLASS_SHJ8 = 8; // SHJ-8バッチログ処理
|
||||
const CLASS_SHJ9 = 9; // SHJ-9売上集計処理
|
||||
const CLASS_SHJ10 = 10; // SHJ-10財政年度売上集計処理
|
||||
const CLASS_MAIL_SEND = 11; // メール送信処理
|
||||
|
||||
/**
|
||||
* キューステータスの定数
|
||||
*/
|
||||
const STATUS_PENDING = 0; // 待機中
|
||||
const STATUS_COMPLETED = 1; // 完了
|
||||
const STATUS_ERROR = 2; // エラー
|
||||
const STATUS_CANCELLED = 3; // キャンセル
|
||||
|
||||
/**
|
||||
* 駐輪場との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function park()
|
||||
{
|
||||
return $this->belongsTo(Park::class, 'park_id', 'park_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーとの関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 契約との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function contract()
|
||||
{
|
||||
return $this->belongsTo(RegularContract::class, 'contract_id', 'contract_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* バッチ処理用キューを作成
|
||||
*
|
||||
* @param int $queClass キュークラス
|
||||
* @param string $comment コメント
|
||||
* @param int $status ステータス
|
||||
* @param string|null $workInstructions 作業指示
|
||||
* @param int|null $parkId 駐輪場ID
|
||||
* @return OperatorQue 作成されたキュー
|
||||
*/
|
||||
public static function createBatchQueue(
|
||||
int $queClass,
|
||||
string $comment,
|
||||
int $status = self::STATUS_COMPLETED,
|
||||
?string $workInstructions = null,
|
||||
?int $parkId = null
|
||||
): OperatorQue {
|
||||
return self::create([
|
||||
'que_class' => $queClass,
|
||||
'user_id' => null,
|
||||
'contract_id' => null,
|
||||
'park_id' => $parkId,
|
||||
'que_comment' => $comment,
|
||||
'que_status' => $status,
|
||||
'que_status_comment' => self::getStatusComment($status),
|
||||
'work_instructions' => $workInstructions
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* SHJ-9用キューを作成
|
||||
*
|
||||
* @param string $message メッセージ
|
||||
* @param int $batchLogId バッチログID
|
||||
* @param int $status ステータス
|
||||
* @return OperatorQue 作成されたキュー
|
||||
*/
|
||||
public static function createShjNineQueue(
|
||||
string $message,
|
||||
int $batchLogId,
|
||||
int $status = self::STATUS_COMPLETED
|
||||
): OperatorQue {
|
||||
return self::createBatchQueue(
|
||||
self::CLASS_SHJ9,
|
||||
$message,
|
||||
$status,
|
||||
"SHJ-9売上集計処理 BatchLogID: {$batchLogId}"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定期間のキューを取得
|
||||
*
|
||||
* @param string $startDate 開始日
|
||||
* @param string $endDate 終了日
|
||||
* @param int|null $queClass キュークラス
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getQueuesByPeriod(string $startDate, string $endDate, ?int $queClass = null)
|
||||
{
|
||||
$query = self::whereBetween('created_at', [$startDate, $endDate]);
|
||||
|
||||
if ($queClass) {
|
||||
$query->where('que_class', $queClass);
|
||||
}
|
||||
|
||||
return $query->with(['park', 'user', 'contract'])
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 未完了のキューを取得
|
||||
*
|
||||
* @param int|null $queClass キュークラス
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getPendingQueues(?int $queClass = null)
|
||||
{
|
||||
$query = self::where('que_status', self::STATUS_PENDING);
|
||||
|
||||
if ($queClass) {
|
||||
$query->where('que_class', $queClass);
|
||||
}
|
||||
|
||||
return $query->with(['park', 'user', 'contract'])
|
||||
->orderBy('created_at')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* キューを完了状態に更新
|
||||
*
|
||||
* @param string|null $comment 完了コメント
|
||||
* @return bool 更新結果
|
||||
*/
|
||||
public function markAsCompleted(?string $comment = null): bool
|
||||
{
|
||||
return $this->update([
|
||||
'que_status' => self::STATUS_COMPLETED,
|
||||
'que_status_comment' => $comment ?? self::getStatusComment(self::STATUS_COMPLETED),
|
||||
'updated_at' => now()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* キューをエラー状態に更新
|
||||
*
|
||||
* @param string $errorMessage エラーメッセージ
|
||||
* @return bool 更新結果
|
||||
*/
|
||||
public function markAsError(string $errorMessage): bool
|
||||
{
|
||||
return $this->update([
|
||||
'que_status' => self::STATUS_ERROR,
|
||||
'que_status_comment' => $errorMessage,
|
||||
'updated_at' => now()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* ステータスコメントを取得
|
||||
*
|
||||
* @param int $status ステータス
|
||||
* @return string ステータスコメント
|
||||
*/
|
||||
public static function getStatusComment(int $status): string
|
||||
{
|
||||
switch ($status) {
|
||||
case self::STATUS_PENDING:
|
||||
return '待機中';
|
||||
case self::STATUS_COMPLETED:
|
||||
return '完了';
|
||||
case self::STATUS_ERROR:
|
||||
return 'エラー';
|
||||
case self::STATUS_CANCELLED:
|
||||
return 'キャンセル';
|
||||
default:
|
||||
return '不明';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* キュークラス名を取得
|
||||
*
|
||||
* @param int $queClass キュークラス
|
||||
* @return string クラス名
|
||||
*/
|
||||
public static function getClassName(int $queClass): string
|
||||
{
|
||||
switch ($queClass) {
|
||||
case self::CLASS_SHJ4C:
|
||||
return 'SHJ-4C室割当処理';
|
||||
case self::CLASS_SHJ6:
|
||||
return 'SHJ-6サーバ死活監視処理';
|
||||
case self::CLASS_SHJ8:
|
||||
return 'SHJ-8バッチログ処理';
|
||||
case self::CLASS_SHJ9:
|
||||
return 'SHJ-9売上集計処理';
|
||||
case self::CLASS_SHJ10:
|
||||
return 'SHJ-10財政年度売上集計処理';
|
||||
case self::CLASS_MAIL_SEND:
|
||||
return 'メール送信処理';
|
||||
default:
|
||||
return "クラス{$queClass}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字列表現
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'OperatorQue[ID:%d, Class:%s, Status:%s, Date:%s]',
|
||||
$this->que_id,
|
||||
self::getClassName($this->que_class),
|
||||
self::getStatusComment($this->que_status),
|
||||
$this->created_at ? $this->created_at->format('Y-m-d H:i:s') : 'N/A'
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -42,3 +42,5 @@ class Park extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -58,3 +58,5 @@ class PriceA extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
251
app/Models/PrintJobLog.php
Normal file
251
app/Models/PrintJobLog.php
Normal file
@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* プリンタジョブログモデル - print_job_logテーブル
|
||||
*
|
||||
* プリンタ制御プログラムの実行ログを管理
|
||||
*/
|
||||
class PrintJobLog extends Model
|
||||
{
|
||||
/**
|
||||
* テーブル名
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'print_job_log';
|
||||
|
||||
/**
|
||||
* プライマリキー
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'log_id';
|
||||
|
||||
/**
|
||||
* 一括代入可能な属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'park_id', // 駐輪場ID
|
||||
'user_id', // ユーザーID
|
||||
'contract_id', // 契約ID
|
||||
'process_name', // プロセス名
|
||||
'job_name', // ジョブ名
|
||||
'status', // ステータス
|
||||
'error_code', // エラーコード
|
||||
'status_comment', // ステータスコメント
|
||||
'created_at' // 作成日時
|
||||
];
|
||||
|
||||
/**
|
||||
* キャストする属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'log_id' => 'integer',
|
||||
'park_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'contract_id' => 'integer',
|
||||
'error_code' => 'integer',
|
||||
'created_at' => 'datetime'
|
||||
];
|
||||
|
||||
/**
|
||||
* エラーコードの定数
|
||||
*/
|
||||
const ERROR_CODE_THRESHOLD = 100; // エラー判定閾値(>=100がエラー)
|
||||
|
||||
/**
|
||||
* updateされない設定(created_atのみ)
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* 駐輪場との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function park()
|
||||
{
|
||||
return $this->belongsTo(Park::class, 'park_id', 'park_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーとの関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 契約との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function contract()
|
||||
{
|
||||
return $this->belongsTo(RegularContract::class, 'contract_id', 'contract_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 過去15分間のエラーログを取得
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getRecentErrorLogs()
|
||||
{
|
||||
$fifteenMinutesAgo = Carbon::now()->subMinutes(15);
|
||||
|
||||
return self::where('created_at', '>=', $fifteenMinutesAgo)
|
||||
->where('error_code', '>=', self::ERROR_CODE_THRESHOLD)
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定期間内のエラーログを取得
|
||||
*
|
||||
* @param string $startTime 開始時刻
|
||||
* @param string $endTime 終了時刻
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getErrorLogsByPeriod(string $startTime, string $endTime)
|
||||
{
|
||||
return self::whereBetween('created_at', [$startTime, $endTime])
|
||||
->where('error_code', '>=', self::ERROR_CODE_THRESHOLD)
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定期間内の全ログを取得
|
||||
*
|
||||
* @param string $startTime 開始時刻
|
||||
* @param string $endTime 終了時刻
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getLogsByPeriod(string $startTime, string $endTime)
|
||||
{
|
||||
return self::whereBetween('created_at', [$startTime, $endTime])
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* プリンタジョブログを作成
|
||||
*
|
||||
* @param array $data ログデータ
|
||||
* @return PrintJobLog 作成されたログ
|
||||
*/
|
||||
public static function createLog(array $data): PrintJobLog
|
||||
{
|
||||
$defaultData = [
|
||||
'park_id' => null,
|
||||
'user_id' => null,
|
||||
'contract_id' => null,
|
||||
'process_name' => '',
|
||||
'job_name' => '',
|
||||
'status' => '',
|
||||
'error_code' => 0,
|
||||
'status_comment' => '',
|
||||
'created_at' => now()
|
||||
];
|
||||
|
||||
$mergedData = array_merge($defaultData, $data);
|
||||
|
||||
return self::create($mergedData);
|
||||
}
|
||||
|
||||
/**
|
||||
* エラーログかどうかを判定
|
||||
*
|
||||
* @return bool エラーログかどうか
|
||||
*/
|
||||
public function isError(): bool
|
||||
{
|
||||
return $this->error_code >= self::ERROR_CODE_THRESHOLD;
|
||||
}
|
||||
|
||||
/**
|
||||
* 正常ログかどうかを判定
|
||||
*
|
||||
* @return bool 正常ログかどうか
|
||||
*/
|
||||
public function isNormal(): bool
|
||||
{
|
||||
return $this->error_code < self::ERROR_CODE_THRESHOLD;
|
||||
}
|
||||
|
||||
/**
|
||||
* エラーレベルを取得
|
||||
*
|
||||
* @return string エラーレベル
|
||||
*/
|
||||
public function getErrorLevel(): string
|
||||
{
|
||||
if ($this->error_code >= 200) {
|
||||
return '重大エラー';
|
||||
} elseif ($this->error_code >= self::ERROR_CODE_THRESHOLD) {
|
||||
return 'エラー';
|
||||
} else {
|
||||
return '正常';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* エラーログの統計情報を取得
|
||||
*
|
||||
* @param string $startTime 開始時刻
|
||||
* @param string $endTime 終了時刻
|
||||
* @return array 統計情報
|
||||
*/
|
||||
public static function getErrorStatistics(string $startTime, string $endTime): array
|
||||
{
|
||||
$errorLogs = self::getErrorLogsByPeriod($startTime, $endTime);
|
||||
$totalLogs = self::getLogsByPeriod($startTime, $endTime);
|
||||
|
||||
$errorByCode = $errorLogs->groupBy('error_code')->map->count();
|
||||
$errorByProcess = $errorLogs->groupBy('process_name')->map->count();
|
||||
|
||||
return [
|
||||
'total_logs' => $totalLogs->count(),
|
||||
'error_logs' => $errorLogs->count(),
|
||||
'error_rate' => $totalLogs->count() > 0 ?
|
||||
round(($errorLogs->count() / $totalLogs->count()) * 100, 2) : 0,
|
||||
'error_by_code' => $errorByCode->toArray(),
|
||||
'error_by_process' => $errorByProcess->toArray(),
|
||||
'period' => [
|
||||
'start' => $startTime,
|
||||
'end' => $endTime
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字列表現
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'PrintJobLog[ID:%d, Process:%s, ErrorCode:%d, Time:%s]',
|
||||
$this->log_id,
|
||||
$this->process_name,
|
||||
$this->error_code,
|
||||
$this->created_at ? $this->created_at->format('Y-m-d H:i:s') : 'N/A'
|
||||
);
|
||||
}
|
||||
}
|
||||
106
app/Models/Psection.php
Normal file
106
app/Models/Psection.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* 車種区分モデル - psectionテーブル
|
||||
*
|
||||
* 駐輪場の車種区分マスタデータを管理
|
||||
*/
|
||||
class Psection extends Model
|
||||
{
|
||||
/**
|
||||
* テーブル名
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'psection';
|
||||
|
||||
/**
|
||||
* プライマリキー
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'psection_id';
|
||||
|
||||
/**
|
||||
* 一括代入可能な属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'psection_subject', // 車種区分名
|
||||
'operator_id', // オペレータID
|
||||
'created_at', // 作成日時
|
||||
'updated_at' // 更新日時
|
||||
];
|
||||
|
||||
/**
|
||||
* キャストする属性
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'psection_id' => 'integer',
|
||||
'operator_id' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime'
|
||||
];
|
||||
|
||||
/**
|
||||
* 売上集計との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function earningsSummaries()
|
||||
{
|
||||
return $this->hasMany(EarningsSummary::class, 'psection_id', 'psection_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 定期契約との関連
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function regularContracts()
|
||||
{
|
||||
return $this->hasMany(RegularContract::class, 'psection_id', 'psection_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* アクティブな車種区分一覧を取得
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public static function getActivePsections()
|
||||
{
|
||||
return self::orderBy('psection_id')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 車種区分名で検索
|
||||
*
|
||||
* @param string $subject 車種区分名
|
||||
* @return Psection|null
|
||||
*/
|
||||
public static function findBySubject(string $subject): ?Psection
|
||||
{
|
||||
return self::where('psection_subject', $subject)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字列表現
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf(
|
||||
'Psection[ID:%d, Subject:%s]',
|
||||
$this->psection_id,
|
||||
$this->psection_subject
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -33,3 +33,5 @@ class Ptype extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -72,3 +72,5 @@ class RegularContract extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -5,6 +5,9 @@ namespace App\Providers;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Services\ShjFourCService;
|
||||
use App\Services\ShjMailSendService;
|
||||
use App\Services\ShjNineService;
|
||||
use App\Services\ShjTenService;
|
||||
use App\Services\ShjSixService;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@ -30,7 +33,41 @@ class AppServiceProvider extends ServiceProvider
|
||||
);
|
||||
});
|
||||
|
||||
// SHJ-9売上集計処理サービスを登録
|
||||
$this->app->singleton(ShjNineService::class, function ($app) {
|
||||
return new ShjNineService(
|
||||
$app->make(\App\Models\Park::class),
|
||||
$app->make(\App\Models\RegularContract::class),
|
||||
$app->make(\App\Models\EarningsSummary::class),
|
||||
$app->make(\App\Models\Psection::class),
|
||||
$app->make(\App\Models\Batch\BatchLog::class),
|
||||
$app->make(\App\Models\OperatorQue::class)
|
||||
);
|
||||
});
|
||||
|
||||
// SHJ-10財政年度売上集計処理サービスを登録
|
||||
$this->app->singleton(ShjTenService::class, function ($app) {
|
||||
return new ShjTenService(
|
||||
$app->make(\App\Models\Park::class),
|
||||
$app->make(\App\Models\RegularContract::class),
|
||||
$app->make(\App\Models\EarningsSummary::class),
|
||||
$app->make(\App\Models\Psection::class),
|
||||
$app->make(\App\Models\Batch\BatchLog::class),
|
||||
$app->make(\App\Models\OperatorQue::class)
|
||||
);
|
||||
});
|
||||
|
||||
// SHJ-6サーバ死活監視処理サービスを登録
|
||||
$this->app->singleton(ShjSixService::class, function ($app) {
|
||||
return new ShjSixService(
|
||||
$app->make(\App\Models\Device::class),
|
||||
$app->make(\App\Models\HardwareCheckLog::class),
|
||||
$app->make(\App\Models\PrintJobLog::class),
|
||||
$app->make(\App\Models\Batch\BatchLog::class),
|
||||
$app->make(\App\Models\OperatorQue::class),
|
||||
$app->make(\App\Services\ShjMailSendService::class)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -42,3 +42,4 @@ class LegacyServiceProvider extends ServiceProvider
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -32,3 +32,5 @@ class FileService
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -25,3 +25,5 @@ class OperatorQueService
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
595
app/Services/ShjNineService.php
Normal file
595
app/Services/ShjNineService.php
Normal file
@ -0,0 +1,595 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Park;
|
||||
use App\Models\RegularContract;
|
||||
use App\Models\EarningsSummary;
|
||||
use App\Models\Psection;
|
||||
use App\Models\Batch\BatchLog;
|
||||
use App\Models\OperatorQue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* SHJ-9 売上集計処理サービス
|
||||
*
|
||||
* 日次・月次・年次の売上集計処理を実行するビジネスロジック
|
||||
* バッチ処理「SHJ-9売上集計」の核となる処理を担当
|
||||
*/
|
||||
class ShjNineService
|
||||
{
|
||||
/**
|
||||
* Park モデル
|
||||
*
|
||||
* @var Park
|
||||
*/
|
||||
protected $parkModel;
|
||||
|
||||
/**
|
||||
* RegularContract モデル
|
||||
*
|
||||
* @var RegularContract
|
||||
*/
|
||||
protected $contractModel;
|
||||
|
||||
/**
|
||||
* EarningsSummary モデル
|
||||
*
|
||||
* @var EarningsSummary
|
||||
*/
|
||||
protected $earningsSummaryModel;
|
||||
|
||||
/**
|
||||
* Psection モデル
|
||||
*
|
||||
* @var Psection
|
||||
*/
|
||||
protected $psectionModel;
|
||||
|
||||
/**
|
||||
* BatchLog モデル
|
||||
*
|
||||
* @var BatchLog
|
||||
*/
|
||||
protected $batchLogModel;
|
||||
|
||||
/**
|
||||
* OperatorQue モデル
|
||||
*
|
||||
* @var OperatorQue
|
||||
*/
|
||||
protected $operatorQueModel;
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*
|
||||
* @param Park $parkModel
|
||||
* @param RegularContract $contractModel
|
||||
* @param EarningsSummary $earningsSummaryModel
|
||||
* @param Psection $psectionModel
|
||||
* @param BatchLog $batchLogModel
|
||||
* @param OperatorQue $operatorQueModel
|
||||
*/
|
||||
public function __construct(
|
||||
Park $parkModel,
|
||||
RegularContract $contractModel,
|
||||
EarningsSummary $earningsSummaryModel,
|
||||
Psection $psectionModel,
|
||||
BatchLog $batchLogModel,
|
||||
OperatorQue $operatorQueModel
|
||||
) {
|
||||
$this->parkModel = $parkModel;
|
||||
$this->contractModel = $contractModel;
|
||||
$this->earningsSummaryModel = $earningsSummaryModel;
|
||||
$this->psectionModel = $psectionModel;
|
||||
$this->batchLogModel = $batchLogModel;
|
||||
$this->operatorQueModel = $operatorQueModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* SHJ-9 売上集計処理メイン実行
|
||||
*
|
||||
* 処理フロー:
|
||||
* 【処理1】集計対象を設定する
|
||||
* 【処理2】駐輪場マスタを取得する
|
||||
* 【判断1】取得件数判定
|
||||
* 【処理3】車種区分毎に算出する
|
||||
* 【判断2】取得判定
|
||||
* 【処理4】売上集計結果を削除→登録する
|
||||
* 【処理5】オペレータキュー作成およびバッチ処理ログを作成する
|
||||
*
|
||||
* @param string $type 集計種別(daily/monthly/yearly)
|
||||
* @param string $aggregationDate 集計対象日
|
||||
* @return array 処理結果
|
||||
*/
|
||||
public function executeEarningsAggregation(string $type, string $aggregationDate): array
|
||||
{
|
||||
$batchLogId = null;
|
||||
|
||||
try {
|
||||
// 【処理1】集計対象を設定する
|
||||
$aggregationTarget = $this->setAggregationTarget($type, $aggregationDate);
|
||||
|
||||
// バッチ処理開始ログ作成
|
||||
$batchLog = BatchLog::createBatchLog(
|
||||
'shj9',
|
||||
BatchLog::STATUS_START,
|
||||
[
|
||||
'type' => $type,
|
||||
'aggregation_date' => $aggregationDate,
|
||||
'aggregation_target' => $aggregationTarget
|
||||
],
|
||||
"SHJ-9 売上集計処理開始 ({$type})"
|
||||
);
|
||||
$batchLogId = $batchLog->id;
|
||||
|
||||
Log::info('SHJ-9 売上集計処理開始', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'type' => $type,
|
||||
'aggregation_date' => $aggregationDate,
|
||||
'aggregation_target' => $aggregationTarget
|
||||
]);
|
||||
|
||||
// 【処理2】駐輪場マスタを取得する
|
||||
$parkInfo = $this->getParkInformation();
|
||||
|
||||
// 【判断1】取得件数判定
|
||||
if (empty($parkInfo)) {
|
||||
$message = '売上集計(' . $this->getTypeLabel($type) . '):駐輪場マスタが存在していません。';
|
||||
|
||||
// バッチログ更新
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_WARNING,
|
||||
'end_time' => now(),
|
||||
'message' => $message,
|
||||
'success_count' => 1 // 処理は成功したが対象なし
|
||||
]);
|
||||
|
||||
// 【処理5】オペレータキュー作成
|
||||
$this->createOperatorQueue($message, $batchLogId);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => $message,
|
||||
'processed_parks' => 0,
|
||||
'summary_records' => 0,
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
|
||||
// 【処理3】車種区分毎に算出する & 【処理4】売上集計結果を削除→登録する
|
||||
$summaryRecords = 0;
|
||||
$processedParks = 0;
|
||||
|
||||
foreach ($parkInfo as $park) {
|
||||
$parkSummaryRecords = $this->processEarningsForPark($park, $aggregationTarget, $type);
|
||||
|
||||
if ($parkSummaryRecords > 0) {
|
||||
$processedParks++;
|
||||
$summaryRecords += $parkSummaryRecords;
|
||||
}
|
||||
}
|
||||
|
||||
// 【判断2】取得判定
|
||||
if ($summaryRecords === 0) {
|
||||
$message = '対象なしの結果を設定する(契約)';
|
||||
|
||||
// バッチログ更新
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_WARNING,
|
||||
'end_time' => now(),
|
||||
'message' => $message,
|
||||
'success_count' => 1
|
||||
]);
|
||||
|
||||
// 【処理5】オペレータキュー作成
|
||||
$this->createOperatorQueue($message, $batchLogId);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => $message,
|
||||
'processed_parks' => $processedParks,
|
||||
'summary_records' => 0,
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
|
||||
// バッチ処理完了ログ更新
|
||||
$completionMessage = "SHJ-9 売上集計処理正常完了 ({$type}) - 駐輪場数: {$processedParks}, 集計レコード数: {$summaryRecords}";
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_SUCCESS,
|
||||
'end_time' => now(),
|
||||
'message' => $completionMessage,
|
||||
'success_count' => 1
|
||||
]);
|
||||
|
||||
// 【処理5】オペレータキュー作成
|
||||
$this->createOperatorQueue($completionMessage, $batchLogId);
|
||||
|
||||
Log::info('SHJ-9 売上集計処理完了', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'processed_parks' => $processedParks,
|
||||
'summary_records' => $summaryRecords
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'SHJ-9 売上集計処理が正常に完了しました',
|
||||
'processed_parks' => $processedParks,
|
||||
'summary_records' => $summaryRecords,
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = 'SHJ-9 売上集計処理でエラーが発生: ' . $e->getMessage();
|
||||
|
||||
if (isset($batchLog) && $batchLog) {
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_ERROR,
|
||||
'end_time' => now(),
|
||||
'message' => $errorMessage,
|
||||
'error_details' => $e->getMessage(),
|
||||
'error_count' => 1
|
||||
]);
|
||||
}
|
||||
|
||||
Log::error('SHJ-9 売上集計処理エラー', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'exception' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $errorMessage,
|
||||
'details' => $e->getMessage(),
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理1】集計対象を設定する
|
||||
*
|
||||
* @param string $type 集計種別
|
||||
* @param string $aggregationDate 集計対象日
|
||||
* @return array 集計対象情報
|
||||
*/
|
||||
private function setAggregationTarget(string $type, string $aggregationDate): array
|
||||
{
|
||||
$date = Carbon::parse($aggregationDate);
|
||||
|
||||
switch ($type) {
|
||||
case 'daily':
|
||||
return [
|
||||
'type' => 'daily',
|
||||
'start_date' => $date->format('Y-m-d'),
|
||||
'end_date' => $date->format('Y-m-d'),
|
||||
'summary_type' => '日次'
|
||||
];
|
||||
|
||||
case 'monthly':
|
||||
return [
|
||||
'type' => 'monthly',
|
||||
'start_date' => $date->startOfMonth()->format('Y-m-d'),
|
||||
'end_date' => $date->endOfMonth()->format('Y-m-d'),
|
||||
'summary_type' => '月次'
|
||||
];
|
||||
|
||||
case 'yearly':
|
||||
return [
|
||||
'type' => 'yearly',
|
||||
'start_date' => $date->startOfYear()->format('Y-m-d'),
|
||||
'end_date' => $date->endOfYear()->format('Y-m-d'),
|
||||
'summary_type' => '年次'
|
||||
];
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("不正な集計種別: {$type}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理2】駐輪場マスタを取得する
|
||||
*
|
||||
* 仕様書のSQLクエリに基づく駐輪場情報取得
|
||||
* SELECT 駐輪場ID, 駐輪場名
|
||||
* FROM 駐輪場マスタ
|
||||
* WHERE 閉設フラグ <> 1
|
||||
* ORDER BY 駐輪場ふりがな
|
||||
*
|
||||
* @return array 駐輪場情報
|
||||
*/
|
||||
private function getParkInformation(): array
|
||||
{
|
||||
try {
|
||||
$parkInfo = DB::table('park')
|
||||
->select(['park_id', 'park_name'])
|
||||
->where('park_close_flag', '<>', 1)
|
||||
->orderBy('park_ruby')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
Log::info('駐輪場マスタ取得完了', [
|
||||
'park_count' => count($parkInfo)
|
||||
]);
|
||||
|
||||
return $parkInfo;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('駐輪場マスタ取得エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 駐輪場毎の売上集計処理
|
||||
*
|
||||
* @param object $park 駐輪場情報
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @param string $type 集計種別
|
||||
* @return int 作成された集計レコード数
|
||||
*/
|
||||
private function processEarningsForPark($park, array $aggregationTarget, string $type): int
|
||||
{
|
||||
try {
|
||||
// 【処理4】既存の売上集計結果を削除
|
||||
$this->deleteExistingSummary($park->park_id, $aggregationTarget);
|
||||
|
||||
// 【処理3】車種区分毎に算出する
|
||||
$psections = $this->getPsectionInformation();
|
||||
$summaryRecords = 0;
|
||||
|
||||
foreach ($psections as $psection) {
|
||||
$earningsData = $this->calculateEarningsForPsection(
|
||||
$park->park_id,
|
||||
$psection->psection_id,
|
||||
$aggregationTarget
|
||||
);
|
||||
|
||||
if ($this->hasEarningsData($earningsData)) {
|
||||
// 売上集計結果を登録
|
||||
$this->createEarningsSummary($park, $psection, $aggregationTarget, $earningsData, $type);
|
||||
$summaryRecords++;
|
||||
}
|
||||
}
|
||||
|
||||
Log::info('駐輪場売上集計完了', [
|
||||
'park_id' => $park->park_id,
|
||||
'park_name' => $park->park_name,
|
||||
'summary_records' => $summaryRecords
|
||||
]);
|
||||
|
||||
return $summaryRecords;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('駐輪場売上集計エラー', [
|
||||
'park_id' => $park->park_id,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 車種区分情報取得
|
||||
*
|
||||
* @return array 車種区分情報
|
||||
*/
|
||||
private function getPsectionInformation(): array
|
||||
{
|
||||
return DB::table('psection')
|
||||
->select(['psection_id', 'psection_subject'])
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理3】車種区分毎に売上を算出する
|
||||
*
|
||||
* 4つの項目を計算:
|
||||
* ①売上・件数
|
||||
* ②一時金売上
|
||||
* ③解約返戻金
|
||||
* ④再発行金額・件数
|
||||
*
|
||||
* @param int $parkId 駐輪場ID
|
||||
* @param int $psectionId 車種区分ID
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @return array 売上データ
|
||||
*/
|
||||
private function calculateEarningsForPsection(int $parkId, int $psectionId, array $aggregationTarget): array
|
||||
{
|
||||
$startDate = $aggregationTarget['start_date'];
|
||||
$endDate = $aggregationTarget['end_date'];
|
||||
|
||||
// ①売上・件数(billing_amount)
|
||||
$salesData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as sales_count'),
|
||||
DB::raw('COALESCE(SUM(billing_amount), 0) as sales_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->where('contract_flag', 1)
|
||||
->whereBetween('contract_payment_day', [$startDate, $endDate])
|
||||
->whereNull('contract_cancelday')
|
||||
->first();
|
||||
|
||||
// ②一時金売上(contract_money)
|
||||
$temporaryData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as temporary_count'),
|
||||
DB::raw('COALESCE(SUM(contract_money), 0) as temporary_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->where('contract_flag', 1)
|
||||
->whereBetween('contract_payment_day', [$startDate, $endDate])
|
||||
->whereNotNull('contract_money')
|
||||
->where('contract_money', '>', 0)
|
||||
->first();
|
||||
|
||||
// ③解約返戻金(refunds)
|
||||
$refundData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as refund_count'),
|
||||
DB::raw('COALESCE(SUM(refunds), 0) as refund_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->whereBetween('contract_cancelday', [$startDate, $endDate])
|
||||
->whereNotNull('refunds')
|
||||
->where('refunds', '>', 0)
|
||||
->first();
|
||||
|
||||
// ④再発行金額・件数(seal_reissue_request)
|
||||
$reissueData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as reissue_count'),
|
||||
DB::raw('COALESCE(SUM(contract_seal_issue), 0) as reissue_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->where('seal_reissue_request', 1)
|
||||
->whereBetween('updated_at', [$startDate, $endDate])
|
||||
->first();
|
||||
|
||||
return [
|
||||
'sales_count' => $salesData->sales_count ?? 0,
|
||||
'sales_amount' => $salesData->sales_amount ?? 0,
|
||||
'temporary_count' => $temporaryData->temporary_count ?? 0,
|
||||
'temporary_amount' => $temporaryData->temporary_amount ?? 0,
|
||||
'refund_count' => $refundData->refund_count ?? 0,
|
||||
'refund_amount' => $refundData->refund_amount ?? 0,
|
||||
'reissue_count' => $reissueData->reissue_count ?? 0,
|
||||
'reissue_amount' => $reissueData->reissue_amount ?? 0
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 売上データの存在チェック
|
||||
*
|
||||
* @param array $earningsData 売上データ
|
||||
* @return bool データが存在するかどうか
|
||||
*/
|
||||
private function hasEarningsData(array $earningsData): bool
|
||||
{
|
||||
return $earningsData['sales_count'] > 0 ||
|
||||
$earningsData['temporary_count'] > 0 ||
|
||||
$earningsData['refund_count'] > 0 ||
|
||||
$earningsData['reissue_count'] > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理4】既存の売上集計結果を削除
|
||||
*
|
||||
* @param int $parkId 駐輪場ID
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @return void
|
||||
*/
|
||||
private function deleteExistingSummary(int $parkId, array $aggregationTarget): void
|
||||
{
|
||||
DB::table('earnings_summary')
|
||||
->where('park_id', $parkId)
|
||||
->where('summary_start_date', $aggregationTarget['start_date'])
|
||||
->where('summary_end_date', $aggregationTarget['end_date'])
|
||||
->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 売上集計結果を登録
|
||||
*
|
||||
* @param object $park 駐輪場情報
|
||||
* @param object $psection 車種区分情報
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @param array $earningsData 売上データ
|
||||
* @param string $type 集計種別
|
||||
* @return void
|
||||
*/
|
||||
private function createEarningsSummary($park, $psection, array $aggregationTarget, array $earningsData, string $type): void
|
||||
{
|
||||
DB::table('earnings_summary')->insert([
|
||||
'park_id' => $park->park_id,
|
||||
'summary_type' => $aggregationTarget['summary_type'],
|
||||
'summary_start_date' => $aggregationTarget['start_date'],
|
||||
'summary_end_date' => $aggregationTarget['end_date'],
|
||||
'earnings_date' => $aggregationTarget['end_date'], // 集計日として終了日を使用
|
||||
'psection_id' => $psection->psection_id,
|
||||
'usertype_subject1' => $psection->psection_subject,
|
||||
'regular_new_count' => $earningsData['sales_count'],
|
||||
'regular_new_amount' => $earningsData['sales_amount'],
|
||||
'turnsum' => $earningsData['temporary_amount'],
|
||||
'turnsum_count' => $earningsData['temporary_count'],
|
||||
'refunds' => $earningsData['refund_amount'],
|
||||
'reissue_count' => $earningsData['reissue_count'],
|
||||
'reissue_amount' => $earningsData['reissue_amount'],
|
||||
'summary_note' => "SHJ-9 {$type} 売上集計結果",
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
'operator_id' => 0 // システム処理
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理5】オペレータキュー作成
|
||||
*
|
||||
* @param string $message メッセージ
|
||||
* @param int $batchLogId バッチログID
|
||||
* @return void
|
||||
*/
|
||||
private function createOperatorQueue(string $message, int $batchLogId): void
|
||||
{
|
||||
try {
|
||||
DB::table('operator_que')->insert([
|
||||
'que_class' => 9, // SHJ-9用のクラス
|
||||
'user_id' => null,
|
||||
'contract_id' => null,
|
||||
'park_id' => null,
|
||||
'que_comment' => $message,
|
||||
'que_status' => 1, // 完了
|
||||
'que_status_comment' => 'バッチ処理完了',
|
||||
'work_instructions' => "SHJ-9売上集計処理 BatchLogID: {$batchLogId}",
|
||||
'created_at' => now(),
|
||||
'updated_at' => now()
|
||||
]);
|
||||
|
||||
Log::info('オペレータキュー作成完了', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'message' => $message
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('オペレータキュー作成エラー', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 集計種別のラベル取得
|
||||
*
|
||||
* @param string $type 集計種別
|
||||
* @return string ラベル
|
||||
*/
|
||||
private function getTypeLabel(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case 'daily':
|
||||
return '日次';
|
||||
case 'monthly':
|
||||
return '月次';
|
||||
case 'yearly':
|
||||
return '年次';
|
||||
default:
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
710
app/Services/ShjSixService.php
Normal file
710
app/Services/ShjSixService.php
Normal file
@ -0,0 +1,710 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Device;
|
||||
use App\Models\HardwareCheckLog;
|
||||
use App\Models\PrintJobLog;
|
||||
use App\Models\Batch\BatchLog;
|
||||
use App\Models\OperatorQue;
|
||||
use App\Models\User;
|
||||
use App\Models\Park;
|
||||
use App\Services\ShjMailSendService;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* SHJ-6 サーバ死活監視処理サービス
|
||||
*
|
||||
* サーバとデバイスの死活監視、ハードウェア状態監視、プリンタログ監視を実行
|
||||
* 異常検出時のメール通知機能を含む統合モニタリングサービス
|
||||
*/
|
||||
class ShjSixService
|
||||
{
|
||||
/**
|
||||
* Device モデル
|
||||
*
|
||||
* @var Device
|
||||
*/
|
||||
protected $deviceModel;
|
||||
|
||||
/**
|
||||
* HardwareCheckLog モデル
|
||||
*
|
||||
* @var HardwareCheckLog
|
||||
*/
|
||||
protected $hardwareCheckLogModel;
|
||||
|
||||
/**
|
||||
* PrintJobLog モデル
|
||||
*
|
||||
* @var PrintJobLog
|
||||
*/
|
||||
protected $printJobLogModel;
|
||||
|
||||
/**
|
||||
* BatchLog モデル
|
||||
*
|
||||
* @var BatchLog
|
||||
*/
|
||||
protected $batchLogModel;
|
||||
|
||||
/**
|
||||
* OperatorQue モデル
|
||||
*
|
||||
* @var OperatorQue
|
||||
*/
|
||||
protected $operatorQueModel;
|
||||
|
||||
/**
|
||||
* ShjMailSendService
|
||||
*
|
||||
* @var ShjMailSendService
|
||||
*/
|
||||
protected $mailSendService;
|
||||
|
||||
/**
|
||||
* 固定メールアドレス(DB反映NG時用)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FIXED_EMAIL_ADDRESS = 'system-alert@so-manager.com';
|
||||
|
||||
/**
|
||||
* プリンタログ監視期間(分)
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const PRINTER_LOG_MONITOR_MINUTES = 15;
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*
|
||||
* @param Device $deviceModel
|
||||
* @param HardwareCheckLog $hardwareCheckLogModel
|
||||
* @param PrintJobLog $printJobLogModel
|
||||
* @param BatchLog $batchLogModel
|
||||
* @param OperatorQue $operatorQueModel
|
||||
* @param ShjMailSendService $mailSendService
|
||||
*/
|
||||
public function __construct(
|
||||
Device $deviceModel,
|
||||
HardwareCheckLog $hardwareCheckLogModel,
|
||||
PrintJobLog $printJobLogModel,
|
||||
BatchLog $batchLogModel,
|
||||
OperatorQue $operatorQueModel,
|
||||
ShjMailSendService $mailSendService
|
||||
) {
|
||||
$this->deviceModel = $deviceModel;
|
||||
$this->hardwareCheckLogModel = $hardwareCheckLogModel;
|
||||
$this->printJobLogModel = $printJobLogModel;
|
||||
$this->batchLogModel = $batchLogModel;
|
||||
$this->operatorQueModel = $operatorQueModel;
|
||||
$this->mailSendService = $mailSendService;
|
||||
}
|
||||
|
||||
/**
|
||||
* SHJ-6 サーバ死活監視処理メイン実行
|
||||
*
|
||||
* 処理フロー:
|
||||
* 【処理1】サーバ死活監視(DBアクセス)
|
||||
* 【処理2】デバイス管理マスタを取得する
|
||||
* 【処理3】デバイス毎のハードウェア状態を取得する
|
||||
* 【処理4】プリンタ制御プログラムログを取得する
|
||||
* 【判断3】エラーログ有無
|
||||
* 【処理5】バッチ処理ログを作成する
|
||||
* ※ 異常時は共通A処理を実行
|
||||
*
|
||||
* @return array 処理結果
|
||||
*/
|
||||
public function executeServerMonitoring(): array
|
||||
{
|
||||
$batchLogId = null;
|
||||
$warnings = [];
|
||||
$errorDetails = [];
|
||||
|
||||
try {
|
||||
// バッチ処理開始ログ作成
|
||||
$batchLog = BatchLog::createBatchLog(
|
||||
'shj6',
|
||||
BatchLog::STATUS_START,
|
||||
[],
|
||||
'SHJ-6 サーバ死活監視処理開始'
|
||||
);
|
||||
$batchLogId = $batchLog->id;
|
||||
|
||||
Log::info('SHJ-6 サーバ死活監視処理開始', [
|
||||
'batch_log_id' => $batchLogId
|
||||
]);
|
||||
|
||||
// 【処理1】サーバ死活監視(DBアクセス)
|
||||
$dbAccessResult = $this->checkDatabaseAccess();
|
||||
if (!$dbAccessResult['success']) {
|
||||
// DB接続NGの場合は共通A処理実行
|
||||
$this->executeCommonProcessA($batchLogId, 'DB接続エラー: ' . $dbAccessResult['message']);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'データベース接続エラーが発生しました',
|
||||
'error_details' => [$dbAccessResult['message']],
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
|
||||
// 【処理2】デバイス管理マスタを取得する
|
||||
$devices = $this->getDeviceManagementData();
|
||||
Log::info('デバイス管理マスタ取得完了', [
|
||||
'device_count' => count($devices)
|
||||
]);
|
||||
|
||||
// 【処理3】デバイス毎のハードウェア状態を取得する
|
||||
$hardwareStatusResult = $this->getHardwareStatus($devices);
|
||||
if (!$hardwareStatusResult['success']) {
|
||||
// ハードウェア状態取得できなかった場合は共通A処理実行
|
||||
$this->executeCommonProcessA($batchLogId, 'ハードウェア状態取得エラー: ' . $hardwareStatusResult['message']);
|
||||
$warnings[] = 'ハードウェア状態の一部で異常を検出しました';
|
||||
$errorDetails[] = $hardwareStatusResult['message'];
|
||||
}
|
||||
|
||||
// 【処理4】プリンタ制御プログラムログを取得する
|
||||
$printerLogResult = $this->getPrinterControlLogs();
|
||||
|
||||
// 【判断3】エラーログ有無
|
||||
if ($printerLogResult['has_errors']) {
|
||||
// エラーログ有の場合は共通A処理実行
|
||||
$this->executeCommonProcessA($batchLogId, 'プリンタエラーログ検出: ' . $printerLogResult['error_summary']);
|
||||
$warnings[] = 'プリンタ制御でエラーが検出されました';
|
||||
$errorDetails[] = $printerLogResult['error_summary'];
|
||||
}
|
||||
|
||||
// 【処理5】バッチ処理ログを作成する
|
||||
$monitoringSummary = $this->createMonitoringSummary($devices, $hardwareStatusResult, $printerLogResult);
|
||||
|
||||
$status = empty($warnings) ? BatchLog::STATUS_SUCCESS : BatchLog::STATUS_WARNING;
|
||||
$message = empty($warnings) ?
|
||||
'SHJ-6 サーバ死活監視処理正常完了' :
|
||||
'SHJ-6 サーバ死活監視処理完了(警告あり)';
|
||||
|
||||
$batchLog->update([
|
||||
'status' => $status,
|
||||
'end_time' => now(),
|
||||
'message' => $message,
|
||||
'success_count' => 1
|
||||
]);
|
||||
|
||||
Log::info('SHJ-6 サーバ死活監視処理完了', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'monitoring_summary' => $monitoringSummary,
|
||||
'warnings' => $warnings
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'SHJ-6 サーバ死活監視処理が完了しました',
|
||||
'monitoring_summary' => $monitoringSummary,
|
||||
'warnings' => $warnings,
|
||||
'error_details' => $errorDetails,
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = 'SHJ-6 サーバ死活監視処理でエラーが発生: ' . $e->getMessage();
|
||||
|
||||
if (isset($batchLog) && $batchLog) {
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_ERROR,
|
||||
'end_time' => now(),
|
||||
'message' => $errorMessage,
|
||||
'error_details' => $e->getMessage(),
|
||||
'error_count' => 1
|
||||
]);
|
||||
}
|
||||
|
||||
// 例外発生時も共通A処理実行
|
||||
$this->executeCommonProcessA($batchLogId, $errorMessage);
|
||||
|
||||
Log::error('SHJ-6 サーバ死活監視処理エラー', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'exception' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $errorMessage,
|
||||
'error_details' => [$e->getMessage()],
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理1】サーバ死活監視(DBアクセス)
|
||||
*
|
||||
* @return array アクセス結果
|
||||
*/
|
||||
private function checkDatabaseAccess(): array
|
||||
{
|
||||
try {
|
||||
// 設定マスタテーブルへの簡単なクエリでDB接続確認
|
||||
$result = DB::select('SELECT 1 as test');
|
||||
|
||||
if (empty($result)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'データベースクエリの結果が空です'
|
||||
];
|
||||
}
|
||||
|
||||
Log::info('データベース接続確認成功');
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'データベース接続正常'
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('データベース接続エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理2】デバイス管理マスタを取得する
|
||||
*
|
||||
* @return array デバイス情報
|
||||
*/
|
||||
private function getDeviceManagementData(): array
|
||||
{
|
||||
try {
|
||||
$devices = DB::table('device')
|
||||
->select([
|
||||
'device_id',
|
||||
'park_id',
|
||||
'device_type',
|
||||
'device_subject',
|
||||
'device_identifier',
|
||||
'device_work',
|
||||
'device_workstart',
|
||||
'device_replace',
|
||||
'device_remarks',
|
||||
'operator_id'
|
||||
])
|
||||
->where('device_workstart', '<=', now())
|
||||
->whereNull('device_replace')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
Log::info('デバイス管理マスタ取得完了', [
|
||||
'device_count' => count($devices)
|
||||
]);
|
||||
|
||||
return $devices;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('デバイス管理マスタ取得エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理3】デバイス毎のハードウェア状態を取得する
|
||||
*
|
||||
* @param array $devices デバイス一覧
|
||||
* @return array ハードウェア状態結果
|
||||
*/
|
||||
private function getHardwareStatus(array $devices): array
|
||||
{
|
||||
try {
|
||||
$normalDevices = 0;
|
||||
$abnormalDevices = 0;
|
||||
$abnormalDetails = [];
|
||||
|
||||
foreach ($devices as $device) {
|
||||
$latestStatus = HardwareCheckLog::getLatestStatusByDevice($device->device_id);
|
||||
|
||||
if (!$latestStatus) {
|
||||
$abnormalDevices++;
|
||||
$abnormalDetails[] = "デバイスID {$device->device_id}: ハードウェア状態ログが存在しません";
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($latestStatus->isNormal()) {
|
||||
$normalDevices++;
|
||||
} else {
|
||||
$abnormalDevices++;
|
||||
$abnormalDetails[] = "デバイスID {$device->device_id}: {$latestStatus->getStatusNameAttribute()} - {$latestStatus->status_comment}";
|
||||
}
|
||||
}
|
||||
|
||||
Log::info('ハードウェア状態取得完了', [
|
||||
'total_devices' => count($devices),
|
||||
'normal_devices' => $normalDevices,
|
||||
'abnormal_devices' => $abnormalDevices
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => $abnormalDevices === 0,
|
||||
'total_devices' => count($devices),
|
||||
'normal_devices' => $normalDevices,
|
||||
'abnormal_devices' => $abnormalDevices,
|
||||
'abnormal_details' => $abnormalDetails,
|
||||
'message' => $abnormalDevices > 0 ?
|
||||
"{$abnormalDevices}台のデバイスで異常を検出" :
|
||||
'全デバイス正常'
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('ハードウェア状態取得エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
'abnormal_details' => ["ハードウェア状態取得中にエラーが発生: " . $e->getMessage()]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理4】プリンタ制御プログラムログを取得する
|
||||
*
|
||||
* @return array プリンタログ結果
|
||||
*/
|
||||
private function getPrinterControlLogs(): array
|
||||
{
|
||||
try {
|
||||
// 過去15分間のエラーログを取得
|
||||
$errorLogs = PrintJobLog::getRecentErrorLogs();
|
||||
|
||||
$hasErrors = $errorLogs->count() > 0;
|
||||
$errorSummary = '';
|
||||
$errorDetails = [];
|
||||
|
||||
if ($hasErrors) {
|
||||
$errorsByCode = $errorLogs->groupBy('error_code');
|
||||
$errorSummaryParts = [];
|
||||
|
||||
foreach ($errorsByCode as $errorCode => $logs) {
|
||||
$count = $logs->count();
|
||||
$errorSummaryParts[] = "エラーコード{$errorCode}: {$count}件";
|
||||
|
||||
foreach ($logs as $log) {
|
||||
$errorDetails[] = sprintf(
|
||||
"[%s] %s - エラーコード: %d, %s",
|
||||
$log->created_at->format('Y-m-d H:i:s'),
|
||||
$log->process_name,
|
||||
$log->error_code,
|
||||
$log->status_comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$errorSummary = implode(', ', $errorSummaryParts);
|
||||
}
|
||||
|
||||
Log::info('プリンタ制御プログラムログ取得完了', [
|
||||
'monitoring_period_minutes' => self::PRINTER_LOG_MONITOR_MINUTES,
|
||||
'error_logs_count' => $errorLogs->count(),
|
||||
'has_errors' => $hasErrors
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'has_errors' => $hasErrors,
|
||||
'error_count' => $errorLogs->count(),
|
||||
'error_summary' => $errorSummary,
|
||||
'error_details' => $errorDetails,
|
||||
'monitoring_period' => self::PRINTER_LOG_MONITOR_MINUTES . '分間'
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('プリンタ制御プログラムログ取得エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'has_errors' => true,
|
||||
'error_summary' => 'ログ取得エラー: ' . $e->getMessage(),
|
||||
'error_details' => ["プリンタログ取得中にエラーが発生: " . $e->getMessage()]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 監視結果サマリーを作成
|
||||
*
|
||||
* @param array $devices デバイス一覧
|
||||
* @param array $hardwareResult ハードウェア結果
|
||||
* @param array $printerResult プリンタ結果
|
||||
* @return string 監視サマリー
|
||||
*/
|
||||
private function createMonitoringSummary(array $devices, array $hardwareResult, array $printerResult): string
|
||||
{
|
||||
$summary = [
|
||||
'デバイス数: ' . count($devices),
|
||||
'ハードウェア正常: ' . ($hardwareResult['normal_devices'] ?? 0) . '台',
|
||||
'ハードウェア異常: ' . ($hardwareResult['abnormal_devices'] ?? 0) . '台',
|
||||
'プリンタエラー: ' . ($printerResult['error_count'] ?? 0) . '件'
|
||||
];
|
||||
|
||||
return implode(', ', $summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 共通A処理:監視結果を反映
|
||||
*
|
||||
* @param int|null $batchLogId バッチログID
|
||||
* @param string $alertMessage アラートメッセージ
|
||||
* @return void
|
||||
*/
|
||||
private function executeCommonProcessA(?int $batchLogId, string $alertMessage): void
|
||||
{
|
||||
try {
|
||||
Log::info('共通A処理開始', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'alert_message' => $alertMessage
|
||||
]);
|
||||
|
||||
// 【共通判断1】DB反映可否判定
|
||||
$canReflectToDb = $this->canReflectToDatabase();
|
||||
|
||||
if ($canReflectToDb) {
|
||||
// 【共通処理1】オペレータキューを登録する
|
||||
$this->registerOperatorQueue($alertMessage, $batchLogId);
|
||||
|
||||
// 【共通処理2】メール送信対象オペレータを取得する
|
||||
$operators = $this->getMailTargetOperators();
|
||||
|
||||
// 【共通判断2】送信対象有無
|
||||
if (!empty($operators)) {
|
||||
foreach ($operators as $operator) {
|
||||
$this->sendAlertMail($operator['email'], $alertMessage, 'オペレータ');
|
||||
}
|
||||
}
|
||||
|
||||
// 【共通処理3】駐輪場管理者を取得する
|
||||
$parkManagers = $this->getParkManagers();
|
||||
|
||||
// 【共通判断3】送信対象有無
|
||||
if (!empty($parkManagers)) {
|
||||
foreach ($parkManagers as $manager) {
|
||||
$this->sendAlertMail($manager['email'], $alertMessage, '駐輪場管理者');
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// DB反映NGの場合は固定メールアドレスに送信
|
||||
$this->sendAlertMail(self::FIXED_EMAIL_ADDRESS, $alertMessage, 'システム管理者');
|
||||
}
|
||||
|
||||
Log::info('共通A処理完了', [
|
||||
'batch_log_id' => $batchLogId
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('共通A処理エラー', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DB反映可否判定
|
||||
*
|
||||
* @return bool 反映可能かどうか
|
||||
*/
|
||||
private function canReflectToDatabase(): bool
|
||||
{
|
||||
try {
|
||||
// 簡単なINSERTテストでDB反映可否を確認
|
||||
DB::beginTransaction();
|
||||
$testId = DB::table('operator_que')->insertGetId([
|
||||
'que_class' => 6,
|
||||
'que_comment' => 'DB反映テスト',
|
||||
'que_status' => 0,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now()
|
||||
]);
|
||||
|
||||
// テストレコードを削除
|
||||
DB::table('operator_que')->where('que_id', $testId)->delete();
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
Log::warning('DB反映不可', ['error' => $e->getMessage()]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* オペレータキューを登録
|
||||
*
|
||||
* @param string $alertMessage アラートメッセージ
|
||||
* @param int|null $batchLogId バッチログID
|
||||
* @return void
|
||||
*/
|
||||
private function registerOperatorQueue(string $alertMessage, ?int $batchLogId): void
|
||||
{
|
||||
try {
|
||||
OperatorQue::create([
|
||||
'que_class' => 6, // SHJ-6用のクラス
|
||||
'user_id' => null,
|
||||
'contract_id' => null,
|
||||
'park_id' => null,
|
||||
'que_comment' => $alertMessage,
|
||||
'que_status' => 0, // 待機中
|
||||
'que_status_comment' => 'システム監視アラート',
|
||||
'work_instructions' => "SHJ-6監視処理 BatchLogID: {$batchLogId}",
|
||||
'created_at' => now(),
|
||||
'updated_at' => now()
|
||||
]);
|
||||
|
||||
Log::info('オペレータキュー登録完了', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'alert_message' => $alertMessage
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('オペレータキュー登録エラー', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* メール送信対象オペレータを取得
|
||||
*
|
||||
* @return array オペレータ一覧
|
||||
*/
|
||||
private function getMailTargetOperators(): array
|
||||
{
|
||||
try {
|
||||
// user_typeがオペレータのユーザーを取得(仮の条件)
|
||||
$operators = DB::table('users')
|
||||
->select(['user_id', 'email', 'name'])
|
||||
->where('user_type', 'operator') // 実際のテーブル構造に合わせて調整
|
||||
->whereNotNull('email')
|
||||
->where('email', '!=', '')
|
||||
->get()
|
||||
->map(function ($user) {
|
||||
return [
|
||||
'user_id' => $user->user_id,
|
||||
'email' => $user->email,
|
||||
'name' => $user->name ?? 'オペレータ'
|
||||
];
|
||||
})
|
||||
->toArray();
|
||||
|
||||
Log::info('メール送信対象オペレータ取得完了', [
|
||||
'operator_count' => count($operators)
|
||||
]);
|
||||
|
||||
return $operators;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('メール送信対象オペレータ取得エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 駐輪場管理者を取得
|
||||
*
|
||||
* @return array 駐輪場管理者一覧
|
||||
*/
|
||||
private function getParkManagers(): array
|
||||
{
|
||||
try {
|
||||
// 駐輪場管理者を取得(仮の条件)
|
||||
$managers = DB::table('users')
|
||||
->select(['user_id', 'email', 'name'])
|
||||
->where('user_type', 'park_manager') // 実際のテーブル構造に合わせて調整
|
||||
->whereNotNull('email')
|
||||
->where('email', '!=', '')
|
||||
->get()
|
||||
->map(function ($user) {
|
||||
return [
|
||||
'user_id' => $user->user_id,
|
||||
'email' => $user->email,
|
||||
'name' => $user->name ?? '駐輪場管理者'
|
||||
];
|
||||
})
|
||||
->toArray();
|
||||
|
||||
Log::info('駐輪場管理者取得完了', [
|
||||
'manager_count' => count($managers)
|
||||
]);
|
||||
|
||||
return $managers;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('駐輪場管理者取得エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* アラートメールを送信
|
||||
*
|
||||
* @param string $email メールアドレス
|
||||
* @param string $alertMessage アラートメッセージ
|
||||
* @param string $recipientType 受信者タイプ
|
||||
* @return void
|
||||
*/
|
||||
private function sendAlertMail(string $email, string $alertMessage, string $recipientType): void
|
||||
{
|
||||
try {
|
||||
// SHJメール送信機能を使用(メールテンプレートID=1を使用、実際の値に調整)
|
||||
$result = $this->mailSendService->executeMailSend(
|
||||
$email,
|
||||
'', // 予備メールアドレスは空
|
||||
1 // システムアラート用メールテンプレートID
|
||||
);
|
||||
|
||||
if ($result['success']) {
|
||||
Log::info('アラートメール送信成功', [
|
||||
'email' => $email,
|
||||
'recipient_type' => $recipientType,
|
||||
'alert_message' => $alertMessage
|
||||
]);
|
||||
} else {
|
||||
Log::error('アラートメール送信失敗', [
|
||||
'email' => $email,
|
||||
'recipient_type' => $recipientType,
|
||||
'error' => $result['message']
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('アラートメール送信エラー', [
|
||||
'email' => $email,
|
||||
'recipient_type' => $recipientType,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
583
app/Services/ShjTenService.php
Normal file
583
app/Services/ShjTenService.php
Normal file
@ -0,0 +1,583 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Park;
|
||||
use App\Models\RegularContract;
|
||||
use App\Models\EarningsSummary;
|
||||
use App\Models\Psection;
|
||||
use App\Models\Batch\BatchLog;
|
||||
use App\Models\OperatorQue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* SHJ-10 売上集計処理サービス
|
||||
*
|
||||
* 財政年度ベースの年次・月次売上集計処理を実行するビジネスロジック
|
||||
* バッチ処理「SHJ-10売上集計」の核となる処理を担当
|
||||
*/
|
||||
class ShjTenService
|
||||
{
|
||||
/**
|
||||
* Park モデル
|
||||
*
|
||||
* @var Park
|
||||
*/
|
||||
protected $parkModel;
|
||||
|
||||
/**
|
||||
* RegularContract モデル
|
||||
*
|
||||
* @var RegularContract
|
||||
*/
|
||||
protected $contractModel;
|
||||
|
||||
/**
|
||||
* EarningsSummary モデル
|
||||
*
|
||||
* @var EarningsSummary
|
||||
*/
|
||||
protected $earningsSummaryModel;
|
||||
|
||||
/**
|
||||
* Psection モデル
|
||||
*
|
||||
* @var Psection
|
||||
*/
|
||||
protected $psectionModel;
|
||||
|
||||
/**
|
||||
* BatchLog モデル
|
||||
*
|
||||
* @var BatchLog
|
||||
*/
|
||||
protected $batchLogModel;
|
||||
|
||||
/**
|
||||
* OperatorQue モデル
|
||||
*
|
||||
* @var OperatorQue
|
||||
*/
|
||||
protected $operatorQueModel;
|
||||
|
||||
/**
|
||||
* 財政年度開始月
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const FISCAL_START_MONTH = 4;
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*
|
||||
* @param Park $parkModel
|
||||
* @param RegularContract $contractModel
|
||||
* @param EarningsSummary $earningsSummaryModel
|
||||
* @param Psection $psectionModel
|
||||
* @param BatchLog $batchLogModel
|
||||
* @param OperatorQue $operatorQueModel
|
||||
*/
|
||||
public function __construct(
|
||||
Park $parkModel,
|
||||
RegularContract $contractModel,
|
||||
EarningsSummary $earningsSummaryModel,
|
||||
Psection $psectionModel,
|
||||
BatchLog $batchLogModel,
|
||||
OperatorQue $operatorQueModel
|
||||
) {
|
||||
$this->parkModel = $parkModel;
|
||||
$this->contractModel = $contractModel;
|
||||
$this->earningsSummaryModel = $earningsSummaryModel;
|
||||
$this->psectionModel = $psectionModel;
|
||||
$this->batchLogModel = $batchLogModel;
|
||||
$this->operatorQueModel = $operatorQueModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* SHJ-10 財政年度売上集計処理メイン実行
|
||||
*
|
||||
* 処理フロー:
|
||||
* 【処理1】集計対象を設定する
|
||||
* 【処理2】駐輪場マスタを取得する
|
||||
* 【判断1】取得件数判定
|
||||
* 【処理3】車種区分毎に算出する
|
||||
* 【判断2】取得判定
|
||||
* 【処理4】売上集計結果を削除→登録する
|
||||
* 【処理5】オペレータキュー作成およびバッチ処理ログを作成する
|
||||
*
|
||||
* @param string $type 集計種別(yearly/monthly)
|
||||
* @param string $target 集計対象
|
||||
* @param array $fiscalPeriod 財政期間情報
|
||||
* @return array 処理結果
|
||||
*/
|
||||
public function executeFiscalEarningsAggregation(string $type, string $target, array $fiscalPeriod): array
|
||||
{
|
||||
$batchLogId = null;
|
||||
|
||||
try {
|
||||
// 【処理1】集計対象を設定する(財政年度ベース)
|
||||
$aggregationTarget = $this->setFiscalAggregationTarget($fiscalPeriod);
|
||||
|
||||
// バッチ処理開始ログ作成
|
||||
$batchLog = BatchLog::createBatchLog(
|
||||
'shj10',
|
||||
BatchLog::STATUS_START,
|
||||
[
|
||||
'type' => $type,
|
||||
'target' => $target,
|
||||
'fiscal_period' => $fiscalPeriod,
|
||||
'aggregation_target' => $aggregationTarget
|
||||
],
|
||||
"SHJ-10 売上集計処理開始 ({$type}: {$fiscalPeriod['target_label']})"
|
||||
);
|
||||
$batchLogId = $batchLog->id;
|
||||
|
||||
Log::info('SHJ-10 売上集計処理開始', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'type' => $type,
|
||||
'target' => $target,
|
||||
'fiscal_period' => $fiscalPeriod,
|
||||
'aggregation_target' => $aggregationTarget
|
||||
]);
|
||||
|
||||
// 【処理2】駐輪場マスタを取得する
|
||||
$parkInfo = $this->getParkInformation();
|
||||
|
||||
// 【判断1】取得件数判定
|
||||
if (empty($parkInfo)) {
|
||||
$typeLabel = $this->getTypeLabel($type);
|
||||
$message = "売上集計({$typeLabel}):駐輪場マスタが存在していません。";
|
||||
|
||||
// バッチログ更新
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_WARNING,
|
||||
'end_time' => now(),
|
||||
'message' => $message,
|
||||
'success_count' => 1 // 処理は成功したが対象なし
|
||||
]);
|
||||
|
||||
// 【処理5】オペレータキュー作成
|
||||
$this->createOperatorQueue($message, $batchLogId);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => $message,
|
||||
'processed_parks' => 0,
|
||||
'summary_records' => 0,
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
|
||||
// 【処理3】車種区分毎に算出する & 【処理4】売上集計結果を削除→登録する
|
||||
$summaryRecords = 0;
|
||||
$processedParks = 0;
|
||||
|
||||
foreach ($parkInfo as $park) {
|
||||
$parkSummaryRecords = $this->processFiscalEarningsForPark($park, $aggregationTarget, $fiscalPeriod);
|
||||
|
||||
if ($parkSummaryRecords > 0) {
|
||||
$processedParks++;
|
||||
$summaryRecords += $parkSummaryRecords;
|
||||
}
|
||||
}
|
||||
|
||||
// 【判断2】取得判定
|
||||
if ($summaryRecords === 0) {
|
||||
$message = '対象なしの結果を設定する(契約)';
|
||||
|
||||
// バッチログ更新
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_WARNING,
|
||||
'end_time' => now(),
|
||||
'message' => $message,
|
||||
'success_count' => 1
|
||||
]);
|
||||
|
||||
// 【処理5】オペレータキュー作成
|
||||
$this->createOperatorQueue($message, $batchLogId);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => $message,
|
||||
'processed_parks' => $processedParks,
|
||||
'summary_records' => 0,
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
|
||||
// バッチ処理完了ログ更新
|
||||
$completionMessage = "SHJ-10 売上集計処理正常完了 ({$type}: {$fiscalPeriod['target_label']}) - 駐輪場数: {$processedParks}, 集計レコード数: {$summaryRecords}";
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_SUCCESS,
|
||||
'end_time' => now(),
|
||||
'message' => $completionMessage,
|
||||
'success_count' => 1
|
||||
]);
|
||||
|
||||
// 【処理5】オペレータキュー作成
|
||||
$this->createOperatorQueue($completionMessage, $batchLogId);
|
||||
|
||||
Log::info('SHJ-10 売上集計処理完了', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'processed_parks' => $processedParks,
|
||||
'summary_records' => $summaryRecords
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'SHJ-10 売上集計処理が正常に完了しました',
|
||||
'processed_parks' => $processedParks,
|
||||
'summary_records' => $summaryRecords,
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = 'SHJ-10 売上集計処理でエラーが発生: ' . $e->getMessage();
|
||||
|
||||
if (isset($batchLog) && $batchLog) {
|
||||
$batchLog->update([
|
||||
'status' => BatchLog::STATUS_ERROR,
|
||||
'end_time' => now(),
|
||||
'message' => $errorMessage,
|
||||
'error_details' => $e->getMessage(),
|
||||
'error_count' => 1
|
||||
]);
|
||||
}
|
||||
|
||||
Log::error('SHJ-10 売上集計処理エラー', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'exception' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $errorMessage,
|
||||
'details' => $e->getMessage(),
|
||||
'batch_log_id' => $batchLogId
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理1】財政年度集計対象を設定する
|
||||
*
|
||||
* @param array $fiscalPeriod 財政期間情報
|
||||
* @return array 集計対象情報
|
||||
*/
|
||||
private function setFiscalAggregationTarget(array $fiscalPeriod): array
|
||||
{
|
||||
return [
|
||||
'type' => $fiscalPeriod['type'],
|
||||
'start_date' => $fiscalPeriod['start_date'],
|
||||
'end_date' => $fiscalPeriod['end_date'],
|
||||
'summary_type' => $fiscalPeriod['summary_type'],
|
||||
'fiscal_year' => $fiscalPeriod['fiscal_year'],
|
||||
'target_label' => $fiscalPeriod['target_label']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理2】駐輪場マスタを取得する
|
||||
*
|
||||
* 仕様書のSQLクエリに基づく駐輪場情報取得
|
||||
* SELECT 駐輪場ID, 駐輪場名
|
||||
* FROM 駐輪場マスタ
|
||||
* WHERE 閉設フラグ <> 1
|
||||
* ORDER BY 駐輪場ふりがな
|
||||
*
|
||||
* @return array 駐輪場情報
|
||||
*/
|
||||
private function getParkInformation(): array
|
||||
{
|
||||
try {
|
||||
$parkInfo = DB::table('park')
|
||||
->select(['park_id', 'park_name'])
|
||||
->where('park_close_flag', '<>', 1)
|
||||
->orderBy('park_ruby')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
Log::info('駐輪場マスタ取得完了', [
|
||||
'park_count' => count($parkInfo)
|
||||
]);
|
||||
|
||||
return $parkInfo;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('駐輪場マスタ取得エラー', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 駐輪場毎の財政年度売上集計処理
|
||||
*
|
||||
* @param object $park 駐輪場情報
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @param array $fiscalPeriod 財政期間情報
|
||||
* @return int 作成された集計レコード数
|
||||
*/
|
||||
private function processFiscalEarningsForPark($park, array $aggregationTarget, array $fiscalPeriod): int
|
||||
{
|
||||
try {
|
||||
// 【処理4】既存の売上集計結果を削除
|
||||
$this->deleteExistingFiscalSummary($park->park_id, $aggregationTarget);
|
||||
|
||||
// 【処理3】車種区分毎に算出する
|
||||
$psections = $this->getPsectionInformation();
|
||||
$summaryRecords = 0;
|
||||
|
||||
foreach ($psections as $psection) {
|
||||
$earningsData = $this->calculateFiscalEarningsForPsection(
|
||||
$park->park_id,
|
||||
$psection->psection_id,
|
||||
$aggregationTarget
|
||||
);
|
||||
|
||||
if ($this->hasEarningsData($earningsData)) {
|
||||
// 売上集計結果を登録
|
||||
$this->createFiscalEarningsSummary($park, $psection, $aggregationTarget, $earningsData, $fiscalPeriod);
|
||||
$summaryRecords++;
|
||||
}
|
||||
}
|
||||
|
||||
Log::info('駐輪場財政年度売上集計完了', [
|
||||
'park_id' => $park->park_id,
|
||||
'park_name' => $park->park_name,
|
||||
'summary_records' => $summaryRecords,
|
||||
'fiscal_period' => $fiscalPeriod['target_label']
|
||||
]);
|
||||
|
||||
return $summaryRecords;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('駐輪場財政年度売上集計エラー', [
|
||||
'park_id' => $park->park_id,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 車種区分情報取得
|
||||
*
|
||||
* @return array 車種区分情報
|
||||
*/
|
||||
private function getPsectionInformation(): array
|
||||
{
|
||||
return DB::table('psection')
|
||||
->select(['psection_id', 'psection_subject'])
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理3】車種区分毎に財政年度売上を算出する
|
||||
*
|
||||
* 4つの項目を計算:
|
||||
* ①売上・件数
|
||||
* ②一時金売上
|
||||
* ③解約返戻金
|
||||
* ④再発行金額・件数
|
||||
*
|
||||
* @param int $parkId 駐輪場ID
|
||||
* @param int $psectionId 車種区分ID
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @return array 売上データ
|
||||
*/
|
||||
private function calculateFiscalEarningsForPsection(int $parkId, int $psectionId, array $aggregationTarget): array
|
||||
{
|
||||
$startDate = $aggregationTarget['start_date'];
|
||||
$endDate = $aggregationTarget['end_date'];
|
||||
|
||||
// ①売上・件数(billing_amount)
|
||||
$salesData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as sales_count'),
|
||||
DB::raw('COALESCE(SUM(billing_amount), 0) as sales_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->where('contract_flag', 1)
|
||||
->whereBetween('contract_payment_day', [$startDate, $endDate])
|
||||
->whereNull('contract_cancelday')
|
||||
->first();
|
||||
|
||||
// ②一時金売上(contract_money)
|
||||
$temporaryData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as temporary_count'),
|
||||
DB::raw('COALESCE(SUM(contract_money), 0) as temporary_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->where('contract_flag', 1)
|
||||
->whereBetween('contract_payment_day', [$startDate, $endDate])
|
||||
->whereNotNull('contract_money')
|
||||
->where('contract_money', '>', 0)
|
||||
->first();
|
||||
|
||||
// ③解約返戻金(refunds)
|
||||
$refundData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as refund_count'),
|
||||
DB::raw('COALESCE(SUM(refunds), 0) as refund_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->whereBetween('contract_cancelday', [$startDate, $endDate])
|
||||
->whereNotNull('refunds')
|
||||
->where('refunds', '>', 0)
|
||||
->first();
|
||||
|
||||
// ④再発行金額・件数(seal_reissue_request)
|
||||
$reissueData = DB::table('regular_contract')
|
||||
->select([
|
||||
DB::raw('COUNT(*) as reissue_count'),
|
||||
DB::raw('COALESCE(SUM(contract_seal_issue), 0) as reissue_amount')
|
||||
])
|
||||
->where('park_id', $parkId)
|
||||
->where('psection_id', $psectionId)
|
||||
->where('seal_reissue_request', 1)
|
||||
->whereBetween('updated_at', [$startDate, $endDate])
|
||||
->first();
|
||||
|
||||
return [
|
||||
'sales_count' => $salesData->sales_count ?? 0,
|
||||
'sales_amount' => $salesData->sales_amount ?? 0,
|
||||
'temporary_count' => $temporaryData->temporary_count ?? 0,
|
||||
'temporary_amount' => $temporaryData->temporary_amount ?? 0,
|
||||
'refund_count' => $refundData->refund_count ?? 0,
|
||||
'refund_amount' => $refundData->refund_amount ?? 0,
|
||||
'reissue_count' => $reissueData->reissue_count ?? 0,
|
||||
'reissue_amount' => $reissueData->reissue_amount ?? 0
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 売上データの存在チェック
|
||||
*
|
||||
* @param array $earningsData 売上データ
|
||||
* @return bool データが存在するかどうか
|
||||
*/
|
||||
private function hasEarningsData(array $earningsData): bool
|
||||
{
|
||||
return $earningsData['sales_count'] > 0 ||
|
||||
$earningsData['temporary_count'] > 0 ||
|
||||
$earningsData['refund_count'] > 0 ||
|
||||
$earningsData['reissue_count'] > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理4】既存の財政年度売上集計結果を削除
|
||||
*
|
||||
* @param int $parkId 駐輪場ID
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @return void
|
||||
*/
|
||||
private function deleteExistingFiscalSummary(int $parkId, array $aggregationTarget): void
|
||||
{
|
||||
DB::table('earnings_summary')
|
||||
->where('park_id', $parkId)
|
||||
->where('summary_start_date', $aggregationTarget['start_date'])
|
||||
->where('summary_end_date', $aggregationTarget['end_date'])
|
||||
->where('summary_type', $aggregationTarget['summary_type'])
|
||||
->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 財政年度売上集計結果を登録
|
||||
*
|
||||
* @param object $park 駐輪場情報
|
||||
* @param object $psection 車種区分情報
|
||||
* @param array $aggregationTarget 集計対象
|
||||
* @param array $earningsData 売上データ
|
||||
* @param array $fiscalPeriod 財政期間情報
|
||||
* @return void
|
||||
*/
|
||||
private function createFiscalEarningsSummary($park, $psection, array $aggregationTarget, array $earningsData, array $fiscalPeriod): void
|
||||
{
|
||||
DB::table('earnings_summary')->insert([
|
||||
'park_id' => $park->park_id,
|
||||
'summary_type' => $aggregationTarget['summary_type'], // 1:年次, 2:月次
|
||||
'summary_start_date' => $aggregationTarget['start_date'],
|
||||
'summary_end_date' => $aggregationTarget['end_date'],
|
||||
'earnings_date' => $aggregationTarget['end_date'], // 集計日として終了日を使用
|
||||
'psection_id' => $psection->psection_id,
|
||||
'usertype_subject1' => $psection->psection_subject,
|
||||
'regular_new_count' => $earningsData['sales_count'],
|
||||
'regular_new_amount' => $earningsData['sales_amount'],
|
||||
'turnsum' => $earningsData['temporary_amount'],
|
||||
'turnsum_count' => $earningsData['temporary_count'],
|
||||
'refunds' => $earningsData['refund_amount'],
|
||||
'reissue_count' => $earningsData['reissue_count'],
|
||||
'reissue_amount' => $earningsData['reissue_amount'],
|
||||
'summary_note' => "SHJ-10 {$fiscalPeriod['target_label']} 財政年度売上集計結果",
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
'operator_id' => 0 // システム処理
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【処理5】オペレータキュー作成
|
||||
*
|
||||
* @param string $message メッセージ
|
||||
* @param int $batchLogId バッチログID
|
||||
* @return void
|
||||
*/
|
||||
private function createOperatorQueue(string $message, int $batchLogId): void
|
||||
{
|
||||
try {
|
||||
DB::table('operator_que')->insert([
|
||||
'que_class' => 10, // SHJ-10用のクラス
|
||||
'user_id' => null,
|
||||
'contract_id' => null,
|
||||
'park_id' => null,
|
||||
'que_comment' => $message,
|
||||
'que_status' => 1, // 完了
|
||||
'que_status_comment' => 'バッチ処理完了',
|
||||
'work_instructions' => "SHJ-10売上集計処理 BatchLogID: {$batchLogId}",
|
||||
'created_at' => now(),
|
||||
'updated_at' => now()
|
||||
]);
|
||||
|
||||
Log::info('オペレータキュー作成完了', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'message' => $message
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('オペレータキュー作成エラー', [
|
||||
'batch_log_id' => $batchLogId,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 集計種別のラベル取得
|
||||
*
|
||||
* @param string $type 集計種別
|
||||
* @return string ラベル
|
||||
*/
|
||||
private function getTypeLabel(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case 'yearly':
|
||||
return '年次';
|
||||
case 'monthly':
|
||||
return '月次';
|
||||
default:
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,3 +53,5 @@ class UserService
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -26,3 +26,5 @@ class Csv
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -28,3 +28,5 @@ class Files
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
24
create_device_table.sql
Normal file
24
create_device_table.sql
Normal file
@ -0,0 +1,24 @@
|
||||
--
|
||||
-- SHJ-6 デバイス管理マスタテーブル
|
||||
-- デバイス情報を管理するマスタテーブル
|
||||
--
|
||||
|
||||
CREATE TABLE `device` (
|
||||
`device_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'デバイスID(PK)',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '登録日時',
|
||||
`updated_at` datetime DEFAULT NULL COMMENT '更新日時',
|
||||
`park_id` int(10) UNSIGNED DEFAULT NULL COMMENT '駐輪場ID',
|
||||
`device_type` varchar(255) DEFAULT NULL COMMENT 'デバイス種別',
|
||||
`device_subject` varchar(255) DEFAULT NULL COMMENT 'デバイス名',
|
||||
`device_identifier` varchar(255) DEFAULT NULL COMMENT '識別子(IP/FQDN)',
|
||||
`device_work` varchar(255) DEFAULT NULL COMMENT '稼働(状態)',
|
||||
`device_workstart` date DEFAULT NULL COMMENT '稼働開始日',
|
||||
`device_replace` date DEFAULT NULL COMMENT 'リプレース予定日',
|
||||
`device_remarks` varchar(255) DEFAULT NULL COMMENT '備考',
|
||||
`operator_id` int(10) UNSIGNED DEFAULT NULL COMMENT '更新オペレータID',
|
||||
PRIMARY KEY (`device_id`),
|
||||
KEY `idx_park_id` (`park_id`),
|
||||
KEY `idx_device_type` (`device_type`),
|
||||
KEY `idx_workstart` (`device_workstart`),
|
||||
KEY `idx_replace` (`device_replace`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='デバイス管理マスタテーブル';
|
||||
39
create_earnings_summary_table.sql
Normal file
39
create_earnings_summary_table.sql
Normal file
@ -0,0 +1,39 @@
|
||||
--
|
||||
-- SHJ-9 売上集計結果テーブル
|
||||
-- 日次売上集計データを保存するテーブル
|
||||
--
|
||||
|
||||
CREATE TABLE `earnings_summary` (
|
||||
`earnings_summary_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '売上集計ID',
|
||||
`park_id` int(10) UNSIGNED NOT NULL COMMENT '駐輪場ID',
|
||||
`summary_type` varchar(255) DEFAULT NULL COMMENT '集計区分',
|
||||
`summary_start_date` date DEFAULT NULL COMMENT '集計開始日',
|
||||
`summary_end_date` date DEFAULT NULL COMMENT '集計終了日',
|
||||
`earnings_date` date DEFAULT NULL COMMENT '売上日',
|
||||
`psection_id` int(10) UNSIGNED DEFAULT NULL COMMENT '車種区分ID',
|
||||
`usertype_subject1` varchar(255) DEFAULT NULL COMMENT '規格',
|
||||
`enable_months` int(10) UNSIGNED DEFAULT NULL COMMENT '期間(月数)',
|
||||
`regular_new_count` int(10) UNSIGNED DEFAULT 0 COMMENT '期間件数',
|
||||
`regular_new_amount` decimal(10,2) DEFAULT 0.00 COMMENT '期間金額',
|
||||
`regular_new_reduction_count` int(10) UNSIGNED DEFAULT 0 COMMENT '期間成免件数',
|
||||
`regular_new_reduction_amount` decimal(10,2) DEFAULT 0.00 COMMENT '期間成免金額',
|
||||
`regular_update_count` int(10) UNSIGNED DEFAULT 0 COMMENT '更新件数',
|
||||
`regular_update_amount` decimal(10,2) DEFAULT 0.00 COMMENT '更新金額',
|
||||
`regular_update_reduction_count` int(10) UNSIGNED DEFAULT 0 COMMENT '更新成免件数',
|
||||
`regular_update_reduction_amount` decimal(10,2) DEFAULT 0.00 COMMENT '更新成免金額',
|
||||
`turnsum_count` int(10) UNSIGNED DEFAULT 0 COMMENT '残金件数',
|
||||
`turnsum` decimal(10,2) DEFAULT 0.00 COMMENT '残金',
|
||||
`refunds` decimal(10,2) DEFAULT 0.00 COMMENT '解時返戻金',
|
||||
`other_income` decimal(10,2) DEFAULT 0.00 COMMENT '分別収入',
|
||||
`other_spending` decimal(10,2) DEFAULT 0.00 COMMENT '分別支出',
|
||||
`reissue_count` int(10) UNSIGNED DEFAULT 0 COMMENT '発行件数',
|
||||
`reissue_amount` decimal(10,2) DEFAULT 0.00 COMMENT '発行金額',
|
||||
`summary_note` text DEFAULT NULL COMMENT '計備考',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '登録日時',
|
||||
`updated_at` datetime DEFAULT NULL COMMENT '更新日時',
|
||||
`operator_id` int(10) UNSIGNED DEFAULT NULL COMMENT '新法・ページID',
|
||||
PRIMARY KEY (`earnings_summary_id`),
|
||||
KEY `idx_park_earnings_date` (`park_id`, `earnings_date`),
|
||||
KEY `idx_psection` (`psection_id`),
|
||||
KEY `idx_earnings_date` (`earnings_date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='売上集計結果テーブル';
|
||||
19
create_hardware_check_log_table.sql
Normal file
19
create_hardware_check_log_table.sql
Normal file
@ -0,0 +1,19 @@
|
||||
--
|
||||
-- SHJ-6 ハードウェアチェックログテーブル
|
||||
-- デバイスのハードウェア状態監視ログを保存するテーブル
|
||||
--
|
||||
|
||||
CREATE TABLE `hardware_check_log` (
|
||||
`log_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ハードウェアチェックログID(PK)',
|
||||
`device_id` int(10) UNSIGNED NOT NULL COMMENT 'デバイスID',
|
||||
`status` int(10) UNSIGNED DEFAULT NULL COMMENT 'ステータス',
|
||||
`status_comment` varchar(255) DEFAULT NULL COMMENT 'ステータスコメント',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '登録日時',
|
||||
`updated_at` datetime DEFAULT NULL COMMENT '更新日時',
|
||||
`operator_id` int(10) UNSIGNED DEFAULT NULL COMMENT 'オペレータID',
|
||||
PRIMARY KEY (`log_id`),
|
||||
KEY `idx_device_id` (`device_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_created_at` (`created_at`),
|
||||
KEY `idx_device_created` (`device_id`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='ハードウェアチェックログテーブル';
|
||||
24
create_print_job_log_table.sql
Normal file
24
create_print_job_log_table.sql
Normal file
@ -0,0 +1,24 @@
|
||||
--
|
||||
-- SHJ-6 プリンタジョブログテーブル
|
||||
-- プリンタ制御プログラムの実行ログを保存するテーブル
|
||||
--
|
||||
|
||||
CREATE TABLE `print_job_log` (
|
||||
`log_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '処理ログID(PK)',
|
||||
`park_id` int(10) UNSIGNED DEFAULT NULL COMMENT '駐輪場ID',
|
||||
`user_id` int(10) UNSIGNED DEFAULT NULL COMMENT 'ユーザーID',
|
||||
`contract_id` int(10) UNSIGNED DEFAULT NULL COMMENT '契約ID',
|
||||
`process_name` varchar(255) DEFAULT NULL COMMENT 'プロセス名',
|
||||
`job_name` varchar(255) DEFAULT NULL COMMENT 'ジョブ名',
|
||||
`status` varchar(255) DEFAULT NULL COMMENT 'ステータス',
|
||||
`error_code` int(10) UNSIGNED DEFAULT NULL COMMENT 'エラーコード',
|
||||
`status_comment` varchar(255) DEFAULT NULL COMMENT 'ステータスコメント',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '登録日時',
|
||||
PRIMARY KEY (`log_id`),
|
||||
KEY `idx_park_id` (`park_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_contract_id` (`contract_id`),
|
||||
KEY `idx_error_code` (`error_code`),
|
||||
KEY `idx_created_at` (`created_at`),
|
||||
KEY `idx_created_error` (`created_at`, `error_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='プリンタジョブログテーブル';
|
||||
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('earnings_summary', function (Blueprint $table) {
|
||||
$table->id('earnings_summary_id')->comment('売上集計ID');
|
||||
$table->unsignedInteger('park_id')->comment('駐輪場ID');
|
||||
$table->string('summary_type', 255)->nullable()->comment('集計区分');
|
||||
$table->date('summary_start_date')->nullable()->comment('集計開始日');
|
||||
$table->date('summary_end_date')->nullable()->comment('集計終了日');
|
||||
$table->date('earnings_date')->nullable()->comment('売上日');
|
||||
$table->unsignedInteger('psection_id')->nullable()->comment('車種区分ID');
|
||||
$table->string('usertype_subject1', 255)->nullable()->comment('規格');
|
||||
$table->unsignedInteger('enable_months')->nullable()->comment('期間(月数)');
|
||||
$table->unsignedInteger('regular_new_count')->nullable()->comment('期間件数');
|
||||
$table->decimal('regular_new_amount', 10, 2)->nullable()->comment('期間金額');
|
||||
$table->unsignedInteger('regular_new_reduction_count')->nullable()->comment('期間成免件数');
|
||||
$table->decimal('regular_new_reduction_amount', 10, 2)->nullable()->comment('期間成免金額');
|
||||
$table->unsignedInteger('regular_update_count')->nullable()->comment('更新件数');
|
||||
$table->decimal('regular_update_amount', 10, 2)->nullable()->comment('更新金額');
|
||||
$table->unsignedInteger('regular_update_reduction_count')->nullable()->comment('更新成免件数');
|
||||
$table->decimal('regular_update_reduction_amount', 10, 2)->nullable()->comment('更新成免金額');
|
||||
$table->unsignedInteger('turnsum_count')->nullable()->comment('残金件数');
|
||||
$table->decimal('turnsum', 10, 2)->nullable()->comment('残金');
|
||||
$table->decimal('refunds', 10, 2)->nullable()->comment('解時返戻金');
|
||||
$table->decimal('other_income', 10, 2)->nullable()->comment('分別収入');
|
||||
$table->decimal('other_spending', 10, 2)->nullable()->comment('分別支出');
|
||||
$table->unsignedInteger('reissue_count')->nullable()->comment('発行件数');
|
||||
$table->decimal('reissue_amount', 10, 2)->nullable()->comment('発行金額');
|
||||
$table->text('summary_note')->nullable()->comment('計備考');
|
||||
$table->datetime('created_at')->nullable()->comment('登録日時');
|
||||
$table->datetime('updated_at')->nullable()->comment('更新日時');
|
||||
$table->unsignedInteger('operator_id')->nullable()->comment('新法・ページID');
|
||||
|
||||
// インデックス
|
||||
$table->index(['park_id', 'earnings_date'], 'idx_park_earnings_date');
|
||||
$table->index(['psection_id'], 'idx_psection');
|
||||
$table->index(['earnings_date'], 'idx_earnings_date');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('earnings_summary');
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user