Skip to main content

Overview

Core Projects uses employee records for authentication, authorization, and tracking sales performance. Each employee belongs to a department and has an assigned role (cargo) that determines their system access.

Employee Model

Employees are users of the system with authentication capabilities:
class Empleado extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
    
    protected $table = 'empleados';
    protected $primaryKey = 'id_empleado';
    
    protected $fillable = [
        'nombre',           // First name
        'apellido',         // Last name
        'email',            // Login email (unique)
        'telefono',         // Phone
        'id_cargo',         // Role/position
        'id_dependencia',   // Department
        'estado',           // Active/inactive
        'password',         // Hashed password
    ];
    
    protected $hidden = [
        'password',
        'remember_token',
    ];
    
    protected $casts = [
        'estado' => 'boolean',
        'password' => 'hashed',
    ];
    
    public function cargo()
    {
        return $this->belongsTo(Cargo::class, 'id_cargo');
    }
    
    public function dependencia()
    {
        return $this->belongsTo(Dependencia::class, 'id_dependencia');
    }
}

Employee Roles (Cargos)

Employees are assigned roles that define their responsibilities:

Commercial Roles

  • Asesora Comercial: Sales advisor
  • Directora Comercial: Commercial director
  • Sales roles track performance and commissions

Administrative Roles

  • Administrador: System administrator
  • Gerente: Manager with dashboard access
  • Administrative roles have different permissions

Support Roles

  • Contabilidad: Accounting
  • Servicio al Cliente: Customer service
  • Support roles have limited access

Custom Roles

Additional roles can be configured based on organizational needs

Creating Employees

Employees are created through the admin interface:
public function store(Request $request)
{
    $validated = $request->validate([
        'nombre' => 'required|string|max:120',
        'apellido' => 'required|string|max:120',
        'email' => 'required|email|max:150|unique:empleados,email',
        'password' => 'required|string|min:6',
        'telefono' => 'nullable|string|max:30',
        'id_cargo' => 'required|exists:cargos,id_cargo',
        'id_dependencia' => 'required|exists:dependencias,id_dependencia',
        'estado' => 'boolean',
    ]);
    
    $validated['password'] = Hash::make($validated['password']);
    
    Empleado::create($validated);
    
    return redirect()
        ->route('empleados.index')
        ->with('success', 'Empleado creado exitosamente');
}

Password Security

Password Requirements

  • Minimum 6 characters (configurable)
  • Automatically hashed using Laravel’s bcrypt
  • Cannot be retrieved in plain text
  • Can be reset by administrators

Employee List

The employee index provides search and filtering:
public function index(Request $request)
{
    $empleado = $request->user()->load('cargo');
    $query = Empleado::with(['cargo', 'dependencia']);
    
    // Search by name, last name, or email
    if ($request->has('search') && $request->search != '') {
        $search = $request->search;
        $query->where(function ($q) use ($search) {
            $q->where('nombre', 'ILIKE', "%$search%")
              ->orWhere('apellido', 'ILIKE', "%$search%")
              ->orWhere('email', 'ILIKE', "%$search%");
        });
    }
    
    $empleados = $query->orderBy('nombre')
        ->paginate(10)
        ->withQueryString();
    
    return Inertia::render('Admin/Empleados/Index', [
        'empleados' => $empleados,
        'filters' => $request->only('search'),
        'empleado' => $empleado,
    ]);
}

Employee List Features

  • Search by name, last name, or email
  • Filter by department or role
  • View active/inactive status
  • Pagination for large datasets
  • Quick access to edit/view details

Updating Employees

Employee information can be updated with validation:
public function update(Request $request, $id)
{
    $empleado = Empleado::findOrFail($id);
    
    $validated = $request->validate([
        'nombre' => 'required|string|max:120',
        'apellido' => 'required|string|max:120',
        'email' => [
            'required', 
            'email', 
            'max:150', 
            Rule::unique('empleados', 'email')
                ->ignore($empleado->id_empleado, 'id_empleado')
        ],
        'telefono' => 'nullable|string|max:30',
        'id_cargo' => 'required|exists:cargos,id_cargo',
        'id_dependencia' => 'required|exists:dependencias,id_dependencia',
        'estado' => 'boolean',
        'password' => 'nullable|string|min:6',
    ]);
    
    // Only update password if provided
    if (!empty($validated['password'])) {
        $validated['password'] = Hash::make($validated['password']);
    } else {
        unset($validated['password']);
    }
    
    $empleado->update($validated);
    
    return redirect()
        ->route('empleados.index')
        ->with('success', 'Empleado actualizado exitosamente');
}
Email uniqueness is enforced. Changing an employee’s email to one already in use will fail validation.

Employee Status

