Ir al contenido
Portal de documentación del EGD
Menú de la sección

Formulario «Nuevo / Editar documento»

Carpeta: app/src/app/dashboard/documentos/administrativos/nuevo/. Estado (2026-10-09): el formulario es el compacto de Ccirhack (main/ccirhack): tarjetas pequeñas en dos columnas (texto de 10–12 px, campos de 28 px, field-styles.ts) con Destinatarios a todo el ancho, que cabe en una vista; la cabecera usa botones propios (BASE_BTN) en una fila.

Se revirtieron, a petición del equipo, los rediseños propuestos por Frontend para este formulario (cabecera con StatusBar, campos subrayados con etiqueta flotante, tarjetas por fila con SortableCardRow, secciones contraíbles, panel único). Siguen disponibles en el historial de Git (commits 1f552d6d y 8ca006d9) si se retoma la discusión. No se aplica a este formulario la regla de app/AGENTS.md sobre campos subrayados (FloatingUnderline*): queda pendiente de decidir con el equipo si se unifica.

Funcionalidad (de Ccirhack)

  • Nuevo (NewDocumentForm sin documentId): «Grabar» crea el documento y navega a …/[id]/editar. Editar (con documentId): carga el documento, «Grabar» solo se habilita si hay cambios (isDirty) y el documento es borrador.
  • Emisión personal (NewDocumentForm isPersonal, rutas documentos/personales): el remitente muestra Dependencia, Local/Sede/Agencia y «Firmado por» (uno mismo, sin jefe), se crea con isPersonalEmission y vuelve al listado de personales. «Responder» desde Recepción abre «Nuevo» con ?refId= y precarga esa referencia. Firmar solo se habilita al firmante del documento (currentUserId); si no lo eres, el botón explica «Solo el jefe de la oficina puede firmar este documento».
  • Remitente: en «Nuevo», la oficina activa y el usuario de la sesión; en «Editar», el autor y la oficina grabados del documento (documentAuthorName/documentOfficeName).
  • Cabecera (20-oct-2026, solo interfaz; la lógica no cambió): el estado es un recorrido de cuatro píldoras «En proyecto | Para despacho | Firmado | Emitido» («Para despacho» es cuando el documento espera la firma del jefe y los vistos buenos, y hasta que se firma todavía puede regresar a proyecto; los estados posteriores de recepción reemplazan a «Emitido»). Mientras el documento está en proyecto el conjunto de botones es fijo y en el mismo lugar —Grabar, Generar, Cargar, Abrir, Cargar anexos y «Enviar a despacho»— y los que aún no aplican se ven apagados (borde discontinuo, aria-disabled) sin texto debajo: el motivo sale en el tooltip compartido (al instante con foco de teclado) y se anuncia como descripción; el botón de color es el paso que toca (grabar → generar → cargar el PDF → enviar a firma). Una vez generado el documento, «Generar» pasa a ser «Editar» (abre el Word) y su flecha solo ofrece «Regenerar» (un botón del mismo ancho que «Editar» con su flecha; el aviso de confirmación sigue diciendo «Volver a generar»), con confirmación porque reemplaza el Word editado. «Volver» es una flecha sin texto a la izquierda del título («Volver a documentos administrativos» o «…personales», que llevan al listado de la tabla). La primera fila reúne la flecha, el título y las píldoras (a la derecha); los botones van en la fila siguiente y solo suben a la primera cuando el ancho del contenedor supera 1750 px. «Anular» está en el menú «Más». «Regresar a proyecto» es un botón (antes, la píldora «En proyecto»). Fuera de borrador: «Firmar» (con candado y el motivo si falta algo, p. ej. vistos buenos pendientes), «Ver documento», «Ver anexos» (apagado si el documento no tiene anexos). Vistos buenos (20-oct-2026): lista de texto —nombre y dependencia, estado «Pendiente»— con asa y flechas para reordenar; el lápiz abre la fila para cambiar dependencia y personal («Listo» / «Cancelar»); «Agregar visador», «Uno a uno» y «Agregar grupo» (panel con selector de grupo); estado vacío con explicación; interruptor «Con orden». Comportamiento completo en docs/manual-usuario/documento-administrativo.md. Referencias y observación interna (20-oct-2026): Referencias pasa de una tabla de 10 a 11 px a una lista (tipo y número, fecha, etiqueta Emitido o Recibido, y las acciones ver documento, ver anexos y quitar) con estado vacío explicativo y la nota de que el expediente se hereda del primer documento; Observación interna lleva el aviso «Solo tu oficina la ve» en el encabezado y el contador de caracteres (máximo 2000). Destinatarios (20-oct-2026): el tipo es un control segmentado «Oficinas | Persona jurídica | Ciudadano | Otros» (equivale a «Institución» en el manual v5.1); «Agregar grupo» (panel con selector) y «Agregar destinatario» arriba a la derecha, sin el botón del pie de la tabla; bloque «Aplicar a todos los destinatarios» con un solo botón; tabla con texto de 12 px, número en círculo y estado vacío explicativo; ayudas breves. Comportamiento en docs/manual-usuario/documento-administrativo.md. Remitente (21-oct-2026): datos de solo lectura con icono e iniciales (no campos deshabilitados), candado «Datos de tu sesión y de la oficina»; en el administrativo se agrega Firmado por (quien dirige la oficina, con su cargo; «Sin encargado asignado» si no hay), con la misma consulta de encargatura vigente de Destinatarios; en el personal, Dependencia, Local/sede/agencia y Firmado por («Tú»). Expediente, N.º de emisión y Documento (21-oct-2026): campos de 36 px y texto de 13 px; obligatorios con asterisco rojo en la etiqueta (no en el título de la tarjeta); ReadOnlyData (nuevo/readonly-data.tsx) muestra los datos de solo lectura con icono, etiqueta pequeña y valor (Remitente, Fecha, expediente heredado y número de emisión), con candado y motivo en el encabezado cuando no se pueden cambiar; aviso de «sin series asignadas» con icono; «Elige primero la serie» en el expediente; «Atender en» con el sufijo «días». Opciones del documento (21-oct-2026): «Documento reservado» pasa a «Acceso restringido» (casilla con una línea de ayuda: solo quienes participan ven el detalle en el seguimiento) y «Con orden» de Vistos buenos también es casilla: ambas son opciones que se guardan con el documento y se muestran como casillas, para que se lean igual que el resto de las opciones del formulario (el Design System admite también el interruptor al guardar). Espaciado del formulario (21-oct-2026, Design System): una sola medida de 16 px para todo el espacio exterior del formulario (arriba, a los costados y abajo, entre tarjetas en vertical, entre las dos columnas y entre la cabecera y la primera tarjeta; el contenedor de la página aporta 16 px arriba y abajo y el margen lateral se fija a 16 px), y el contenido de cada tarjeta con un margen interno de 12 px, el mismo del título, de modo que iconos, etiquetas y campos queden alineados con el encabezado; 12 px entre campos de la tarjeta Documento y 10 px en Expediente y Remitente. No añadir márgenes laterales propios a los textos de ayuda dentro de una tarjeta. Cabecera en tarjeta (21-oct-2026): en una tarjeta (sgd-panel, como las demás, con el margen del contenido y no de borde a borde) que se desplaza con el contenido, con dos zonas separadas por una línea —arriba la identidad con el estado en flechas a la derecha, debajo las acciones— con flechas de estado finas (28 px de alto y texto de 13 px); el espacio superior es el de los costados (24 px): fila de ruta (botón «Nuevo» solo con el documento grabado, con confirmación si hay cambios sin grabar; enlace al listado; título con el número del documento y menú ⋮ con «Anular») y fila de acciones con el recorrido de estado en flechas a la derecha (reemplaza las píldoras). Sustituye a la flecha «Volver» y al menú «Más» de la fila de botones. Pendiente: «Solicitar vistos buenos» desde «Para firma» (el servidor solo permite aprobar, observar y anotar un visado ya pedido), fila de ruta con contador de anexos y paso al documento anterior o siguiente.
  • Acciones de la cabecera (anterior): Generar Doc. (con «Editar Docx» en su menú ▾), Cargar Doc., Abrir Doc., Cargar Anexos / Ver (modal anexos/attachments-modal.tsx) y Anular (no implementado). Con el documento ya fuera de borrador (en despacho, trámite "Para Despacho"): desaparece «Grabar», el cuerpo queda inerte y atenuado, y aparece «Firmar Doc.» (abre SignDocumentDialog con el PDF final, onEmit valida/sube/emite -- ver app/docs/components/firma-digital.md; es un botón simple, sin menú ▾; «Ver documento» abre el PDF y no hay «Abrir Docx»: en despacho no se edita, para editar se usa «Regresar a proyecto»). Con el documento ya Emitido (trámite "Emitido"), la cabecera se reduce a solo «Ver Documento» y «Cargar Anexos / Ver» -- ni «Firmar Doc.» ni «Anular» tienen sentido sobre un documento ya firmado y emitido; el estado EN PROYECTO/EMITIDO sigue igual.
  • Etiquetas del botón de anexos (23-oct-2026): «Cargar anexos» en proyecto y «Ver anexos» (ícono de ojo) fuera de borrador; AttachmentsModal recibe title («Cargar anexos» / «Anexos del documento»). El tooltip dice «Clic para cargar anexos» o «Clic para ver los anexos» y, sin anexos en proyecto, «Aún no hay anexos…».
  • Lote del 23-oct-2026: sin tarjeta «N.º de emisión» (la cabecera dice «El N.º de emisión se asigna al grabar» hasta grabar); SectionCard admite required (asterisco + «(obligatorio)» oculto) y Destinatarios lo usa; EntityPickerDialog usa un alto de lista clamp(20rem, 100dvh − 18rem, 36rem); «Ver anexos» queda activo con referencias aunque no haya anexos propios; la cabecera lleva un botón «Copiar número del documento» junto al número.
  • Ventana de anexos: especificación completa (estructura, acciones, selección y eliminación de varios, casuísticas, pendientes) en anexos.md.
  • Firma de anexos por el jefe (25-oct-2026): con anexos «Requiere firma» sin resolver, «Firmar»/«Emitir» del documento se bloquea con «Faltan N anexos por firmar» y «Ver anexos» se resalta con «N por firmar»; el firmante resuelve cada uno en la ventana de anexos (signerMode). Detalle en docs/components/anexos.md y en el manual.
  • Anexos fuera de borrador: AttachmentsModal recibe readOnly (!isDraft acá; en la bandeja de Emisión, doc.status !== "draft"; en Recepción, siempre) -- el modal sigue abriéndose para consultar los anexos ya cargados, pero oculta «Agregar archivo(s)» en vez del botón. El backend también lo exige (UploadAttachments devuelve ErrDocumentReasonForbidden si el documento no está en draft): la UI no es la única barrera.
  • Estado del trámite (tramitStatusName): «EN PROYECTO» | «PARA DESPACHO» (pasa a despacho con dispatchDocument) | «EMITIDO» | otros estados de recepción como paso único. El autor puede regresar a «En proyecto» desde «Para despacho» o «Emitido» (revertDocument, con confirmación: limpia vistos buenos y firma). La firma emite el documento (emitDocument, onEmit de SignDocumentDialog).
  • Secciones: Expediente (solo lectura, se hereda de la primera referencia), Emisión (número), Remitente, Documento (tipo filtrado por oficina, asunto, fecha, plazo, reservado), Vistos Buenos, Referencias, Observación Interna y Destinatario (tablas con selectores en diálogo).
  • Los datos que se envían (createDocument/updateDocument) no dependen del diseño.

