Scripts pequeños para checar estatus y checadas desde alguna aplicación biotime abierta en internet.
  • Python 98.2%
  • Dockerfile 1.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Hector Villarreal 9c3bb47d43
All checks were successful
CI / test (push) Successful in 5s
CI / deploy (push) Successful in 5s
Merge pull request 'Pruebas, Docker con cron y CI/CD en Forgejo' (#2) from ci/docker-tests-deploy into main
Reviewed-on: #2
2026-09-17 00:00:44 +00:00
.forgejo/workflows Deploy: tomar la carpeta de datos de la variable BIOTIME_DATA_DIR 2026-09-16 17:53:20 -06:00
tests Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00
.dockerignore Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00
.env.example Varios destinatarios, alertas aparte y nombre visible del remitente 2026-09-16 14:03:59 -06:00
.gitignore Initial commit: monitor y reporte de nómina de BioTime 2026-09-16 13:53:46 -06:00
biotime.py Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00
CLAUDE.md CLAUDE.md: unir la regla de PR con la sección de flujo de Git 2026-09-16 17:59:36 -06:00
compose.yaml Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00
crontab Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00
Dockerfile Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00
monitor.py Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00
README.md Deploy: tomar la carpeta de datos de la variable BIOTIME_DATA_DIR 2026-09-16 17:53:20 -06:00
weekly_report.py Agregar pruebas, Docker con cron y CI/CD en Forgejo 2026-09-16 14:46:45 -06:00

biotime-scripts

Scripts para sacarle provecho a un servidor ZKTeco BioTime (8.x/9.x) usando su API REST:

  • monitor.py: avisa por correo cuando BioTime deja de responder o cuando un checador pierde conexión, y otra vez cuando se recupera.
  • weekly_report.py: manda por correo el reporte de asistencias del periodo de nómina (sábado a viernes). Incluye horas por empleado, checadas incompletas y quién no checó nada.

Solo usan la librería estándar de Python (3.12 o más reciente), sin dependencias que instalar.

Configuración

cp .env.example .env
chmod 600 .env
Variable Descripción
BIOTIME_URL URL pública de BioTime, por ejemplo https://biotime.ejemplo.com
USER / PASSWORD Usuario de BioTime. Tiene que ser superusuario: la API no da tokens a otros usuarios
SMTP_HOST, SMTP_PORT, SMTP_SECURITY Servidor de correo saliente. SMTP_SECURITY puede ser starttls, ssl o none
SMTP_USER / SMTP_PASSWORD Cuenta de correo. En Gmail se usa una contraseña de aplicación
SMTP_FROM Nombre visible (BioTime) o dirección completa (BioTime <correo@dominio.com>)
MAIL_TO Destinatarios del reporte, separados por coma
ALERT_MAIL_TO Destinatarios de las alertas del monitor. Si está vacío se usa MAIL_TO
REPORT_TITLE Título que aparece dentro del correo del reporte
DEVICE_MAX_MINUTES Minutos que puede pasar un checador sin conectarse antes de mandar alerta (10 por defecto)
EXCLUDE_EMP_CODES IDs de empleados que no deben salir en el reporte (usuarios de prueba, administradores)

Uso

# Monitor: no manda correo si nada cambió desde la última revisión
python3 monitor.py
python3 monitor.py --dry-run      # imprime el resultado y no guarda estado

# Reporte del último periodo sábadoviernes completo
python3 weekly_report.py
python3 weekly_report.py --dry-run                   # no manda correo: guarda reporte.html
python3 weekly_report.py --desde 2026-09-05 --dry-run  # periodo de 7 días a partir de esa fecha

Docker (Unraid)

compose.yaml levanta un contenedor con crond que corre el monitor cada 5 minutos y el reporte el sábado a las 9:00 de México. A esa hora ya marcaron salida los turnos nocturnos del viernes. El horario está en crontab y usa la hora de México (TZ=America/Mexico_City).

El .env y .monitor_state.json se guardan en el volumen /data. Por defecto es /mnt/user/appdata/biotime, y se cambia con la variable BIOTIME_DATA_DIR al correr docker compose. En CI se toma de la variable de Actions BIOTIME_DATA_DIR del repo (Configuración → Acciones → Variables). Antes del primer deploy:

mkdir -p /mnt/user/appdata/biotime                # o la ruta de BIOTIME_DATA_DIR
cp .env.example /mnt/user/appdata/biotime/.env   # y llénalo
chmod 600 /mnt/user/appdata/biotime/.env
docker logs -f biotime                                   # salida del monitor y del reporte
docker exec biotime python monitor.py --dry-run
docker exec biotime python weekly_report.py --dry-run    # deja reporte.html en /data

Fuera de Docker, los scripts buscan .env en su propia carpeta. DATA_DIR cambia esa ubicación.

Pruebas

Usan unittest y datos ficticios; no se conectan a BioTime ni mandan correos.

python3 -m unittest                   # local
docker build --target test .          # igual que en CI, con Python 3.12

CI/CD (Forgejo Actions)

.forgejo/workflows/ci.yml:

  • Pull request a main: corre las pruebas (test).
  • Push a main (incluye los merges): corre las pruebas y, si pasan, hace deploy con docker compose -p biotime up -d --build.

Requisitos:

  • Runner en el mismo Unraid, con la etiqueta docker y que monte el socket de Docker en los jobs (por ejemplo container.docker_host: automount en su configuración). No se agrega -v /var/run/docker.sock en el workflow: si el runner ya lo monta, Docker falla con Duplicate mount point.
  • Protección de main (Configuración → Ramas → Agregar regla): desactiva el push directo y activa Requerir que pasen las verificaciones de estado con el patrón CI / test*. Así no se puede hacer merge si las pruebas fallan.

Programación con cron (sin Docker)

Horas en UTC (México centro = UTC-6):

*/5 * * * *  cd ~/biotime-scripts && python3 monitor.py >> monitor.log 2>&1
0 15 * * 6   cd ~/biotime-scripts && python3 weekly_report.py >> report.log 2>&1

Cómo se arma el reporte

  • Cada entrada se empareja con la siguiente salida, siempre que no pasen más de 16 horas entre las dos.
  • Un turno cuenta en el día de su entrada. Así, el turno nocturno del viernes entra en el periodo aunque la salida sea el sábado en la mañana.
  • Si hay checadas del mismo empleado con menos de 2 minutos de diferencia, se cuenta solo la primera.
  • 07:00? significa entrada sin salida, ?07:00 salida sin entrada y (+1) que la salida fue al día siguiente.

Problemas conocidos de BioTime

  • Checador en el área "Default (Reservado)": BioTime no intercambia datos con ese checador. Hay que pasarlo a un área normal, que debe ser la misma de los empleados.
  • Solo se envían al checador los empleados de su misma área.
  • La paginación de la API regresa enlaces next con la dirección interna (http://127.0.0.1:<puerto>/...). biotime.py solo toma la ruta y la consulta de ese enlace.
  • Zona horaria Etc/GMT-6: con la nomenclatura estándar, el signo va al revés y significa UTC+6. Revisa que la hora de las checadas salga correcta.