krgm.so-manager-dev.com/app/Services/UsingStatusService.php

104 lines
3.3 KiB
PHP
Raw Permalink 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
{
/**
* 駐輪場別利用率統計を取得
*
* @param int|null $parkId 駐輪場IDnull の場合は全て)
* @return Collection 統計データのコレクション
*/
public function getUtilizationStats(?int $parkId = null): Collection
{
// 暫定的な収容台数実DBに無いカラムのため
$defaultCapacity = [
1 => 100, // 自転車
2 => 50, // 原付
3 => 30, // その他
];
$query = DB::table('park as p')
->leftJoin('price_a as pr', 'p.park_id', '=', 'pr.park_id')
->leftJoin('ptype as pt', 'pr.price_ptypeid', '=', 'pt.ptype_id')
->leftJoin('regular_contract as rc', function ($join) {
$join->on('pr.price_parkplaceid', '=', 'rc.price_parkplaceid')
->where('rc.contract_cancel_flag', '=', 0);
})
->select([
'p.park_id',
'p.park_name',
'pt.ptype_id',
'pt.ptype_subject',
DB::raw('COUNT(rc.contract_id) as current_count'),
])
->whereNotNull('pr.price_parkplaceid')
->whereNotNull('pt.ptype_id')
->where('p.park_close_flag', '!=', 1);
if ($parkId) {
$query->where('p.park_id', $parkId);
}
$results = $query
->groupBy(['p.park_id', 'p.park_name', 'pt.ptype_id', 'pt.ptype_subject'])
->orderBy('p.park_name')
->orderBy('pt.ptype_subject')
->get();
// 後計算で容量・空き・利用率を付与
foreach ($results as $result) {
$capacity = $defaultCapacity[$result->ptype_id] ?? 50;
$result->park_limit = $capacity;
$result->available = $capacity - $result->current_count;
$result->usage_rate = $capacity > 0 ? round(($result->current_count / $capacity * 100), 1) : 0;
}
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,
];
}
}