Documento en solo lectura (24-oct-2026; datos como texto desde el 25-oct-2026)

Fuera de «En proyecto» el formulario no se edita, pero tampoco se bloquea con inert (ocultaba los datos a los lectores de pantalla y no dejaba seleccionarlos ni copiarlos). Regla (25-oct-2026): una caja de entrada promete que se puede escribir; si no se puede, no debe parecer caja. Por eso los datos de las tarjetas se muestran como texto (icono, etiqueta y valor, ReadOnlyData, el mismo patrón de «Documento recibido»), y los controles que quedan (tablas de destinatarios y vistos buenos) pierden borde y fondo. El cuerpo se envuelve en FormReadOnlyProvider (ui/form-read-only.tsx):

ElementoEn solo lectura
Tarjeta «Documento»ReadOnlyData: Tipo de documento, Asunto (completo, respeta los saltos de línea), Fecha (la de emisión o creación, no la de hoy), «Atender en» («5 días» o «Sin plazo» atenuado) y «Acceso restringido» («Sí…» o «No»). Sin asteriscos, contador, flecha ni casilla. Insignia «Solo lectura» con candado en la cabecera. El nombre del tipo lo pide useReadOnlyDocumentType, que también avisa al formulario del tipo resuelto (encabezado y barra de acciones).
«Observación interna»La nota como texto, o «Sin observación interna» atenuado.
«Con orden» (vistos buenos)«Con orden: sí» o «Con orden: no».
Input, TextareareadOnly automático (enfocables, legibles, copiables) y, por CSS ([data-form-readonly]), sin borde, sin fondo y sin sangría: se leen como texto. Una propiedad readOnly explícita manda sobre el contexto.
Checkboxaria-readonly="true" y no cambia; se anuncia con su estado.
SearchableCombobox (listas de opciones)Campo readOnly con la selección, sin abrir la lista y sin chevron.
EntityPickerDialog (dependencia, personal, trámite, prioridad en destinatarios)Se muestra como campo de texto de solo lectura, sin diálogo de búsqueda.
Acciones de las seccionesSe ocultan con useFormReadOnly(): «Agregar visador/grupo», «Uno a uno», «Limpiar», asa y flechas de orden, editar y quitar visador; «Agregar» y «Quitar» referencia; «Agregar destinatario/grupo», «Aplicar a todos», eliminar fila y las pestañas de tipo (queda «Tipo: Oficinas»).
«Indicaciones» de un destinatarioAl hacer clic abre la ventana para leer el texto completo (campo de solo lectura, botón «Cerrar», sin «Guardar»).
AvisoUna línea al inicio del cuerpo: «Este documento ya no está «En proyecto», por eso solo se puede consultar.»

