Saltar a contenido

Configuración y entornos — Control de Asistencia

Toda la configuración vive en config.ini en la raíz del proyecto. Se lee al arrancar, por lo que cualquier cambio exige reiniciar el servicio.

Credenciales

config.ini está en .gitignore y nunca se sube al repositorio. Usa config.example.ini como plantilla.

Secciones de config.ini

Sección Clave Descripción
[sync] interval_minutes Frecuencia de la corrida (default 5)
exit_hour Hora local desde la que un punch cuenta como salida (17)
auto_close_hour Hora local de cierre de asistencias abiertas (17)
utc_offset_hours Offset UTC de la zona local (Panamá -5)
exclude_zk_ids IDs sin empleado en ninguna instancia de Odoo
log_file / unmatched_log Rutas de log
[zk.<n>] name, ip, port, password Conexión al reloj
[odoo.<n>] label, url, db, user, api_key Credenciales de la instancia
exclude_zk_ids IDs inexistentes en esta instancia

Los exclude_zk_ids se separan por espacio o coma. Para agregar otro reloj u otra instancia de Odoo, se duplica la sección con otro sufijo.

API Key de Odoo

Sigue la guía Generar una API Key en Odoo.

La IP del reloj es DHCP — reserva pendiente

Hoy el F22 toma su IP por DHCP, así que cada vez que se reinicia puede quedarse con una dirección distinta y romper la conexión hasta que alguien actualice ip a mano con utils/find_zk.py y reinicie el servicio.

Lo correcto es asignarle una IP estática por reserva DHCP en el router (atando su MAC a una dirección fija). Esa configuración está pendiente — ver Troubleshooting → El reloj cambió de IP.

Ejemplo

[zk.principal]
name     = Oficina Principal
ip       = 192.168.68.121
port     = 4370
password = 0

[odoo.main]
label   = Produccion
url     = https://<instancia>.odoo.com
db      = <nombre-base-de-datos>
user    = usuario@empresa.com
api_key = <api-key-de-odoo>

[sync]
interval_minutes = 5
exit_hour        = 17
auto_close_hour  = 17
utc_offset_hours = -5
exclude_zk_ids   =
log_file         = C:\ruta\al\proyecto\logs\sync.log
unmatched_log    = C:\ruta\al\proyecto\logs\unmatched.log

Producción vs. staging

sync.py no acepta un flag --config: el destino lo determina el config.ini activo. La estrategia es mantener un archivo por entorno y copiar el que corresponda.

Archivo Uso En git
config.ini Config activa (la que usa el servicio) No
config.production.ini Credenciales de producción No
config.staging.ini Credenciales de staging No
config.example.ini Plantilla sin credenciales

El procedimiento de cambio de entorno está en Instalar y operar el servicio de Windows.

CLI

python sync.py                                       # modo servicio (scheduler)
python sync.py --dry-run                             # imprime el payload, no envía
python sync.py --desde 2026-05-01                    # mueve watermark y arranca
python sync.py --desde 2026-05-01 --device sucursal  # solo un dispositivo

--desde pide confirmación interactiva (s/n) mostrando el watermark actual y el nuevo valor de cada dispositivo afectado.

Utilidades (utils/)

Todas leen del config.ini de la raíz.

Script Qué hace
status.py Conectividad por dispositivo, última sync, pendientes y últimos errores
match_report.py Cruza usuarios del reloj con empleados de Odoo: quién tiene zk_user_id, quién no, y qué nombres difieren
close_open_attendances.py Cierra manualmente asistencias abiertas de días anteriores
marcaciones_hoy.py Marcaciones del día leídas directo del reloj, sin pasar por Odoo
delete_attendance.py Elimina asistencias de Odoo por empleado y fecha (--empleado, --fecha, --instancia, --dry-run)
fix_attendance.py Compara Odoo contra el reloj y corrige check_in / check_out (--fix-entradas, --fix-salidas)
find_zk.py Escanea la subred para localizar el reloj cuando DHCP le cambia la IP, y ofrece actualizar config.ini
users.py Exporta usuarios del reloj a data/zk_users.csv
rename_users.py Edita nombres de usuarios directamente en el dispositivo, de forma interactiva
delete_users.py Elimina usuarios del dispositivo con backup previo en data/deleted_users_<ts>.json
restore_users.py Restaura usuarios desde un backup generado por delete_users.py

Casi todos aceptan --dry-run

Los scripts que escriben (en Odoo o en el dispositivo) soportan --dry-run para simular sin aplicar cambios. Úsalo siempre primero.