<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nucleo360</title>
    <description>The latest articles on DEV Community by Nucleo360 (@nucleo360).</description>
    <link>https://dev.to/nucleo360</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4049825%2Ff10385b8-77c2-4bdb-a237-50dc6b9b9b19.png</url>
      <title>DEV Community: Nucleo360</title>
      <link>https://dev.to/nucleo360</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nucleo360"/>
    <language>en</language>
    <item>
      <title>Exportar el registro horario para Inspección de Trabajo o auditoría interna: formatos, integridad y trazabilidad</title>
      <dc:creator>Nucleo360</dc:creator>
      <pubDate>Mon, 27 Jul 2026 16:26:20 +0000</pubDate>
      <link>https://dev.to/nucleo360/exportar-el-registro-horario-para-inspeccion-de-trabajo-o-auditoria-interna-formatos-integridad-y-16l5</link>
      <guid>https://dev.to/nucleo360/exportar-el-registro-horario-para-inspeccion-de-trabajo-o-auditoria-interna-formatos-integridad-y-16l5</guid>
      <description>&lt;p&gt;Hay dos momentos en los que el registro horario deja de ser un trámite y se convierte en &lt;strong&gt;evidencia&lt;/strong&gt;: cuando la Inspección de Trabajo lo pide y cuando una auditoría interna lo revisa. En ambos casos, la pregunta técnica es la misma: ¿puedes entregar los datos en un formato adecuado, completos y con garantías de que nadie los ha retocado?&lt;/p&gt;