Reglas:

  1. DialogContent reinicia el contexto: una ventana abierta desde la zona (anexos, indicaciones) conserva sus propios controles. Quien necesite el valor dentro del diálogo lo lee fuera de él con useFormReadOnly().
  2. La barra de acciones, el motivo de «Observado» y el botón «Regresar a proyecto» quedan fuera del proveedor y siguen activos.
  3. Sin atenuar el cuerpo (antes 90 % de opacidad): el texto conserva su contraste pleno y las etiquetas van en el gris secundario. El contenedor se anuncia como grupo «Datos del documento (solo lectura)».
  4. Foco: los campos de solo lectura (data-form-readonly) conservan un foco visible con teclado (2.4.7), pero neutro: borde de 2 px en el color del texto, sin el azul ni el halo de los campos editables; tras un clic o toque (data-input-modality="pointer") no se dibuja, y el cursor es normal (las «Indicaciones», que abren una ventana de lectura, conservan la mano). Así un campo enfocado no parece editable.
  5. Un control nuevo que se edite en este formulario debe leer el contexto (o usar Input, Textarea, Checkbox o los selectores compartidos); si no, quedaría editable.

Documento recibido (revisión de Recepción, 24-oct-2026)

La pantalla recepcion/[id]/recepcion-review-content.tsx usa el mismo lenguaje visual que el formulario de emisión (antes tenía cabecera y campos de otra época: botones de 13 px, cajas grises y texto de 12 px).

  • Cabecera: tarjeta sgd-panel, igual que la del formulario de emisión. Arriba a la izquierda, la ruta «Recepción de documentos › Documento recibido» (el primer tramo vuelve a la bandeja; reemplaza al botón «Volver») y debajo el título Tipo N° número (h1 de 16 px, recortado si no cabe) con, a su derecha, el icono de copiar el número (CopyNumberButton, compartido con el formulario) y el menú ⋮ con Anular (solo cuando hay algo que anular; ya no es un botón de la fila de acciones). A la derecha de la fila, el recorrido de estado en flechas (StatusSteps, src/components/user/status-steps.tsx, compartido con el formulario) con los estados de la copia: Pendiente › Recibido › Atendido › Archivado; Observado y Anulado cierran el recorrido con su paso (Pendiente › Recibido › Observado; Pendiente › Anulado) y Archivado omite Atendido, que es opcional. En pantallas angostas el recorrido se desplaza dentro de su contenedor (enfocable con teclado). Debajo, la fila de acciones con los botones compartidos (Action, src/components/user/toolbar-action.tsx): Recibir, Ver documento, Ver anexos y Responder.
  • Ver anexos con contador (24-oct-2026), una sola implementación: el contador ya existía en el formulario de emisión (attachmentNames → Action items); no se duplicó. Su lectura se extrajo a useAttachmentNames (src/features/documents/use-attachment-names.ts: lee al abrir y al cerrar la ventana de anexos, con onIncrease para el aviso «El documento tiene N anexos» del formulario) y el botón con sus reglas a ViewAttachmentsAction (src/components/user/view-attachments-action.tsx: insignia verde con la cantidad y tooltip con los nombres; apagado sin anexos ni referencias, «Este documento no tiene anexos ni referencias»; con referencias avisa «Sin anexos propios. Clic para ver los de las referencias»; reason fuerza otro motivo, p. ej. «Graba el documento primero»). Lo usan el formulario de emisión, «Documento recibido», la revisión de visto bueno y la edición de Mesa de partes (que ya trae sus anexos en la solicitud, por eso no usa el hook). Una pantalla nueva con «Ver anexos» debe usar estas dos piezas, no volver a leer ni a escribir las reglas. Los anexos de las referencias también cuentan: «Ver anexos» no se apaga por no tener anexos propios si el documento tiene referencias, porque la ventana de anexos muestra además los de cada documento referenciado; solo se apaga sin anexos ni referencias.
  • Catálogo vivo (/design-system/componentes › «Cabecera de un documento», document-header-showcase.tsx): muestra la tarjeta completa con su recorrido (en curso y archivado con cinta), los cuatro estados de «Ver anexos» (con anexos propios, cargando o sin lectura, sin anexos pero con referencias, sin anexos ni referencias), copiar número, logo institucional y la insignia del visto bueno propio, con las reglas. Un cambio en cualquiera de estas piezas se refleja y se documenta ahí.
  • Piezas compartidas de la cabecera: StatusSteps (recorrido en flechas), CopyNumberButton (copiar el número), el menú ⋮ con Anular y Action/ViewAttachmentsAction. En pantallas angostas Action deja solo el icono pero conserva el nombre accesible (max-sm:sr-only; antes hidden lo quitaba y los botones quedaban sin nombre).
  • Cinta: Archivado y Anulado muestran además la cinta de estado en la esquina (ver cinta-estado.md); la primera fila reserva su esquina y el recorrido se desplaza a la izquierda de la cinta, como en el formulario.
  • Cuerpo: una sola medida de 16 px entre tarjetas, dos columnas desde lg. Los datos son ReadOnlyData (icono, etiqueta y valor; el asunto y las observaciones respetan los saltos de línea con multiline), no cajas grises. «Referencias» (ReferenceListCard) usa las mismas filas que la tarjeta del formulario (icono, nombre, fecha, Emitido o Recibido, «Ver documento» y «Ver anexos»), sin «Quitar». «Destinatario» lista cada destino con su insignia; el propio se resalta.
  • Observar o archivar (antes «Atención / Archivar»; «Atención» no correspondía: el panel no tiene ninguna acción de atender y su título mezclaba un sustantivo con verbos): dos paneles, «Observar» y «Archivar», sin título propio: el botón de abajo ya lleva ese nombre y repetirlo como encabezado duplicaba la etiqueta (cada panel es un role="group" con su nombre accesible; los campos se distinguen por «Motivo de la observación» / «Motivo del archivamiento» y «Fecha de observación» / «Fecha de archivamiento»). La obligatoriedad se marca como en el resto de formularios, con asterisco rojo en la etiqueta del campo obligatorio (el motivo de la observación; aria-required) y sin asterisco ni el texto «(opcional)» en el opcional (el motivo del archivamiento). Los campos son los normales del sistema (los mismos del formulario de emisión), no los de subrayado: etiqueta arriba con FieldLabel (components/admin/field-label.tsx, con el contador de 2000 caracteres a la derecha), Textarea con borde y, para las fechas, DateField (components/ui/date-field.tsx: se escribe dd/mm/aaaa con las barras automáticas o se elige en el calendario propio del sistema, botón de la derecha o Alt + ↓; no el calendario nativo del navegador), con la fecha máxima de hoy. «Observar» usa el botón de contorno de peligro y se habilita con una observación y una fecha válida; «Archivar» usa el botón principal y se habilita con una fecha válida (una fecha incompleta o inexistente muestra su error bajo el campo y apaga el botón, en lugar de enviar la del servidor). La observación de la revisión de visto bueno usa el mismo FieldLabel + Textarea. Los campos de subrayado con etiqueta flotante quedan solo para donde el formulario de emisión ya los usa.
  • Texto de ayuda dentro del campo (placeholder): da un ejemplo entendible, no repite la etiqueta («Escribe el motivo…» bajo «Motivo de la observación» no aporta). Observar: «Por ejemplo: falta adjuntar el informe técnico firmado.»; Archivar obligatorio: «Por ejemplo: duplicado, no corresponde a la oficina.»; Archivar opcional: «Por ejemplo: se respondió con el oficio adjunto.»; observación de visto bueno: «Por ejemplo: falta el cuadro comparativo de costos.»
  • Regla de la observación al archivar (decisión del 24-oct-2026): Observar exige el motivo siempre (el remitente necesita saber qué corregir). Archivar exige el motivo solo si el documento no se atendió (estado Pendiente, Recibido u Observado: se cierra sin respuesta y debe quedar escrito por qué, p. ej. «duplicado» o «no corresponde a la oficina»); con el documento ya Atendido el motivo es opcional. No se encontró una norma peruana que obligue a registrarlo; se decidió por trazabilidad. Front: la etiqueta «Motivo del archivamiento» lleva asterisco rojo y aria-required, el campo propone un ejemplo, sin texto de ayuda adicional (el asterisco basta), y el botón «Archivar» se apaga sin motivo. Back: ArchiveDocument devuelve ErrArchiveReasonRequired («indica el motivo del archivamiento: el documento no se atendió», HTTP 422) con la función ArchiveReasonRequired(estado), probada; además el texto de solo espacios cuenta como sin observación (se guarda nulo). La columna NOTES sigue admitiendo nulos: la regla vive en el front y el back.
  • Un documento solo se modifica «En proyecto» (validado en front, back y base de datos, 24-oct-2026). Front: fuera de «En proyecto» el formulario queda en solo lectura (FormReadOnlyProvider), las secciones ocultan agregar, quitar y reordenar, y la ventana de anexos abre en solo lectura (sin agregar, eliminar ni marcar firma). Back: UpdateDocument, UploadAttachments, BringAttachment, ToggleAttachmentSignature y SignAttachment ya exigían el estado draft; se detectaron y corrigieron tres operaciones que solo estaban protegidas por la interfaz: GenerateDocx, LoadDoc (cargar el PDF o el DOCX, que reemplazan los archivos del documento) y DeleteAttachment (ni siquiera consultaba el documento). Las tres devuelven ErrDocumentReasonForbidden (HTTP 403) fuera de «En proyecto». Prueba draft_only_test.go (cada operación rechazada en Pendiente de visto bueno, Firmado, Enviado y Anulado; eliminar un anexo en proyecto sí funciona); sin la corrección, la prueba falla. Base de datos: no hay restricción que lo imponga (el CHECK de STATUS solo limita los valores permitidos); la regla vive en el back. Cambios que no son de edición del documento (visto bueno, firma y emisión, recepción, anular, eliminar un documento anulado, regresar a proyecto) tienen sus propias reglas de estado. Pendiente: una prueba que recorra también UpdateDocument con un fake completo.
  • Mínimo del motivo (24-oct-2026): un motivo de observación o de archivamiento debe tener al menos 5 caracteres sin contar espacios («Duplicado» pasa, una sola letra no). Aplica a Observar (siempre), a Archivar (si es obligatorio, y si es opcional solo cuando se escribe algo) y a la observación del visto bueno. Front: el botón se apaga hasta llegar al mínimo y, solo si ya se empezó a escribir, ReasonHint avisa «Faltan N caracteres.» (components/ui/reason-hint.tsx, con reasonMissing y MIN_REASON_CHARS de lib/reason.ts). Back: ReasonTooShort / MinReasonChars (document/app/document/reason.go, probados) y ErrReasonTooShort (HTTP 422) en Observar, Archivar y observar un visto bueno; las notas en borrador del visto bueno («Guardar nota») no se validan.
  • Recorrido de estado, Observado y Anulado en rojo (24-oct-2026): el paso actual es alerta (rojo con icono de error) cuando el estado pide acción o cerró mal: Observado (hay que levantar la observación) y Anulado. Aplica al formulario de emisión (trámite Observado o Anulado), «Documento recibido», la revisión de visto bueno y Mesa de partes. El resto de estados siguen con el paso actual de color.
  • Observación de Observar y de Archivar: obligatoria u opcional (revisado en front, back y base de datos, 24-oct-2026): Observar exige la observación (front: el botón se apaga sin texto; back: ObserveDocument devuelve ErrReceptionNoteRequired, «la observación es obligatoria», que se responde como error de validación; la regla vive solo en el back y el front, la columna no la exige). Archivar no la exige en ninguna capa: el front la deja sin asterisco (el campo opcional no lleva «(opcional)», como el resto de formularios), no apaga el botón y envía notes solo si hay texto; ArchiveDocument no valida Notes; y en la base de datos TRS_DERIVATION.NOTES admite nulos (CLOB en Oracle, text en PostgreSQL, sin longitud máxima). Observaciones: (1) NOTES es una sola columna para Observar y Archivar y UpdateStatus solo la escribe si llega texto, así que archivar sin observación conserva la observación anterior de Observar y esa nota aparece después como «Observación» del estado Archivado; (2) el límite de 2000 caracteres existe solo en el front (el back y la columna no lo limitan); (3) un texto de solo espacios al archivar se guarda tal cual; (4) la fecha (at) es opcional en el back (sin ella usa el momento actual), no se valida contra el futuro y una fecha mal escrita se ignora sin error: por eso el front ahora exige una fecha válida.
