krgm.so-manager-dev.com/app/Services/UsingStatusService.php
你的名字 2abeb50a50
All checks were successful
Deploy main / deploy (push) Successful in 23s
【指摘対応】
2025-10-10 16:28:29 +09:00

106 lines
3.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Services;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Collection;
use App\Models\Park;
/**
* 利用率状況サービス
* - 旧 UsingStatusHelper の機能をサービスとして集約
* - 画面やAPIから本サービスを経由して取得する
*/
class UsingStatusService
{
/**
* 駐輪場別利用率統計を取得
*
* 取得元:
* - 限界収容台数: park_number.park_limit
* - 現在収容台数: park_number.park_number
* - 空き : park_number.park_limit - park_number.park_number
* - 利用率 : (現在収容台数 / 限界収容台数) * 100
*
* @param int|null $parkId 駐輪場IDnull の場合は全て)
* @return Collection
*/
public function getUtilizationStats(?int $parkId = null): \Illuminate\Support\Collection
{
// park_number に車種IDが ptype_id で入っている前提
// 異なる場合は 'pn.ptype_id' 部分を実テーブル定義に合わせて変更してください
// ✅ Laravel 12対応psectionテーブルから車種を取得するように変更
$query = \DB::table('park as p')
->join('park_number as pn', 'p.park_id', '=', 'pn.park_id')
// 旧: join('ptype as pt', 'pn.ptype_id', '=', 'pt.ptype_id')
->leftJoin('psection as ps', 'pn.psection_id', '=', 'ps.psection_id') // ✅ 新しい車種取得方法
->select([
'p.park_id',
'p.park_name',
// 'pt.ptype_id',
// 'pt.ptype_subject',
'ps.psection_subject', // 車種psection_subjectに変更
// 限界収容台数
'pn.park_limit',
// 現在収容台数
\DB::raw('COALESCE(pn.park_number, 0) as current_count'),
// 空き = 収容上限 - 現在
\DB::raw('GREATEST(0, COALESCE(pn.park_limit, 0) - COALESCE(pn.park_number, 0)) as available'),
// 利用率 = 現在 / 上限 * 100
\DB::raw("CASE
WHEN COALESCE(pn.park_limit, 0) > 0
THEN ROUND((COALESCE(pn.park_number, 0) / pn.park_limit) * 100, 1)
ELSE 0
END as usage_rate"),
])
->where('p.park_close_flag', '!=', 1);
if (!empty($parkId)) {
$query->where('p.park_id', $parkId);
}
$results = $query
// 表示順:自転車 → 原付 → その他
->orderByRaw("CASE ps.psection_subject WHEN '自転車' THEN 1 WHEN '原付' THEN 2 ELSE 3 END")
->orderBy('p.park_name')
->get();
return $results;
}
/**
* 駐輪場一覧を取得(選択用)
*/
public function getParkList(): Collection
{
return Park::select('park_id', 'park_name')
->where('park_close_flag', '!=', 1)
->orderBy('park_name')
->get();
}
/**
* 合計行の計算
*
* @param Collection $stats
* @return array{total_limit:int,total_current:int,total_available:int,total_usage_rate:float}
*/
public function calculateTotals(Collection $stats): array
{
$totalLimit = (int) $stats->sum('park_limit');
$totalCurrent = (int) $stats->sum('current_count');
$totalAvailable = $totalLimit - $totalCurrent;
$totalUsageRate = $totalLimit > 0 ? round(($totalCurrent / $totalLimit * 100), 1) : 0.0;
return [
'total_limit' => $totalLimit,
'total_current' => $totalCurrent,
'total_available' => $totalAvailable,
'total_usage_rate' => $totalUsageRate,
];
}
}