Saltar a contenido

Registrar y asignar un tag NFC

Esta guía te lleva paso a paso por la tarea concreta de dejar operativo un tag NFC en blanco: darlo de alta en stock y asignarlo a un sanitario, para que cuando el personal apoye el celular sobre la placa, el tap registre trabajos contra el sanitario correcto.

Alcance: qué es 'registrar un dispositivo NFC' acá

En WorkDone Sanitarios, registrar un dispositivo NFC significa dar de alta una placa/tag NFC — la entidad TagNfc, el chip físico que se pega al sanitario — y asignarla a un sanitario. NO se trata de registrar un teléfono ni un dispositivo de operario (eso es otra cosa: el Dispositivo que se vincula en el login). Acá hablamos del chip que el personal acerca con el celular para registrar una limpieza.

El ciclo de vida completo del tag (estados, transiciones válidas y auditoría) vive en la referencia Ciclo de vida de los tags NFC. Esta página es la receta operativa; aquella, el porqué.

Prerequisitos

Necesitás Detalle Cómo verificarlo
Rol ADMIN Las mutaciones NFC desde la app móvil (alta-stock, asignar, desasignar, reasignar) son solo ADMIN. Un operador de limpieza o supervisor no puede ejecutarlas. Drawer → Configuración → "Rol del operario actual" debe decir ADMIN. La pantalla Gestión NFC solo aparece para ADMIN.
Un tag NFC físico en blanco NTAG215 o NTAG213. En producción se usan los antimetal (Atlantico3D) sobre superficie metálica; para pruebas cualquier NTAG común alcanza. Un chip que al resolverlo dé NO_REGISTRADO.
El sanitario destino ya creado El tag se asigna a un sanitario existente (ej. AEP-T-B12). Aparece en el árbol Sucursal›Sector›Sanitario de GET /api/v1/app/sanitarios/disponibles (con tiene_tag por cada uno).
La app móvil logueada como ADMIN El alta de stock solo se hace desde la app, porque hay que leer el chip onsite. No existe alta de stock en el BackOffice web. Que la app esté sincronizando (chip 🟢 Conectado abajo).

El alta de stock NO se puede hacer desde la web

ALTA_STOCK requiere leer el chip físico en el lugar, así que solo existe en la app móvil (rol ADMIN). El BackOffice web puede desasignar, reasignar, dar de baja y re-dar de alta, pero no dar de alta en stock.

El recorrido en una imagen

flowchart TD
    A[Tag NFC en blanco] -->|Paso 1 ALTA_STOCK| B[EN_STOCK]
    B -->|Paso 2 ASIGNACION| C[ASIGNADO]
    C -->|Paso 3 verificar resolver| D[Tap registra trabajos]

Y los tres estados posibles del tag, con las transiciones que vas a usar:

stateDiagram-v2
    [*] --> EN_STOCK: ALTA_STOCK
    EN_STOCK --> ASIGNADO: ASIGNACION
    ASIGNADO --> EN_STOCK: DESASIGNACION
    ASIGNADO --> ASIGNADO: REASIGNACION otro sanitario
    EN_STOCK --> BAJA: BAJA
    BAJA --> EN_STOCK: RE_ALTA solo web

Cómo leer el diagrama

  • ALTA_STOCK es idempotente: si el tag ya existe, devuelve el existente sin generar evento.
  • REASIGNACION es un bucle sobre ASIGNADO: el tag cambia de sanitario en una sola operación atómica, sin pasar por EN_STOCK.
  • BAJA sale solo desde EN_STOCK. Un tag ASIGNADO hay que desasignarlo primero.
  • RE_ALTA (BAJA → EN_STOCK) está disponible solo desde el BackOffice web, nunca por la app/sync.

Paso 1 — Alta en stock