Estado de la copiaRecibirVer documento / anexosResponderAnularObservarArchivar (motivo)Cinta
No leídoPrincipalSíApagado: «Recibe el documento antes de responder»Apagado: «Aún no recibiste el documento»SíSíNo
RecibidoApagado: «Este documento ya fue recibido»SíSíSíSíSíNo
AtendidoApagadoSíSíSíNoSíNo
ObservadoApagadoSíSíSíSíSíNo
ArchivadoApagadoSíSíSíNoNo«Archivado»
AnuladoApagadoSíSíSíNoNo«Anulado»

(La disponibilidad de «Observar», «Archivar» y «Anular» no cambió: sale de canObserve, canArchive y canUndo.) En pantalla de celular las acciones muestran solo el icono con su nombre accesible, la insignia pasa bajo el título y no hay desborde horizontal.

Bandejas. En «Recepción de documentos» y las bandejas que comparten su menú (No leídos, Recibidos y Delegados), el N.º de emisión de cada fila es un enlace que abre esta pantalla (la misma a la que lleva «Ver detalle»), también en la vista de tarjetas. Se configura con linkNumberTo de DocumentsEmissionTable; en Administrativos y Personales el enlace usa linkNumber y lleva al formulario (/editar).

Revisión de visto bueno (24-oct-2026)

