Las reglas transversales son acuerdos de diseño que aplican a todos los módulos de ArccNova v2. En lugar de repetirlas en cada especificación de módulo, los módulos las referencian por número de regla (RT-XX). Esta guía es la fuente única de verdad de todas ellas, organizadas por área temática.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/DevCarlosRodriguez/Documentacion-Arccnova-2.0/llms.txt
Use this file to discover all available pages before exploring further.
1. Fechas y zona horaria (RT-16, RT-17)
El sistema mantiene una separación clara entre el almacenamiento en UTC y la presentación en hora local:| Capa | Responsabilidad |
|---|---|
| Backend | Guarda todas las marcas de tiempo en UTC |
| Frontend | Convierte a hora local para mostrar al usuario |
Punto abierto (flag 7): los cortes de caja y el “día” de los vencimientos deben anclarse a la zona horaria del proyecto. El campo
TimeZone en el proyecto y el detalle de diseño lo define el arquitecto; no bloquea el arranque.2. Monedas y tipo de cambio (RT-18, RT-19, RT-20)
- Conversión en cobros
- Fuente y actualización
- Indicadores financieros
Una venta pactada en una moneda puede cobrarse en otra. El sistema convierte automáticamente usando el tipo de cambio del día del pago (C32), no el tipo de cambio de la fecha de la venta ni un promedio.
3. Archivos adjuntos (RT-12, RT-13)
Tipos y límites
| Parámetro | Valor |
|---|---|
| Tipos permitidos | jpg, png, webp, pdf, docx, xlsx |
| Tamaño máximo por archivo | 10 MB |
| Cantidad por registro | Sin límite |
| Retención | Indefinida (T06) |
Flujo técnico (decisión 8)
El binario nunca transita por la API. El flujo es el siguiente:El frontend solicita una URL prefirmada
El frontend llama al backend para obtener una URL prefirmada de S3 (o MinIO en desarrollo) para el archivo que va a subir.
El frontend sube el binario directamente a S3
Con la URL prefirmada recibida, el frontend realiza un
PUT directamente contra S3, enviando el archivo con el Content-Type correcto. La API no interviene en esta transferencia.4. Notificaciones (RT-14, RT-15)
La lista de eventos que generan notificaciones es cerrada y exhaustiva para esta versión (T05). No se prevé ampliarla sin un cambio de especificación.Eventos que notifican
| # | Evento |
|---|---|
| 1 | Cobro no identificado recibido |
| 2 | Solicitud de RH pendiente de aprobar |
| 3 | Pago en línea recibido |
Eventos que explícitamente NO notifican
- Cuota vencida
- Reserva por vencer
- Documento de empleado por vencer
Canal de entrega
Cada notificación se entrega por ambos canales simultáneamente:- Notificación dentro del sistema (in-app)
- Correo electrónico
5. Días festivos (RT-21, RT-22)
El sistema mantiene un único catálogo de festivos con un campo discriminador de ámbito, en lugar de catálogos separados por nivel (decisión 17, ADR-021):| Ámbito | Descripción |
|---|---|
Global | Festivos aplicables a todas las empresas del sistema |
Empresa | Festivos configurados por y para una empresa específica |
Proyecto | Festivos aplicables a un proyecto específico |
Consumidores del catálogo de festivos
Módulo Collections (Cobros)
Los festivos extienden los días de gracia de los vencimientos de cuotas (C24). Si una fecha de vencimiento cae en un día festivo, el sistema la desplaza al siguiente día hábil.
Módulo HR (Nómina)
Los festivos se usan para calcular la prima de nómina. Cada festivo lleva dos multiplicadores: uno para horas normales y otro para horas extra. Un multiplicador de
1.00 significa festivo sin prima (R22).6. Motor de aprobaciones (RT-23, RT-24, RT-25)
El móduloShared.Approvals provee un motor de aprobaciones compartido para todos los módulos que lo necesiten (decisión 18, ADR-018).
Características del motor
| Característica | Valor |
|---|---|
| Niveles | Un solo nivel (no hay cadenas ni jerarquía de jefe directo) |
| Resultado | Binario: aprobar o rechazar |
| Quién resuelve | Cualquier usuario con el permiso requerido por el tipo de entidad aprobable |
Estados de una solicitud
Consumidores en esta versión
- RH: vacaciones, comisiones, tiempo extra
7. Firma electrónica (RT-26, RT-27, RT-28)
La estrategia de firma electrónica está diseñada en 4 fases. Esta versión implementa únicamente la fase 1:- Fase 1 (implementada)
- Fases 2-4 (preparadas, no construidas)
Trazo simple dibujado en pantalla + capa de transparencia.El flujo incluye:
- Aviso informativo antes de firmar
- Cláusula de aceptación expresa en el contrato
- Casilla de confirmación previa al trazo
- Aviso en el acuse final
Reglas de la firma híbrida (C20, R18)
Una firma híbrida ocurre cuando un contrato tiene una firma digital y otra manuscrita. Las reglas son:| Regla | Descripción |
|---|---|
| Dos firmantes | Cliente y responsable |
| Orden en firma híbrida | Si hay una firma digital y una manuscrita, la digital va primero |
| Ambas digitales | Si ambas son digitales, no hay orden obligatorio |
| Marca de agua en preview | Mientras las firmas digitales estén incompletas, el documento muestra marca de agua. Se retira al completarse, dejando el documento listo para la firma manuscrita |
| Enlace remoto | El enlace de firma remota expira; el vencimiento es configurable por token |
| Rechazo | Un firmante puede rechazar la firma (R18) |
8. Render y generación de documentos (RT-29, RT-30)
ArccNova distingue dos categorías de documentos con estrategias de generación completamente diferentes:Documentos operativos
Reportes, vistas, recibos informativosEl backend expone los datos; el frontend genera el documento (PDF, Excel, etc.) en el lado del cliente (decisión 9). Ejemplos: reportes de ventas, estados de cuenta informativos.
Documentos con valor legal
Contratos, hoja de liquidación, recibos de nóminaEl backend los genera con QuestPDF, calcula el hash SHA-256 como registro de auditoría, y persiste el PDF en un bucket de S3 aislado (decisión 10, ADR-014). Ese binario inmutable es el único descargable.
9. Patrones de datos (RT-31, RT-32, RT-33)
Estos tres patrones aplican sin excepción a todas las entidades operativas del sistema:RT-31 — Soft delete en todo el sistema
RT-31 — Soft delete en todo el sistema
Los registros eliminados nunca se borran físicamente. Se conservan en base de datos con los siguientes campos:
Los registros eliminados desaparecen de catálogos y selectores de la UI, pero se conservan para trazabilidad (C11).
| Campo | Descripción |
|---|---|
IsDeleted | true si el registro está eliminado |
DeletedBy | Identificador del usuario que eliminó |
DeletedAt | Marca de tiempo UTC de la eliminación |
IsActive es un concepto distinto: pausa el registro sin eliminarlo. Un registro puede tener IsActive = false e IsDeleted = false simultáneamente.RT-32 — Auditoría en toda tabla operativa
RT-32 — Auditoría en toda tabla operativa
Toda tabla operativa lleva cuatro campos de auditoría:
| Campo | Descripción |
|---|---|
CreatedBy | Identificador del usuario creador |
CreatedAt | Marca de tiempo UTC de creación |
UpdatedBy | Identificador del último usuario que modificó |
UpdatedAt | Marca de tiempo UTC de la última modificación |
RT-33 — Folios correlativos por proyecto
RT-33 — Folios correlativos por proyecto
El proyecto define y mantiene dos correlativos secuenciales:
- Correlativo de contrato: se asigna al firmar un nuevo contrato de venta (C09).
- Correlativo de recibo: se incrementa automáticamente al registrar un cobro identificado (Cobros-Flujos §5).
10. Tiempo real (RT-34)
El sistema utiliza Server-Sent Events (SSE) para las actualizaciones en tiempo real, no SignalR (decisión 19, ADR-019).| Evento en tiempo real | Descripción |
|---|---|
| Cobros no identificados | Contador y lista se actualizan cuando llega un cobro sin identificar |
| Confirmación de pago en línea | Webhook de Stripe → backend → retransmisión por SSE al navegador |
La elección de SSE sobre SignalR responde a la simplicidad del protocolo y a que los casos de uso de tiempo real en esta versión son todos unidireccionales (servidor → cliente). No se usa WebSockets bidireccionales.
11. Límites del plan (RT-35)
Toda acción que crea un recurso limitable pasa por el control de cuota del módulo BillingSaas antes de ejecutarse, siguiendo el patrónExecuteWithQuotaAsync: