/ app / Models / User.php
User.php
  1  <?php
  2  
  3  namespace App\Models;
  4  
  5  use App\Enums\UserTypeEnum;
  6  use App\Models\Dossier;
  7  use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  8  use Spatie\Activitylog\LogOptions;
  9  use Illuminate\Support\Facades\Auth;
 10  use Spatie\Permission\Traits\HasRoles;
 11  use Tymon\JWTAuth\Contracts\JWTSubject;
 12  use Illuminate\Notifications\Notifiable;
 13  use Spatie\Activitylog\Traits\LogsActivity;
 14  use Illuminate\Database\Eloquent\SoftDeletes;
 15  use Laravel\Fortify\TwoFactorAuthenticatable;
 16  use Illuminate\Database\Eloquent\Casts\Attribute;
 17  use Illuminate\Database\Eloquent\Relations\MorphOne;
 18  use Illuminate\Database\Eloquent\Relations\MorphMany;
 19  use Illuminate\Database\Eloquent\Factories\HasFactory;
 20  use Illuminate\Database\Eloquent\Relations\MorphToMany;
 21  use Illuminate\Foundation\Auth\User as Authenticatable;
 22  
 23  class User extends Authenticatable implements JWTSubject
 24  {
 25      use HasFactory, Notifiable, SoftDeletes, LogsActivity, HasRoles, TwoFactorAuthenticatable;
 26  
 27      /**
 28       * The attributes that should be hidden for arrays.
 29       *
 30       * @var array
 31       */
 32      protected $hidden = [
 33          'password',
 34          'totp',
 35          'gpg',
 36          'gpg_pass',
 37      ];
 38  
 39      /**
 40       * The attributes that are mass assignable.
 41       *
 42       * @var array
 43       */
 44      protected $guarded = [];
 45  
 46      public function getJWTIdentifier()
 47      {
 48          return $this->getKey();
 49      }
 50  
 51      /**
 52       * Return a key value array, containing any custom claims to be added to the JWT.
 53       *
 54       * @return array
 55       */
 56      public function getJWTCustomClaims()
 57      {
 58          return [];
 59      }
 60  
 61      public function isInternal()
 62      {
 63          return $this->user_type_id === UserTypeEnum::INTERNAL->value;
 64      }
 65  
 66      public function isExternal()
 67      {
 68          return $this->user_type_id === UserTypeEnum::EXTERNAL->value;
 69      }
 70  
 71      public function getActivitylogOptions(): LogOptions
 72      {
 73          return LogOptions::defaults()
 74              ->logOnly([
 75                  'id',
 76                  'username',
 77                  'totp',
 78                  'user_type_id',
 79                  'user_type.name',
 80                  'personal_identification_number',
 81                  'email',
 82                  'name',
 83                  'address',
 84                  'internal_identification_number',
 85              ])->logOnlyDirty()
 86              ->dontSubmitEmptyLogs()
 87              ->useLogName($this->id);
 88      }
 89  
 90      /**
 91       * Get the user's first name.
 92       */
 93      protected function fullname(): Attribute
 94      {
 95          return Attribute::make(
 96              get: fn() => $this->name . ($this->lastname ? ' ' . $this->lastname : ''),
 97          );
 98      }
 99  
100      /**
101       * PHPWord
102       * @return Attribute
103       */
104      protected function printingName(): Attribute
105      {
106          return Attribute::make(
107              //Vamos a usar el fullName aquí,
108              // si se da el caso de que se tenga que cambiar, ya se verá
109              get: function ($value) {
110                  return $this->fullName;
111              },
112          );
113      }
114  
115      // Gets user object by username
116      public static function getUserByUsername(string $username)
117      {
118          return User::where('username', $username)->firstOrFail();
119      }
120  
121      public function activeKey(): MorphOne
122      {
123          return $this->morphOne(GpgKey::class, 'entity');
124      }
125  
126      public function user_type()
127      {
128          return $this->belongsTo(UserType::class);
129      }
130  
131      public function entity(): Entity|null
132      {
133          return $this->entities() ? $this->entities()->first() : null;
134      }
135  
136      public function isPoc(Entity $entity): bool
137      {
138          return $this->entities()->whereEntityId($entity->id)->first()->pivot->is_poc;
139      }
140  
141      // MORPH
142  
143      public function entities(): MorphToMany
144      {
145          return $this->morphedByMany(Entity::class, 'entity', 'entity_user')
146              ->withPivot(['role_id', 'is_poc'])->using(EntityUser::class);
147      }
148  
149      public function laboratory()
150      {
151          return $this->entities()->where('entity_type_id', 1)->first();
152      }
153  
154      public function dossiers(): MorphToMany
155      {
156          return $this->morphedByMany(Dossier::class, 'entity', 'entity_user')
157              ->withPivot('role_id')->using(EntityUser::class);
158      }
159  
160      // MORPH
161  
162      public function roles(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
163      {
164          return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
165      }
166  
167      public function mainRole(): Role|null
168      {
169          return $this->roles()->orderBy('id', 'asc')->first();
170      }
171  
172      public function hasPerm(string $permission)
173      {
174          return in_array(1, $this->roles->pluck($permission)->toArray());
175      }
176  
177      public function isAuth()
178      {
179          return $this->id == Auth::user()->id;
180      }
181  
182      // DOSSIERS
183  
184      public function dossiersAsInformedPersonal()
185      {
186          return $this->belongsToMany(Dossier::class, 'informed_user_dossier', 'user_id', 'dossier_id');
187      }
188  
189      public function dossiersAsSecondaryCertifier()
190      {
191          return $this->belongsToMany(Dossier::class, 'user_dossier', 'user_id', 'dossier_id')
192              ->wherePivotIn('external', [false, 0]);
193      }
194  
195      public function dossiersAsExternalCertifier()
196      {
197          return $this->belongsToMany(Dossier::class, 'user_dossier', 'user_id', 'dossier_id')
198              ->wherePivotIn('external', [true, 1]);
199      }
200  
201      public function dossiersAsPrincipalCertifier()
202      {
203          return $this->hasMany(Dossier::class, 'principal_certifier_id');
204      }
205  
206      public function getDossiersByUser()
207      {
208          $dossierIds = EntityUser::where('entity_type', 'App\Models\Dossier')
209              ->where('user_id', $this->id)->pluck('entity_id');
210          return Dossier::whereIn('id', $dossierIds)->get();
211      }
212  
213      public function allDossiers()
214      {
215          $princDossiers = $this->dossiersAsPrincipalCertifier ?? collect();
216          $dossiers = $this->getDossiersByUser() ?? collect();
217  
218          $allDossiers = collect([$princDossiers, $dossiers])->flatten();
219  
220          return $allDossiers;
221      }
222  
223      public function allStages()
224      {
225          $dossiers = $this->allDossiers();
226          $stages = collect();
227  
228          foreach ($dossiers as $dossier) {
229              $stages->merge($dossier->stages);
230          }
231  
232          return $stages;
233      }
234  
235      public function isInDossier(Dossier $dossier)
236      {
237          return $dossier->principalCertifier?->id == $this->id or
238              User::technicalManager()->id == $this->id or
239              $this->dossiers()->where('dossiers.id', $dossier->id)->exists();
240      }
241  
242      public function hasToeInAnyDossier()
243      {
244          return $this->dossiers()
245              ->whereHas('principalCertifier', fn($query) => $query->where('users.id', $this->id))
246              ->whereHas('toe')
247              ->exists();
248      }
249  
250      public function isCertifierInDossier(Dossier $dossier)
251      {
252          if ($this->id == $dossier->principal_certifier_id) {
253              return true;
254          }
255  
256          $isSecondary = $dossier->secondaryCertifiers()->pluck('id')->contains($this->id);
257          $isExternal = $dossier->externalCertifiers()->pluck('id')->contains($this->id);
258  
259          return $isSecondary || $isExternal;
260      }
261  
262      public function dossierLogs()
263      {
264          return $this->hasMany(DossierLog::class);
265      }
266  
267      // TASKS
268      public function tasks()
269      {
270          return $this->hasMany(Task::class);
271      }
272  
273      //CAN VALIDATE
274      public static function canValidate()
275      {
276          $allUsers = self::all();
277          $usersCanValidate = [];
278  
279          foreach ($allUsers as $user) {
280              $roles = $user->roles->toArray();
281  
282              if (in_array(1, array_column($roles, 'can_validate_and_approve'))) {
283                  array_push($usersCanValidate, $user);
284              }
285          }
286  
287          return collect($usersCanValidate);
288      }
289  
290      //MEET
291      public function audits()
292      {
293          return $this->belongsToMany(Audit::class, 'audits_users', 'user_id', 'audit_id');
294      }
295  
296      public function meets(): BelongsToMany
297      {
298          return $this->belongsToMany(Meet::class, 'meet_user', 'user_id', 'meet_id')->withPivot('id');
299      }
300  
301      // GPG
302      // Assign GPG fingerprint
303      public function addFingerprintFromGpgKey(string $fingerprint)
304      {
305          $this->gpg_fingerprint = $fingerprint;
306          $this->save();
307      }
308  
309      public function getFullName()
310      {
311          return $this->name . ' ' . $this->lastname;
312      }
313  
314      public function gpg_keys(): MorphMany
315      {
316          return $this->morphMany(GpgKey::class, 'entity');
317      }
318  
319      // Recommendations
320  
321      public function recommendations()
322      {
323          return $this->hasMany(Recommendation::class);
324      }
325  
326      public function getRoleInDossier($dossierId)
327      {
328          $dossier = Dossier::find($dossierId);
329          if (!$dossier) {
330              return __('roles.' . $this->roles->first()->name);
331          }
332  
333          if ($this->id == $dossier->principal_certifier_id) {
334              return __('roles.principal_certifier');
335          }
336  
337          $role = EntityUser::where('entity_type', Dossier::class)
338              ->where('entity_id', $dossierId)
339              ->where('user_id', $this->id)
340              ->first()
341              ->role
342              ->name ?? null;
343  
344          $traduccion = $role ? __("roles.$role") : __('roles.unassigned');
345          return $traduccion;
346      }
347  
348      public function getRolesInDossier($dossierId)
349      {
350          $dossier = Dossier::find($dossierId);
351          if (!$dossier) {
352              return $this->roles->pluck('name');
353          }
354  
355          $roles = collect();
356          if ($this->id == $dossier->principal_certifier_id) {
357              $roles->push(__('roles.principal_certifier'));
358          }
359  
360          $entityRoles = EntityUser::where('entity_type', Dossier::class)
361              ->where('entity_id', $dossierId)
362              ->where('user_id', $this->id)
363              ->get();
364  
365          foreach ($entityRoles as $entityRole) {
366              $roleName = $entityRole->role->name;
367              $roles->push(__('roles.' . $roleName));
368          }
369  
370          return $roles;
371      }
372  
373      public function getDossierRole($dossierId)
374      {
375          if ($this->id == Dossier::find($dossierId)->principal_certifier_id) {
376              return Role::whereName('principal_certifier')->first();
377          }
378  
379          $role = EntityUser::where('entity_type', Dossier::class)
380              ->where('entity_id', $dossierId)
381              ->where('user_id', $this->id)
382              ->first()
383              ->role ?? null;
384  
385          return $role;
386      }
387  
388  
389      public function outputs(): MorphToMany
390      {
391          return $this->morphToMany(OutPut::class, 'outputable');
392      }
393  
394      public static function technicalManager()
395      {
396          $technicalManager = Role::whereName('technical_manager')->first()->users()->first();
397          if ($technicalManager) {
398              return $technicalManager;
399          }
400  
401          $root = Role::whereName('root')->first()->users()->first();
402          if ($root) {
403              return $root;
404          }
405  
406          return null;
407      }
408  
409      public function dossiersAsPOC()
410      {
411          return $this->belongsToMany(Dossier::class, 'dossier_poc');
412      }
413  
414      public function getExternalRoleNames()
415      {
416          return Role::query()
417              ->whereIn('id', $this->entities()->pluck('role_id'))
418              ->pluck('name');
419      }
420  }