La pantalla vistos-buenos/[id]/vb-review-content.tsx sigue el mismo patrón que «Documento recibido» (antes: barra pegada arriba, botones de 12 px en negrita, cajas grises y texto de 10 a 12 px). Solo cambia la presentación; las reglas de qué se puede hacer (canAct, blockedByOrder) y las llamadas al servidor no cambian.

  • Cabecera: tarjeta sgd-panel. Ruta «Vistos buenos › Revisión de visto bueno» (el primer tramo vuelve a la bandeja y reemplaza a «Volver»), título Tipo N° número y, a la derecha, la insignia del visto bueno de quien revisa en tipo oración: «Sin VB» (aviso), «Con VB» (éxito) u «Observado» (error). Debajo, los botones compartidos (Action): Guardar nota (antes «Grabar»; guarda solo la nota de observación en borrador), Visar documento (el paso que toca, de color), Ver documento y Ver anexos. Los atajos se conservan: G, M, A, X y O.
  • Botones apagados con motivo: los que no aplican quedan apagados (borde discontinuo, sin ejecutar la acción) y explican el motivo en el tooltip y como descripción: «Este documento ya no admite vistos buenos», «Ya diste tu visto bueno» o «Espera a que los revisores anteriores den su visto bueno».
  • Cuerpo: una sola medida de 16 px entre tarjetas. Izquierda: Expediente, Remitente, Documento (ReadOnlyData) y Referencias (ReferenceListCard). Derecha: Vistos buenos, Tu observación y Destinatario. La tarjeta «Emisión» ya no existe: el número es el título de la cabecera.
  • Vistos buenos: el avance escrito («1 de 3 vistos buenos aprobados»; la concordancia sigue al total), lo que falta en una línea de ayuda (se quitó la barra de avance: con el avance escrito y las insignias de cada fila se veía cargado) con countLabel («2 pendientes · 1 observado», sin mostrar los ceros; no se repiten insignias porque cada fila ya lleva la suya) y la lista de revisores con su oficina y la nota si la dejaron. La propia fila se resalta y lleva «(tú)». Con orden se muestra #n y la nota «Con orden: los vistos buenos se dan en el orden de la lista».
  • Tu observación (solo si quien abre la pantalla es revisor): FloatingUnderlineTextarea con contador de 2000 caracteres; «Observar» usa el botón de contorno de peligro y se habilita con una nota escrita; «Anular observación» aparece si ya observó. Los avisos («Este documento ya no admite vistos buenos», «Ya diste tu visto bueno», «Espera a que los revisores anteriores…») salen sobre el campo, con icono.
