- Changed asset status label from "status" to "technicalStatus" in AssetForm component. - Added help text for technical status in AssetForm. - Updated test cases to reflect changes in asset status from "available" to "operational". - Enhanced workstation form to utilize new asset status checks and display appropriate messages. - Refactored asset context to replace "available" with "notRetired" across various application policies and repositories. - Introduced new utility functions for asset status management, including technical status determination and assignment validation. - Added integration tests for asset state verification and unlinking assets from workstations.
9.7 KiB
Inventario de activos
Uso
La ficha de compañía incorpora la sección Activos. El listado permite buscar por nombre, plantilla, estado o sede. Nuevo activo abre un modal; Editar y Ficha e historial son acciones explícitas. No se muestran formularios junto al listado.
Un activo representa un elemento concreto, identificado mediante UUID v7. Su nombre sirve para reconocerlo (por ejemplo PORT-ANA-01), pero no sustituye al UUID y puede repetirse. La compañía y la plantilla son obligatorias. Sede, notas y características son opcionales salvo los campos marcados obligatorios en la plantilla. La persona se relaciona mediante un puesto de trabajo o un perfil de usuario.
Estados técnicos manuales: Operativo, Averiado, En mantenimiento y Retirado. Un activo operativo se muestra Disponible si ningún puesto activo lo utiliza, o En uso si figura como exclusivo o compartido en uno o varios puestos activos. La asignación se calcula desde la composición, independientemente del responsable. Los puestos inactivos y las revisiones históricas no cuentan como uso vigente. Para retirarlo se exige desvincularlo primero de todos los puestos activos, conservando sede e historial. La eliminación definitiva existente sigue protegida por referencias; no hay transferencia entre compañías.
La sede y la persona pertenecen a la compañía. Solo se permiten nuevas asignaciones a personas activas. Una persona que se desactiva conserva su asignación anterior, para facilitar la revisión y retirada; puede desasignarse. Las personas no reciben acceso a Metis Desk.
Características y plantillas
El alta utiliza una plantilla activa global o propia de la compañía. Se captura una copia de su nombre, campos, tipos, unidades, valores de lista y obligatoriedad. La plantilla del activo queda fija. Cambiar o desactivar la definición del catálogo no cambia las fichas ni las revisiones existentes. Un activo existente sigue siendo editable aunque su plantilla se desactive.
Esta decisión evita que una edición del catálogo elimine características o convierta datos ya guardados en inválidos. Las nuevas características y opciones incorporadas posteriormente a una plantilla se aplican a los nuevos activos. La adaptación de fichas existentes a futuras versiones queda fuera de esta entrega.
Se validan texto, número, fecha real, sí/no y lista. No se aceptan campos ajenos a la especificación, tipos incorrectos ni opciones de lista desconocidas. Los valores cero y falso se conservan y satisfacen la obligatoriedad; un campo sin completar se omite. No se almacenan contraseñas mediante este catálogo.
Alta rápida y ayuda
Plantilla y sede reutilizan SelectWithAction. El botón «+» abre un modal adicional; guardar selecciona el elemento creado sin perder los datos del activo y cancelar conserva el formulario principal. La nueva plantilla es exclusiva de esa compañía.
Solo se permite un nivel de alta adicional: al crear una plantilla desde el activo se seleccionan campos existentes, sin abrir un tercer modal de alta de campo. Los elementos guardados permanecen aunque después se cancele el activo. El modal explica este comportamiento. Los estados y las opciones de una característica son valores cerrados para esa ficha.
La ayuda aparece inmediatamente antes de Guardar y Cancelar. Los formularios amplios tienen desplazamiento y conservan navegación por teclado. La fecha se confirma al introducirla y se conserva al actualizar otros campos o cancelar un alta relacionada.
Historial y arquitectura
Asset es la raíz de consistencia de cada activo. AssetRevision conserva una instantánea completa de cada cambio con UUID propio, actor autenticado y fecha UTC. AssetValues y AssetSpecification son Value Objects inmutables con igualdad semántica. Las referencias se reconstruyen como UniqueID; Name representa los nombres.
El alta crea una primera revisión. Cambiar datos, estado, sede o características añade una revisión, conservando la identidad del activo y las revisiones anteriores. Guardar los mismos valores normalizados no crea otra revisión. La ficha muestra todas las revisiones y sus valores, no solo un contador.
Las migraciones explícitas crean assets y asset_revisions, con claves foráneas para compañía, plantilla, sede, persona y actor; las revisiones también conservan las referencias de sede y persona. Infrastructure reconstruye y comprueba identidades, tipos, historial y pertenencia. No regenera identificadores ni sustituye datos corruptos.
Las escrituras son transaccionales, bloquean catálogo y compañía en un orden fijo y guardan únicamente revisiones nuevas. El repositorio valida la pertenencia de referencias y el ámbito del activo. Las operaciones se mantienen en domain, application e infrastructure; Sequelize queda en Infrastructure.
GET /api/assets/:companyId consulta el inventario. POST /api/assets/:companyId y POST /api/assets/:companyId/:id/update crean y editan. Todas requieren sesión; las escrituras usan origen y CSRF. El actor procede de la sesión, nunca del cuerpo enviado por el navegador.
Validación y siguientes entregas
Las pruebas verifican características opcionales y obligatorias, tipos, fechas, cero y falso, UUID, igualdad semántica, aislamiento por compañía, historial, desactivaciones, rehidratación y protección de las escrituras. La comprobación en navegador incluye alta rápida, cancelación, conservación de fechas y consulta del historial.
Las relaciones entre activos están disponibles en ambas fichas. Los puestos de trabajo están disponibles como agrupaciones sin anidación. Los perfiles y sus configuraciones están implementados, así como la autorización de teletrabajo. La conectividad remota, el registro mínimo de equipos personales y los procesos de salida mantienen su orden en el plan.
La ficha de cada activo, incluida su vista lateral, incorpora Asistencia técnica remota: varios métodos, catálogo de herramientas, preferido opcional e historial.
Marca del activo
El campo de serie Marca se selecciona desde el catálogo global de marcas, con alta rápida. Continúa siendo opcional por defecto. AssetValues guarda una referencia UUID opcional y la característica conserva el nombre como instantánea en cada revisión. Las marcas inactivas existentes y los textos anteriores se mantienen; la importación no reescribe fichas ni historial.
Persistencia relacional
Los puestos de trabajo y la asistencia técnica se almacenan también de forma relacional, conservando sus revisiones. Véase normalización de la persistencia.
Estado técnico, asignación y elegibilidad
values.status en la API representa el estado técnico. assigned y displayStatus son datos calculados al construir las respuestas de alta, edición y consulta; no se persisten como columnas. Listados, búsqueda, ordenación y fichas muestran displayStatus. El formulario solo ofrece estados técnicos y explica la distinción.
assetTechnicalStatus, assetDisplayStatus y canAssignAsset son funciones puras pequeñas del dominio. La selección de activos del puesto reutiliza la regla de asignación y muestra por qué un elemento está bloqueado. Una nueva asociación a un puesto activo, o su reactivación, requiere un activo Operativo. Las reservas exclusivas y compartidas mantienen sus restricciones y bloqueos transaccionales. Una asociación existente puede conservarse al editar un puesto si su activo se avería o entra en mantenimiento; cambiarlo de exclusivo a compartido o viceversa se considera una nueva asociación.
Una avería o mantenimiento no borra asignaciones, perfiles ni software, y prevalece visualmente sobre En uso. Se conserva la información del puesto para organizar la reparación. Al recuperar Operativo vuelve a mostrarse En uso si sigue asignado. Al dar de baja/eliminar un puesto o retirar un miembro se recalcula el uso; un activo compartido permanece En uso mientras otro puesto activo lo utilice. Un activo averiado o en mantenimiento conserva su estado al liberarse.
El servicio de inventario exporta notRetired, en sustitución del booleano genérico available. Perfiles, software, correo, impresoras, certificados, accesos remotos, procesos y consultas de soporte utilizan ese contrato explícito. Se conserva su criterio para registrar configuraciones: no retirado no significa libre ni operativo. La creación/activación de un perfil mantiene además los requisitos de persona y ordenador principal de un puesto activo. Las configuraciones existentes y sus avisos siguen documentando preparación/retirada manual, sin simular operaciones sobre equipos.
La persistencia conserva los códigos originales Disponible/En uso en los registros existentes y sus revisiones. Se interpretan como estado técnico Operativo al consultar la situación actual; no se inventan asignaciones ni se reescribe el historial. Las nuevas entradas HTTP solo aceptan los cuatro estados técnicos. Una consulta y un guardado semánticamente equivalente no añaden revisiones de normalización. El mapper sigue comprobando que el estado original de raíz y última revisión coincida. La restricción SQL se amplía idempotentemente para admitir los nuevos estados, preservando la lectura de los registros originales; no se añade JSON ni nuevas columnas de estados calculados.
Pruebas de reglas puras, elegibilidad exclusiva/compartida, historial e idempotencia, uso compartido por varios puestos, avería/reparación conservando asignaciones, bloqueo de nuevas asociaciones, retirada con referencias activas, liberación por baja/eliminación y respuestas HTTP/MariaDB. Los escenarios de retirada en las pruebas desvinculan primero los puestos, como exige el nuevo comportamiento.