schneespur/release/schneespur-1.0.2/app/Http/Controllers/Portal/PortalDashboardController.php
Michael 7288b93500 Release v1.0.2: diagnostic infrastructure core
Add neutral diagnostic framework for future reporting modules:
- DiagnosticReporterInterface, Registry, Manager, PayloadSanitizer
- Laravel exception hook in bootstrap/app.php
- Module permission declarations (requires_permissions in module.json)
- Core diagnostic report points (module boot/install/update failures)
- Module documentation update (moduldoku.md)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-18 16:54:11 +00:00

48 lines
1.7 KiB
PHP

<?php
namespace App\Http\Controllers\Portal;
use App\Http\Controllers\Controller;
use App\Models\Job;
use App\Services\SeasonService;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class PortalDashboardController extends Controller
{
public function __invoke(SeasonService $seasonService): View
{
$customer = auth('customer')->user();
$season = $seasonService->currentOrLastSeason();
$totalJobs = Job::where('customer_id', $customer->id)
->whereNotNull('ended_at')
->whereBetween('started_at', [$season->start, $season->end])
->count();
$isSqlite = DB::getDriverName() === 'sqlite';
$durationExpr = $isSqlite
? "SUM((JULIANDAY(COALESCE(ended_at, started_at)) - JULIANDAY(started_at)) * 1440)"
: "SUM(TIMESTAMPDIFF(MINUTE, started_at, COALESCE(ended_at, started_at)))";
$totalMinutes = (int) Job::selectRaw("{$durationExpr} as total_minutes")
->where('customer_id', $customer->id)
->whereNotNull('ended_at')
->whereBetween('started_at', [$season->start, $season->end])
->value('total_minutes');
$totalHours = number_format($totalMinutes / 60, 1);
$lastJob = Job::where('customer_id', $customer->id)
->whereNotNull('ended_at')
->latest('started_at')
->first();
$objects = $customer->objects()
->withMax(['serviceJobs as last_job_at' => fn ($q) => $q->whereNotNull('ended_at')], 'started_at')
->orderBy('name')
->get();
return view('portal.home', compact('season', 'totalJobs', 'totalHours', 'lastJob', 'objects'));
}
}