info('Starte Synchronisation von Kulturreisen-Buchungen...'); $force = $this->option('force'); // Statistiken $stats = [ 'processed' => 0, 'created' => 0, 'updated' => 0, 'skipped' => 0, 'errors' => 0, ]; // Hole alle Buchungen mit Kunden $query = Booking::with(['customer', 'lead.status']) ->whereNotNull('customer_id') ->whereHas('customer', function ($q) { $q->whereNotNull('email') ->where('email', '!=', ''); }) // Nur Buchungen, bei denen die Reise bereits beendet ist (end_date in der Vergangenheit) ->whereNotNull('end_date') ->where('end_date', '<', now()); if (!$force) { // Nur Buchungen der letzten 30 Tage (basierend auf Rückreisedatum) wenn nicht --force $query->where('end_date', '>=', now()->subDays(30)); } $bookings = $query->get(); $this->info("Verarbeite {$bookings->count()} Buchungen..."); $bar = $this->output->createProgressBar($bookings->count()); $bar->start(); foreach ($bookings as $booking) { try { $stats['processed']++; $customer = $booking->customer; // Validiere E-Mail if (!$customer || !$customer->email || !filter_var($customer->email, FILTER_VALIDATE_EMAIL)) { $stats['skipped']++; $bar->advance(); continue; } // Filtere Alias/Proxy E-Mail-Adressen von Buchungsplattformen $blockedDomains = [ '@guest.booking.com', '@messages.homeaway.com', '@fewo.check24.de', '@booking.com', '@homeaway.com', '@check24.de', '@partner.booking.com', ]; $emailLower = strtolower($customer->email); $isBlockedEmail = false; foreach ($blockedDomains as $domain) { if (str_ends_with($emailLower, strtolower($domain))) { $isBlockedEmail = true; break; } } if ($isBlockedEmail) { $stats['skipped']++; $bar->advance(); continue; } // Generiere Hash für Duplikat-Erkennung $syncHash = NewsletterContact::generateSyncHash( $customer->email, NewsletterContact::SOURCE_BOOKING_KULTURREISEN ); // Suche oder erstelle Kontakt $contact = NewsletterContact::withTrashed() ->where('email', strtolower(trim($customer->email))) ->first(); $isNew = false; if (!$contact) { // Neuer Kontakt $contact = new NewsletterContact(); $isNew = true; $stats['created']++; } else { // Wenn gelöscht, wiederherstellen if ($contact->trashed()) { $contact->restore(); } $stats['updated']++; } // Aktualisiere Kontaktdaten $contact->email = strtolower(trim($customer->email)); $contact->firstname = $customer->firstname ?: $contact->firstname; $contact->lastname = $customer->name ?: $contact->lastname; // Setze Gruppe Kulturreisen $contact->group_kulturreisen = true; // Source nur bei neuem Kontakt setzen if ($isNew) { $contact->source = NewsletterContact::SOURCE_BOOKING_KULTURREISEN; $contact->subscribed_at = $booking->booking_date ?: $booking->created_at; } // Referenz zum Customer $contact->customer_id = $customer->id; // Aktualisiere Buchungsstatistiken $customerBookings = Booking::where('customer_id', $customer->id)->count(); $contact->total_bookings_kulturreisen = $customerBookings; // Letztes Buchungsdatum $lastBooking = Booking::where('customer_id', $customer->id) ->orderBy('booking_date', 'DESC') ->first(); if ($lastBooking && $lastBooking->booking_date) { $contact->last_booking_at = $lastBooking->booking_date; } // Letztes Reiseenddatum (end_date) - nur abgeschlossene Reisen $lastTravelEndBooking = Booking::where('customer_id', $customer->id) ->whereNotNull('end_date') ->where('end_date', '<', now()) ->orderBy('end_date', 'DESC') ->first(); if ($lastTravelEndBooking && $lastTravelEndBooking->end_date) { if (!$contact->last_travel_end_date || $lastTravelEndBooking->end_date->gt($contact->last_travel_end_date)) { $contact->last_travel_end_date = $lastTravelEndBooking->end_date; } } // Status if ($isNew || $contact->status === NewsletterContact::STATUS_INACTIVE) { $contact->status = NewsletterContact::STATUS_ACTIVE; } $contact->sync_hash = $syncHash; $contact->last_synced_at = now(); $contact->save(); // Log erstellen if ($isNew) { $contact->logs()->create([ 'action' => 'booking_added', 'description' => 'Kontakt durch Kulturreisen-Buchung erstellt', 'metadata' => [ 'booking_id' => $booking->id, // Metadaten-Key bleibt `lead_id`; Wert kommt aus booking.inquiry_id. 'lead_id' => $booking->inquiry_id, ], ]); } } catch (\Exception $e) { $stats['errors']++; $this->error("Fehler bei Buchung {$booking->id}: " . $e->getMessage()); } $bar->advance(); } $bar->finish(); $this->newLine(2); // Statistiken ausgeben $this->info('Synchronisation abgeschlossen!'); $this->table( ['Statistik', 'Anzahl'], [ ['Verarbeitet', $stats['processed']], ['Neu erstellt', $stats['created']], ['Aktualisiert', $stats['updated']], ['Übersprungen', $stats['skipped']], ['Fehler', $stats['errors']], ] ); return 0; } }