> ## Documentation Index
> Fetch the complete documentation index at: https://docs.filexpress.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Reglas laborales

> Consultar y configurar jornadas, recargos y tolerancias, y copiar las plantillas por país

| Operación | Permiso |
| - | - |
| Consultar reglas, plantillas y reglas vigentes | `hr.labor_rules` |
| Crear, copiar desde plantilla y editar | `hr.labor_rules.write` |

Las reglas laborales definen franjas diurna/nocturna, jornadas máximas, recargos y tolerancias con los que FileXpress clasifica la asistencia. Ver [Reglas laborales](/docs/rrhh/reglas-laborales) en el manual.

<Warning>
  Las plantillas por país son un punto de partida. La empresa debe validarlas con su asesor laboral antes de usarlas para pagar.
</Warning>

## Listar reglas de la empresa

```http theme={null}
GET /hr/labor-rules
```

**Permiso requerido:** `hr.labor_rules`

Devuelve todas las vigencias de la empresa (la más reciente primero), cuál rige hoy y las reglas efectivas.

```json theme={null}
{
  "status": true,
  "data": {
    "rule_sets": [
      {
        "id": "uuid",
        "business_id": "uuid",
        "country_code": "SV",
        "name": "El Salvador – Código de Trabajo",
        "source_template_id": "uuid",
        "effective_from": "2026-01-01",
        "effective_to": null,
        "schema_version": 1,
        "params": { "timezone": "America/El_Salvador", "...": "ver Parámetros" },
        "is_active": true,
        "is_template": false
      }
    ],
    "current_id": "uuid",
    "effective": { "id": "uuid", "name": "El Salvador – Código de Trabajo", "is_template": false, "...": "..." }
  }
}
```

| Campo | Descripción |
| - | - |
| `current_id` | Vigencia propia que rige hoy. `null` si la empresa no tiene reglas propias vigentes. |
| `effective` | Reglas que rigen hoy: la vigencia propia o, si no hay, la plantilla del país (`is_template: true`). `null` si tampoco hay plantilla. |

## Listar plantillas por país

```http theme={null}
GET /hr/labor-rules/templates?country_code=CO
```

**Permiso requerido:** `hr.labor_rules`

| Parámetro | Requerido | Descripción |
| - | - | - |
| `country_code` | No | Código ISO de 2 letras (`SV`, `GT`, `CO`). Sin el parámetro devuelve todas. |

Devuelve una lista de objetos con el mismo formato de `rule_sets` (con `business_id: null` e `is_template: true`). Colombia tiene varias plantillas con vigencias sucesivas.

## Consultar reglas vigentes en una fecha

```http theme={null}
GET /hr/labor-rules/effective?date=2026-10-01
```

**Permiso requerido:** `hr.labor_rules`

| Parámetro | Requerido | Descripción |
| - | - | - |
| `date` | No | Fecha (`YYYY-MM-DD`). Por defecto, hoy en la zona horaria de la empresa. |

```json theme={null}
{
  "status": true,
  "data": {
    "date": "2026-10-01",
    "rule_set": { "id": "uuid", "name": "El Salvador – Código de Trabajo", "...": "..." },
    "source": "business",
    "params": { "timezone": "America/El_Salvador", "...": "ver Parámetros" }
  }
}
```

`source` indica de dónde salen los parámetros: `business` (reglas propias), `template` (plantilla del país) o `default` (valores por defecto del sistema; `rule_set` es `null`).

## Copiar desde plantilla

```http theme={null}
POST /hr/labor-rules/from-template
```

**Permiso requerido:** `hr.labor_rules.write`

```json theme={null}
{ "template_id": "uuid", "effective_from": "2026-11-01" }
```

| Campo | Requerido | Descripción |
| - | - | - |
| `template_id` | Sí | ID de una plantilla (`GET /hr/labor-rules/templates`). |
| `effective_from` | Sí | Inicio de la vigencia (`YYYY-MM-DD`). |

**Comportamiento**

* Crea una vigencia de la empresa con los parámetros de la plantilla y vigencia indefinida.
* Si la empresa tiene una vigencia activa abierta (sin fecha final) que empieza antes, se cierra el día anterior a `effective_from`.
* Encola el recálculo de la asistencia afectada.

**Respuesta `201`**: el conjunto de reglas creado, con `recalculation_queued`.

| Código | Causa |
| - | - |
| `404` | La plantilla no existe. |
| `422` | Validación, o la vigencia se solapa con otra activa de la empresa. |

## Crear reglas

```http theme={null}
POST /hr/labor-rules
```

**Permiso requerido:** `hr.labor_rules.write`

