Skip to main content

Overview

The Positions API (Cargos) allows you to manage employee positions and roles within Core Projects. Positions define job titles and responsibilities, and are used to control access and permissions through role-based access control. This API supports CRUD operations, employee listings, and employee counting.

The Position Object

id_cargo
integer
Unique identifier for the position
nombre
string
Position name/title (max 80 characters, must be unique)
descripcion
string
Position description explaining responsibilities and duties (max 200 characters)
empleados
array
Array of employees assigned to this position
empleados_count
integer
Number of employees assigned to this position (available when using withCount endpoint)
created_at
timestamp
Timestamp when the position was created
updated_at
timestamp
Timestamp when the position was last updated

List All Positions

GET /api/cargos
Returns a list of all positions with their associated employees.

Response

{
  "success": true,
  "data": [
    {
      "id_cargo": 1,
      "nombre": "Gerente de Proyectos",
      "descripcion": "Responsable de la gestión y supervisión de proyectos de construcción",
      "empleados": [
        {
          "id_empleado": 1,
          "nombre": "Juan",
          "apellido": "Pérez",
          "email": "[email protected]",
          "estado": true,
          "dependencia": {
            "id_dependencia": 1,
            "nombre": "Proyectos"
          }
        }
      ],
      "created_at": "2024-01-10T08:00:00.000000Z",
      "updated_at": "2024-01-10T08:00:00.000000Z"
    },
    {
      "id_cargo": 2,
      "nombre": "Arquitecto",
      "descripcion": "Diseño y planificación arquitectónica de proyectos",
      "empleados": [],
      "created_at": "2024-01-10T08:00:00.000000Z",
      "updated_at": "2024-01-10T08:00:00.000000Z"
    }
  ]
}

Create Position

POST /api/cargos
Creates a new position in the organization.

Body Parameters

nombre
string
required
Position name/title (max 80 characters, must be unique)
descripcion
string
Position description (max 200 characters)

Request Example

{
  "nombre": "Ingeniero Civil",
  "descripcion": "Responsable del diseño y supervisión de estructuras civiles"
}

Response

{
  "success": true,
  "message": "Cargo creado exitosamente",
  "data": {
    "id_cargo": 3,
    "nombre": "Ingeniero Civil",
    "descripcion": "Responsable del diseño y supervisión de estructuras civiles",
    "created_at": "2024-01-20T10:30:00.000000Z",
    "updated_at": "2024-01-20T10:30:00.000000Z"
  }
}

Validation Errors

{
  "success": false,
  "errors": {
    "nombre": ["Este cargo ya existe en el sistema"],
    "descripcion": ["La descripción no puede exceder 200 caracteres"]
  }
}

Get Position

GET /api/cargos/{id}
Retrieves a specific position by ID with all associated employees and their departments.

Path Parameters

id
integer
required
The position’s unique identifier (id_cargo)

Response

{
  "success": true,
  "data": {
    "id_cargo": 1,
    "nombre": "Gerente de Proyectos",
    "descripcion": "Responsable de la gestión y supervisión de proyectos de construcción",
    "empleados": [
      {
        "id_empleado": 1,
        "nombre": "Juan",
        "apellido": "Pérez",
        "email": "[email protected]",
        "telefono": "+57 300 123 4567",
        "estado": true,
        "dependencia": {
          "id_dependencia": 1,
          "nombre": "Proyectos",
          "descripcion": "Departamento de gestión de proyectos"
        }
      },
      {
        "id_empleado": 4,
        "nombre": "Carlos",
        "apellido": "Ramírez",
        "email": "[email protected]",
        "telefono": "+57 302 345 6789",
        "estado": true,
        "dependencia": {
          "id_dependencia": 1,
          "nombre": "Proyectos",
          "descripcion": "Departamento de gestión de proyectos"
        }
      }
    ],
    "created_at": "2024-01-10T08:00:00.000000Z",
    "updated_at": "2024-01-10T08:00:00.000000Z"
  }
}

Error Response

{
  "success": false,
  "message": "Cargo no encontrado"
}

Update Position

PUT /api/cargos/{id}
Updates an existing position’s information.

Path Parameters

id
integer
required
The position’s unique identifier (id_cargo)

Body Parameters

nombre
string
required
Position name/title (max 80 characters, must be unique except for current record)
descripcion
string
Position description (max 200 characters)

Request Example

{
  "nombre": "Gerente Senior de Proyectos",
  "descripcion": "Responsable de la gestión, supervisión y coordinación de múltiples proyectos"
}

Response

{
  "success": true,
  "message": "Cargo actualizado exitosamente",
  "data": {
    "id_cargo": 1,
    "nombre": "Gerente Senior de Proyectos",
    "descripcion": "Responsable de la gestión, supervisión y coordinación de múltiples proyectos",
    "created_at": "2024-01-10T08:00:00.000000Z",
    "updated_at": "2024-01-21T09:15:00.000000Z"
  }
}

Delete Position

DELETE /api/cargos/{id}
Deletes a position from the system. This operation will fail if the position has associated employees.

Path Parameters

id
integer
required
The position’s unique identifier (id_cargo)

Response

{
  "success": true,
  "message": "Cargo eliminado exitosamente"
}

Error Responses

Position Not Found
{
  "success": false,
  "message": "Cargo no encontrado"
}
Has Associated Employees
{
  "success": false,
  "message": "No se puede eliminar el cargo porque tiene empleados asociados"
}
You cannot delete a position that has employees assigned to it. First reassign or remove the employees, then delete the position.

List Positions with Count

GET /api/cargos/with-count
Returns all positions with a count of employees assigned to each position.

Response