CasoGuardar notaVisar documentoObservarAviso y otros
Sin visto buenoSíPrincipalSí, con nota escrita—
Con visto buenoApagado: «Ya diste tu visto bueno»Apagado: igualApagadoInsignia «Con VB»; nota de solo lectura
ObservadoSíPrincipal (se puede visar tras anular)Sí«Anular observación» sobre la nota
Espera su turno (con orden)SíApagado: «Espera a que los revisores anteriores den su visto bueno»ApagadoAviso sobre la nota
Documento fuera de revisiónApagado: «Este documento ya no admite vistos buenos»Apagado: igualApagadoAviso sobre la nota; Ver documento y Ver anexos siguen activos

Verificación

Reordenación accesible (lote 1, 15/10/2026)

Destinatarios y Vistos Buenos conservan sus tablas compactas. Ambos reutilizan ui/row-reorder-controls.tsx: asa con nombre contextual, sensores Pointer/Keyboard de dnd-kit y botones Subir/Bajar de 24 px. Espacio/Enter inicia y confirma el arrastre por teclado, las flechas mueven y Escape cancela. Los botones cubren el uso con clic/toque sin arrastrar (2.5.7, independiente de 2.1.1). Al mover se enfoca el asa en su nueva posición; las instrucciones y anuncios están en español. El ejemplo de /design-system/componentes#a11y-heading usa el mismo control, sin datos reales.

