SHJ-4 SHJ-5改修
All checks were successful
Deploy api / deploy (push) Successful in 23s

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-02-06 10:42:35 +09:00
parent e3a60540be
commit 8499e0a01c
2 changed files with 49 additions and 37 deletions

View File

@ -234,6 +234,8 @@ class ShjFourCService
'T1.zone_standard as zone_standard', 'T1.zone_standard as zone_standard',
'T1.zone_tolerance as zone_tolerance', 'T1.zone_tolerance as zone_tolerance',
'T1.zone_sort', 'T1.zone_sort',
'T1.zone_pplace_start', // 車室番号開始NULLの場合は1
'T1.zone_pplace_end', // 車室番号終了NULLの場合は許容台数まで
'T2.update_grace_period_start_date', 'T2.update_grace_period_start_date',
'T2.update_grace_period_end_date' 'T2.update_grace_period_end_date'
]) ])
@ -270,10 +272,18 @@ class ShjFourCService
/** /**
* 【判断1】割当判定処理 * 【判断1】割当判定処理
* *
* ゾーンIDごとにわか順(インクリメント、内部変数.対象番号とする)に * ゾーンIDごとに車室番号開始から順(インクリメント、内部変数.対象番号とする)に
* ゾーン内標準台数に達するまで、定期契約マスタから該当する車室番号で * 車室番号終了に達するまで、定期契約マスタから該当する車室番号で
* 契約済みの情報の有無を確認する * 契約済みの情報の有無を確認する
* *
* 【パフォーマンス改善】
* 変更前: 各車室番号ごとに1回SQLクエリ最大1200回
* 変更後: ゾーンごとに使用中の車室番号を一括取得1回
*
* 【車室番号範囲対応】
* zone_pplace_start: 開始番号NULLの場合は1
* zone_pplace_end: 終了番号NULLの場合は開始番号+許容台数-1
*
* @param array $zoneInfo ゾーン情報 * @param array $zoneInfo ゾーン情報
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param int $ptypeId 駐輪分類ID * @param int $ptypeId 駐輪分類ID
@ -284,19 +294,22 @@ class ShjFourCService
{ {
try { try {
foreach ($zoneInfo as $zone) { foreach ($zoneInfo as $zone) {
// ゾーン内標準台数まで車室番号をインクリメントして検索 // 【改善】使用中の車室番号を一括取得1回のクエリ
for ($pplaceNo = 1; $pplaceNo <= $zone->zone_standard; $pplaceNo++) { $occupiedNumbers = $this->getOccupiedRoomNumbers(
// 該当する車室番号で契約済みの情報の有無を確認
$contractInfo = $this->getRegularContractInfo(
$parkId, $parkId,
$zone->zone_id, $zone->zone_id,
$pplaceNo,
(int) $zone->update_grace_period_start_date, (int) $zone->update_grace_period_start_date,
(int) $zone->update_grace_period_end_date (int) $zone->update_grace_period_end_date
); );
// 契約情報が存在しない場合、この車室番号は空き // 【車室番号範囲対応】開始・終了番号を取得
if ($contractInfo === null) { $start = $zone->zone_pplace_start ?? 1;
$end = $zone->zone_pplace_end ?? ($start + $zone->zone_tolerance - 1);
// PHP側で空き番号を検索開始番号から終了番号まで
for ($pplaceNo = $start; $pplaceNo <= $end; $pplaceNo++) {
// 使用中でなければ空き
if (!in_array($pplaceNo, $occupiedNumbers, true)) {
Log::info('SHJ-4C 割当OK', [ Log::info('SHJ-4C 割当OK', [
'zone_id' => $zone->zone_id, 'zone_id' => $zone->zone_id,
'zone_name' => $zone->zone_name, 'zone_name' => $zone->zone_name,
@ -342,48 +355,47 @@ class ShjFourCService
} }
/** /**
* 定期契約情報取得 * 使用中の車室番号を一括取得
* *
* 設計書のSQLクエリに基づく定期契約マスタ検索 * 【パフォーマンス改善】
* 特定の車室番号で契約済みの情報の有無を確認する * 1ゾーンあたり1回のSQLクエリで全ての使用中車室番号を取得
* *
* @param int $parkId 駐輪場ID * @param int $parkId 駐輪場ID
* @param int $zoneId ゾーンID * @param int $zoneId ゾーンID
* @param int $pplaceNo 車室番号(対象番号)
* @param int $updateGracePeriodStartDate 更新期間開始日 * @param int $updateGracePeriodStartDate 更新期間開始日
* @param int $updateGracePeriodEndDate 更新期間終了日 * @param int $updateGracePeriodEndDate 更新期間終了日
* @return array|null 定期契約情報存在しない場合はnull * @return array 使用中の車室番号配列
*/ */
private function getRegularContractInfo( private function getOccupiedRoomNumbers(
int $parkId, int $parkId,
int $zoneId, int $zoneId,
int $pplaceNo,
int $updateGracePeriodStartDate, int $updateGracePeriodStartDate,
int $updateGracePeriodEndDate int $updateGracePeriodEndDate
): ?array { ): array {
$currentDate = Carbon::now()->format('y.%m.%d'); $currentDate = Carbon::now()->format('Y-m-d');
$query = DB::table('regular_contract as T1') $query = DB::table('regular_contract as T1')
->select(['T1.contract_id']) ->select('T1.pplace_no')
->where('T1.park_id', $parkId) ->where('T1.park_id', $parkId)
->where('T1.zone_id', $zoneId) ->where('T1.zone_id', $zoneId)
->where('T1.pplace_no', $pplaceNo); ->where('T1.contract_flag', 1)
->whereNotNull('T1.pplace_no');
// 【「JOB1.更新期間開始日」<=「JOB1. 更新期間終了日」の場合】 // パターンA/B の条件(既存ロジックと同じ)
if ($updateGracePeriodStartDate <= $updateGracePeriodEndDate) { if ($updateGracePeriodStartDate <= $updateGracePeriodEndDate) {
// パターンA: T1.有効期間E >= date_format(now(), '%y.%m.%d') // パターンA: 有効期間E >= 現在日付
$query->whereRaw("date_format(T1.contract_periode, '%y.%m.%d') >= ?", [$currentDate]); $query->where('T1.contract_periode', '>=', $currentDate);
} else { } else {
// 【その他の場合】 // パターンB: 有効期間E + 更新期間終了日 >= 現在日付
// パターンB: T1.有効期間E + 「JOB1. 更新期間終了日」>= date_format(now(), '%y.%m.%d') $query->whereRaw(
$query->whereRaw("DATE_ADD(T1.contract_periode, INTERVAL ? DAY) >= ?", [$updateGracePeriodEndDate, $currentDate]); "DATE_ADD(T1.contract_periode, INTERVAL ? DAY) >= ?",
[$updateGracePeriodEndDate, $currentDate]
);
} }
$query->where('T1.contract_flag', 1); return $query->pluck('pplace_no')->map(function ($val) {
return (int) $val;
$result = $query->first(); })->toArray();
return $result ? (array) $result : null;
} }
/** /**

View File

@ -12,7 +12,7 @@ class ExampleTest extends TestCase
*/ */
public function test_the_application_returns_a_successful_response(): void public function test_the_application_returns_a_successful_response(): void
{ {
$response = $this->get('/'); $response = $this->get('/up');
$response->assertStatus(200); $response->assertStatus(200);
} }