```json theme={null}
{
  "country_code": "SV",
  "name": "Reglas 2027",
  "effective_from": "2027-01-01",
  "effective_to": null,
  "is_active": true,
  "params": {
    "timezone": "America/El_Salvador",
    "day_band": { "start": "06:00", "end": "19:00" },
    "mixed_rule": { "type": "night_if_night_minutes_gt", "threshold_minutes": 240 },
    "max_ordinary": {
      "daily": { "day": 480, "night": 420, "mixed": 480 },
      "weekly": { "day": 2640, "night": 2340, "mixed": 2640 }
    },
    "week_starts_on": 1,
    "default_rest_days": [7],
    "default_daily_minutes": { "1": 480, "2": 480, "3": 480, "4": 480, "5": 480, "6": 240, "7": 0 },
    "overtime": {
      "basis": ["daily", "weekly"],
      "daily_cap_minutes": null,
      "weekly_cap_minutes": null,
      "total_daily_cap_minutes": null,
      "requires_approval": false
    },
    "surcharges": {
      "ordinary_day": 0, "ordinary_night": 0.25,
      "overtime_day": 1.0, "overtime_night": 1.5,
      "rest_day": 0.5, "holiday": 1.0,
      "combination": "multiplicative"
    },
    "rest_day_compensatory": true,
    "breaks": { "paid": false, "min_minutes": 30, "auto_deduct_minutes": 0 },
    "tolerances": { "late_grace_minutes": 5, "early_leave_grace_minutes": 0, "absence_after_minutes": null },
    "rounding": { "unit_minutes": 1, "mode": "none" },
    "min_hourly_wage": 1.70,
    "currency": "USD"
  }
}
```

| Campo | Requerido | Descripción |
| - | - | - |
| `country_code` | Sí | País (2 letras). |
| `name` | Sí | Nombre (máx. 255). |
| `effective_from` | Sí | Inicio de vigencia (`YYYY-MM-DD`). |
| `effective_to` | No | Fin de vigencia. `null` = indefinida. |
| `params` | Sí | Parámetros completos (ver abajo). |
| `is_active` | No | Por defecto `true`. Dos vigencias activas no pueden solaparse. |

### Parámetros

Todos los minutos son enteros; los recargos son **fracción adicional** sobre la hora ordinaria diurna (`0.25` = +25 %).

| Parámetro | Descripción |
| - | - |
| `timezone` | Zona horaria IANA (ej. `America/Guatemala`). |
| `day_band.start`, `day_band.end` | Franja diurna `HH:MM`; el resto es nocturna. |
| `mixed_rule.type` | `night_if_night_minutes_gt` (nocturna si los minutos nocturnos **superan** el umbral), `night_if_night_minutes_gte` (si lo **igualan o superan**) o `per_hour` (sin jornada mixta: cada hora según su franja). |
| `mixed_rule.threshold_minutes` | Umbral en minutos. Requerido salvo con `per_hour`. |
| `max_ordinary.daily.{day,night,mixed}` | Máximo de minutos ordinarios por día según la clase de jornada. |
| `max_ordinary.weekly.{day,night,mixed}` | Máximo semanal. |
| `week_starts_on` | Día de inicio de semana (1 = lunes … 7 = domingo). |
| `default_rest_days` | Días de descanso para empleados sin horario (1–7). |
| `default_daily_minutes` | Jornada por día de la semana (`"1"`…`"7"`) para empleados sin horario. |
| `overtime.basis` | `daily`, `weekly` o ambos. |
| `overtime.daily_cap_minutes`, `overtime.weekly_cap_minutes`, `overtime.total_daily_cap_minutes` | Topes que generan **avisos** (no recortan horas). `null` = sin tope. |
| `overtime.requires_approval` | Si es `true`, las horas extra generan un aviso para revisión. |
| `surcharges.{ordinary_day, ordinary_night, overtime_day, overtime_night, rest_day, holiday}` | Recargos. |
| `surcharges.combination` | `additive`: `1 + recargo + recargo del día`. `multiplicative`: `(1 + recargo) × (1 + recargo del día)`. |
| `rest_day_compensatory` | Si el trabajo en día de descanso otorga día compensatorio. |
| `breaks.paid`, `breaks.min_minutes`, `breaks.auto_deduct_minutes` | Descanso pagado o no, mínimo y descuento automático. |
| `tolerances.late_grace_minutes`, `tolerances.early_leave_grace_minutes` | Tolerancias de entrada y salida. |
| `tolerances.absence_after_minutes` | Tardanza a partir de la cual el día es ausencia. `null` = no aplica. |
| `rounding.unit_minutes`, `rounding.mode` | Unidad (1–60) y modo: `none`, `floor`, `ceil`, `nearest`. |
| `min_hourly_wage` | Salario mínimo por hora (opcional), para avisos. |
| `currency` | Moneda ISO de 3 letras. |

**Respuesta `201`**: el conjunto de reglas creado (mismo formato que `rule_sets`) más `recalculation_queued` (`true` si se encoló el recálculo de la asistencia afectada).

| Código | Causa |
| - | - |
| `422` | Validación de campos o de `params` (los errores de parámetros vienen como `params.<clave>`), fin de vigencia anterior al inicio o vigencia que se solapa con otra activa. |

## Editar reglas

```http theme={null}
PUT /hr/labor-rules/{id}
```

**Permiso requerido:** `hr.labor_rules.write`

Envía solo los campos que cambian. Si envías `params`, debe ir **completo** (reemplaza los anteriores). Solo se pueden editar vigencias de la empresa, no plantillas.

```json theme={null}
{ "effective_to": "2026-12-31" }
```

**Comportamiento**

* Si ya hay asistencia calculada en la vigencia, se recalcula (los últimos 90 días como máximo). Los días incluidos en planillas procesadas o pagadas no cambian.

**Respuesta `200`**: el conjunto de reglas actualizado, con `recalculation_queued`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.