app/Services/ShjTenService.php を削除
Some checks failed
Deploy main / deploy (push) Has been cancelled

This commit is contained in:
go.unhi 2025-10-23 20:38:01 +09:00
parent a484231216
commit dbc059ef2c

View File

@ -1,583 +0,0 @@
<?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;
}
}
}