Files
drivetimeplaner/www/api.fahrschultermin.de/app/Http/Controllers/WorkTimesheetController.php

128 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Repositories\WorkTimesheetRepository;
use App\Support\Auth;
use App\Support\Request;
use App\Support\Response;
final class WorkTimesheetController
{
public function index(Request $request): void
{
$user = Auth::requireUser();
$instructorId = (int) $request->query('instructor_id');
$from = (string) $request->query('from');
$to = (string) $request->query('to');
if ($instructorId <= 0 || $from === '' || $to === '') {
Response::json(['message' => 'instructor_id, from und to sind erforderlich'], 422);
}
$repo = new WorkTimesheetRepository();
$tenantId = (int) $user['tenant_id'];
$instructor = $repo->getInstructor($tenantId, $instructorId);
if ($instructor === null) {
Response::json(['message' => 'Fahrlehrer nicht gefunden'], 404);
}
$appointments = $repo->getAppointmentsForInstructor($tenantId, $instructorId, $from, $to);
// Gruppiere nach Datum
$daysMap = [];
foreach ($appointments as $apt) {
$date = date('Y-m-d', strtotime($apt['start_at']));
if (!isset($daysMap[$date])) {
$daysMap[$date] = [];
}
$daysMap[$date][] = $apt;
}
$days = [];
$typeSummaryMap = [];
foreach ($daysMap as $date => $aptList) {
$dayTotalMinutes = 0;
$dayTotalUe = 0.0;
$appointmentsOut = [];
foreach ($aptList as $apt) {
$startAt = new \DateTimeImmutable($apt['start_at']);
$endAt = new \DateTimeImmutable($apt['end_at']);
$durationMinutes = (int) round(($endAt->getTimestamp() - $startAt->getTimestamp()) / 60);
$ue = round((float) $apt['units'], 2);
$appointmentsOut[] = [
'type' => $apt['lesson_type_name'],
'start_at' => $startAt->format('H:i'),
'end_at' => $endAt->format('H:i'),
'duration_minutes' => $durationMinutes,
'ue' => $ue,
'ue_formatted' => self::formatUe($ue),
];
$dayTotalMinutes += $durationMinutes;
$dayTotalUe += $ue;
// Type summary
$typeKey = $apt['lesson_type_name'];
if (!isset($typeSummaryMap[$typeKey])) {
$typeSummaryMap[$typeKey] = ['type' => $apt['lesson_type_name'], 'total_minutes' => 0, 'total_ue' => 0.0, 'count' => 0];
}
$typeSummaryMap[$typeKey]['total_minutes'] += $durationMinutes;
$typeSummaryMap[$typeKey]['total_ue'] += $ue;
$typeSummaryMap[$typeKey]['count']++;
}
$days[] = [
'date' => $date,
'appointments' => $appointmentsOut,
'day_total_minutes' => $dayTotalMinutes,
'day_total_ue' => round($dayTotalUe, 2),
'day_total_ue_formatted' => self::formatUe($dayTotalUe),
];
}
// Gesamtsumme
$totalMinutes = 0;
$totalUe = 0.0;
foreach ($typeSummaryMap as $entry) {
$totalMinutes += $entry['total_minutes'];
$totalUe += $entry['total_ue'];
}
// Typ-Zusammenfassung sortieren
$typeSummary = array_values($typeSummaryMap);
usort($typeSummary, static fn($a, $b) => $a['type'] <=> $b['type']);
// UE formatiert
foreach ($typeSummary as &$entry) {
$entry['total_ue'] = round($entry['total_ue'], 2);
$entry['total_ue_formatted'] = self::formatUe($entry['total_ue']);
}
Response::json([
'data' => [
'instructor' => $instructor,
'period' => ['from' => $from, 'to' => $to],
'days' => $days,
'type_summary' => $typeSummary,
'summary' => [
'total_minutes' => $totalMinutes,
'total_ue' => round($totalUe, 2),
'total_ue_formatted' => self::formatUe($totalUe),
],
],
]);
}
private static function formatUe(float $ue): string
{
return str_replace('.', ',', number_format($ue, 2, ',', '')) . ' UE';
}
}