WIP: Sicherheitsnetz vor Phase-1-R\u00fcckbau
Enth\u00e4lt gemischt: Laravel-10-Upgrade + Phase 1 (Contacts-Modul, Duplicats-Commands, Soft-Delete+Merge-Fields) + Phase 2 Code-Umstellungen (inquiry_id, $table='contacts'/'inquiries') + Offers-Modul (Migrationen, Models, offer_id in Booking, offer-Disk in filesystems.php). Phase 2 + Offers werden im folgenden Commit nach dev/backups/phase2-offers-2026-04-17/ verschoben, damit der Workspace auf Phase-1-only (= Test-System-Stand) reduziert ist und direkt auf Live deploybar wird. Tarball-Backup zus\u00e4tzlich unter: ../backups-safety/workspace-pre-phase1-rollback-2026-04-17.tar.gz Made-with: Cursor
This commit is contained in:
parent
389d5d1820
commit
e3dc1afd8e
165 changed files with 21914 additions and 3516 deletions
164
app/Models/Contact.php
Normal file
164
app/Models/Contact.php
Normal file
|
|
@ -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: 'contacts' (nach Phase 2 — RENAME TABLE customer → contacts).
|
||||
*
|
||||
* @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 = 'contacts';
|
||||
|
||||
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',
|
||||
];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue