Convoca Shifts
Guía para administradores: gestión de turnos de voluntariado de un centro social.
Versión cubierta: 2.5.26 · WP: 6.4+ · PHP: 8.1+ · Requiere: convoca-core y convoca-members activos.
Manual para la junta directiva (sin conocimientos técnicos)¶
Esta página es la referencia técnica del plugin. Para el día a día hay un manual en tres partes, en castellano y con capturas:
1. Introducción¶
Convoca Shifts gestiona los turnos de apertura de un centro social o asociación. Cubre el ciclo completo: creación de turnos, calendario visual (FullCalendar), auto-apuntado de voluntarios, control de asistencia, sincronización de horas con Convoca Members y exportación CSV.
Concepto clave: el tipo de contenido real es centro_turno (no turno). Los menús, shortcodes y la API usan "turnos" como nombre amigable.
Dependencias:
| Plugin | Rol | Consecuencia si falta |
|---|---|---|
| convoca-core | Utilidades, licencias, logger, Upgrade_Manager | El plugin no carga (aviso en admin y retorno) |
| convoca-members | Las personas asignables (voluntarios aprobados y monitores), CPT registro_hora, certificados |
Sin él no hay a quién asignar ni horas que acreditar: los selectores salen vacíos y la pantalla lo explica |
Al activarse, el plugin registra el CPT, crea la tabla de registro de actividad y programa el cron. No crea roles ni toca capacidades: el vocabulario de personas es de Convoca Core y quién es voluntario o monitor lo aporta Convoca Members por el contrato convoca_shifts_personas_asignables.

