Initial commit - Horux Despachos NL
This commit is contained in:
219
docs/superpowers/specs/2026-04-12-conciliacion-design.md
Normal file
219
docs/superpowers/specs/2026-04-12-conciliacion-design.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# Modulo de Conciliacion — Spec
|
||||
|
||||
**Fecha:** 2026-04-12
|
||||
**Estado:** Aprobado
|
||||
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Permitir al usuario conciliar CFDIs emitidos y recibidos mes a mes, registrando fecha de pago y banco. Solo se permite conciliar del ano actual en adelante.
|
||||
|
||||
---
|
||||
|
||||
## Modelo de datos (BD tenant — raw SQL)
|
||||
|
||||
### Tabla `bancos` (nueva)
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS bancos (
|
||||
id SERIAL PRIMARY KEY,
|
||||
banco VARCHAR(100) NOT NULL,
|
||||
terminacion_cuenta VARCHAR(4) NOT NULL,
|
||||
creado_en TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### Tabla `conciliaciones` (nueva)
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS conciliaciones (
|
||||
id SERIAL PRIMARY KEY,
|
||||
anio VARCHAR(4) NOT NULL,
|
||||
mes VARCHAR(2) NOT NULL,
|
||||
id_cfdi INTEGER NOT NULL UNIQUE REFERENCES cfdis(id),
|
||||
fecha_de_pago DATE NOT NULL,
|
||||
id_banco INTEGER NOT NULL REFERENCES bancos(id),
|
||||
creado_en TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_conciliaciones_anio_mes ON conciliaciones(anio, mes);
|
||||
CREATE INDEX IF NOT EXISTS idx_conciliaciones_id_cfdi ON conciliaciones(id_cfdi);
|
||||
```
|
||||
|
||||
### Columnas en `cfdis`
|
||||
|
||||
- `conciliado VARCHAR(50)` — ya existe. Se actualiza a `'true'` al conciliar, `NULL` al desconciliar.
|
||||
- `id_conciliacion INTEGER REFERENCES conciliaciones(id)` — nueva. FK a la conciliacion asociada. NULL si no conciliado.
|
||||
|
||||
Al conciliar: se crean registros en `conciliaciones`, se actualiza `cfdis.conciliado = 'true'` y `cfdis.id_conciliacion = conciliaciones.id`.
|
||||
Al desconciliar: se pone `cfdis.conciliado = NULL`, `cfdis.id_conciliacion = NULL`, y se elimina el registro de `conciliaciones`.
|
||||
|
||||
### DDL para tenants nuevos
|
||||
|
||||
Agregar `bancos`, `conciliaciones` en `database.ts` -> `createTables()` despues de `alertas`.
|
||||
Agregar `id_conciliacion INTEGER REFERENCES conciliaciones(id)` en la tabla `cfdis`.
|
||||
|
||||
### Migracion para tenants existentes
|
||||
|
||||
`CREATE TABLE IF NOT EXISTS` para `bancos` y `conciliaciones`, luego `ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS id_conciliacion INTEGER REFERENCES conciliaciones(id)`.
|
||||
|
||||
---
|
||||
|
||||
## Reglas de negocio
|
||||
|
||||
1. Solo se concilian CFDIs del **ano de alta del tenant en adelante** (se obtiene del `createdAt` del tenant en la BD central). Esto permite que una empresa registrada en 2025 pueda conciliar 2025, 2026, etc.
|
||||
2. `anio` y `mes` de `conciliaciones` se derivan automaticamente de `fecha_de_pago`.
|
||||
3. Un CFDI solo puede tener una conciliacion (`id_cfdi` es UNIQUE en conciliaciones, `id_conciliacion` en cfdis).
|
||||
4. Solo CFDIs vigentes (`status NOT IN ('Cancelado', '0')`).
|
||||
5. Al conciliar: INSERT en `conciliaciones` + UPDATE `cfdis` SET `conciliado = 'true'`, `id_conciliacion = <id>`.
|
||||
6. Al desconciliar: UPDATE `cfdis` SET `conciliado = NULL`, `id_conciliacion = NULL` + DELETE de `conciliaciones`.
|
||||
7. No se puede eliminar un banco que tenga conciliaciones asociadas.
|
||||
|
||||
---
|
||||
|
||||
## API endpoints
|
||||
|
||||
### Conciliacion
|
||||
|
||||
| Metodo | Ruta | Descripcion | Auth |
|
||||
|--------|------|-------------|------|
|
||||
| GET | `/conciliacion` | Lista CFDIs con estado de conciliacion | JWT + Tenant |
|
||||
| POST | `/conciliacion` | Conciliar CFDIs (batch) | JWT + Tenant + admin/contador |
|
||||
| DELETE | `/conciliacion/:id` | Desconciliar un CFDI | JWT + Tenant + admin/contador |
|
||||
|
||||
#### `GET /conciliacion`
|
||||
|
||||
**Query params:**
|
||||
- `tipo`: `EMITIDO` | `RECIBIDO` (requerido)
|
||||
- `fechaInicio`, `fechaFin`: rango de fecha de emision
|
||||
- `regimen`: clave de regimen fiscal (opcional)
|
||||
- `estado`: `conciliado` | `pendiente` (opcional, default: todos)
|
||||
|
||||
**Response:** Array de CFDIs con campo adicional `conciliacion` (null si pendiente, objeto si conciliado):
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "...",
|
||||
"rfcEmisor": "...",
|
||||
"nombreEmisor": "...",
|
||||
"total": 1000,
|
||||
"totalMxn": 1000,
|
||||
"fechaEmision": "...",
|
||||
"conciliado": "true",
|
||||
"idConciliacion": 5,
|
||||
"conciliacion": {
|
||||
"id": 5,
|
||||
"fechaDePago": "2026-04-10",
|
||||
"banco": "BBVA",
|
||||
"terminacionCuenta": "1234"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `POST /conciliacion`
|
||||
|
||||
**Body:**
|
||||
```json
|
||||
{
|
||||
"cfdiIds": [1, 2, 3],
|
||||
"fechaDePago": "2026-04-10",
|
||||
"idBanco": 1
|
||||
}
|
||||
```
|
||||
|
||||
**Logica:**
|
||||
1. Validar que todos los CFDIs existen, estan vigentes, y no estan ya conciliados.
|
||||
2. Validar que `fechaDePago` es del ano actual en adelante.
|
||||
3. Derivar `anio` y `mes` de `fechaDePago`.
|
||||
4. Para cada CFDI: INSERT en `conciliaciones`, UPDATE `cfdis` SET `conciliado = 'true'`, `id_conciliacion = <new id>`.
|
||||
|
||||
#### `DELETE /conciliacion/:id`
|
||||
|
||||
1. Buscar la conciliacion por id.
|
||||
2. UPDATE `cfdis` SET `conciliado = NULL`, `id_conciliacion = NULL` WHERE `id_conciliacion = :id`.
|
||||
3. DELETE FROM `conciliaciones` WHERE `id = :id`.
|
||||
|
||||
### Bancos
|
||||
|
||||
| Metodo | Ruta | Descripcion | Auth |
|
||||
|--------|------|-------------|------|
|
||||
| GET | `/bancos` | Listar bancos del tenant | JWT + Tenant |
|
||||
| POST | `/bancos` | Crear banco | JWT + Tenant + admin |
|
||||
| PUT | `/bancos/:id` | Editar banco | JWT + Tenant + admin |
|
||||
| DELETE | `/bancos/:id` | Eliminar banco (si no tiene conciliaciones) | JWT + Tenant + admin |
|
||||
|
||||
---
|
||||
|
||||
## Frontend
|
||||
|
||||
### Pagina `/conciliacion`
|
||||
|
||||
**Acceso:** Feature-gated por `conciliacion` (Business, Enterprise). Roles: admin y contador (lectura+escritura), visor (solo lectura).
|
||||
|
||||
**Layout:**
|
||||
```
|
||||
[Header: "Conciliacion"]
|
||||
[Filtros: PeriodSelector | RegimenSelector]
|
||||
[Tabs: Emitidas | Recibidas]
|
||||
[Seccion: "Por conciliar" — tabla con checkboxes]
|
||||
[Barra de accion: Banco (dropdown) + Fecha de pago (date) + Boton "Conciliar"]
|
||||
[Seccion: "Conciliadas" — tabla con info de conciliacion + boton desconciliar]
|
||||
```
|
||||
|
||||
**Tabla "Por conciliar":**
|
||||
- Checkbox (no visible para visor)
|
||||
- UUID (corto), Fecha emision, RFC Emisor/Receptor, Nombre, Total MXN, Metodo Pago
|
||||
- Boton "Ver factura" (CfdiViewerModal)
|
||||
|
||||
**Tabla "Conciliadas":**
|
||||
- UUID, Fecha emision, RFC, Nombre, Total MXN
|
||||
- Fecha de pago, Banco (nombre + terminacion)
|
||||
- Boton "Desconciliar" (no visible para visor)
|
||||
- Boton "Ver factura"
|
||||
|
||||
**Flujo de conciliacion:**
|
||||
1. Usuario selecciona checkboxes en "Por conciliar"
|
||||
2. Aparece barra de accion sticky en la parte inferior
|
||||
3. Selecciona banco (dropdown de bancos del tenant) y fecha de pago
|
||||
4. Click "Conciliar N facturas"
|
||||
5. Confirmacion -> POST `/conciliacion` -> refresh datos
|
||||
|
||||
### Seccion de bancos en `/configuracion`
|
||||
|
||||
Solo visible para admin. Card con:
|
||||
- Lista de bancos existentes: Nombre + terminacion + boton eliminar
|
||||
- Formulario inline: Nombre banco + Terminacion (max 4 digitos) + boton agregar
|
||||
|
||||
### Navegacion
|
||||
|
||||
Agregar "Conciliacion" al sidebar con feature gate `conciliacion`, visible para admin, contador, visor. Ubicacion: despues de Reportes.
|
||||
|
||||
---
|
||||
|
||||
## Archivos a crear/modificar
|
||||
|
||||
### Backend (crear)
|
||||
- `apps/api/src/services/conciliacion.service.ts`
|
||||
- `apps/api/src/controllers/conciliacion.controller.ts`
|
||||
- `apps/api/src/routes/conciliacion.routes.ts`
|
||||
- `apps/api/src/services/bancos.service.ts`
|
||||
- `apps/api/src/controllers/bancos.controller.ts`
|
||||
- `apps/api/src/routes/bancos.routes.ts`
|
||||
|
||||
### Backend (modificar)
|
||||
- `apps/api/src/app.ts` — registrar rutas de conciliacion y bancos
|
||||
- `apps/api/src/config/database.ts` — agregar tablas `bancos` y `conciliaciones` en `createTables()`, agregar `id_conciliacion` en `cfdis`
|
||||
|
||||
### Frontend (crear)
|
||||
- `apps/web/app/(dashboard)/conciliacion/page.tsx`
|
||||
- `apps/web/lib/api/conciliacion.ts`
|
||||
- `apps/web/lib/api/bancos.ts`
|
||||
- `apps/web/lib/hooks/use-conciliacion.ts`
|
||||
- `apps/web/lib/hooks/use-bancos.ts`
|
||||
|
||||
### Frontend (modificar)
|
||||
- `apps/web/components/layouts/sidebar.tsx` (y variantes) — agregar nav item
|
||||
- `apps/web/app/(dashboard)/configuracion/page.tsx` — agregar seccion de bancos
|
||||
|
||||
### Migracion
|
||||
- Aplicar DDL a tenant existente (`horux_ede123456ab1`): crear tablas + agregar columna
|
||||
Reference in New Issue
Block a user