{
  "success": true,
  "data": [
    {
      "id_cargo": 1,
      "nombre": "Gerente de Proyectos",
      "descripcion": "Responsable de la gestión de proyectos",
      "empleados_count": 3,
      "created_at": "2024-01-10T08:00:00.000000Z",
      "updated_at": "2024-01-10T08:00:00.000000Z"
    },
    {
      "id_cargo": 2,
      "nombre": "Arquitecto",
      "descripcion": "Diseño arquitectónico",
      "empleados_count": 5,
      "created_at": "2024-01-10T08:00:00.000000Z",
      "updated_at": "2024-01-10T08:00:00.000000Z"
    },
    {
      "id_cargo": 3,
      "nombre": "Ingeniero Civil",
      "descripcion": "Diseño de estructuras",
      "empleados_count": 8,
      "created_at": "2024-01-10T08:00:00.000000Z",
      "updated_at": "2024-01-10T08:00:00.000000Z"
    }
  ]
}
This endpoint is particularly useful for organizational charts and reporting dashboards that need to show staffing levels by role.

Get Position Employees

GET /api/cargos/{id}/empleados
Returns all active employees assigned to a specific position with their department information.

Path Parameters

id
integer
required
The position’s unique identifier (id_cargo)

Response

{
  "success": true,
  "data": {
    "cargo": "Gerente de Proyectos",
    "descripcion": "Responsable de la gestión y supervisión de proyectos de construcción",
    "empleados": [
      {
        "id_empleado": 1,
        "nombre": "Juan",
        "apellido": "Pérez",
        "email": "[email protected]",
        "telefono": "+57 300 123 4567",
        "estado": true,
        "dependencia": {
          "id_dependencia": 1,
          "nombre": "Proyectos",
          "descripcion": "Departamento de gestión de proyectos"
        }
      },
      {
        "id_empleado": 4,
        "nombre": "Carlos",
        "apellido": "Ramírez",
        "email": "[email protected]",
        "telefono": "+57 302 345 6789",
        "estado": true,
        "dependencia": {
          "id_dependencia": 2,
          "nombre": "Ventas",
          "descripcion": "Departamento comercial"
        }
      }
    ]
  }
}
This endpoint only returns employees with estado = true (active employees).

Error Response

{
  "success": false,
  "message": "Cargo no encontrado"
}

Relationships

Has Many

Empleados (Employees)
  • Foreign Key: empleados.id_cargo
  • References: id_cargo
  • A position can have many employees
  • Deletion is prevented if employees exist

Validation Rules

Create Position

FieldRulesError Messages
nombrerequired, string, max:80, unique:cargos”Este cargo ya existe en el sistema”
descripcionnullable, string, max:200”La descripción no puede exceder 200 caracteres”

Update Position

Same rules as creation, except:
  • nombre uniqueness excludes the current record

Database Schema

Table: cargos

Columns:
- id_cargo (primary key)
- nombre (varchar 80, unique)
- descripcion (varchar 200, nullable)
- created_at (timestamp)
- updated_at (timestamp)

Relationships:
- Has many empleados (one-to-many)

Role-Based Access Control

Positions (cargos) are used for role-based access control throughout the application. The middleware cargo:1 in the commented routes suggests that certain positions have administrative privileges.

Example Middleware Usage

// From routes/api.php (commented)
Route::middleware(['auth:sanctum', 'cargo:1'])->group(function () {
    Route::get('paises/', [PaisController::class, 'index']);
});
This indicates that position ID 1 likely represents an administrative role with elevated permissions.

Business Rules

  1. Unique Names: Position names must be unique across the organization
  2. Deletion Constraints: Positions with employees cannot be deleted
  3. Employee Filtering: The empleados endpoint only returns active employees
  4. Cascade Prevention: No cascade delete - must manually reassign employees first
  5. Role-Based Permissions: Certain positions may have system-level permissions

Common Use Cases

Organizational Structure

Use the with-count endpoint to visualize your organizational structure:
const response = await fetch('/api/cargos/with-count');
const { data } = await response.json();

// Display position hierarchy with employee counts
data.forEach(position => {
  console.log(`${position.nombre}: ${position.empleados_count} employees`);
});

Position Reassignment

Before deleting a position, reassign employees:
// 1. Get all employees with this position
const positionResponse = await fetch('/api/cargos/1/empleados');
const { data: { empleados } } = await positionResponse.json();

// 2. Reassign each employee to a new position
for (const emp of empleados) {
  await fetch(`/api/empleados/${emp.id_empleado}`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ...emp, id_cargo: 2 })
  });
}

// 3. Now delete the position
await fetch('/api/cargos/1', { method: 'DELETE' });

Permission Checking

// Get current user's position
const userResponse = await fetch('/api/user');
const user = await userResponse.json();

// Check if user has admin position (id_cargo = 1)
const isAdmin = user.id_cargo === 1;

if (isAdmin) {
  // Show admin features
  console.log('User has administrative access');
}

Staffing Report by Role

const positionsResponse = await fetch('/api/cargos/with-count');
const { data: positions } = await positionsResponse.json();

// Generate staffing report
const totalEmployees = positions.reduce(
  (sum, pos) => sum + pos.empleados_count, 
  0
);

console.log(`Total Employees: ${totalEmployees}`);
console.log('\nBreakdown by Position:');
positions.forEach(pos => {
  const percentage = ((pos.empleados_count / totalEmployees) * 100).toFixed(1);
  console.log(`${pos.nombre}: ${pos.empleados_count} (${percentage}%)`);
});

Notes

Position IDs and Permissions: Position ID 1 appears to have special significance in the codebase for administrative access. Be cautious when modifying or deleting this position.
Best Practice: Always check for associated employees before attempting to delete a position. Use the with-count or empleados endpoint first.

Build docs developers (and LLMs) love