osb/app/Models/User.php

304 lines
5.9 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Collection as DatabaseCollection;
use Laravel\Passport\HasApiTokens;
use Leenooks\Traits\ScopeActive;
use Leenooks\Traits\UserSwitch;
use App\Interfaces\IDs;
use App\Notifications\ResetPassword as ResetPasswordNotification;
/**
* Class User
*
* Attributes for users:
* + role : User's role
*/
class User extends Authenticatable implements IDs
{
use HasFactory,HasApiTokens,Notifiable,UserSwitch,ScopeActive;
private const CACHE_TIME = 3600;
protected $casts = [
'last_access' => 'datetime:Y-m-d H:i:s',
];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Role hierarchy order
*
* @var array
*/
public const role_order = [
'wholesaler',
'reseller',
'customer',
];
/* OVERRIDES */
/**
* Users password reset email notification
*
* @param string $token
*/
public function sendPasswordResetNotification($token)
{
$this->notify((new ResetPasswordNotification($token))->onQueue('high'));
}
/* INTERFACES */
public function getLIDAttribute(): string
{
return sprintf('#%04s',$this->id);
}
public function getSIDAttribute(): string
{
return sprintf('%02s-%s',$this->site_id,$this->getLIDAttribute());
}
/* RELATIONS */
/**
* This user's accounts
*/
public function accounts()
{
return $this->hasMany(Account::class)
->active();
}
/**
* The accounts that this user manages
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
* @note This cannot be preloaded with load() or with() - $this is a blank object
*/
public function accounts_all()
{
return $this->hasMany(Account::class)
->when((! is_null($this->rtm) && $this->id),
fn($query)=>$query->orWhereIn('rtm_id',$this->rtm?->children_all()->pluck('id')))
->active();
}
/**
* This users language configuration
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function language()
{
return $this->belongsTo(Language::class);
}
/**
* Return the routes to market account for this user
*/
public function rtm()
{
return $this->hasOneThrough(Rtm::class,Account::class);
}
/**
* Supplier configuration for this user
*
* @deprecated To move to account->suppliers()
*/
public function suppliers()
{
return $this->belongsToMany(Supplier::class)
->withPivot('id','created_at');
}
/* ATTRIBUTES */
/**
* This is an alias method, as it is used by the framework
*
* @return string
*/
public function getNameAttribute(): string
{
return $this->full_name;
}
/**
* Logged in user's full name
*
* @return string
*/
public function getFullNameAttribute(): string
{
return sprintf('%s %s',$this->firstname,$this->lastname);
}
/**
* Return a friendly string of this persons role
*
* @return string
*/
public function getRoleAttribute(): string
{
return ucfirst($this->role());
}
public function getSurFirstNameAttribute()
{
return sprintf('%s, %s',$this->lastname,$this->firstname);
}
/* SCOPES */
/**
* Search for a record
*
* @param $query
* @param string $term
*/
public function scopeSearch($query,string $term)
{
// Build our where clause
// First Name, Last name
if (preg_match('/\s+/',$term)) {
[$fn,$ln] = explode(' ',$term,2);
$query->where(function($query1) use ($fn,$ln,$term) {
$query1->where(function($query2) use ($fn,$ln) {
return $query2
->where('firstname','ilike','%'.$fn.'%')
->where('lastname','ilike','%'.$ln.'%');
});
});
} elseif (is_numeric($term)) {
$query->where('users.id','like','%'.$term.'%');
} elseif (preg_match('/@/',$term)) {
$query->where('email','ilike','%'.$term.'%');
} else {
$query
->Where('firstname','ilike','%'.$term.'%')
->orWhere('lastname','ilike','%'.$term.'%');
}
return $query;
}
/* METHODS */
/**
* Determine if the user is an admin of the user with $id
*
* @param User|null $user
* @return bool
*/
public function isAdmin(User $user=NULL): bool
{
return $user->exists
&& $this->isReseller()
&& $this->accounts_all
->pluck('user_id')
->contains($user->id);
}
/**
* Determine if the logged in user is a reseller or wholesaler
*
* @return bool
*/
public function isReseller(): bool
{
return in_array($this->role(),['wholesaler','reseller']);
}
/**
* Determine if the logged in user is a wholesaler
*
* @return bool
*/
public function isWholesaler(): bool
{
return in_array($this->role(),['wholesaler']);
}
/**
* Get all the items for the next invoice
*
* @param bool $future
* @return DatabaseCollection
* @deprecated This should be done in accounts
*/
public function next_invoice_items(bool $future=FALSE): Collection
{
return collect();
$result = new DatabaseCollection;
$this->services->load(['invoice_items.taxes']);
foreach ($this->services as $o) {
if ($future) {
if ($o->invoice_next->subDays(config('app.invoice_inadvance'))->isPast())
continue;
} else {
if ($o->invoice_next->subDays(config('app.invoice_inadvance'))->isFuture())
continue;
}
foreach ($o->next_invoice_items($future) as $oo)
$result->push($oo);
}
$result->load([
'product.translate',
'service.type',
]);
return $result;
}
/**
* Determine what the logged in user's role is
* + Wholesaler - aka Super User
* + Reseller - services accounts on behalf of their customers
* + Customer - end user customer
*
* @return string
*/
public function role()
{
return $this->rtm
? ($this->rtm->parent_id ? 'reseller' : 'wholesaler')
: 'customer';
}
}