'integer', 'otp_attempts' => 'integer', 'token_expires_at' => 'datetime', 'otp_expires_at' => 'datetime', 'auth_verified_at' => 'datetime', 'signed_at' => 'datetime', 'consent_agreed_at' => 'datetime', ]; protected $hidden = [ 'access_token', 'otp_code', ]; // === Relations === public function contract(): BelongsTo { return $this->belongsTo(EsignContract::class, 'contract_id'); } public function signFields(): HasMany { return $this->hasMany(EsignSignField::class, 'signer_id'); } // === Helpers === public function isVerified(): bool { return $this->auth_verified_at !== null; } public function hasSigned(): bool { return $this->signed_at !== null; } public function canSign(): bool { return $this->isVerified() && ! $this->hasSigned() && $this->status !== self::STATUS_REJECTED && $this->contract->canSign(); } }