destinatario/constants.ts centraliza reorderRecipients: solo reordena el tipo visible, conserva datos y posiciones de otros tipos y mantiene la regla existente ORIGINAL/COPIA por puesto en Oficinas. Prueba de regresión: desde app, node --test scripts/reorder-recipients.test.mjs (Node 24, soporte de tipos TypeScript). Cuatro casos ejecutados correctamente. La validación de interacción/foco en navegador, seis apariencias y NVDA sigue pendiente; no declarar cerrado N2 solo por las pruebas del modelo.

Verificación histórica (09/10/2026)

2026-10-09, navegador integrado con una página temporal (retirada): el formulario carga con las tarjetas en dos columnas y la cabecera en una fila; sin errores de compilación (tsc 0, ESLint 0 errores). No probado: crear/editar/despachar/firmar contra el backend real, lector de pantalla, ni el scroll interno con una ventana alta (el contenedor del formulario depende del main del layout del dashboard).

Revisión de visto bueno: cabecera completa (24-oct-2026)

La cabecera de la revisión de visto bueno usa las mismas piezas: icono de copiar el número junto al título, tu visto bueno («Sin VB», «Con VB», «Observado») en una insignia junto al título y, a la derecha, el recorrido del documento en flechas (En proyecto › Vistos buenos › Firma › Emitido; el paso de vistos buenos es el actual mientras el documento espera visados, y un documento anulado muestra «Anulado» con la cinta de estado). «Ver anexos» lleva el contador.