Employees can be active or inactive:
Can log in, create sales, and perform their role’s functions. Appear in sales advisor dropdowns.
Cannot log in. Used for former employees to maintain historical data integrity without allowing system access.

Departments (Dependencias)

Employees are organized into departments:
class Dependencia extends Model
{
    protected $fillable = [
        'nombre',         // Department name
        'descripcion',    // Description
    ];
    
    public function empleados()
    {
        return $this->hasMany(Empleado::class, 'id_dependencia');
    }
}
Common Departments:
  • Ventas (Sales)
  • Gerencia (Management)
  • Contabilidad (Accounting)
  • Administración (Administration)
  • Marketing
  • Servicio al Cliente (Customer Service)

Roles Configuration (Cargos)

Roles define employee permissions and capabilities:
class Cargo extends Model
{
    protected $fillable = [
        'nombre',         // Role name
        'descripcion',    // Description
    ];
    
    public function empleados()
    {
        return $this->hasMany(Empleado::class, 'id_cargo');
    }
}

Role-Based Access

Admin Access

Full system access including:
  • Project configuration
  • Employee management
  • System settings
  • All reports

Sales Access

Sales-focused access:
  • Create/edit sales
  • View client information
  • Access quotation tool
  • Commission reports

Management Access

Strategic oversight:
  • Dashboard analytics
  • Sales reports
  • Performance metrics
  • Goal tracking

Accounting Access

Financial operations:
  • Payment processing
  • Financial reports
  • Amortization schedules
  • Export capabilities

Authentication

Employees log in using email and password:
class EmpleadoAuthController extends Controller
{
    public function login(Request $request)
    {
        $credentials = $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);
        
        // Add active status check
        $credentials['estado'] = true;
        
        if (Auth::guard('empleado')->attempt($credentials, $request->remember)) {
            $request->session()->regenerate();
            return redirect()->intended('dashboard');
        }
        
        return back()->withErrors([
            'email' => 'Las credenciales no coinciden con nuestros registros.',
        ]);
    }
}
Only active employees can log in. Inactive employees will be denied access even with correct credentials.

Sales Tracking

Employee performance is tracked through sales records:
// Get employee sales statistics
$empleado = Empleado::with('cargo')->find($id);

$ventas = Venta::where('id_empleado', $id)
    ->where('tipo_operacion', 'venta')
    ->get();

$separaciones = Venta::where('id_empleado', $id)
    ->where('tipo_operacion', 'separacion')
    ->get();

$totalVentas = $ventas->sum('valor_total');
$unidadesVendidas = $ventas->count();
$tasaConversion = $separaciones->count() > 0 
    ? ($ventas->count() / $separaciones->count()) * 100 
    : 0;

Commission Tracking

Sales advisors earn commissions based on configured policies:

Commission Calculation

Commissions are calculated based on:
  • Sale value
  • Project-specific commission policies
  • Employee role
  • Sale completion status
See Financial Management for commission policy details.

Management Dashboard Access

Certain roles have access to the management dashboard:
// In GerenciaDashboardWebController
$cargo = Cargo::whereIn('nombre', [
    'Directora Comercial', 
    'Asesora Comercial'
])->get();

$empleados = $cargo->isNotEmpty()
    ? Empleado::whereIn('id_cargo', $cargo->pluck('id_cargo'))
        ->select('id_empleado', 'nombre', 'apellido')
        ->get() 
    : collect();

Login Activity Tracking

The system tracks employee logins:
class LoginLog extends Model
{
    protected $fillable = [
        'id_empleado',
        'email',
        'ip_address',
        'user_agent',
        'login_at',
    ];
    
    public function empleado()
    {
        return $this->belongsTo(Empleado::class, 'id_empleado');
    }
}
Administrators can view login history for security auditing.

Deleting Employees

Employees can be deleted if they have no associated records:
public function destroy($id)
{
    $empleado = Empleado::findOrFail($id);
    
    // Check for associated sales
    if ($empleado->ventas()->count() > 0) {
        return back()->withErrors([
            'delete' => 'No se puede eliminar el empleado porque tiene ventas asociadas.'
        ]);
    }
    
    $empleado->delete();
    
    return redirect()
        ->route('empleados.index')
        ->with('success', 'Empleado eliminado exitosamente');
}
It’s recommended to deactivate employees rather than delete them to preserve historical data integrity.

Best Practices

Assign appropriate roles to employees based on their job functions. Don’t give everyone admin access.
When employees leave, deactivate their accounts rather than deleting them to maintain audit trails.
Encourage or enforce periodic password changes for security.
Regularly review login logs for unusual activity or unauthorized access attempts.
Ensure employee phone and email information is up to date for internal communication.

Build docs developers (and LLMs) love