Con la app en la pantalla Gestión NFC, apoyá el celular sobre el tag en blanco. La app resuelve el estado (NO_REGISTRADO) y te ofrece "Dar de alta en stock". Confirmá con un alias descriptivo (ej. tag #14 lote mayo).

Pantalla de la app móvil esperando que acerques el celular a un tag NFC, con el simulador de UUID en modo DEV

La app móvil esperando el tap: "Acercá el celular a un tag". Apoyás el celular sobre el chip para que la app lo lea y resuelva su estado. El campo "DEV — simular tag (UUID)" solo aparece en builds de desarrollo, para simular el tap sin un chip físico.

Esto graba/registra el tag como EN_STOCK en el backend. El endpoint que la app encola y envía por sync es:

POST /api/v1/app/nfc/alta-stock
Authorization: Bearer <jwt-operario-ADMIN>
Content-Type: application/json
{
  "uuid_tag": "aaaa1111-1111-1111-1111-111111111111",
  "alias": "tag #14 lote mayo"
}

Es idempotente: podés re-leer sin miedo

alta-stock es idempotente por uuid normalizado: si el tag ya existe, el backend devuelve el tag actual sin crear evento ni modificar nada. Volver a apoyar el celular sobre un tag ya dado de alta no rompe nada ni duplica registros.

Grabar el tag físico (NDEF)

Si además vas a grabar el chip (con una app tipo "NFC Tools" / "NFC TagWriter"), escribí en el NDEF la URL https://workdone.lubeca.tech/t/{uuid}, donde {uuid} es el mismo uuid_tag que diste de alta. Ese UUID es la fuente de verdad: el backend normaliza el UUID (trim, mayúsculas, sin espacios) en cada lectura, así que el formato no importa, pero el valor sí tiene que coincidir.

Resultado verificable: al resolver el tag, su estado pasa a EN_STOCK.

Paso 2 — Asignar a un sanitario

Con el tag ya EN_STOCK, la app te ofrece "Asignar a sanitario". Elegí el sanitario destino del árbol Sucursal›Sector›Sanitario y confirmá. La app encola y sincroniza:

POST /api/v1/app/nfc/asignar
Authorization: Bearer <jwt-operario-ADMIN>
Content-Type: application/json
{
  "uuid_tag": "aaaa1111-1111-1111-1111-111111111111",
  "sanitario_id": 12
}

Esto ejecuta la transición EN_STOCK → ASIGNADO: el tag queda vinculado al sanitario, con asignado_en seteado y activo = true.

Conflicto de asignación: el primero en sincronizar gana

Solo puede haber un tag ASIGNADO por sanitario (constraint en la base). Si el sanitario destino ya tiene un tag asignado, o si el tag no está EN_STOCK, la operación devuelve CONFLICTO_ASIGNACION (HTTP 409). Cuando dos dispositivos asignan offline al mismo sanitario, el primero en el orden de sincronización gana y el segundo recibe el conflicto (el orden lo define ts_local_device ASC). Si te pasa, la app revierte el optimismo local y te avisa.

Resultado verificable: al resolver el tag, su estado pasa a ASIGNADO y trae los datos del sanitario.

Paso 3 — Verificar

Confirmá que el tag quedó operativo resolviéndolo:

GET /api/v1/app/nfc/resolver/aaaa1111-1111-1111-1111-111111111111
Authorization: Bearer <jwt-operario>

Respuesta esperada:

{
  "estado": "ASIGNADO",
  "alias": "tag #14 lote mayo",
  "sanitario": {
    "id": 12,
    "codigo": "AEP-T-B12",
    "nombre": "Baño Hombres Terminal A",
    "sector": "Terminal A",
    "sucursal": "AEP"
  }
}

Prueba final (la que vale): que un operario de limpieza apoye el celular sobre el tag. Debería pasar a estado VERDE y arrancar el timer del trabajo. La app resuelve taps solo contra tags en estado ASIGNADO, así que si llegaste hasta acá, el tag ya está operativo.

Operaciones adicionales

Una vez asignado, el tag puede moverse o retirarse. Todas estas mutaciones pasan por el mismo servicio (TagNfcLifecycleService) y dejan auditoría.

Reasignar a otro sanitario

Mueve el tag de un sanitario a otro en un solo paso atómico, sin pasar por EN_STOCK:

POST /api/v1/app/nfc/reasignar
{
  "uuid_tag": "aaaa1111-1111-1111-1111-111111111111",
  "sanitario_nuevo_id": 20,
  "notas": "se movió la placa al baño contiguo"
}

Reasignar NO es 'desasignar + asignar'

REASIGNACION genera un único evento de auditoría con sanitario_anterior y sanitario_nuevo poblados, para preservar la trazabilidad del movimiento como una sola operación. Caso borde: si el sanitario nuevo es el mismo que el anterior, no se valida el conflicto.

Desasignar (devolver a stock)

POST /api/v1/app/nfc/desasignar
{ "uuid_tag": "aaaa1111-1111-1111-1111-111111111111" }

Limpia el sanitario y devuelve el tag a EN_STOCK.

Dar de baja

La baja (desactivar definitivamente) y la re-alta se hacen desde el BackOffice web, no por la app móvil. Recordá: BAJA solo es posible desde EN_STOCK — un tag asignado hay que desasignarlo primero.

Desde el BackOffice, la pantalla Tags NFC lista todos los tags ya registrados y te deja gestionarlos: filtrarlos por estado (Todos / En stock / Asignados / Baja), y desasignar o reasignar cada uno con los botones de la columna Acciones.

Pantalla Tags NFC del BackOffice web, con la tabla de tags registrados y las acciones Desasignar y Reasignar

La pantalla Tags NFC del BackOffice: tabla con Alias, UUID, Estado, Sanitario y fecha de asignación, más las acciones Desasignar / Reasignar por fila. El aviso "Alta de tags" recuerda que el alta se hace desde la app móvil (requiere leer el chip onsite); desde acá solo se gestionan los tags ya registrados.

Tabla de transiciones válidas

Acción De → A Dónde
ALTA_STOCK [*]EN_STOCK Solo app móvil (leer el chip onsite)
ASIGNACION EN_STOCKASIGNADO App o web
DESASIGNACION ASIGNADOEN_STOCK App o web
REASIGNACION ASIGNADOASIGNADO (otro sanitario, atómico) App o web
BAJA EN_STOCKBAJA App o web — solo desde EN_STOCK
RE_ALTA BAJAEN_STOCK Solo web (BackOffice)

Problemas comunes

403 / ROL_INSUFICIENTE — 'no me deja dar de alta ni asignar'

Las mutaciones NFC son solo ADMIN. Si tu operario no es ADMIN, el backend rechaza la operación con HTTP 403 y código ROL_INSUFICIENTE. Verificá tu rol en Configuración. En la cola de sync, los ítems NFC de un operario no-ADMIN se ignoran sin abortar el sync.

TRANSICION_INVALIDA — 'la operación no aplica al estado del tag'

La máquina de estados rechazó la operación porque el tag no está en el estado de origen esperado (HTTP 409). Ejemplos: dar de baja un tag ASIGNADO (hay que desasignar primero), o desasignar/reasignar un tag que no está ASIGNADO. Resolvé el tag primero (GET /nfc/resolver/{uuid}) para ver en qué estado está y qué transición corresponde.

CONFLICTO_ASIGNACION — 'el sanitario ya tiene tag'

El sanitario destino ya tiene un tag ASIGNADO, o el tag no está EN_STOCK (HTTP 409). Solo puede haber un tag asignado por sanitario: desasigná el actual o reasignalo, según corresponda.

TAG_DESCONOCIDO al tapear — 'el tag no registra nada'

Si un operario apoya el celular sobre un tag que no fue dado de alta (whitelist estricta: tag no registrado = inutilizable), el tap genera un trabajo en modo OFFLINE_PENDIENTE_RESOLUCION y dispara una alerta TAG_DESCONOCIDO. La solución es volver al Paso 1 y dar de alta ese UUID.

Auditoría: todo cambio queda registrado

Cada transición exitosa persiste un TagNfcEvento (tabla inmutable). El evento captura el tag, el UUID normalizado, la acción, los sanitarios anterior/nuevo, el operario, el dispositivo, la fecha y las notas. Nada cambia el estado de un tag sin dejar rastro. El detalle completo del modelo de auditoría está en Ciclo de vida de los tags NFC.


Para el contrato completo de los endpoints NFC, ver API HTTP — App móvil · gestión NFC. Para entender la máquina de estados en profundidad, Ciclo de vida de los tags NFC. Si todavía no tenés el backend corriendo para probar esto, empezá por Montar el entorno del backend.