Edición de Mesa de partes: cabecera con Action (24-oct-2026)

features/mesa-partes/components/form/edit-toolbar.tsx deja la barra antigua (botones de 13 px, etiquetas en mayúsculas como «PARA VERIFICAR») y usa la tarjeta del formulario: ruta «Mesa de partes › Editar registro», título N° número con copiar y menú ⋮ (Anular, solo en «En registros» con permiso), insignia del expediente («Exp: …» o «Sin expediente») y recorrido En registros › Para verificar › Registrado (Anulado reemplaza al recorrido con la cinta de estado). Acciones, todas Action y en sentido de oración: Actualizar (de color; apagado sin cambios o fuera de «En registros»), Cargar documento, Ver documento, Subir anexos, Ver anexos (con contador; habilitado también con solo referencias: la ventana lista los anexos propios y, por cada referencia, abre la ventana de anexos compartida en solo lectura), Voucher (apagado hasta registrar), Cargo (registrado) y las transiciones de estado: Para verificar (apagado sin documento o sin permiso), Volver a en registros, Registrar documento (de color; apagado con cambios sin guardar), Volver a para verificar y Reactivar. «Volver» se reemplaza por el primer tramo de la ruta. Las reglas, permisos y llamadas no cambian; los atajos G, C, A, X y R se conservan.

Registro y edición de Mesa de partes: formulario como el de emisión (29-oct-2026)

La cabecera de edición se había perdido en un merge (volvió la barra antigua con «PARA VERIFICAR» en mayúsculas): se restituye con lo agregado después (Observar, Subsanar en «Observado», Anular también en «Observado», aviso de expediente faltante en «Para verificar») y el recorrido suma Observado y Anulado en rojo y Subsanado. El registro nuevo (form-toolbar.tsx) usa la misma tarjeta: ruta «Mesa de partes › Nuevo registro» (o «Subsanar …»), título con «El N° se asigna al grabar», recorrido En registros › Para verificar › Registrado y acciones Action: Grabar (G), Cargar documento, Ver documento y Voucher apagados con su motivo, y Cancelar (C). Las páginas ya no repiten la miga de pan sobre la tarjeta. Cuerpo: dos columnas desde lg con 16 px entre tarjetas (Expediente y Remitente a la izquierda; Documento y Referencias a la derecha) y Destinatarios a todo el ancho, con la SectionCard del formulario de emisión. La tarjeta «Detalle» desaparece: fecha, año y N° de emisión son ReadOnlyData en Expediente. Los campos dejan el subrayado con etiqueta flotante y usan los del formulario de emisión (shared/form-fields.tsx: etiqueta arriba con asterisco rojo en los obligatorios, control con borde de 36 px, ayuda o error debajo, contador dentro de los textos largos); las listas (tipo, origen, TUPA, ubigeo) buscan en el mismo campo. «Sensible» pasa a «Acceso restringido» (casilla con ayuda), como en emisión y en la vista de solo lectura. Referencias es una lista con ver documento, ver anexos y quitar con confirmación; Destinatarios lleva asterisco de tarjeta obligatoria, número en círculo y estado vacío explicativo. Los datos que se envían no cambian.

Íconos de los datos de solo lectura (24-oct-2026)

ReadOnlyData muestra el ícono solo, en gris suave de 18 px, sin el recuadro tintado que llevaba antes en cada fila (se veía cargado y repetía color sin aportar información: la etiqueta ya dice qué es el dato). Conserva el hueco de 28 px para que etiquetas y valores sigan alineados con el título de la tarjeta. Aplica al formulario de emisión (Expediente, Remitente, Documento, número de emisión), «Documento recibido» y la revisión de visto bueno. Las iniciales de las personas («Elaborado por», «Firmado por») conservan su avatar redondo. Las filas de Referencias (ReferenceListCard, usada en «Documento recibido» y la revisión de visto bueno, y la tarjeta del formulario) siguen el mismo criterio: ícono de documento solo, en gris suave de 18 px, sin recuadro. Propuesta aprobada: A, solo ícono en gris suave (mockup comparado con B, color de marca).