Commit graph

5 commits

Author SHA1 Message Date
Alberto Martinez
34c0da30d8 fix(padron): vista previa de documentos, eliminar y reemplazar por tipo (#26)
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Problema
En el expediente del padrón, al ver un documento el navegador lo trataba como descarga (cabeceras `application/octet-stream` + `attachment` y blob sin MIME). No había forma de eliminar archivos cargados y al subir otro del mismo tipo algunos entornos fallaban o no refrescaban bien la lista vigente.

## Cambios
- **API:** los GET de documentos (trabajador, proyecto, empresa) envían el `Content-Type` real del archivo y `Content-Disposition: inline` por defecto (`?disposition=attachment` para forzar descarga).
- **UI:** `DocumentPreviewDialog` pide `disposition=inline` y reconstruye el blob con MIME correcto para que PDF/imagen se vean en el diálogo.
- **Eliminar:** RPC `core.fn_worker_document_delete`, `DELETE /v1/workers/:id/documents/:docId`, permiso `documents.delete` (incluido en `manage_documents`), botón de papelera en vigentes e histórico.
- **Reemplazar:** `fn_worker_document_store` marca como no vigentes **todas** las filas del mismo tipo antes del INSERT; se limpia el `FileUpload` tras subir; filtro `is_current` tolera booleano o `1`.

## Migraciones
- Core: `040-fn-worker-document-delete.sql`, `041-fn-worker-document-store-replace.sql`
- IAM: `006-documents-delete-permission.sql`

## Verificación
Tras aplicar Liquibase, en un trabajador del padrón: abrir ojo en PDF/JPG (debe verse en modal), eliminar un doc de prueba, subir dos veces el mismo tipo (debe quedar una vigente y la anterior en histórico).
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a href="https://cursor.com/agents/bc-d8a5d34a-ead9-4912-8296-322cff799783?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-d8a5d34a-ead9-4912-8296-322cff799783&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>
2026-09-16 21:17:39 +00:00
Cursor Agent
a9fbca232d
Fix IAM v2 migrate: split DO block and harden role backfill
The migrate job failed at changeset 005h during Coolify deploy. Liquibase
was splitting the DO $$ block on inner semicolons (splitStatements:true),
which breaks PL/pgSQL. Move the unique-index DO block to 005h2 with
splitStatements:false.

Add 005g2 to create missing operativo roles per tenant, backfill any
remaining role_id values, demote duplicate tenant_admin users to operativo,
and remove orphan users without tenant_id before SET NOT NULL.

Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 18:57:19 +00:00
Cursor Agent
25ceb6a6bd
Add IAM v2 roles/permissions migration and project doc types
Introduce Liquibase changeset 005 for IAM schema v2: CRUD permission codes,
tenant-scoped roles with system tenant_admin, role_permissions by role_id,
user scope fields and user_projects, RLS policies, and full RPC suite for
roles and users. Add core changeset 031 for technical project document types.

Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 18:10:45 +00:00
Alberto Martinez
41273dfb04 Gastos, almacén y control presupuestal
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Validación de endpoints y SPs

Se probaron todos los endpoints nuevos (gastos, almacén, control presupuestal, IAM) y sus RPCs asociados.

### Bugs corregidos en migraciones/SQL

1. **IAM grants en schema core** — `iam-004e` intentaba `GRANT` sobre `core` con rol `iam_owner` (sin permiso). Los grants cruzados se movieron a `core-027-iam-rpc-cross-grants.sql`.
2. **`_cost_settings` ambiguo** — columnas `budget_warn_pct` etc. colisionaban con `RETURNS TABLE` en PL/pgSQL, rompiendo `fn_expense_create` y control presupuestal. Corregido en `core-028-fix-cost-settings-ambiguous.sql`.

### Tests añadidos

- `api/cost_modules_test.ts` — CRUD RPC gastos, flujo almacén completo, control presupuestal, IAM permisos
- `scripts/crud-smoke-test.sh` — smoke HTTP de todos los endpoints nuevos

### Resultados

- `deno test cost_modules_test.ts` — 5/5 OK
- `./scripts/crud-smoke-test.sh` — todos los checks OK (gastos CRUD, IVA, cost-settings, almacén, transferencias, cost-control, IAM)
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a href="https://cursor.com/agents/bc-eeec3b5c-f789-43e8-a353-0755e4706377?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-eeec3b5c-f789-43e8-a353-0755e4706377&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>
2026-09-04 04:29:02 +00:00
Cursor Agent
b87b0205a8
db: migrar infraestructura de BD a Postgres (fase 0-1)
- Fase 0: scripts de aprovisionamiento (db/provision/) para roles, dos
  bases de datos separadas (panels_platform / panels_product con
  esquemas iam+core) y ACLs de Redis por modulo, con verificacion
  automatizada de aislamiento (verify-isolation.sh) y setup local
  reproducible (dev-local.sh).
- Fase 1: changelogs de Liquibase reescritos para Postgres
  (db/platform, db/iam, db/core reemplazan db/app + los changesets
  SQLite de platform). Baseline como estado final (no replay literal),
  tipos traducidos (IDENTITY, TIMESTAMPTZ/DATE, NUMERIC, BOOLEAN,
  CITEXT), contexts dev vs. schema/catalogos, RLS por tenant_id como
  defensa en profundidad, uploaded_by/created_by como snapshot
  desnormalizado (sin FK hacia iam).
- Migraciones ya no corren en el arranque de la API: paso explicito de
  deploy via db/update.sh con credenciales _owner.

Verificado end-to-end contra Postgres 16 + Redis local.

Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-02 20:00:49 +00:00