app/Services/ShjNineService.php を削除
Some checks failed
Deploy main / deploy (push) Has been cancelled
Some checks failed
Deploy main / deploy (push) Has been cancelled
This commit is contained in:
parent
f4d66e3f20
commit
8c0413157a
@ -1,595 +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-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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user