316 lines
6.8 KiB
PHP
316 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Traits\LogsActivity;
|
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
|
use Tymon\JWTAuth\Contracts\JWTSubject;
|
|
|
|
class Customer extends Authenticatable implements JWTSubject
|
|
{
|
|
use HasFactory, HasUuids, SoftDeletes, LogsActivity;
|
|
|
|
protected $table = 'customers';
|
|
|
|
/**
|
|
* Chỉ định cột sẽ nhận UUID.
|
|
* Mặc định HasUuids dùng cột 'id', mình đổi sang 'uuid'.
|
|
*/
|
|
public function uniqueIds()
|
|
{
|
|
return ['uuid'];
|
|
}
|
|
|
|
/**
|
|
* Điểm tích luỹ cộng cho một khoản nạp: 1 credit / 100 VNĐ.
|
|
* Trước đây khớp sao kê tự động cộng credit bằng nguyên số tiền còn duyệt tay cộng
|
|
* amount/100, cùng một khoản ra hai kết quả lệch nhau 100 lần — nay đi chung một chỗ.
|
|
*/
|
|
public static function creditFor(int $amount): int
|
|
{
|
|
return (int) floor(max(0, $amount) / 100);
|
|
}
|
|
|
|
protected $fillable = [
|
|
'fullname',
|
|
'username',
|
|
'avatar',
|
|
'address',
|
|
'state',
|
|
'city',
|
|
'postcode',
|
|
'country',
|
|
'company',
|
|
'phone',
|
|
'email',
|
|
'email_verified_at',
|
|
'email_verify',
|
|
'email_verify_code',
|
|
'email_verify_code_expired_at',
|
|
'email_hash',
|
|
'email_marketing',
|
|
'receive_deposit',
|
|
'identity_number',
|
|
'front_identity_number',
|
|
'back_identity_number',
|
|
'password',
|
|
'note',
|
|
'type',
|
|
'credit',
|
|
'total',
|
|
'total_pending',
|
|
'remember_token',
|
|
'status',
|
|
'gender',
|
|
'province_code',
|
|
'ward_code',
|
|
];
|
|
|
|
protected $updatable = [
|
|
'fullname',
|
|
'username',
|
|
'phone',
|
|
'company',
|
|
'address',
|
|
'province_code',
|
|
'ward_code',
|
|
'gender',
|
|
];
|
|
|
|
public function updatableFill(array $data): self
|
|
{
|
|
$data = array_intersect_key($data, array_flip($this->updatable));
|
|
foreach ($data as $key => $value) {
|
|
$this->{$key} = $value;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Appends for API
|
|
*/
|
|
protected $appends = [
|
|
'point',
|
|
'gender_label',
|
|
];
|
|
|
|
protected $casts = [
|
|
'gender' => \App\Enums\Client\ClientGender::class,
|
|
'email_verified_at' => 'datetime',
|
|
];
|
|
|
|
/**
|
|
* The attributes that should be hidden for serialization.
|
|
*
|
|
* @var array<int, string>
|
|
*/
|
|
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ệ N-N với DnsDomain (DNS Manager) qua bảng pivot dns_domain_user.
|
|
*/
|
|
public function dnsDomain()
|
|
{
|
|
return $this->belongsToMany(
|
|
DnsDomain::class,
|
|
'dns_domain_user',
|
|
'user_id',
|
|
'domain_id',
|
|
)->withTimestamps();
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* Quan hệ với ModuleSnapshotLimit (Snapshot).
|
|
*/
|
|
public function snapShot()
|
|
{
|
|
return $this->hasOne(ModuleSnapshotLimit::class);
|
|
}
|
|
public function getStatus()
|
|
{
|
|
return match ($this->attributes['status']) {
|
|
1 => '<span class="badge bg-success">Actived</span>',
|
|
2 => '<span class="badge bg-secondary">De-actived</span>',
|
|
default => '<span class="badge bg-danger">Banned</span>'
|
|
};
|
|
}
|
|
|
|
public function getEmailMarketingBoolAttribute()
|
|
{
|
|
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);
|
|
}
|
|
}
|