mein-sterntours/dev/backups/phase2-offers-2026-04-17/PATCHES/Contact.php.phase1-only.diff
2026-04-17 17:19:11 +02:00

170 lines
5.4 KiB
Diff

diff --git a/app/Models/Contact.php b/app/Models/Contact.php
new file mode 100644
index 0000000..6d941e8
--- /dev/null
+++ b/app/Models/Contact.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace App\Models;
+
+use App\Models\Sym\TravelCountry;
+use Carbon\Carbon;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
+
+/**
+ * Kontakt-Modell — saubere Neuimplementierung auf Basis der customer-Tabelle.
+ *
+ * Unterschiede zum alten Customer-Modell:
+ * - Global Scope schließt zusammengeführte Duplikate (merged_into_id IS NOT NULL) aus
+ * - merged_into_id + merged_at in $fillable
+ * - mergedInto() / mergedContacts() Beziehungen
+ *
+ * Tabellen-Name: 'customer' (wird in Phase 2 in 'contacts' umbenannt).
+ *
+ * @property int $id
+ * @property int|null $salutation_id
+ * @property string|null $title
+ * @property string|null $name
+ * @property string|null $firstname
+ * @property Carbon|null $birthdate
+ * @property string|null $company
+ * @property string|null $street
+ * @property string|null $zip
+ * @property string|null $city
+ * @property string|null $email
+ * @property string|null $phone
+ * @property string|null $phonebusiness
+ * @property string|null $phonemobile
+ * @property string|null $fax
+ * @property int|null $merged_into_id
+ * @property Carbon|null $merged_at
+ * @property Carbon $created_at
+ * @property Carbon $updated_at
+ * @property-read Contact|null $mergedInto
+ * @property-read Collection|Contact[] $mergedContacts
+ * @property-read Collection|Lead[] $leads
+ * @property-read Collection|Booking[] $bookings
+ */
+class Contact extends Model
+{
+ use HasFactory, SoftDeletes;
+
+ protected $connection = 'mysql';
+
+ protected $table = 'customer';
+
+ protected $casts = [
+ 'salutation_id' => 'int',
+ 'credit_card_type_id' => 'int',
+ 'country_id' => 'int',
+ 'merged_into_id' => 'int',
+ 'birthdate' => 'datetime',
+ 'credit_card_expiration_date' => 'datetime',
+ 'merged_at' => 'datetime',
+ ];
+
+ protected $fillable = [
+ 'salutation_id',
+ 'title',
+ 'name',
+ 'firstname',
+ 'birthdate',
+ 'company',
+ 'street',
+ 'zip',
+ 'city',
+ 'email',
+ 'phone',
+ 'phonebusiness',
+ 'phonemobile',
+ 'fax',
+ 'bank',
+ 'bank_code',
+ 'bank_account_number',
+ 'credit_card_type_id',
+ 'credit_card_number',
+ 'credit_card_expiration_date',
+ 'participants_remarks',
+ 'miscellaneous_remarks',
+ 'country_id',
+ 'merged_into_id',
+ 'merged_at',
+ ];
+
+ /**
+ * Globaler Scope: zusammengeführte Duplikate werden standardmäßig ausgeblendet.
+ * Für Zugriff auf alle inkl. Duplikate: Contact::withoutGlobalScope('not_merged')
+ */
+ protected static function booted(): void
+ {
+ static::addGlobalScope('not_merged', function (Builder $query) {
+ $query->whereNull('merged_into_id');
+ });
+ }
+
+ // ── Beziehungen ──────────────────────────────────────────────────────────
+
+ public function mergedInto(): \Illuminate\Database\Eloquent\Relations\BelongsTo
+ {
+ return $this->belongsTo(Contact::class, 'merged_into_id')
+ ->withoutGlobalScope('not_merged');
+ }
+
+ public function mergedContacts(): \Illuminate\Database\Eloquent\Relations\HasMany
+ {
+ return $this->hasMany(Contact::class, 'merged_into_id')
+ ->withoutGlobalScope('not_merged');
+ }
+
+ public function leads(): \Illuminate\Database\Eloquent\Relations\HasMany
+ {
+ return $this->hasMany(Lead::class, 'customer_id')->orderByDesc('created_at');
+ }
+
+ public function bookings(): \Illuminate\Database\Eloquent\Relations\HasMany
+ {
+ return $this->hasMany(Booking::class, 'customer_id')->orderByDesc('created_at');
+ }
+
+ public function salutation(): \Illuminate\Database\Eloquent\Relations\BelongsTo
+ {
+ return $this->belongsTo(Salutation::class);
+ }
+
+ public function travel_country(): \Illuminate\Database\Eloquent\Relations\BelongsTo
+ {
+ return $this->belongsTo(TravelCountry::class, 'country_id');
+ }
+
+ // ── Hilfsmethoden ────────────────────────────────────────────────────────
+
+ public function fullName(): string
+ {
+ if ($this->firstname) {
+ return $this->firstname . ' ' . $this->name;
+ }
+ return (string) $this->name;
+ }
+
+ public function isMerged(): bool
+ {
+ return $this->merged_into_id !== null;
+ }
+
+ public static function getCountriesArray(): \Illuminate\Support\Collection
+ {
+ return TravelCountry::where('is_customer_country', 1)->get()->pluck('name', 'id');
+ }
+
+ public static $salutationType = [
+ 1 => 'Herr',
+ 2 => 'Frau',
+ 3 => 'Divers/keine Anrede',
+ 4 => 'Firma',
+ ];
+}