# Verificar QR (1) - [verifyQR]

### 🧾 Descripción

Este servicio permite **validar si un empleado tiene permitido registrarse** (por ejemplo, marcar asistencia) **en función del último escaneo de QR del bus** registrado en el ERP.

La lógica se basa en verificar si el empleado escaneó su QR dentro de las **últimas 4 horas (14400 segundos)**.

El servicio consulta la tabla:

- `Registro de Escaneres de Bus`
- `Tabla Lista Blanca`

Mediante `dbErp()` para obtener el escaneo más reciente disponible.

---

# 🚀 Endpoint

### **POST /verify-qr**

---

# 📥 Request Body (Ejemplo)

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-%7B-%22employee%22%3A-%22hr-em"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`<span class="hljs-punctuation">{</span>  <span class="hljs-attr">"employee"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"HR-EMP-00045"</span><span class="hljs-punctuation">}</span>`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>### Parámetros

<div class="_tableContainer_1rjym_1" id="bkmrk-campo-tipo-obligator"><div class="group _tableWrapper_1rjym_13 flex w-fit flex-col-reverse" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)" data-end="956" data-start="809"><thead data-end="853" data-start="809"><tr data-end="853" data-start="809"><th data-col-size="sm" data-end="817" data-start="809">Campo</th><th data-col-size="sm" data-end="824" data-start="817">Tipo</th><th data-col-size="sm" data-end="838" data-start="824">Obligatorio</th><th data-col-size="sm" data-end="853" data-start="838">Descripción</th></tr></thead><tbody data-end="956" data-start="899"><tr data-end="956" data-start="899"><td data-col-size="sm" data-end="910" data-start="899">employee</td><td data-col-size="sm" data-end="919" data-start="910">string</td><td data-col-size="sm" data-end="924" data-start="919">✔️</td><td data-col-size="sm" data-end="956" data-start="924">Código de empleado a validar</td></tr></tbody></table>

</div></div>---

# 🔐 Seguridad

El servicio usa comunicación interna con ERP mediante:

- `dbErp()`
- Autenticación interna utilizando cookies o token del ERP.

No requiere autenticación adicional desde el cliente.

---

# 🧠 Flujo del Servicio (Explicación real)

1. **Validación inicial del parámetro**
    
    
    - Si `employee` está vacío → se devuelve error.
2. **Consulta del último escaneo registrado en ERP**
    
    Se ejecuta:
    
    <div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.8711%;"></col></colgroup><tbody><tr><td>`<span class="hljs-keyword">SELECT</span> tpr.name, teas.empleado, teas.fecha<span class="hljs-keyword">FROM</span> `tabRegistro de Escaneres de Bus` tpr<span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> `tabTabla Lista Blanca` teas <span class="hljs-keyword">ON</span> teas.parent <span class="hljs-operator">=</span> tpr.name<span class="hljs-keyword">WHERE</span> teas.empleado <span class="hljs-operator">=</span> employee<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> teas.fecha <span class="hljs-keyword">DESC</span>LIMIT <span class="hljs-number">1</span>`</td></tr></tbody></table>
    
    </div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>
3. **Si no existen registros**
    
    
    - Se retorna mensaje indicando que no se encontró escaneo.
4. **Cálculo de la diferencia de tiempo**
    
    Se obtiene el tiempo transcurrido entre:
    
    
    - Fecha del escaneo (`fecha`)
    - Fecha actual
    
    Se obtiene con:
    
    <div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.8711%;"></col></colgroup><tbody><tr><td>`<span class="hljs-variable">$diff</span> = <span class="hljs-variable">$fechaEscaneoCarbon</span>-><span class="hljs-title function_ invoke__">diffInSeconds</span>(<span class="hljs-title function_ invoke__">now</span>());`</td></tr></tbody></table>
    
    </div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>
5. **Aplicación de la regla de validación**
    
    
    - Si la diferencia es **menor a 4 horas (14400 segundos)** → **permitido**
    - Si es mayor → **denegado**
6. **Manejo de excepciones**  
    Si ocurre un error interno, se retorna el mensaje de error.

---

# 📤 Response 200 – Ejemplos

### ✔️ Caso permitido (último escaneo dentro de 4 horas)

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-%7B-%22status%22%3A-true%2C-%22m"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`<span class="hljs-punctuation">{</span>  <span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"msn"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"permitido"</span><span class="hljs-punctuation">}</span>`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>---

### ✔️ Caso denegado (más de 4 horas sin escanear)

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-%7B-%22status%22%3A-true%2C-%22m-1"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`<span class="hljs-punctuation">{</span>  <span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"msn"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"denegado"</span><span class="hljs-punctuation">}</span>`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>---

### ❌ No existe escaneo asociado al empleado

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-%7B-%22status%22%3A-false%2C-%22"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`<span class="hljs-punctuation">{</span>  <span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"msn"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"No se ha encontrado un escaner de bus para el empleado"</span><span class="hljs-punctuation">}</span>`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>---

### ❌ Parámetro inválido

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-%7B-%22status%22%3A-false%2C-%22-1"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`<span class="hljs-punctuation">{</span>  <span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"msn"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"El empleado no puede estar vacio"</span><span class="hljs-punctuation">}</span>`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>---

### ❌ Error interno

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-%7B-%22status%22%3A-false%2C-%22-2"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`<span class="hljs-punctuation">{</span>  <span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"msn"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Error interno: <mensaje>"</span><span class="hljs-punctuation">}</span>`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>---

# 📚 Schemas utilizados

### **Registro de Escaneres de Bus (consulta)**

Campos consultados:

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-%7B-%22name%22%3A-%22string%22%2C-"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`<span class="hljs-punctuation">{</span>  <span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"string"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"empleado"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"string"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"fecha"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"datetime"</span><span class="hljs-punctuation">}</span>`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>---

# 🗃 Lógica en Pseudo-código

<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary" id="bkmrk-if-employee-is-empty"><div class="sticky top-9"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"><table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 99.881%;"></col></colgroup><tbody><tr><td>`if employee is empty:    return error("El empleado no puede estar vacio")data = GET ultimo registro de escaneo del bus para employeeif no data:    return error("No se ha encontrado un escaneo")fechaEscaneo = data.fechadiferencia = now() - fechaEscaneo (en segundos)if diferencia < 14400:    return permitidoelse:    return denegado`</td></tr></tbody></table>

</div></div></div><div class="overflow-y-auto p-4" dir="ltr"></div></div>