2. Modelo de datos¶
2.1. Estados del turno (_estado)¶
| Valor | Visual | Significado |
|---|---|---|
abierto_disponible |
🟡 Pendiente | Turno abierto, sin cubrir (o cubierto si tiene responsable) |
abierto_ocupado |
🔵 Ocupado | Actividad interna; no inscribible por voluntarios |
cerrado |
🔴 Cerrado | Festivo / sin apertura |
2.2. Estado de asistencia (_estado_real)¶
Independiente del estado del turno; solo tiene sentido cuando hay responsable asignado.
| Valor | Visual |
|---|---|
pendiente |
⏳ Pendiente |
realizado |
✅ Realizado |
no_asistio |
❌ No asistió |
justificada |
📝 Ausencia justificada |
cancelada_aviso |
🔔 Ausencia avisada con antelación |
Los estados justificada y cancelada_aviso no cuentan como falta (ver §7.4).
2.3. Meta keys del turno¶
| Meta | Tipo | Descripción |
|---|---|---|
_hora_fin |
string | Hora de fin del turno |
_estado |
string | Estado del turno (ver 2.1) |
_id_responsable |
integer | ID del usuario responsable (0 = sin asignar) |
_estado_real |
string | Asistencia (ver 2.2) |
_necesita_apoyo |
boolean | El turno necesita acompañamiento (p. ej. sin llaves) |
_notas |
string | Notas libres |
_monitor |
integer | ID del usuario con rol monitor_actividad |
_actividad |
string | (legacy) nombre de actividad |
_fecha_inicio |
string | Fecha real de inicio usada por consultas y la API; si no existe, se usa post_date como respaldo |
_convoca_shifts_horas_contabilizadas |
float | Horas ya sumadas al voluntario en Members (evita doble conteo) |
_convoca_shifts_reminder_sent |
integer | Marca de recordatorio enviado |
_convoca_fecha_aviso |
string | Fecha del aviso de ausencia (estados justificada/cancelada_aviso) |
_convoca_ausencia_motivo |
string | Motivo de la ausencia justificada |
La fecha/hora de inicio vive en post_date; el título del turno se regenera automáticamente al guardar según el estado y el responsable (convoca_shifts_sync_turno_on_save): 🔴 Centro Cerrado / 🔵 {actividad} / 🟢 Cubierto - {nombre} / 🟡 Pendiente. Un turno con fecha futura se fuerza a publish para que no caiga en estado "Programado".
2.4. Taxonomía¶
convoca_shifts_actividad(Actividades, jerárquica): clasifica los turnos "ocupados". Cada término admite una metaconvoca_shifts_url_info(enlace a la entrada del blog con información e inscripciones). Se gestiona desde el menú lateral del CPT.
3. Menús de administración¶
Todos los submenús cuelgan del CPT Turnos Centro (centro_turno).
| Menú | Slug | Capacidad | Descripción |
|---|---|---|---|
| Añadir Turno Rápido | convoca_shifts_turno_rapido |
convoca_shifts_manage_turnos |
Creación rápida con mini-calendario (sustituye al editor estándar) |
| Generar Turnos | convoca_shifts_generar_turnos |
convoca_shifts_manage_turnos |
Duplicar semana, crear semana tipo, exportar CSV |
| Gestionar Voluntarios | convoca_shifts_voluntarios_pendientes |
convoca_shifts_manage_turnos |
Aprobar / revocar voluntarios |
| Estadísticas | convoca_shifts_estadisticas |
convoca_shifts_view_stats |
Tabla de actividad + registro de actividad |
| Auditoría Horas | convoca_shifts_auditoria_horas |
convoca_shifts_audit_horas |
Recalcular horas acumuladas |
| Ajustes | convoca_shifts_settings |
manage_inscripciones |
Ajustes + pestaña Estado |
| Estado | convoca_shifts_status |
manage_options |
Diagnóstico del sistema |
El listado de turnos es una tabla personalizada (WP_List_Table); la URL nativa edit.php?post_type=centro_turno redirige a ella. La edición usa un editor propio (convoca-shifts-editar-turno, página oculta del menú).
Capacidades y roles relevantes:
| Capacidad | Quién la tiene | Para qué |
|---|---|---|
gestionar_mis_turnos |
voluntarios aprobados | Apuntarse/desapuntarse, crear turnos básicos |
convoca_shifts_manage_turnos |
administradores | Gestionar turnos |
convoca_shifts_view_stats |
— | Ver estadísticas |
convoca_shifts_audit_horas |
— | Auditoría de horas |
manage_inscripciones |
— | Acceder a Ajustes |
Roles: voluntario_aprobado y monitor_actividad, creados por Convoca Core. Shifts no los crea ni los modifica: pide la lista de personas al contrato y sólo asigna a quien esté en ella.
4. Crear turnos¶
4.1. Añadir Turno Rápido¶
- Ve a Turnos Centro → Añadir Turno Rápido.
- Haz clic en un día del mini-calendario (solo hoy o días futuros).
- Elige horario: presets ☀️ Mañana (10-13h) / 🌇 Tarde (17-20h) o ⚙️ Personalizado.
- Estado inicial, opcional 🛟 "Necesita apoyo".
- Guardar Turno.
4.2. Editor de turno¶
Desde el listado, botón Editar. Campos: fecha, hora inicio, hora fin, responsable (solo voluntarios aprobados), estado del centro, actividad + monitor/a (solo si estado = ocupado), "Necesita apoyo" y estado de asistencia.
El horario se restringe al horario del centro (ver §12): los turnos fuera de rango se ajustan automáticamente.
5. Listado, filtros y acciones¶
El listado muestra columnas: Fecha, Horario, Estado, Responsable, Apoyo, Asistencia y Acciones.
- Filtros: estado, asistencia y apoyo.
- Búsqueda por texto.
- Acciones en bloque: ✅ Marcar Realizado / ❌ Marcar No asistió.
- Marcar asistencia dispara la sincronización de horas (ver §7).
6. Asignación y auto-apuntado¶
6.1. Cómo se apunta un voluntario¶
- El voluntario inicia sesión y ve el calendario (
[convoca_calendario]). - Solo puede apuntarse a turnos con estado
abierto_disponible. - No puede apuntarse a turnos ya pasados (usa
_fecha_inicio, nopost_date). - El sistema comprueba solapamientos: si el voluntario ya tiene otro turno que se solapa en el horario, rechaza la asignación (
convoca_shifts_check_user_overlap). - La asignación es atómica (transacción +
FOR UPDATE+ UPDATE/INSERT) para evitar carreras entre dos voluntarios; si alguien se adelantó, responde 409 "Alguien se ha adelantado".
Al cubrirse, el título pasa a "🟢 Cubierto - {nombre}", se registra la actividad turno_cubierto y se notifica por correo al administrador del sitio.
6.2. Desapuntarse¶
El responsable (o un administrador) puede liberar el turno. El título vuelve a "🟡 Pendiente" y el estado a abierto_disponible. Un turno cerrado no se puede liberar por el frontend.
6.3. Apuntarse al próximo¶
El shortcode [convoca_boton_apuntarse] y la API /turnos/apuntarse-proximo seleccionan automáticamente el siguiente turno libre (estado disponible, sin responsable y con fecha futura), comprobando también solapamientos.
7. Asistencia y sincronización de horas¶
7.1. Flujo¶
Cuando un turno con responsable se marca como realizado, Hour_Sync:
- Calcula las horas entre
_fecha_inicioy_hora_fin. - Suma las horas a la meta del usuario
_convoca_horas_voluntariado_total(UPSERT atómico). - Guarda
_convoca_shifts_horas_contabilizadasen el turno (evita doble conteo). - Crea una entrada en el CPT
registro_hora(de Convoca Members) con estadoaprobada, enlazada al socio vía_convoca_member_id.
Si el estado pasa de realizado a otra cosa, se restan las horas y se elimina la marca.
7.2. Fix E2E-11: enlace canónico _convoca_member_id¶
Históricamente el registro se escribía con la clave _convoca_miembro_id (con "i"), que Voluntariado_Manager y Certificate_Generator de Members no leen. Resultado: las horas de turnos no se acumulaban al voluntario ni aparecían en el certificado.
En 2.5.2:
Hour_Syncescribe la clave canónica_convoca_member_id.- La migración
upgrade_to_2_5_2_member_meta_key(Upgrade Manager) renombra las filas históricas_convoca_miembro_id→_convoca_member_idal actualizar el plugin.
7.3. Hook público¶
Tras cada sincronización de horas (solo si hubo cambio), se dispara:
/**
* @param int $user_id ID del voluntario.
* @param float $diff_horas Horas sumadas (positivo) o restadas (negativo).
*/
do_action( 'convoca_after_horas_voluntario_actualizadas', $user_id, $diff_horas );
Nota interna: se dispara vía
Convoca\Core\Utils::do_action('convoca_after_horas_voluntario_actualizadas', 'convoca_horas_voluntario_actualizadas', …)— permite que otros plugins se enganchen con un hook alternativo.
7.4. Ausencias y penalización suave (No-Show)¶
Cuando un turno queda sin asistencia (no_asistio), el include No_Show_Manager.php registra una falta sin justificar en el contador del voluntario (user meta _convoca_no_shows, mapa turno→fecha, idempotente por turno) con una ventana móvil de 90 días (opción convoca_shifts_ventana_dias).
| Opción | Default | Descripción |
|---|---|---|
convoca_shifts_ventana_dias |
90 | Ventana móvil (días) para contar las faltas |
convoca_shifts_aviso_socio_en |
2 | Faltas en la ventana para avisar al voluntario por email |
convoca_shifts_aviso_admin_cada |
3 | Cada N faltas se avisa al administrador |
- Al alcanzar el umbral (
convoca_shifts_aviso_socio_en) se envía un email automático al voluntario. - Cada N faltas (
convoca_shifts_aviso_admin_cada) se avisa al administrador. - Sin bloqueos ni pérdida de puntos.
- Las faltas sin justificar NO suman horas.
Filtros: convoca_shifts_no_show_email_socio y convoca_shifts_no_show_email_admin.
7.5. Ausencia justificada¶
El estado del turno se amplía con dos estados de ausencia que NO cuentan como falta en el contador de §7.4 (al justificar se limpia el registro):
| Estado | Significado |
|---|---|
justificada |
Ausencia justificada |
cancelada_aviso |
Ausencia avisada con antelación |
Metas asociadas: _convoca_fecha_aviso (fecha del aviso) y _convoca_ausencia_motivo (motivo).
Flujo admin: selector de estado + fecha de aviso + motivo en el editor de turno, quick edit, acciones masivas «Marcar justificada» / «Marcar cancelada con aviso», y badges/filtros en el listado.
8. Generar turnos¶
Acceso: Turnos Centro → Generar Turnos.
8.1. Duplicar semana anterior¶
Copia todos los turnos de los últimos 7 días y los reprograma exactamente una semana después. Detalles de comportamiento:
- Se conserva el estado original (un
cerradosiguecerrado). - No se copia el responsable (los nuevos quedan sin asignar).
- Se omiten duplicados (si ya existe un turno en la misma fecha+hora).
- El horario se re-ajusta al horario del centro.
- Se ejecuta con bloqueo y transacción; borra la caché del resumen.
8.2. Crear semana tipo¶
Elige la fecha del lunes y configura por día: activo, hora inicio/fin, estado, actividad y monitor/a (si es "ocupado"), y "necesita apoyo". Genera los turnos omitiendo duplicados.
8.3. Exportar historial a CSV¶
Botón Exportar historial a CSV (en la misma página). Exporta todos los turnos publicados (sin selector de rango ni de columnas). Columnas: ID, Título, Fecha Inicio, Fecha Fin, Estado, Responsable, Necesita Apoyo, Asistencia, Notas. Incluye BOM UTF-8 para Excel.
Hay una segunda exportación en Estadísticas → Exportar Estadísticas a CSV (horas por voluntario), con protección anti inyección de fórmulas.
9. Gestión de voluntarios¶
Acceso: Turnos Centro → Gestionar Voluntarios.
- Aprobar: cambia el rol del usuario a
voluntario_aprobado, envía un correo de confirmación (con adjuntos vía filtroconvoca_voluntario_aprobado_attachments) y dispara el hookconvoca_voluntario_aprobado. - Revocar: cambia el rol a
subscriber, marca la meta_convoca_shifts_aprobado = -1y libera los turnos futuros asignados a ese voluntario (los deja pendientes). No puedes revocarte a ti mismo.
10. Estadísticas y auditoría de horas¶
- Estadísticas: tabla por voluntario (turnos totales, realizados, faltas, horas aprobadas, último turno) + registro de actividad reciente paginado. Las horas se calculan con consultas agregadas SQL (evita N+1).
- Auditoría Horas: muestra
_convoca_horas_voluntariado_totalfrente a los turnosrealizadode cada usuario, con botón Recalcular que re-escanea los turnos y reescribe el contador.
Registro de actividad: tabla {prefix}convoca_shifts_activity_log. Acciones registradas: turno_creado, turno_actualizado, turno_cubierto, turno_liberado, turno_asignado, turno_desasignado, asistencia_ok, asistencia_no, voluntario_aprobado, voluntario_revocado, conflicto_horario_detectado, log_debug_conflict.
11. Shortcodes, bloques y widgets¶
11.1. Shortcodes (registrados)¶
[convoca_calendario] Calendario FullCalendar (sin atributos)
[convoca_proximos_turnos cantidad="5"] Lista de próximos turnos
[convoca_resumen_turnos semana="this"] Resumen semanal (semana="this" | "next")
[convoca_boton_apuntarse] Botón "Me apunto al siguiente turno libre"
Atributos reales: cantidad (próximos turnos) y semana (resumen). No existen los atributos vista ni categoria.
11.2. Bloques de Gutenberg¶
| Bloque | Descripción |
|---|---|
centro-social/calendario |
Calendario interactivo |
centro-social/proximos-turnos |
Próximos turnos (atributo cantidad, default 5) |
centro-social/resumen |
Resumen semanal |
centro-social/boton-apuntarse |
Botón de apuntado rápido |
11.3. Widgets clásicos¶
CST: Calendario, CST: Próximos Turnos (con campo "cantidad"), CST: Resumen Semanal, CST: Botón Apuntarse.
Los assets se cargan solo cuando la página contiene un bloque/shortcode/widget del plugin (filtro convoca_shifts_force_enqueue_assets para forzarlo).
12. Ajustes y Estado del sistema¶
Acceso: Turnos Centro → Ajustes.
| Opción | Default | Descripción |
|---|---|---|
convoca_shifts_calendar_page_url |
— | URL de la página con el calendario |
convoca_shifts_hora_apertura |
09:00 |
Hora de apertura del centro (límite inferior) |
convoca_shifts_hora_cierre |
22:00 |
Hora de cierre del centro (límite superior) |
convoca_shifts_access_page_url |
# |
Enlace "Ir a Acceso" para usuarios no logueados |
El horario del centro restringe la creación de turnos en todas las vías (rápido, semana tipo, duplicar, frontend, REST).
Estado del sistema comprueba: versión de PHP (mín. 8.0), existencia de la página de calendario con su shortcode, tablas compartidas de Core (convoca_logs, convoca_locks) y eventos cron programados.
13. Cron y recordatorios¶
| Evento | Frecuencia | Función |
|---|---|---|
convoca_shifts_hourly_event |
cada hora | Envía recordatorio por correo al responsable de turnos que empiezan en ≤2 h (con responsable, no cerrados, no enviado aún) |
convoca_shifts_daily_event |
diario | Limpia la meta _convoca_shifts_reminder_sent de turnos con >2 días |
Ambos se programan al activar y se limpian al desactivar/desinstalar.
14. API REST¶
Namespace: convoca-shifts/v1.
| Método | Ruta | Acceso | Descripción |
|---|---|---|---|
| GET | /turnos |
público | Lista de eventos (parámetros start, end) |
| GET | /turnos/proximo-libre |
público | Próximo turno sin cubrir |
| POST | /turnos/{id}/apuntarse |
gestionar_mis_turnos o manage_options |
Inscribirse en un turno |
| POST | /turnos/{id}/desapuntarse |
ídem | Liberar el turno |
| POST | /turnos/apuntarse-proximo |
ídem | Inscribirse en el próximo libre |
| POST | /turnos/crear |
ídem | Crear turno (parámetros date, h_start, h_end, estado, apoyo) |
Detalles:
- Todas las rutas de escritura aplican rate limiting (
check_rate_limit). - Crear turno desde el frontend: los no administradores solo pueden crear
abierto_disponibley no en fechas pasadas. /turnos/creary/turnos/apuntarsedevuelven errores tipados (not_found,not_available,past_turno,conflicto_horario,ya_cubierto,no_disponible, etc.).
15. Hooks públicos¶
| Hook | Tipo | Cuándo |
|---|---|---|
convoca_after_horas_voluntario_actualizadas |
action | Tras sumar/restar horas al voluntario ($user_id, $diff_horas) |
convoca_horas_voluntario_actualizadas |
action | Hook alternativo gestionado por Convoca\Core\Utils::do_action |
convoca_voluntario_aprobado |
action | Al aprobar un voluntario ($user_id) |
convoca_voluntario_aprobado_attachments |
filter | Adjuntos del correo de aprobación |
convoca_shifts_confirm_signup |
filter | true para mostrar confirmación antes de apuntarse |
convoca_shifts_force_enqueue_assets |
filter | Forzar carga de assets del frontend |
convoca_shifts_no_show_email_socio |
filter | Email del aviso de faltas al voluntario |
convoca_shifts_no_show_email_admin |
filter | Email del aviso de faltas al administrador |
16. Calidad y CI¶
El repositorio ejecuta cuatro jobs de CI (.github/workflows/ci.yml):
- PHPCS (bloqueante):
phpcs --standard=.phpcs.xml.distconignore_warnings_on_exit 1; cualquier error rompe el build. - PHPStan nivel 5, sin baseline: las excepciones legítimas se declaran inline en
phpstan.neon.dist(ignoreErrors), no en un archivo de baseline. - PHPUnit: suite unitaria en PHP 8.2 y 8.3.
- Plugin Check (PCP): categorías
plugin_repo+security, con 0 errores (los warnings no fallan). Las consultas SQL directas usan%ipara nombres de tabla y literales inline enprepare().
17. Desinstalación¶
Al desinstalar se eliminan los posts centro_turno, los términos de convoca_shifts_actividad, opciones, transients, cron y la tabla de actividad. Para conservar los datos (p. ej. desactivación temporal), define en wp-config.php:
La meta de usuario con prefijo
_convoca_shifts_(aprobado, teléfono, motivación) pertenece a Convoca Members y no se borra aquí.
18. Problemas comunes¶
| Problema | Causa probable / Solución |
|---|---|
| Turno no aparece en el calendario | Verifica que esté publish (no papelera) y dentro del rango de fechas consultado |
| "Página Calendario no encontrada" en Estado | El diagnóstico busca una página con [calendario_centro]; crea la página con ese shortcode o revisa §11 |
| Horas no se acumulan al voluntario | Convoca Members inactivo, o datos anteriores a 2.5.2 sin migrar (ver §7.2); usa "Recalcular" en Auditoría Horas |
| No puedo marcar "realizado" | El turno debe tener responsable asignado |
| Apuntarse da "conflicto de horario" | El voluntario ya tiene otro turno solapado |
| Turno futuro aparece como "Programado" | El plugin fuerza publish al guardar; si persiste, guarda el turno de nuevo |
| No hay submenús visibles | Verifica que tu rol tiene las capacidades de §3 |