schneespur/release/schneespur-1.0.2/app/Services/CsvExportService.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

96 lines
3.1 KiB
PHP

<?php
namespace App\Services;
use App\Models\Job;
use Illuminate\Support\Carbon;
use League\Csv\ByteSequence;
use League\Csv\Writer;
class CsvExportService
{
public function buildCsv(string $variant, ?string $from, ?string $to, ?int $userId = null, ?int $customerId = null): string
{
$csv = Writer::createFromString();
$csv->setOutputBOM(ByteSequence::BOM_UTF8);
$csv->setDelimiter(';');
$csv->insertOne([
__('export.csv_col_date'),
__('export.csv_col_driver'),
__('export.csv_col_customer'),
__('export.csv_col_object_name'),
__('export.csv_col_object_street'),
__('export.csv_col_object_zip'),
__('export.csv_col_object_city'),
__('export.csv_col_type'),
__('export.csv_col_start'),
__('export.csv_col_end'),
__('export.csv_col_duration'),
__('export.csv_col_shift_id'),
__('export.csv_col_source'),
]);
$query = Job::query()
->with([
'customer:id,name',
'customerObject:id,customer_id,name,street,zip,city',
'user' => fn ($q) => $q->withAnonymized(),
'workShift:id',
])
->when($from, fn ($q, $d) => $q->where('started_at', '>=', $d))
->when($to, fn ($q, $d) => $q->where('started_at', '<=', $d . ' 23:59:59'))
->orderBy('started_at');
if ($variant === 'driver' && $userId) {
$query->where('user_id', $userId);
}
if ($variant === 'customer' && $customerId) {
$query->where('customer_id', $customerId);
}
$now = Carbon::now();
foreach ($query->lazy(200) as $job) {
$duration = '';
if ($job->ended_at) {
$duration = (string) (int) round($job->started_at->diffInSeconds($job->ended_at) / 60);
} elseif ($job->started_at) {
$duration = (string) (int) round($job->started_at->diffInSeconds($now) / 60);
}
$csv->insertOne([
$job->started_at->format('d.m.Y'),
$job->user?->displayName() ?? '',
$job->customer?->name ?? '',
$job->customerObject?->name ?? '',
$job->customerObject?->street ?? '',
$job->customerObject?->zip ?? '',
$job->customerObject?->city ?? '',
$job->type->label(),
$job->started_at->format('H:i'),
$job->ended_at?->format('H:i') ?? '',
$duration,
$job->work_shift_id ?? '',
$job->is_manual ? __('export.csv_source_manual') : __('export.csv_source_automatic'),
]);
}
return $csv->toString();
}
public function generateFilename(string $variant, ?string $from, ?string $to): string
{
$parts = ['zeiterfassung', $variant];
if ($from) {
$parts[] = $from;
}
if ($to) {
$parts[] = $to;
}
return implode('-', $parts) . '.csv';
}
}