Cursor Agent
ad152d46f4
merge: #18 gafete job y empresa del tenant
...
Añade 032-fn-badge-job-get al changelog junto a los demás 032.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 21:13:45 +00:00
Cursor Agent
5e4d9a6710
merge: #17 documentos sin fechas de vigencia
...
Añade 032-document-validity-from-upload junto a los demás 032.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 21:13:33 +00:00
Cursor Agent
15ffb3ca29
merge: #15+#16 gastos, proveedores y almacén
...
Conserva los changesets 032 ya unidos y añade 033–035.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 21:13:02 +00:00
Cursor Agent
2f2d23004e
merge: #13 preview programa de obra
...
Incluye ambos changesets 032 (document-get y work-program) en el changelog.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 21:12:47 +00:00
Cursor Agent
31a7c1cbf5
fix: gafete usa la empresa del tenant y corrige fn_badge_job_get
...
El ORDER BY del listado de personas refería la tabla w fuera del
subquery (42P01). El frente del gafete ya no imprime Construcciones
Arctec/Zendala: usa el nombre comercial de la empresa del proyecto.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 20:52:35 +00:00
Cursor Agent
e89b51bf43
fix: subir documentos sin fecha de emisión ni vencimiento
...
La vigencia de 3 meses para alta o reingreso cuenta desde la fecha de
carga. Quien recibe el expediente revisa si el documento es válido.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 20:47:16 +00:00
Cursor Agent
e528d217d3
feat: almacén global, abrir/cerrar por obra y catálogo de materiales
...
El árbol de Almacén deja de listar todas las obras. El almacén global
siempre está disponible y consolida el stock de los almacenes abiertos.
Las obras abren almacén a demanda y al cerrarlo pueden devolver el
remanente al global. Entradas y traspasos usan el catálogo de materiales
con unidades de medida y uno o varios proveedores.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 20:41:18 +00:00
Cursor Agent
61e36696b9
feat: reclasificar gastos sin concepto o cambiar de partida
...
Si un gasto se guardó sin clasificar, ahora se edita desde la lista (clic o Reclasificar) y se le asigna o cambia el concepto del presupuesto.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 20:19:13 +00:00
Cursor Agent
1e5bc22936
fix: catálogo de proveedores y unidades en la captura de gastos
...
Proveedor y unidad pasan a Select de catálogo (no texto libre). Subtotal, IVA y total se calculan al vuelo. El comprobante usa FileUpload de PrimeVue.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 20:06:45 +00:00
Cursor Agent
b7bd167e08
fix: importar programa de obra sin jsonb_object_length
...
Postgres no tiene jsonb_object_length; fn_work_program_replace
tronaba al confirmar el Excel. El conteo de semanas ahora usa
un contador en el loop de periodos.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 19:49:26 +00:00
Cursor Agent
de07975d4a
fix: abrir documentos de proyecto enviando doc_id a la RPC
...
La API pedía el PDF con { id } y fn_project_document_get leía
payload->>'doc_id', así que el id llegaba vacío aunque el archivo
ya estuviera en el bucket. Mismo desajuste en empresa y trabajador.
Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
2026-09-08 19:27:24 +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
496273b41c
feat: Programa de obra por proyecto
...
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary
Implementa el módulo **Programa de obra** por proyecto, vinculado al presupuesto ya existente.
### Flujo
1. Cargar presupuesto (requisito)
2. Definir fechas de inicio/término en el proyecto
3. Crear programa: **importar Excel Neodata/Opus**, **generar automático** o **crear vacío**
4. Editar en cuadrícula (conceptos con `Barra=` y partidas con erogaciones semanales)
5. Visualizar Gantt resumido y comparativo **programado vs ejecutado**
### Backend
- Tablas: `work_programs`, `work_program_periods`, `work_program_concept_slots`, `work_program_partida_amounts`, `work_program_progress`
- RPC: list/get, replace (import), generate (wizard), update celdas, recalculate partidas, vs-cost
- Parser Excel para formatos **por concepto** (`Barra=`) y **por partida** (montos semanales)
- Tests con fixtures reales del usuario
### Frontend
- Nueva página `/programa-obra` con pestañas: Conceptos, Partidas, Gantt, Programado vs costos
- Diálogos de importación y generación automática
- Menú principal, enlace en ficha de proyecto, banner en presupuesto
### Permisos
Reutiliza `manage_budget` en MVP.
## Test plan
- [x] `deno test api/work_program_excel_test.ts` (5 tests)
- [x] `deno check` API modules
- [x] `npm run build` web-panel
- [ ] Migrar DB (`029`, `030`) en entorno con Postgres
- [ ] Importar Excel por concepto y por partida en obra con presupuesto
- [ ] Generar automático con estrategia keyword
- [ ] Recalcular partidas desde conceptos
- [ ] Verificar tab Programado vs costos con gastos registrados
<!-- CURSOR_AGENT_PR_BODY_END -->
<div><a href="https://cursor.com/agents/bc-3985fe74-d26b-4506-bd4d-f9ad57374141?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> <a href="https://cursor.com/background-agent?bcId=bc-3985fe74-d26b-4506-bd4d-f9ad57374141&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> </div>
2026-09-08 04:51:09 +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> <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> </div>
2026-09-04 04:29:02 +00:00
Alberto Martinez
b9bf7044b2
refactor(core): migrate core CRUD to PostgreSQL RPC + unified HTTP errors
...
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary
Migrates the `core` schema business logic from inline `db.prepare()` calls in the API to PostgreSQL RPC functions (`core.fn_*`) with a unified JSON envelope for errors and HTTP status mapping.
### Database (Liquibase changesets 006–017)
- **006** — RPC infra: `rpc_ok`, `rpc_err`, `rpc_created`, `rpc_from_exception`
- **007** — Catalogs and tenant settings
- **008** — Companies CRUD
- **009** — Projects, checklists, document lists
- **010** — Workers CRUD, pipeline, checklist, assign
- **011** — Budget CRUD + `fn_budget_replace`
- **012** — Badge jobs
- **013** — Payroll (settings, attendance, loans, weeks, destajo)
- **014** — Worker import batch + document store
- **015** — Project/company/worker document metadata RPCs
- **016–017** — Fixes: `needs_badge` default on worker create; Liquibase `splitStatements:false` on function changesets
### API
- `api/rpc.ts` — `callCoreFn()`, `RpcCallError` (jsonb payload fix: pass JS object, not `JSON.stringify`)
- `api/http_errors.ts` — `mapRpcToStatus()`, `respondRpc()`, `respondApiError()`, `onAppError()`
- Refactored: `main.ts`, `companies.ts`, `db.ts`, `budget.ts`, `excel.ts`, `payroll.ts`, `payroll_http.ts`
- Front helpers: `web-panel/composables/api-response.ts`, `web-saas/composables/api-response.ts`
### Envelope contract
DB functions return `{ ok, code, layer: "db", message, context, data, errors }`. The API adds `status` (HTTP code) via `respondRpc()` / `respondApiError()`.
### Out of scope
`iam`, `platform`, `saas.ts`, auth/sessions, S3, PDF generation, Excel parsing, and bootstrap scripts still use direct SQL where appropriate.
## Test plan
- [x] `deno check main.ts` — compila sin errores de tipos
- [x] `npm run build` — web-panel y web-saas compilan
- [x] `deno test` — 25 tests unitarios (http_errors, companies, budget, mx, document_validity)
- [x] Liquibase migrations `006`–`017` aplicadas en Postgres local (`--context-filter=dev`)
- [x] API levantada localmente; `/v1/health` OK
- [x] Smoke CRUD vía `scripts/crud-smoke-test.sh`: empresas, proyectos, trabajadores, catálogos (create/get/list/patch)
- [ ] Import Excel de trabajadores (flujo multipart + S3/local storage)
- [ ] Import presupuesto desde Excel
- [ ] Flujo nómina: asistencia → cerrar semana
- [ ] CI en el remoto (sin checks reportados aún)
<!-- CURSOR_AGENT_PR_BODY_END -->
<div><a href="https://cursor.com/agents/bc-06667c14-38e8-42a8-9ed9-6b1322f12ae7?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> <a href="https://cursor.com/background-agent?bcId=bc-06667c14-38e8-42a8-9ed9-6b1322f12ae7&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> </div>
2026-09-04 02:34:43 +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