\App\Enums\Client\ClientGender::class, 'email_verified_at' => 'datetime', 'two_factor_enabled' => 'boolean', 'birthday' => 'date', ]; /** * The attributes that should be hidden for serialization. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * Quan hệ với ModuleHosting (Hosting). */ public function hosting() { return $this->hasMany(ModuleHosting::class); } /** * Quan hệ với ModuleDomain (Domain). */ public function domain() { return $this->hasMany(ModuleDomain::class); } /** * Quan hệ với ModuleVmware (VPS). */ public function vps() { return $this->hasMany(ModuleVmware::class); } /** * Quan hệ với Service (tbl.services). */ public function service() { return $this->hasMany(Service::class); } /** * Quan hệ với Invoice. */ public function invoice() { return $this->hasMany(Invoice::class); } /** * Quan hệ với Ticket. */ public function ticket() { return $this->hasMany(Ticket::class); } /** * Quan hệ với Mail. */ public function mail() { return $this->hasMany(Mail::class); } /** * Quan hệ với File. */ public function file() { return $this->hasMany(File::class, 'customer_id'); } /** * Quan hệ với Order. */ public function order() { return $this->hasMany(Order::class); } /** * Quan hệ với Transaction. */ public function transaction() { return $this->hasMany(Transaction::class); } /** * Quan hệ với InvoiceItem. */ public function invoiceItem() { return $this->hasMany(InvoiceItem::class); } /** * Quan hệ với Log. */ public function log() { return $this->hasMany(Log::class); } public function acceptsMarketingEmail(): bool { return (bool) $this->email_marketing; } public function getReceiveDepositBoolAttribute() { return (bool) $this->receive_deposit; } public function getPointAttribute() { return (string) floor($this->total / 100); } public function getNameAttribute() { return $this->fullname; } public function getCmndBeforeAttribute() { return $this->front_identity_number ?? ''; } public function getCmndAfterAttribute() { return $this->back_identity_number ?? ''; } public function getCmndAttribute() { return $this->identity_number; } public function getOffMailMarketingAttribute() { return $this->email_marketing; } public function province() { return $this->belongsTo(Province::class, 'province_code', 'code'); } public function ward() { return $this->belongsTo(Ward::class, 'ward_code', 'code'); } public function getGenderLabelAttribute() { return $this->gender?->label() ?? 'Khác'; } public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return ['pv' => $this->passwordVersion()]; } /** * Dấu vân tay của hash mật khẩu, nhúng vào JWT. Đổi/đặt lại mật khẩu → giá trị đổi → * mọi access token cũ bị ApiAuthCheck từ chối (không cần blacklist). */ public function passwordVersion(): string { return substr(hash('sha256', (string) $this->password), 0, 16); } }