$notifications * @property-read \Illuminate\Database\Eloquent\Collection $quote_invitations * @property-read \Illuminate\Database\Eloquent\Collection $recurring_invoice_invitations * @property-read \Illuminate\Database\Eloquent\Collection $credit_invitations * @property-read \Illuminate\Database\Eloquent\Collection $invoice_invitations * @mixin \Eloquent */ class ClientContact extends Authenticatable implements HasLocalePreference { use Notifiable; use MakesHash; use PresentableTrait; use SoftDeletes; use HasFactory; use AppSetup; /* Used to authenticate a contact */ protected $guard = 'contact'; protected $touches = ['client']; /* Allow microtime timestamps */ protected $dateFormat = 'Y-m-d H:i:s.u'; protected $presenter = ClientContactPresenter::class; protected $appends = [ 'hashed_id', ]; protected $with = []; protected $casts = [ 'updated_at' => 'timestamp', 'created_at' => 'timestamp', 'deleted_at' => 'timestamp', 'last_login' => 'timestamp', ]; protected $hidden = [ 'password', 'remember_token', 'user_id', 'company_id', 'client_id', 'google_2fa_secret', 'id', 'oauth_provider_id', 'oauth_user_id', 'token', ]; protected $fillable = [ 'first_name', 'last_name', 'phone', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4', 'email', 'is_primary', 'send_email', ]; /** * Whitelisted fields for using from query parameters on subscriptions request. * * @var string[] */ public static $subscription_fillable = [ 'first_name', 'last_name', 'phone', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4', 'email', ]; /* V2 type of scope */ public function scopeCompany($query) { $query->where('company_id', auth()->user()->companyId()); return $query; } /* V1 type of scope */ public function scopeScope($query) { $query->where($this->getTable().'.company_id', '=', auth()->user()->company()->id); return $query; } public function getEntityType() { return self::class; } public function getHashedIdAttribute() { return $this->encodePrimaryKey($this->id); } /**/ public function getRouteKeyName() { return 'contact_id'; } public function getContactIdAttribute() { return $this->encodePrimaryKey($this->id); } public function setAvatarAttribute($value) { if (! filter_var($value, FILTER_VALIDATE_URL) && $value) { $this->attributes['avatar'] = url('/').$value; } else { $this->attributes['avatar'] = $value; } } public function client(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Client::class)->withTrashed(); } public function primary_contact() { return $this->where('is_primary', true); } public function company(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Company::class); } public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(User::class)->withTrashed(); } public function invoice_invitations(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(InvoiceInvitation::class); } public function recurring_invoice_invitations(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(RecurringInvoiceInvitation::class); } public function quote_invitations(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(QuoteInvitation::class); } public function credit_invitations(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(CreditInvitation::class); } public function sendPasswordResetNotification($token) { $this->token = $token; $this->save(); $nmo = new NinjaMailerObject(); $nmo->mailable = new NinjaMailer((new ClientContactResetPasswordObject($token, $this))->build()); $nmo->to_user = $this; $nmo->company = $this->company; $nmo->settings = $this->company->settings; NinjaMailerJob::dispatch($nmo); } public function preferredLocale() { /** @var \Illuminate\Support\Collection<\App\Models\Language> */ $languages = app('languages'); return $languages->first(function ($item) { return $item->id == $this->client->getSetting('language_id'); })->locale; } public function routeNotificationForMail($notification) { return $this->email; } /** * Retrieve the model for a bound value. * * @param mixed $value * @param null $field * @return Model|null */ public function resolveRouteBinding($value, $field = null) { return $this ->withTrashed() ->where('id', $this->decodePrimaryKey($value))->firstOrFail(); } /** * @return mixed|string */ public function avatar() { if ($this->avatar) { return $this->avatar; } return asset('images/svg/user.svg'); } /** * Provides a convenience login click for contacts to bypass the * contact authentication layer * * @return string URL */ public function getLoginLink() { if (Ninja::isHosted()) { $domain = $this->company->domain(); } else { $domain = config('ninja.app_url'); } switch ($this->company->portal_mode) { case 'subdomain': return $domain.'/client/key_login/'.$this->contact_key; case 'iframe': return $domain.'/client/key_login/'.$this->contact_key; case 'domain': return $domain.'/client/key_login/'.$this->contact_key; default: return ''; } } public function getAdminLink($use_react_link = false): string { return $use_react_link ? $this->getReactLink() : config('ninja.app_url'); } private function getReactLink(): string { return config('ninja.react_url')."/#/clients/{$this->client->hashed_id}"; } public function showRff(): bool { if (\strlen($this->first_name) === 0 || \strlen($this->last_name) === 0 || \strlen($this->email) === 0) { return true; } return false; } }