&lt;p&gt;Este artículo repasa cómo hacerlo bien, con &lt;a href="https://nucleo360.com/registro-horario/" rel="noopener noreferrer"&gt;Nucleo360&lt;/a&gt; como caso concreto y con buenas prácticas que aplican a cualquier sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  El marco legal en cuatro líneas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El registro horario es obligatorio para todas las empresas en España desde el &lt;strong&gt;12 de mayo de 2019&lt;/strong&gt; (Real Decreto-ley 8/2019, BOE-A-2019-3481).&lt;/li&gt;
&lt;li&gt;Los registros deben conservarse &lt;strong&gt;4 años&lt;/strong&gt; y permanecer a disposición de las personas trabajadoras, de sus representantes legales y de la Inspección de Trabajo (&lt;strong&gt;art. 34.9 del Estatuto de los Trabajadores&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;No llevarlo (o llevarlo mal) es infracción &lt;strong&gt;grave&lt;/strong&gt;: sanción de &lt;strong&gt;751 a 7.500 €&lt;/strong&gt; (arts. 7.5 y 40.1.b de la LISOS).&lt;/li&gt;
&lt;li&gt;Matiz honesto: la ley obliga a registrar la jornada, pero &lt;strong&gt;no exige que el registro sea digital&lt;/strong&gt;. Digitalizarlo es lo que hace viable todo lo que viene a continuación: exportar en segundos, demostrar integridad y controlar quién accede.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué formato espera cada destinatario
&lt;/h2&gt;

&lt;p&gt;No existe un formato único obligatorio, pero en la práctica cada destinatario espera cosas distintas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Destinatario&lt;/th&gt;
&lt;th&gt;Qué necesita&lt;/th&gt;
&lt;th&gt;Formato razonable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inspección de Trabajo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Registro diario de jornada por persona trabajadora, con horario concreto de inicio y fin, del periodo requerido&lt;/td&gt;
&lt;td&gt;Informe legible (PDF impreso o digital)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auditoría interna / asesor laboral&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Datos tabulares para recalcular totales, detectar patrones y cruzar con nóminas&lt;/td&gt;
&lt;td&gt;CSV u hoja de cálculo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;La propia empresa (archivo)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Copia íntegra del periodo, conservada 4 años&lt;/td&gt;
&lt;td&gt;Ambos, más el hash de integridad (ver abajo)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;En Nucleo360, el informe para la Inspección se genera &lt;strong&gt;en un clic&lt;/strong&gt; desde el módulo de registro horario, con los fichajes de cada persona y día del periodo. Para la parte de análisis, se trabaja con el export tabular del periodo.&lt;/p&gt;

&lt;p&gt;Un consejo operativo: cuando la Inspección requiere documentación, no es el momento de descubrir que tu sistema no exporta lo que necesitas. Haz un simulacro una vez al año: exporta un trimestre completo y revisa que se entiende sin explicaciones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integridad y trazabilidad: el registro inmutable
&lt;/h2&gt;

&lt;p&gt;Un registro horario que se puede editar sin dejar rastro vale poco como evidencia. Los dos atributos que una auditoría va a mirar con lupa:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Inmutabilidad&lt;/strong&gt;: los fichajes no se sobrescriben. Las correcciones (un olvido, un error) quedan como eventos nuevos con su propia traza, no como ediciones silenciosas del dato original.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trazabilidad&lt;/strong&gt;: cada fichaje lleva asociado &lt;strong&gt;quién&lt;/strong&gt; lo hizo, &lt;strong&gt;cuándo&lt;/strong&gt; exactamente y &lt;strong&gt;desde dónde&lt;/strong&gt; (dispositivo/origen). Ese contexto es lo que convierte una fila de datos en un hecho verificable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nucleo360 implementa el registro horario como &lt;strong&gt;registro inmutable con trazabilidad&lt;/strong&gt;: la cadena quién-cuándo-desde-dónde acompaña a cada fichaje, y eso es lo que se refleja después en informes y exports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjnwz5126cygft8ghs79h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjnwz5126cygft8ghs79h.png" alt=" " width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Buena práctica: hash del archivo exportado
&lt;/h2&gt;

&lt;p&gt;El registro dentro del sistema es inmutable, pero el archivo que exportas es un archivo más: puede alterarse, corromperse o confundirse con otra versión. La solución clásica (y gratuita) es calcular su &lt;strong&gt;huella criptográfica (SHA-256)&lt;/strong&gt; en el momento del export y apuntarla en tu acta o registro de auditoría.&lt;/p&gt;

&lt;p&gt;En Windows (PowerShell):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-FileHash&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\registro-horario-2026-T2.csv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Algorithm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SHA256&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Linux o macOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sha256sum &lt;/span&gt;registro-horario-2026-T2.csv
&lt;span class="c"&gt;# En macOS: shasum -a 256 registro-horario-2026-T2.csv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado es una cadena tipo &lt;code&gt;3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b&lt;/code&gt;. Guárdala junto a la fecha del export y quién lo hizo. Meses después, cualquiera puede recalcular el hash del archivo archivado: si coincide, el archivo es &lt;strong&gt;bit a bit&lt;/strong&gt; el mismo que se exportó; si no, algo lo ha tocado. Es un ejemplo de buena práctica genérica, válido para cualquier archivo de evidencia, no solo para fichajes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protección de datos: el export también es tratamiento
&lt;/h2&gt;

&lt;p&gt;Los datos de fichaje son datos personales, así que el export cae de lleno bajo el &lt;strong&gt;RGPD (Reglamento UE 2016/679)&lt;/strong&gt; y la &lt;strong&gt;LOPDGDD (Ley Orgánica 3/2018)&lt;/strong&gt;. Tres reglas prácticas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimización&lt;/strong&gt;: exporta solo los campos necesarios para el fin concreto. Para recalcular jornadas no hace falta el DNI de nadie; un identificador interno de empleado suele bastar. Cuantos menos datos viajen, menos superficie de riesgo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control de accesos por rol&lt;/strong&gt;: no todo el mundo debe poder exportar el registro de toda la plantilla. Limita la capacidad de export a los roles que la necesitan (RRHH, administración) y deja traza de quién exporta qué y cuándo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canales y conservación&lt;/strong&gt;: nada de enviar el CSV por canales no corporativos. Y al cumplirse los plazos de conservación (los 4 años del art. 34.9 ET, o los que fije tu política si son mayores por otra razón legítima), los exports archivados también se depuran.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Checklist antes de dar por buena tu capacidad de auditoría
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Puedo exportar cualquier periodo de los últimos 4 años sin ayuda del proveedor.&lt;/li&gt;
&lt;li&gt;[ ] El informe para la Inspección sale legible: persona, día, hora de inicio y fin.&lt;/li&gt;
&lt;li&gt;[ ] El sistema de registro es inmutable y las correcciones dejan traza (quién-cuándo-desde-dónde).&lt;/li&gt;
&lt;li&gt;[ ] Calculo y archivo el hash SHA-256 de cada export que actúe como evidencia.&lt;/li&gt;
&lt;li&gt;[ ] El export está restringido por rol y los campos exportados son los mínimos necesarios.&lt;/li&gt;
&lt;li&gt;[ ] He hecho un simulacro de requerimiento en el último año.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si tu sistema actual no pasa esta lista, es un buen momento para revisarlo. El módulo de registro horario de Nucleo360 (disponible desde el plan gratuito) está diseñado exactamente para esto: registro inmutable, trazabilidad completa e informe para la Inspección en un clic.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Última actualización: julio de 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nucleo360.com" rel="noopener noreferrer"&gt;Nucleo360&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rrhh</category>
      <category>compliance</category>
      <category>database</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Integrar los datos de fichaje con el software de nóminas: el flujo real (export-validación-gestoría)</title>
      <dc:creator>Nucleo360</dc:creator>
      <pubDate>Mon, 27 Jul 2026 16:17:52 +0000</pubDate>
      <link>https://dev.to/nucleo360/integrar-los-datos-de-fichaje-con-el-software-de-nominas-el-flujo-real-export-validacion-gestoria-524b</link>
      <guid>https://dev.to/nucleo360/integrar-los-datos-de-fichaje-con-el-software-de-nominas-el-flujo-real-export-validacion-gestoria-524b</guid>
      <description>&lt;p&gt;Desde el 12 de mayo de 2019, el Real Decreto-ley 8/2019 (BOE-A-2019-3481) obliga a todas las empresas en España a llevar un registro horario diario de su plantilla. Ese registro no vive aislado: cada mes, alguien tiene que convertir horas trabajadas, horas extra y ausencias en una nómina. Y ahí es donde muchas pymes pierden tiempo (y cometen errores).&lt;/p&gt;

&lt;p&gt;En este artículo documentamos el flujo real para llevar los datos de fichaje de &lt;a href="https://nucleo360.com/registro-horario/" rel="noopener noreferrer"&gt;Nucleo360&lt;/a&gt; hasta el software de nóminas o el gestor laboral, con un paso de validación intermedio que te puede ahorrar más de un disgusto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Empecemos por la honestidad técnica
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Nucleo360 no calcula nóminas.&lt;/strong&gt; Es una decisión de producto deliberada: la plataforma cubre el registro horario, las vacaciones y ausencias, la gestión documental, el canal de denuncias y el resto de la gestión de RRHH de una pyme, y &lt;strong&gt;exporta la documentación y los datos al gestor laboral o al software de nóminas&lt;/strong&gt; que ya usa la empresa. El cálculo de la nómina (convenios, cotizaciones, IRPF) lo hace quien mejor sabe hacerlo: tu asesoría o tu programa de nóminas.&lt;/p&gt;

&lt;p&gt;Eso significa que la integración de la que hablamos aquí no es una sincronización mágica en tiempo real, sino un &lt;strong&gt;pipeline de datos clásico y robusto&lt;/strong&gt;: exportar → validar → entregar. Es aburrido, y por eso funciona.&lt;/p&gt;

&lt;h2&gt;
  
  
  El flujo en tres pasos
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Paso 1 · Exportar el periodo desde Nucleo360
&lt;/h3&gt;

&lt;p&gt;Al cierre de cada mes (o del periodo que pacte tu gestoría), se exportan desde Nucleo360 los datos del registro horario del periodo: fichajes por empleado y día, con sus tramos de entrada y salida y los totales. El registro es &lt;strong&gt;inmutable y con trazabilidad&lt;/strong&gt; (quién fichó, cuándo y desde dónde), así que lo que exportas refleja lo que realmente se registró, no una versión editada a posteriori.&lt;/p&gt;

&lt;p&gt;Para nóminas, lo habitual es trabajar con el export en formato tabular (CSV) o con los informes del periodo, según lo que acepte tu gestor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8isktf0vh5n6u6w2l19e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8isktf0vh5n6u6w2l19e.png" alt=" " width="512" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 2 · Validar antes de enviar
&lt;/h3&gt;

&lt;p&gt;Este es el paso que casi nadie hace y el que más errores evita. Antes de entregar los datos a quien hace la nómina, conviene comprobar tres cosas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Totales por empleado&lt;/strong&gt;: que las horas del mes cuadran con lo esperado (jornada pactada ± extras).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Huecos&lt;/strong&gt;: días laborables sin ningún fichaje. Pueden ser vacaciones o ausencias legítimas (cotéjalo con el módulo de vacaciones), o pueden ser olvidos que hay que resolver &lt;em&gt;antes&lt;/em&gt; de que lleguen a la nómina.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solapes&lt;/strong&gt;: tramos que se pisan entre sí (entrada a las 9:00 y a las 9:30 sin salida intermedia). Suelen indicar un fichaje duplicado o mal cerrado.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aquí tienes un &lt;strong&gt;ejemplo genérico&lt;/strong&gt; en Python (solo librería estándar) que hace exactamente eso sobre un CSV de fichajes. No depende de ningún proveedor: ajusta los nombres de columna a los de tu export real.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
EJEMPLO GENÉRICO de validación de un CSV de fichajes antes de
entregarlo al gestor laboral. Ajusta columnas y delimitador a tu export.

Formato esperado (una fila por tramo de fichaje):
    empleado_id;nombre;fecha;hora_entrada;hora_salida
    E001;Ana;2026-07-01;08:00;15:00
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;

&lt;span class="n"&gt;FORMATO_FECHA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;FORMATO_HORA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%H:%M&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cargar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tramos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# (empleado_id, fecha) -&amp;gt; [(inicio, fin), ...]
&lt;/span&gt;    &lt;span class="n"&gt;nombres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n_linea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fila&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delimiter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;dia&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strptime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fila&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fecha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;FORMATO_FECHA&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;entrada&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;dia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strptime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fila&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hora_entrada&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;FORMATO_HORA&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="n"&gt;salida&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;dia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strptime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fila&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hora_salida&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;FORMATO_HORA&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[ERROR] Línea &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n_linea&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: fila ilegible (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;salida&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;entrada&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Turno nocturno: la salida cae en el día siguiente
&lt;/span&gt;                &lt;span class="n"&gt;salida&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;tramos&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;fila&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;empleado_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dia&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;entrada&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salida&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;nombres&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fila&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;empleado_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fila&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nombre&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tramos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nombres&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tramos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nombres&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;incidencias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dia&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tramos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
        &lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# Solapes dentro del mismo día
&lt;/span&gt;        &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ini_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fin_a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ini_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fin_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ini_b&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;fin_a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[SOLAPE] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dia&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                      &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ini_a&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fin_a&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; se pisa con &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ini_b&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fin_b&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;incidencias&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ini&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fin&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;fin&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ini&lt;/span&gt;
        &lt;span class="n"&gt;dias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Huecos: días laborables (L-V) sin fichajes dentro del rango del archivo.
&lt;/span&gt;    &lt;span class="c1"&gt;# OJO: pueden ser vacaciones o ausencias legítimas; esto solo los señala.
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fechas&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dias&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ultimo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fechas&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fechas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;ultimo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weekday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fechas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[HUECO] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nombres&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;): sin fichajes el &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                      &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(¿vacaciones/ausencia sin cotejar?)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;incidencias&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;--- Totales por empleado ---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
        &lt;span class="n"&gt;horas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nombres&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;horas&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;6.2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; h en &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; días&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;incidencias&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Uso: python valida_fichajes.py fichajes.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tramos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nombres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cargar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tramos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nombres&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; incidencias detectadas.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El script devuelve código de salida distinto de cero si hay incidencias, así que puedes encadenarlo en cualquier automatización: si algo no cuadra, el archivo no sigue viaje hacia la nómina.&lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 3 · Entregar al gestor (bien empaquetado)
&lt;/h3&gt;

&lt;p&gt;La entrega falla casi siempre por detalles tontos de formato, no por los datos. Pacta con tu gestoría o con quien opere el software de nóminas, una sola vez y por escrito:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Columnas y su orden&lt;/strong&gt; (una tabla de mapeo de dos columnas es suficiente).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codificación&lt;/strong&gt;: UTF-8. Los nombres con tildes y eñes lo agradecerán.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delimitador&lt;/strong&gt; (&lt;code&gt;;&lt;/code&gt; es lo habitual en España, porque la coma decimal rompe los CSV con &lt;code&gt;,&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formato de fecha&lt;/strong&gt;: ISO 8601 (&lt;code&gt;2026-07-01&lt;/code&gt;) evita el clásico baile día/mes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fecha de corte&lt;/strong&gt;: qué día del mes se exporta, para que la nómina no espere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y conserva una copia de lo entregado: el registro horario debe conservarse &lt;strong&gt;4 años&lt;/strong&gt; (art. 34.9 del Estatuto de los Trabajadores).&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Y la integración directa por API?
&lt;/h2&gt;

&lt;p&gt;Pregunta legítima de cualquier perfil técnico: «¿puedo saltarme el CSV y tirar de API?».&lt;/p&gt;

&lt;p&gt;Respuesta honesta: a fecha de este artículo, la integración directa vía API con sistemas de nóminas está &lt;strong&gt;[PENDIENTE DE CONFIRMAR CON CLIENTE]&lt;/strong&gt; — no hay una API pública documentada que podamos enseñarte aquí, y preferimos no inventárnosla. El flujo soportado y probado es el que acabas de leer: export, validación y entrega.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Se integra directamente con algún programa de nóminas concreto?
&lt;/h2&gt;

&lt;p&gt;Misma honestidad: &lt;strong&gt;no hay integraciones directas confirmadas&lt;/strong&gt; con programas concretos de nóminas ni con gestorías [PENDIENTE DE CONFIRMAR CON CLIENTE]. Lo que sí funciona hoy es el puente universal: la mayoría de software de nóminas y gestorías aceptan importación de datos tabulares (CSV) o trabajan directamente con los informes del periodo. Pregunta a tu gestor qué formato de importación acepta su herramienta y pacta el mapeo de columnas del Paso 3.&lt;/p&gt;

&lt;p&gt;¿Menos glamuroso que un webhook? Sí. ¿Funciona con cualquier gestoría de España sin depender de que dos proveedores se pongan de acuerdo? También.&lt;/p&gt;

&lt;h2&gt;
  
  
  En resumen
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nucleo360 registra la jornada (registro inmutable, con trazabilidad) y &lt;strong&gt;exporta&lt;/strong&gt;; la nómina la calcula tu gestor o tu software de nóminas.&lt;/li&gt;
&lt;li&gt;Valida siempre antes de entregar: totales, huecos y solapes. El script de arriba es un punto de partida.&lt;/li&gt;
&lt;li&gt;Pacta el formato con tu gestoría una vez y por escrito; UTF-8, &lt;code&gt;;&lt;/code&gt; e ISO 8601 te evitan el 90 % de los problemas.&lt;/li&gt;
&lt;li&gt;API pública e integraciones directas con programas concretos: pendientes de confirmar; hoy el camino es el export.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si quieres ver el módulo de registro horario en detalle (el plan Basic es gratuito y sin permanencia), tienes toda la información en &lt;a href="https://nucleo360.com" rel="noopener noreferrer"&gt;nucleo360.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Última actualización: julio de 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nucleo360.com" rel="noopener noreferrer"&gt;Nucleo360.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rrhh</category>
      <category>puppet</category>
      <category>database</category>
      <category>spanish</category>
    </item>
  </channel>
</rss>
