$booking_documents * @property-read int|null $booking_documents_count * @property-read Collection $customer_mails_reverse * @property-read int|null $customer_mails_reverse_count * @property-read \App\Models\Salutation|null $participant_salutation * @method static \Illuminate\Database\Eloquent\Builder|Booking whereAirportId($value) * @method static \Illuminate\Database\Eloquent\Builder|Booking whereInsuranceOffer($value) * @mixin \Eloquent */ class Booking extends Model { use HasFactory; protected $connection = 'mysql'; protected $table = 'booking'; protected $casts = [ 'customer_id' => 'int', 'inquiry_id' => 'int', 'offer_id' => 'int', 'new_drafts' => 'bool', 'sf_guard_user_id' => 'int', 'branch_id' => 'int', 'airport_id' => 'int', 'service_fee' => 'float', 'travel_country_id' => 'int', 'travel_category_id' => 'int', 'pax' => 'int', 'coupon_id' => 'int', 'website_id' => 'int', 'participant_salutation_id' => 'int', 'travel_company_id' => 'int', 'travel_documents' => 'bool', 'price' => 'float', 'price_total' => 'float', 'deposit_total' => 'float', 'final_payment' => 'float', 'travelagenda_id' => 'int', 'paying_out' => 'int', 'hold' => 'int', //'airline_id' => 'int', 'refund' => 'int', 'xx_tkt' => 'int', 'insurance_offer' => 'int', 'is_rail_fly' => 'bool', 'comfort' => 'bool', 'airline_ids' => 'array', 'participant_pass' => 'bool', 'booking_date' => 'datetime', 'start_date' => 'datetime', 'end_date' => 'datetime', 'participant_birthdate' => 'datetime', 'final_payment_date' => 'datetime', 'refund_date' => 'datetime', 'lawyer_date' => 'datetime', 'xx_tkt_date' => 'datetime', ]; protected $fillable = [ 'booking_date', 'customer_id', 'inquiry_id', 'offer_id', 'new_drafts', 'sf_guard_user_id', 'branch_id', 'service_fee', 'travel_country_id', 'travel_category_id', 'pax', 'coupon_id', 'title', 'comfort', 'start_date', 'end_date', 'website_id', 'travel_number', 'participant_name', 'participant_firstname', 'participant_birthdate', 'participant_salutation_id', 'participant_pass', 'nationality_id', 'ev_number', 'merlin_knr', 'merlin_order_number', 'travel_company_id', 'travel_documents', 'price', 'price_canceled', 'price_total', 'price_balance', 'deposit_total', 'final_payment', 'final_payment_date', 'travelagenda_id', 'insurance_offer', 'paying_out', 'paying_out_status', //'airline_id', 'airport_id', 'airline_ids', 'refund', 'refund_date', 'lawyer_date', 'hold', 'xx_tkt', 'xx_tkt_date', 'filekey', 'is_rail_fly', 'notice', ]; public static $paying_out_types = [ 0 => '-', 1 => 'Gutschein', 2 => 'Auszahlung', 3 => 'Umbuchung', 4 => 'AZ + GS', 5 => 'AZ o. FP', ]; public static $refund_types = [ 0 => '-', 1 => 'eingereicht', 2 => 'erledigt', ]; public static $xx_tkt_types = [ 0 => '-', 1 => 'offen', 2 => 'erledigt', ]; public static $insurance_offer_types = [ 0 => '-', 1 => 'Nein, keine Reiseversicherung gewünscht', 2 => 'Ja, ich wünsche ein Reiseversicherungsangebot' ]; public static $paying_out_status_types = [ 0 => '-', 1 => 'offen', 2 => 'erledigt', ]; public static $hold_types = [ 0 => '-', 1 => 'eingetragen', ]; public static $customer_mail_dirs = [ 11 => ['name' => 'Entwürfe', 'icon' => 'ion-md-create'], 12 => ['name' => 'Papierkorb', 'icon' => 'ion-md-trash'], ]; protected $paying_out_colors = [ 0 => '', 1 => 'info', 2 => 'dark', 3 => 'warning', 4 => 'warning', 5 => 'warning', ]; protected $refund_colors = [ 0 => '', 1 => 'warning', 2 => 'success', ]; protected $xx_tkt_colors = [ 0 => '', 1 => 'danger', 2 => 'success', ]; protected $paying_out_status_colors = [ 0 => '', 1 => 'danger', 2 => 'success', ]; protected $passolutionPDFs = []; /*public function branch() { return $this->belongsTo(Branch::class); }*/ public function coupon() { return $this->belongsTo(Coupon::class); } public function customer() { return $this->belongsTo(Customer::class); } /** * Lead/Inquiry der Buchung. * FK-Spalte `inquiry_id` (vormals `lead_id` — Modul 3 Phase 2 Rename). * Methodenname bleibt `lead()` für Legacy-Kompatibilität; {@see self::inquiry()} * ist der fachlich korrekte Alias und sollte in neuem Code verwendet werden. */ public function lead() { return $this->belongsTo(Lead::class, 'inquiry_id'); } public function inquiry() { return $this->belongsTo(Lead::class, 'inquiry_id'); } /** * Angebot, aus dem diese Buchung entstanden ist (Modul 6, Ticket B8). * Nullable — nicht jede Buchung hat einen Angebots-Vorlauf. */ public function offer() { return $this->belongsTo(\App\Models\Offer::class); } public function sf_guard_user() { return $this->belongsTo(SfGuardUser::class); } public function travel_category() { return $this->belongsTo(TravelCategory::class); } public function travel_company() { return $this->belongsTo(TravelCompany::class); } public function airport() { return $this->belongsTo(Airport::class, 'airport_id'); } /* public function travel_country() { return $this->belongsTo(TravelCountry::class, 'travel_country_id', 'crm_id'); }*/ public function travel_country() { return $this->belongsTo(\App\Models\Sym\TravelCountry::class, 'travel_country_id', 'id'); } public function travel_agenda() { return $this->belongsTo(TravelAgenda::class, 'travelagenda_id'); } /*public function airline() { return $this->belongsTo(Airline::class, 'airline_id'); } */ public function arrangements() { return $this->hasMany(Arrangement::class)->orderBy('view_position', 'DESC'); } public function arrangement_types() { return $this->hasMany(ArrangementType::class); } public function booking_draft_items() { return $this->hasMany(BookingDraftItem::class)->orderBy('pos', 'ASC'); } public function booking_service_items() { return $this->hasMany(BookingServiceItem::class); } public function coupons() { return $this->hasMany(Coupon::class); } public function insurance_certificates() { return $this->hasMany(InsuranceCertificate::class); } public function participants() { return $this->hasMany(Participant::class); } public function participant_salutation() { return $this->belongsTo(Salutation::class, 'participant_salutation_id'); } public function service_provider_entries() { return $this->hasMany(ServiceProviderEntry::class); } public function customer_mails() { return $this->hasMany(CustomerMail::class, 'booking_id', 'id'); } public function customer_mails_reverse() { return $this->hasMany(CustomerMail::class, 'booking_id', 'id')->orderBy('id', 'DESC'); } public function customer_mails_sent_at() { return $this->hasMany(CustomerMail::class, 'booking_id')->orderBy('sent_at', 'ASC'); } public function customer_mail_last() { return $this->hasOne(CustomerMail::class, 'booking_id')->latest(); } public function booking_applications() { return $this->hasMany(BookingApplication::class); } public function booking_confirmations() { return $this->hasMany(BookingConfirmation::class); } public function booking_stornos() { return $this->hasMany(BookingStorno::class); } /*public function booking_invoices() { return $this->hasMany(BookingInvoice::class); }*/ public function booking_vouchers() { return $this->hasMany(BookingVoucher::class); } public function booking_voucher_agencys() { return $this->hasMany(BookingVoucherAgency::class); } public function travel_insurances() { return $this->hasMany(TravelInsurance::class); } public function booking_files() { return $this->hasMany(BookingFile::class); } public function booking_documents() { return $this->hasMany(BookingDocument::class, 'booking_id'); } public function booking_country_services() { return $this->hasMany(BookingCountryService::class, 'booking_id'); } public function booking_country_services_checked() { return $this->hasMany(BookingCountryService::class, 'booking_id')->where('status', '=', 0); } public function booking_company_services() { return $this->hasMany(BookingCompanyService::class, 'booking_id'); } public function booking_company_services_checked() { return $this->hasMany(BookingCompanyService::class, 'booking_id')->where('status', '=', 0); } public function booking_provider_services() { return $this->hasMany(BookingProviderService::class, 'booking_id'); } public function booking_provider_services_checked() { return $this->hasMany(BookingProviderService::class, 'booking_id')->where('status', '=', 0); } public function travel_nationality() { return $this->belongsTo(TravelNationality::class, 'nationality_id'); } public function booking_notices() { return $this->hasMany(BookingNotice::class, 'booking_id')->orderBy('updated_at', 'DESC'); } public function booking_strono() { return $this->hasOne(BookingStorno::class); } public function getAirlinesAsNames() { $ret = ""; if ($this->airline_ids) { foreach ($this->airline_ids as $airline_id) { if ($Airline = Airline::find($airline_id)) { $ret .= $Airline->name . " "; } } } return $ret; } public function getAirlinesIds() { if ($this->airline_ids) { return implode('', $this->airline_ids); } return ""; } public function hasBookingServicesUnchecked() { $country_services = true; $provider_services = true; $company_services = true; $has_country_services = false; $has_provider_services = false; $has_company_services = false; if ($this->travel_country) { foreach ($this->travel_country->getContactLandsModels() as $TravelCountry) { if ($TravelCountry->stern_travel_country) { if ($TravelCountry->stern_travel_country->travel_country_services->count()) { $has_country_services = true; } } } } if ( $has_country_services && !$this->booking_country_services->count() || $this->booking_country_services_checked->count() || ($this->booking_country_services->count() !== TravelCountryService::where('crm_travel_country_id', '=', $this->travel_country_id)->count()) ) { $country_services = false; } foreach ($this->service_provider_entries as $service_provider_entry) { if ($service_provider_entry->service_provider && $service_provider_entry->service_provider->service_provider_services->count()) { $has_provider_services = true; } } if ($has_provider_services && !$this->booking_provider_services->count() || $this->booking_provider_services_checked->count()) { if ($this->service_provider_entries->count()) { $provider_services = false; } } foreach ($this->booking_service_items as $booking_service_item) { if ($booking_service_item->travel_company && $booking_service_item->travel_company->travel_company_services->count()) { $has_company_services = true; } } if ($has_company_services && !$this->booking_company_services->count() || $this->booking_company_services_checked->count()) { if ($this->booking_service_items->count()) { $company_services = false; } } if (!$has_country_services && !$has_provider_services && !$has_company_services) { return false; } if ($country_services && $provider_services && $company_services) { return true; } return false; } public function hasBookingParticipantsPass() { if ($this->participant_firstname) { if (!$this->participant_pass) { return false; } } if ($this->participants->count()) { foreach ($this->participants as $participant) { if (!$participant->participant_pass) { return false; } } } return true; } public function getPassolutionPDF($create = false, $resync = false) { $nats = []; if (count($this->passolutionPDFs)) { return $this->passolutionPDFs; } if (!$this->travel_country) { return $this->passolutionPDFs; } $destco = $this->travel_country->destco; if ($this->travel_nationality) { $nats[$this->travel_nationality->nat] = $this->travel_nationality->nat; } if ($this->participants->count()) { foreach ($this->participants as $participant) { if ($participant->travel_nationality) { $nats[$participant->travel_nationality->nat] = $participant->travel_nationality->nat; } } } if (empty($nats)) { $nats['de'] = 'de'; } foreach ($nats as $nat) { $data = [ 'nat' => $nat, 'destco' => $destco, ]; $passolution = new Passolution($data); $this->passolutionPDFs[] = $passolution->findOrCreatePDF($create, $resync); } return $this->passolutionPDFs; } public function resyncPassolutionPDF() { return $this->getPassolutionPDF(true, true); } public function calculate_price_total() { $travel_draft_item = false; $travel_price_adult = 0; $travel_price_children = 0; $total_adult = 0; $total_children = 0; $travel_adult = 0; $travel_children = 0; foreach ($this->booking_draft_items as $booking_draft_item) { //24 Rundreise ist der Grundeintrag für die Reise if ($booking_draft_item->draft_type_id == 24) { $travel_draft_item = $booking_draft_item; continue; } $prices = $booking_draft_item->getItemPrice(); //Grundpreis Reise //pro Persopn im Zimmer if ($booking_draft_item->draft_type_id == 30) { $travel_price_adult += $prices['adult']; $travel_price_children += $prices['children']; $travel_adult += $booking_draft_item->adult; $travel_children += $booking_draft_item->children; } $total_adult += $prices['adult']; $total_children += $prices['children']; } if ($travel_draft_item) { $travel_draft_item->setPriceAdultRaw($travel_price_adult); $travel_draft_item->setPriceChildrenRaw($travel_price_children); $travel_draft_item->adult = $travel_adult; $travel_draft_item->children = $travel_children; $travel_draft_item->save(); } $this->price = $total_adult + $total_children; $this->price_total = $this->getPriceRaw() + $this->getServiceTotal(true); $this->save(); } public function getPriceAttribute() { return Util::_number_format($this->attributes['price']); } public function getPriceRaw() { return $this->attributes['price']; } public function getPriceCanceledAttribute() { return Util::_number_format($this->attributes['price_canceled']); } public function getPriceCanceledRaw() { return $this->attributes['price_canceled']; } public function getPriceTotalAttribute() { return Util::_number_format($this->attributes['price_total']); } public function getPriceTotalRaw() { return $this->attributes['price_total']; } public function getCanceledAttribute() { return Util::_number_format($this->attributes['canceled']); } public function getCanceledRaw() { return $this->attributes['canceled']; } public function getPriceBalanceAttribute() { return Util::_number_format($this->attributes['price_balance']); } public function getPriceBalanceRaw() { return $this->attributes['price_balance']; } public function getDepositTotalAttribute() { return Util::_number_format($this->attributes['deposit_total']); } public function getDepositTotalRaw() { return $this->attributes['deposit_total']; } public function getFinalPaymentAttribute() { return Util::_number_format($this->attributes['final_payment']); } public function getFinalPaymentRaw() { return $this->attributes['final_payment']; } public function findBeforeDraftItemRelation($reid) { $before = false; foreach ($this->booking_draft_items as $booking_draft_items) { if ($booking_draft_items->id == $reid) { return $before; } $before = $booking_draft_items; } return false; } public function findAfterDraftItemRelation($reid) { $next = false; foreach ($this->booking_draft_items as $booking_draft_items) { if ($next) { return $booking_draft_items; } if ($booking_draft_items->id == $reid) { $next = true; } } return false; } public function getStartDateFormat() { if (!$this->attributes['start_date']) { return ""; } return Carbon::parse($this->attributes['start_date'])->format(\Util::formatDateDB()); } public function getEndDateFormat() { if (!$this->attributes['end_date']) { return ""; } return Carbon::parse($this->attributes['end_date'])->format(\Util::formatDateDB()); } public function getBookingDateFormat() { if (!$this->attributes['booking_date']) { return ""; } return Carbon::parse($this->attributes['booking_date'])->format(\Util::formatDateDB()); } public function getFinalPaymentDateFormat() { if (!$this->attributes['final_payment_date']) { return ""; } return Carbon::parse($this->attributes['final_payment_date'])->format(\Util::formatDateDB()); } public function isCanceled() { return ($this->attributes['canceled'] !== null); } //erlös #getRevenueFactor public function proceeds($raw = false) { $proceeds = $this->attributes['price'] - $this->attributes['price_balance'] - $this->getServiceProviderPaymentsFactorTotal(true); return $raw ? $proceeds : Util::_number_format($proceeds); } public function getServiceTotal($raw = false) { $total = 0; foreach ($this->booking_service_items as $booking_service_item) { $total += $booking_service_item->getServicePriceRaw(); } return $raw ? $total : Util::_number_format($total); } public function getServiceProviderPaymentsFactorTotal($raw = false) { $total = 0; foreach ($this->service_provider_entries as $entry) { $total += $entry->getAmountRaw() / $entry->getFactortRaw(); } return $raw ? $total : Util::_number_format($total); } public function getServiceProviderPaymentsTotal($raw = false) { $total = 0; foreach ($this->service_provider_entries as $entry) { $total += $entry->getAmountRaw(); } return $raw ? $total : Util::_number_format($total); } public function getKontoNumber() { switch ($this->ev_number) { case 'E01': return '4011'; break; case 'E02': return '4012'; break; case 'E03': return '4013'; break; case 'E04': return '4014'; break; } return $this->ev_number; } public function getBookingNumber() { if ($this->lead) { return $this->lead->id; } return null; } public function getPayingOutType() { return isset(self::$paying_out_types[$this->paying_out]) ? self::$paying_out_types[$this->paying_out] : '-'; } public function getInsuranceOfferType() { return isset(self::$insurance_offer_types[$this->insurance_offer]) ? self::$insurance_offer_types[$this->insurance_offer] : '-'; } public function getPayingOutStatusType() { return isset(self::$paying_out_status_types[$this->paying_out_status]) ? self::$paying_out_status_types[$this->paying_out_status] : '-'; } public function getRefundType() { return isset(self::$refund_types[$this->refund]) ? self::$refund_types[$this->refund] : '-'; } public function getXxTktType() { return isset(self::$xx_tkt_types[$this->xx_tkt]) ? self::$xx_tkt_types[$this->xx_tkt] : '-'; } public function getXxTktTypeList() { if (isset(self::$xx_tkt_types[$this->xx_tkt])) { if ($this->xx_tkt == 1 && $this->xx_tkt_date) { return Carbon::parse($this->xx_tkt_date)->format('d.m.Y'); } return self::$xx_tkt_types[$this->xx_tkt]; } return "-"; } public function getRefundTypeList() { if (isset(self::$refund_types[$this->refund])) { if ($this->refund == 1 && $this->refund_date) { return Carbon::parse($this->refund_date)->format('d.m.Y'); } return self::$refund_types[$this->refund]; } return "-"; } public function getPayingOutColor() { return isset($this->paying_out_colors[$this->paying_out]) ? $this->paying_out_colors[$this->paying_out] : ''; } public function getPayingOutStatusColor() { return isset($this->paying_out_status_colors[$this->paying_out_status]) ? $this->paying_out_status_colors[$this->paying_out_status] : ''; } public function getRefundColor() { return isset($this->refund_colors[$this->refund]) ? $this->refund_colors[$this->refund] : '-'; } public function getXxTktColor() { return isset($this->xx_tkt_colors[$this->xx_tkt]) ? $this->xx_tkt_colors[$this->xx_tkt] : '-'; } public function countCustomerMailsBy($dir, $subdir = false) { if ($dir === 11) { return $this->customer_mails->where('draft', true)->where('dir', '!=', 12)->count(); } if ($subdir) { return $this->customer_mails->where('dir', $dir)->where('subdir', $subdir)->count(); } return $this->customer_mails->where('dir', $dir)->count(); } /*DOCUMENTS*/ public function hasDocument($identifier) { return $this->booking_documents->where('identifier', $identifier)->count() ? true : false; } public function getDocument($identifier) { return $this->booking_documents->where('identifier', $identifier)->first(); } public function isDepositPossible($maxIntervalDays = false) { $maxIntervalDays = $maxIntervalDays ? $maxIntervalDays : config('booking.max_interval_days'); $diffInDays = $this->booking_date->diffInDays($this->start_date, false); return $diffInDays > $maxIntervalDays; } public function getConfirmationDeposit($percentageRate = false) { $percentageRate = $percentageRate ? $percentageRate : config('booking.deposit_percentage_rate'); return ($this->isDepositPossible() ? round($this->getPriceRaw() * $percentageRate / 100) : 0); } public function getConfirmationFinalPayment() { return $this->getPriceRaw() - $this->getConfirmationDeposit(); } }