Files
Reem-Notas/app/models/user.rb

86 lines
2.8 KiB
Ruby

# app/models/user.rb
class User < ApplicationRecord
devise :database_authenticatable,
:recoverable,
:rememberable,
:validatable
# ── Roles ──────────────────────────────────────────────────
# externo: acesso somente-leitura ao dashboard (ex.: gerências de outras áreas
# que só precisam visualizar os indicadores). Login normal por e-mail/senha.
enum role: { admin: 0, gerente: 1, operador: 2, motorista: 3, externo: 4 }
ROLES_LABEL = {
'admin' => 'Administrador',
'gerente' => 'Gerente',
'operador' => 'Operador',
'motorista' => 'Motorista',
'externo' => 'Externo (só dashboard)'
}.freeze
# ── Validações ──────────────────────────────────────────────
validates :nome, presence: true, length: { minimum: 3 }
validates :role, presence: true
validates :pin_code,
length: { is: 4 },
numericality: { only_integer: true },
allow_nil: true,
if: :motorista?
validate :pin_unico_para_motoristas, if: :motorista?
# E-mail em branco vira NULL: evita colisão no índice único quando vários
# motoristas são criados sem e-mail (no Postgres NULLs são distintos entre si).
before_validation :normalizar_email_em_branco
# Motoristas podem não ter e-mail (login via PIN)
def email_required?
!motorista?
end
def password_required?
!motorista? ? super : false
end
# ── Escopos ─────────────────────────────────────────────────
scope :ativos, -> { where(ativo: true) }
scope :por_nome, -> { order(:nome) }
scope :nao_motoristas, -> { where.not(role: :motorista) }
# ── Helpers ─────────────────────────────────────────────────
def nome_display
nome.presence || email
end
def role_label
ROLES_LABEL[role] || role.humanize
end
def pode_ver_config?
admin? || gerente?
end
def pode_consolidar?
admin? || gerente? || operador?
end
# Token de login rápido via QR Code (holerite) — Fase 7/8
def regenerar_login_token!
update!(login_token: SecureRandom.urlsafe_base64(24))
end
private
def normalizar_email_em_branco
self.email = nil if email.blank?
end
def pin_unico_para_motoristas
return if pin_code.blank?
conflito = User.motorista.where(pin_code: pin_code).where.not(id: id)
errors.add(:pin_code, 'já está em uso por outro motorista') if conflito.exists?
end
end