fix: Push-Notifications und Reminder-Zeitberechnung

- PushService: Http::asJson() statt withHeaders; EXPO_TOKEN als Bearer-Auth
- services.php: expo.token aus ENV eingetragen
- ScheduleEventReminders: UTC-Reminder-Zeit erst in Lokalzeit umrechnen,
  dann mit lokalem Event-Datum kombinieren → verhindert +24h-Versatz bei
  Mitternacht-Übergängen (z.B. 22:20 UTC = 00:20 Wien)
- Event-Abfrage auf starts_at > now - 1 Tag erweitert, damit auch bereits
  gestartete Events noch Reminder erhalten

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
boban 2026-04-20 00:56:38 +02:00
parent 57b55503fd
commit 772f11b517
3 changed files with 22 additions and 10 deletions

View File

@ -28,7 +28,7 @@ class ScheduleEventReminders extends Command
$this->processTaskReminders($minuteStart, $minuteEnd); $this->processTaskReminders($minuteStart, $minuteEnd);
$events = Event::with('user') $events = Event::with('user')
->where('starts_at', '>', $now) ->where('starts_at', '>', $now->copy()->subDay())
->where('starts_at', '<', $now->copy()->addDay()) ->where('starts_at', '<', $now->copy()->addDay())
->get(); ->get();
@ -212,21 +212,25 @@ class ScheduleEventReminders extends Command
private function calculateSendTime(Event $event, array $reminder, string $tz): ?Carbon private function calculateSendTime(Event $event, array $reminder, string $tz): ?Carbon
{ {
$startUtc = $event->starts_at; $startUtc = $event->starts_at;
$startLocal = $startUtc->copy()->setTimezone($tz);
$sendAt = match ($reminder['type']) { $sendAt = match ($reminder['type']) {
'before' => $startUtc->copy()->subMinutes($reminder['minutes'] ?? 30), 'before' => $startUtc->copy()->subMinutes($reminder['minutes'] ?? 30),
// Stored time is UTC → convert to local first, then combine with local event date → back to UTC
'time_of_day' => Carbon::createFromFormat( 'time_of_day' => Carbon::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
$event->starts_at->setTimezone($tz)->format('Y-m-d') . ' ' . ($reminder['time'] ?? '08:00'), $startLocal->format('Y-m-d') . ' ' .
'UTC' Carbon::createFromFormat('H:i', $reminder['time'] ?? '08:00', 'UTC')->setTimezone($tz)->format('H:i'),
$tz
)->utc(), )->utc(),
'day_before' => Carbon::createFromFormat( 'day_before' => Carbon::createFromFormat(
'Y-m-d H:i', 'Y-m-d H:i',
$event->starts_at->setTimezone($tz)->subDay()->format('Y-m-d') . ' ' . ($reminder['time'] ?? '18:00'), $startLocal->copy()->subDay()->format('Y-m-d') . ' ' .
'UTC' Carbon::createFromFormat('H:i', $reminder['time'] ?? '18:00', 'UTC')->setTimezone($tz)->format('H:i'),
$tz
)->utc(), )->utc(),
'specific' => isset($reminder['datetime']) 'specific' => isset($reminder['datetime'])

View File

@ -42,10 +42,14 @@ class PushService
])->values()->toArray(); ])->values()->toArray();
try { try {
$response = Http::withHeaders([ $expoToken = config('services.expo.token');
'Accept' => 'application/json',
'Content-Type' => 'application/json', $response = Http::asJson()
])->post(self::EXPO_PUSH_URL, $messages); ->withHeaders(array_filter([
'Accept' => 'application/json',
'Authorization' => $expoToken ? 'Bearer ' . $expoToken : null,
]))
->post(self::EXPO_PUSH_URL, $messages);
$receipts = $response->json(); $receipts = $response->json();

View File

@ -42,6 +42,10 @@ return [
'currency' => env('STRIPE_CURRENCY', 'eur'), 'currency' => env('STRIPE_CURRENCY', 'eur'),
], ],
'expo' => [
'token' => env('EXPO_TOKEN'),
],
'openai' => [ 'openai' => [
'key' => env('OPENAI_API_KEY'), 'key' => env('OPENAI_API_KEY'),
'model' => env('OPENAI_MODEL', 'gpt-4o-mini'), 'model' => env('OPENAI_MODEL', 'gpt-4o-mini'),