diff --git a/README.md b/README.md index 9684d3f..898ea7f 100644 --- a/README.md +++ b/README.md @@ -226,3 +226,4 @@ Los mensajes de commit deben estar en español, ser descriptivos y concentrarse - [Manual de Usuario Final](docs/MANUAL_USUARIO.md): Guía paso a paso sobre cómo utilizar el ERP, registrar gastos, el flujo de aprobación y monitorear proyectos. - [Arquitectura y Stack Tecnológico](docs/STACK_ARCHITECTURE.md): Documentación del stack técnico elegido (HTMX, Alpine, Supabase, Django Asíncrono, Celery) y la hoja de ruta de implementación. +- [Auditoría de Código](docs/CODE_AUDIT.md): Informe consolidado de deuda técnica, vulnerabilidades y cuellos de botella (N+1) hallados por los agentes de calidad. diff --git a/datadump.json b/datadump.json new file mode 100644 index 0000000..53c323a --- /dev/null +++ b/datadump.json @@ -0,0 +1 @@ +[{"model": "auth.group", "fields": {"name": "Administrador", "permissions": []}}, {"model": "auth.group", "fields": {"name": "Administrador Finanzas", "permissions": []}}, {"model": "auth.group", "fields": {"name": "Director de Proyecto", "permissions": []}}, {"model": "auth.user", "fields": {"password": "pbkdf2_sha256$1500000$Na8vmR0OjaPxiFZhGQMsOK$3fV5et8UErwOj8jKv9Fxh+mE0/V0Ugupy/DxeUF5WjA=", "last_login": "2026-09-07T02:58:33.276Z", "is_superuser": true, "username": "admin", "first_name": "", "last_name": "", "email": "", "is_staff": true, "is_active": true, "date_joined": "2026-08-19T21:46:15.491Z", "groups": [["Administrador"]], "user_permissions": []}}, {"model": "auth.user", "fields": {"password": "pbkdf2_sha256$1500000$gwNtDACf8K3iHc95sREduL$Rvklh+dADhPd675s4/31pPTIHBqlDI2LCQm6jLUKwvo=", "last_login": null, "is_superuser": false, "username": "finanzas", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2026-08-19T21:46:17.074Z", "groups": [["Administrador Finanzas"]], "user_permissions": []}}, {"model": "auth.user", "fields": {"password": "pbkdf2_sha256$1500000$QH7YSdzh7ePuiPKmF0CZEW$G2VeKgxzIiCvuFLc8LHVkoQHV1gMobqU/BKspqW16/I=", "last_login": null, "is_superuser": false, "username": "miguel_contreras", "first_name": "", "last_name": "", "email": "", "is_staff": false, "is_active": true, "date_joined": "2026-08-19T21:46:18.666Z", "groups": [["Director de Proyecto"]], "user_permissions": []}}, {"model": "auth.user", "fields": {"password": "pbkdf2_sha256$1500000$PNQ1CRnVCDjC6ScG4qk7Pm$ZlnxMvsZMP0sIZO7f8ucEhNAMih/NV9KBJBfzMzlAm8=", "last_login": null, "is_superuser": true, "username": "ginevra_ortega", "first_name": "", "last_name": "", "email": "", "is_staff": true, "is_active": true, "date_joined": "2026-08-19T21:46:20.209Z", "groups": [["Administrador"]], "user_permissions": []}}, {"model": "auth.user", "fields": {"password": "pbkdf2_sha256$1500000$p86VTE1ME5iv5ZrL34I1yo$/MEN6ugUUhMncrfRliEXTo/4ifh+5Du1TlQEWILd0bc=", "last_login": "2026-09-07T03:12:09.743Z", "is_superuser": true, "username": "testadmin", "first_name": "", "last_name": "", "email": "", "is_staff": true, "is_active": true, "date_joined": "2026-09-07T02:52:32.521Z", "groups": [], "user_permissions": []}}, {"model": "expenses.project", "pk": 78, "fields": {"created_at": "2026-09-07T02:51:26.758Z", "updated_at": "2026-09-07T02:51:26.758Z", "code": "CC-IDI", "name": "Centro de Costo I+D+i", "description": "Centro de costo principal para Investigación, Desarrollo e Innovación tecnológica.", "manager": null, "parent": null, "assigned_budget_clp": "350000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 79, "fields": {"created_at": "2026-09-07T02:51:26.761Z", "updated_at": "2026-09-07T02:51:26.762Z", "code": "CC-ADF", "name": "Centro de Costo Administración y Finanzas", "description": "Centro de costo corporativo para Administración, Finanzas y Overhead general.", "manager": null, "parent": null, "assigned_budget_clp": "150000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 80, "fields": {"created_at": "2026-09-07T02:51:26.765Z", "updated_at": "2026-09-07T02:51:26.765Z", "code": "PORT-001", "name": "Portafolio 1", "description": "Portafolio tecnológico para agrupar 5 proyectos.", "manager": null, "parent": 78, "assigned_budget_clp": "50000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 81, "fields": {"created_at": "2026-09-07T02:51:26.770Z", "updated_at": "2026-09-07T02:51:28.343Z", "code": "PRY-101", "name": "Proyecto 1 (Portafolio 1)", "description": "Subproyecto contable imputable de Portafolio 1.", "manager": null, "parent": 80, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": 59, "created_by": null}}, {"model": "expenses.project", "pk": 82, "fields": {"created_at": "2026-09-07T02:51:26.774Z", "updated_at": "2026-09-07T02:51:28.351Z", "code": "PRY-102", "name": "Proyecto 2 (Portafolio 1)", "description": "Subproyecto contable imputable de Portafolio 1.", "manager": null, "parent": 80, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "PAUSADA", "category": 60, "created_by": null}}, {"model": "expenses.project", "pk": 83, "fields": {"created_at": "2026-09-07T02:51:26.778Z", "updated_at": "2026-09-07T02:51:28.360Z", "code": "PRY-103", "name": "Proyecto 3 (Portafolio 1)", "description": "Subproyecto contable imputable de Portafolio 1.", "manager": null, "parent": 80, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": 61, "created_by": null}}, {"model": "expenses.project", "pk": 84, "fields": {"created_at": "2026-09-07T02:51:26.782Z", "updated_at": "2026-09-07T02:51:28.366Z", "code": "PRY-104", "name": "Proyecto 4 (Portafolio 1)", "description": "Subproyecto contable imputable de Portafolio 1.", "manager": null, "parent": 80, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "TERMINADO", "category": 62, "created_by": null}}, {"model": "expenses.project", "pk": 85, "fields": {"created_at": "2026-09-07T02:51:26.786Z", "updated_at": "2026-09-07T02:51:26.786Z", "code": "PRY-105", "name": "Proyecto 5 (Portafolio 1)", "description": "Subproyecto contable imputable de Portafolio 1.", "manager": null, "parent": 80, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 86, "fields": {"created_at": "2026-09-07T02:51:26.790Z", "updated_at": "2026-09-07T02:51:26.790Z", "code": "PORT-002", "name": "Portafolio 2", "description": "Portafolio tecnológico para agrupar 4 proyectos.", "manager": null, "parent": 78, "assigned_budget_clp": "50000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 87, "fields": {"created_at": "2026-09-07T02:51:26.794Z", "updated_at": "2026-09-07T02:51:28.372Z", "code": "PRY-201", "name": "Proyecto 1 (Portafolio 2)", "description": "Subproyecto contable imputable de Portafolio 2.", "manager": null, "parent": 86, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": 59, "created_by": null}}, {"model": "expenses.project", "pk": 88, "fields": {"created_at": "2026-09-07T02:51:26.798Z", "updated_at": "2026-09-07T02:51:28.378Z", "code": "PRY-202", "name": "Proyecto 2 (Portafolio 2)", "description": "Subproyecto contable imputable de Portafolio 2.", "manager": null, "parent": 86, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": 60, "created_by": null}}, {"model": "expenses.project", "pk": 89, "fields": {"created_at": "2026-09-07T02:51:26.803Z", "updated_at": "2026-09-07T02:51:26.803Z", "code": "PRY-203", "name": "Proyecto 3 (Portafolio 2)", "description": "Subproyecto contable imputable de Portafolio 2.", "manager": null, "parent": 86, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 90, "fields": {"created_at": "2026-09-07T02:51:26.808Z", "updated_at": "2026-09-07T02:51:26.808Z", "code": "PRY-204", "name": "Proyecto 4 (Portafolio 2)", "description": "Subproyecto contable imputable de Portafolio 2.", "manager": null, "parent": 86, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 91, "fields": {"created_at": "2026-09-07T02:51:26.812Z", "updated_at": "2026-09-07T02:51:26.812Z", "code": "PORT-003", "name": "Portafolio 3", "description": "Portafolio tecnológico para agrupar 3 proyectos.", "manager": null, "parent": 78, "assigned_budget_clp": "50000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 92, "fields": {"created_at": "2026-09-07T02:51:26.816Z", "updated_at": "2026-09-07T02:51:28.383Z", "code": "PRY-301", "name": "Proyecto 1 (Portafolio 3)", "description": "Subproyecto contable imputable de Portafolio 3.", "manager": null, "parent": 91, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "PAUSADA", "category": 63, "created_by": null}}, {"model": "expenses.project", "pk": 93, "fields": {"created_at": "2026-09-07T02:51:26.820Z", "updated_at": "2026-09-07T02:51:26.820Z", "code": "PRY-302", "name": "Proyecto 2 (Portafolio 3)", "description": "Subproyecto contable imputable de Portafolio 3.", "manager": null, "parent": 91, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 94, "fields": {"created_at": "2026-09-07T02:51:26.825Z", "updated_at": "2026-09-07T02:51:26.825Z", "code": "PRY-303", "name": "Proyecto 3 (Portafolio 3)", "description": "Subproyecto contable imputable de Portafolio 3.", "manager": null, "parent": 91, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 95, "fields": {"created_at": "2026-09-07T02:51:26.829Z", "updated_at": "2026-09-07T02:51:26.830Z", "code": "PORT-004", "name": "Portafolio 4", "description": "Portafolio tecnológico para agrupar 1 proyectos.", "manager": null, "parent": 78, "assigned_budget_clp": "50000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 96, "fields": {"created_at": "2026-09-07T02:51:26.835Z", "updated_at": "2026-09-07T02:51:26.835Z", "code": "PRY-401", "name": "Proyecto 1 (Portafolio 4)", "description": "Subproyecto contable imputable de Portafolio 4.", "manager": null, "parent": 95, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 97, "fields": {"created_at": "2026-09-07T02:51:26.840Z", "updated_at": "2026-09-07T02:51:26.840Z", "code": "PORT-005", "name": "Portafolio 5", "description": "Portafolio tecnológico para agrupar 1 proyectos.", "manager": null, "parent": 78, "assigned_budget_clp": "50000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 98, "fields": {"created_at": "2026-09-07T02:51:26.845Z", "updated_at": "2026-09-07T02:51:26.845Z", "code": "PRY-501", "name": "Proyecto 1 (Portafolio 5)", "description": "Subproyecto contable imputable de Portafolio 5.", "manager": null, "parent": 97, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 99, "fields": {"created_at": "2026-09-07T02:51:26.849Z", "updated_at": "2026-09-07T02:51:26.849Z", "code": "PORT-006", "name": "Portafolio 6", "description": "Portafolio tecnológico para agrupar 1 proyectos.", "manager": null, "parent": 78, "assigned_budget_clp": "50000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 100, "fields": {"created_at": "2026-09-07T02:51:26.853Z", "updated_at": "2026-09-07T02:51:26.853Z", "code": "PRY-601", "name": "Proyecto 1 (Portafolio 6)", "description": "Subproyecto contable imputable de Portafolio 6.", "manager": null, "parent": 99, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 101, "fields": {"created_at": "2026-09-07T02:51:26.857Z", "updated_at": "2026-09-07T02:51:26.857Z", "code": "PORT-007", "name": "Portafolio 7", "description": "Portafolio tecnológico para agrupar 2 proyectos.", "manager": null, "parent": 78, "assigned_budget_clp": "50000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 102, "fields": {"created_at": "2026-09-07T02:51:26.862Z", "updated_at": "2026-09-07T02:51:26.862Z", "code": "PRY-701", "name": "Proyecto 1 (Portafolio 7)", "description": "Subproyecto contable imputable de Portafolio 7.", "manager": null, "parent": 101, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 103, "fields": {"created_at": "2026-09-07T02:51:26.868Z", "updated_at": "2026-09-07T02:51:26.868Z", "code": "PRY-702", "name": "Proyecto 2 (Portafolio 7)", "description": "Subproyecto contable imputable de Portafolio 7.", "manager": null, "parent": 101, "assigned_budget_clp": "10000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 104, "fields": {"created_at": "2026-09-07T02:51:26.872Z", "updated_at": "2026-09-07T02:51:26.872Z", "code": "PORT-008", "name": "Operaciones y Finanzas", "description": "Portafolio administrativo para gastos fijos, soporte y legal.", "manager": null, "parent": 79, "assigned_budget_clp": "80000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 105, "fields": {"created_at": "2026-09-07T02:51:26.876Z", "updated_at": "2026-09-07T02:51:26.876Z", "code": "PRY-801", "name": "Sueldos y Overhead Administrativo", "description": "Gasto operacional fijo de oficina, contabilidad y sueldos staff core.", "manager": null, "parent": 104, "assigned_budget_clp": "40000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.project", "pk": 106, "fields": {"created_at": "2026-09-07T02:51:26.882Z", "updated_at": "2026-09-07T02:51:26.882Z", "code": "PRY-802", "name": "Servicios Financieros y Legal", "description": "Gastos de auditoría externa, patentes y asesoría legal B2B.", "manager": null, "parent": 104, "assigned_budget_clp": "40000000.00", "assigned_budget_usd": "0.00", "actual_cost_clp": "0.00", "payment_method": "Contrato por Fases / Hitos", "total_income_clp": "0.00", "type": "COSTO_DIRECTO_PROYECTO", "status": "ACTIVO", "category": null, "created_by": null}}, {"model": "expenses.category", "pk": 57, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1000", "name": "Recursos Humanos y Especialidades I+D+i", "description": "Partida Principal (Macro-categoría)", "parent": null}}, {"model": "expenses.category", "pk": 58, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1100", "name": "Personal Staff Core (Fijo / Sueldos Base)", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 59, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1201", "name": "Electricidad de Potencia e Infraestructura", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 60, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1202", "name": "Automatización y Control Industrial", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 61, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1203", "name": "Domótica e Inmótica (BMS & Climatización)", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 62, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1204", "name": "Electrónica y Sistemas de Hardware (PCB / Firmware)", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 63, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1205", "name": "Redes, Conectividad e Informática (TI & Ciberseguridad)", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 64, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1206", "name": "Tecnologías Inmersivas y Gemelos Digitales (VR/AR/LiDAR)", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 65, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "1207", "name": "Gestión Administrativa, Dir. de Proyectos (PMP/Agile)", "description": "", "parent": 57}}, {"model": "expenses.category", "pk": 66, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "2000", "name": "Materiales, Insumos e Infraestructura de Trabajo", "description": "Partida Principal (Macro-categoría)", "parent": null}}, {"model": "expenses.category", "pk": 67, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "2100", "name": "Componentes Electrónicos Prototipado", "description": "", "parent": 66}}, {"model": "expenses.category", "pk": 68, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "2200", "name": "Equipamiento Industrial de Campo", "description": "", "parent": 66}}, {"model": "expenses.category", "pk": 69, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "2300", "name": "Materiales Eléctricos y de Montaje", "description": "", "parent": 66}}, {"model": "expenses.category", "pk": 70, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "2400", "name": "Insumos de Oficina, Aseo, Cafetería y Papelería", "description": "", "parent": 66}}, {"model": "expenses.category", "pk": 71, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3000", "name": "Logística y Desplazamiento Terreno", "description": "Partida Principal (Macro-categoría)", "parent": null}}, {"model": "expenses.category", "pk": 72, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3101", "name": "Combustibles / Bencina", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 73, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3102", "name": "Arriendo Vehículos 4x4", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 74, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3103", "name": "Pasajes de Bus Interurbano", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 75, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3104", "name": "Pasajes de Micro / Urbano", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 76, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3105", "name": "Pasajes de Colectivos / Taxis", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 77, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3106", "name": "Uber / Cabify / Didi", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 78, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3107", "name": "Peajes & Tag Nacionales", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 79, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3108", "name": "Reembolso Kilometraje Particular", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 80, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "3200", "name": "Viáticos Alimentación y Alojamiento Terreno", "description": "", "parent": 71}}, {"model": "expenses.category", "pk": 81, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "4000", "name": "Software, Herramientas Digitales y Formación", "description": "Partida Principal (Macro-categoría)", "parent": null}}, {"model": "expenses.category", "pk": 82, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "4100", "name": "Licencias de Ingeniería & Diseño (Altium/Unity/Unreal)", "description": "", "parent": 81}}, {"model": "expenses.category", "pk": 83, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "4200", "name": "Infraestructura y Servidores Cloud Tradicionales", "description": "", "parent": 81}}, {"model": "expenses.category", "pk": 84, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "4300", "name": "Herramientas de Gestión de Proyectos / Software General", "description": "", "parent": 81}}, {"model": "expenses.category", "pk": 85, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "2301", "name": "Arriendo de Oficinas y Espacios de Trabajo", "description": "", "parent": 66}}, {"model": "expenses.category", "pk": 86, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "4201", "name": "Cursos, Capacitación y Certificaciones Técnicas para Especialistas", "description": "", "parent": 81}}, {"model": "expenses.category", "pk": 87, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "7000", "name": "Software, Datos, Inteligencia Artificial y Cloud", "description": "Partida Principal (Macro-categoría)", "parent": null}}, {"model": "expenses.category", "pk": 88, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "7100", "name": "Licencias IA y Modelos Propietarios", "description": "", "parent": 87}}, {"model": "expenses.category", "pk": 89, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "7200", "name": "Cloud & Computación GPU de Alto Rendimiento", "description": "", "parent": 87}}, {"model": "expenses.category", "pk": 90, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "7300", "name": "Consumo de APIs LLM (OpenAI, Anthropic, Gemini)", "description": "", "parent": 87}}, {"model": "expenses.category", "pk": 91, "fields": {"created_at": "2026-09-09T11:14:29.295Z", "updated_at": "2026-09-09T11:14:29.321Z", "code": "7400", "name": "MLOps, Pipelines de Datos y Despliegue de Modelos", "description": "", "parent": 87}}, {"model": "expenses.vendor", "pk": 4, "fields": {"created_at": "2026-08-21T01:27:53.543Z", "updated_at": "2026-08-21T01:27:53.543Z", "rut": "77.888.999-5", "name": "CONEXIONES SPA", "business_line": null, "bank": null, "account_type": null, "account_number": null, "email": null, "payment_terms": 30}}, {"model": "expenses.userprofile", "pk": 1, "fields": {"user": ["admin"], "rut": null, "job_title": "Administrador", "description": "Perfil corporativo de admin (Administrador)", "created_at": "2026-08-19T21:46:17.071Z", "updated_at": "2026-08-19T21:46:17.071Z", "specialties": [63]}}, {"model": "expenses.userprofile", "pk": 2, "fields": {"user": ["finanzas"], "rut": null, "job_title": "Administrador Finanzas", "description": "Perfil corporativo de finanzas (Administrador Finanzas)", "created_at": "2026-08-19T21:46:18.663Z", "updated_at": "2026-08-19T21:46:18.663Z", "specialties": []}}, {"model": "expenses.userprofile", "pk": 3, "fields": {"user": ["miguel_contreras"], "rut": null, "job_title": "Director de Proyecto", "description": "Perfil corporativo de miguel_contreras (Director de Proyecto)", "created_at": "2026-08-19T21:46:20.206Z", "updated_at": "2026-08-19T21:46:20.206Z", "specialties": [59, 60]}}, {"model": "expenses.userprofile", "pk": 4, "fields": {"user": ["ginevra_ortega"], "rut": null, "job_title": "Administrador", "description": "Perfil corporativo de ginevra_ortega (Administrador)", "created_at": "2026-08-19T21:46:21.893Z", "updated_at": "2026-08-19T21:46:21.893Z", "specialties": [60, 61, 62]}}, {"model": "expenses.auditlog", "pk": 1, "fields": {"user": ["admin"], "action": "EXPORT_CSV", "entity_name": null, "entity_id": null, "field_changed": null, "old_value": null, "new_value": null, "description": "Se descargó la matriz de gastos en formato CSV.", "timestamp": "2026-08-20T22:51:59.199Z"}}, {"model": "expenses.auditlog", "pk": 2, "fields": {"user": ["admin"], "action": "EXPORT_CSV", "entity_name": null, "entity_id": null, "field_changed": null, "old_value": null, "new_value": null, "description": "Se descargó la matriz de gastos en formato CSV.", "timestamp": "2026-08-20T22:52:07.762Z"}}, {"model": "expenses.auditlog", "pk": 3, "fields": {"user": ["admin"], "action": "Gasto Creado", "entity_name": "Expense", "entity_id": "a4dfcf4c-0c2d-4fd3-9db0-3928e893753a", "field_changed": null, "old_value": null, "new_value": null, "description": "Se creó el gasto por 1235000 CLP", "timestamp": "2026-08-21T00:47:01.631Z"}}, {"model": "expenses.auditlog", "pk": 4, "fields": {"user": ["admin"], "action": "Gasto Creado", "entity_name": "Expense", "entity_id": "197615ef-b794-4ccb-ae97-8c8b61ff808c", "field_changed": null, "old_value": null, "new_value": null, "description": "Se creó el gasto por 2500000 CLP", "timestamp": "2026-08-21T00:51:32.074Z"}}, {"model": "expenses.auditlog", "pk": 5, "fields": {"user": ["admin"], "action": "Gasto Creado", "entity_name": "Expense", "entity_id": "1be403c1-dae1-4414-98d6-8fe32d1254e1", "field_changed": null, "old_value": null, "new_value": null, "description": "Se creó el gasto por 2500000 CLP", "timestamp": "2026-08-21T00:57:35.112Z"}}, {"model": "expenses.auditlog", "pk": 6, "fields": {"user": ["admin"], "action": "Gasto Creado", "entity_name": "Expense", "entity_id": "37b446f0-d8d0-4fd3-ba4b-fd03376d1e95", "field_changed": null, "old_value": null, "new_value": null, "description": "Se creó el gasto por 2500000 CLP", "timestamp": "2026-08-21T00:57:53.749Z"}}, {"model": "expenses.auditlog", "pk": 7, "fields": {"user": ["admin"], "action": "EXPORT_BANK_TRANSFER", "entity_name": null, "entity_id": null, "field_changed": null, "old_value": null, "new_value": null, "description": "Se exportó la nómina bancaria de transferencias a proveedores.", "timestamp": "2026-08-21T00:57:53.775Z"}}, {"model": "expenses.auditlog", "pk": 8, "fields": {"user": ["admin"], "action": "ELEVATE_REQUEST", "entity_name": "Expense", "entity_id": "197615ef-b794-4ccb-ae97-8c8b61ff808c", "field_changed": null, "old_value": null, "new_value": null, "description": "Solicitud elevada a finanzas", "timestamp": "2026-08-21T00:59:47.470Z"}}, {"model": "expenses.auditlog", "pk": 9, "fields": {"user": ["admin"], "action": "EXPORT_BANK_TRANSFER", "entity_name": null, "entity_id": null, "field_changed": null, "old_value": null, "new_value": null, "description": "Se exportó la nómina bancaria de transferencias a proveedores.", "timestamp": "2026-08-21T00:59:56.593Z"}}, {"model": "expenses.auditlog", "pk": 10, "fields": {"user": ["admin"], "action": "Gasto Creado", "entity_name": "Expense", "entity_id": "020674b5-84e8-4a21-8029-0622125a8b9d", "field_changed": null, "old_value": null, "new_value": null, "description": "Se creó el gasto por 2500000 CLP", "timestamp": "2026-08-21T01:27:53.556Z"}}, {"model": "expenses.auditlog", "pk": 11, "fields": {"user": ["admin"], "action": "EXPORT_BANK_TRANSFER", "entity_name": null, "entity_id": null, "field_changed": null, "old_value": null, "new_value": null, "description": "Se exportó la nómina bancaria de transferencias a proveedores.", "timestamp": "2026-08-21T01:27:53.581Z"}}, {"model": "expenses.auditlog", "pk": 12, "fields": {"user": ["admin"], "action": "Gasto Creado", "entity_name": "Expense", "entity_id": "7ae595c0-a07a-43e6-b15d-5a302e016dbc", "field_changed": null, "old_value": null, "new_value": null, "description": "Se creó el gasto por 20000 CLP", "timestamp": "2026-08-21T01:29:57.618Z"}}, {"model": "expenses.auditlog", "pk": 13, "fields": {"user": ["admin"], "action": "Gasto Eliminado", "entity_name": "Expense", "entity_id": "7ae595c0-a07a-43e6-b15d-5a302e016dbc", "field_changed": null, "old_value": null, "new_value": null, "description": "Se eliminó el gasto de la base de datos", "timestamp": "2026-08-21T01:30:28.678Z"}}, {"model": "expenses.auditlog", "pk": 14, "fields": {"user": ["admin"], "action": "REJECT", "entity_name": "Expense", "entity_id": "197615ef-b794-4ccb-ae97-8c8b61ff808c", "field_changed": null, "old_value": null, "new_value": null, "description": "Gasto observado/rechazado", "timestamp": "2026-08-21T01:30:29.864Z"}}, {"model": "expenses.auditlog", "pk": 15, "fields": {"user": ["admin"], "action": "Gasto Eliminado", "entity_name": "Expense", "entity_id": "197615ef-b794-4ccb-ae97-8c8b61ff808c", "field_changed": null, "old_value": null, "new_value": null, "description": "Se eliminó el gasto de la base de datos", "timestamp": "2026-08-21T01:30:32.128Z"}}, {"model": "expenses.auditlog", "pk": 16, "fields": {"user": ["admin"], "action": "REJECT", "entity_name": "Expense", "entity_id": "1be403c1-dae1-4414-98d6-8fe32d1254e1", "field_changed": null, "old_value": null, "new_value": null, "description": "Gasto observado/rechazado", "timestamp": "2026-08-21T01:30:34.158Z"}}, {"model": "expenses.auditlog", "pk": 17, "fields": {"user": ["admin"], "action": "Gasto Eliminado", "entity_name": "Expense", "entity_id": "1be403c1-dae1-4414-98d6-8fe32d1254e1", "field_changed": null, "old_value": null, "new_value": null, "description": "Se eliminó el gasto de la base de datos", "timestamp": "2026-08-21T01:30:36.491Z"}}, {"model": "expenses.systemsetting", "pk": 1, "fields": {"global_budget": "25000000.00", "usd_exchange_rate": "950.00", "iva_rate": "19.00"}}] diff --git a/docs/CODE_AUDIT.md b/docs/CODE_AUDIT.md new file mode 100644 index 0000000..62117b9 --- /dev/null +++ b/docs/CODE_AUDIT.md @@ -0,0 +1,37 @@ +# Auditoría de Código y Mejores Prácticas + +Este documento consolida los hallazgos de los agentes de validación (Calidad de Código y Mejores Prácticas Django) tras analizar el ERP. + +## 🔴 Riesgos Críticos (Corregir Inmediatamente) + +### 1. Peligro de Pérdida de Datos Financieros +Se están utilizando relaciones de base de datos con `on_delete=models.CASCADE` en registros críticos. +- **Riesgo**: Si se elimina un Proveedor, Django eliminará silenciosamente todas las Órdenes de Compra asociadas a él. Si se elimina el perfil de un Empleado, se borrarán todos sus registros de sueldo (`SalarySlip`) del sistema. +- **Solución**: Cambiar a `models.PROTECT` para prohibir la eliminación de entidades si tienen transacciones asociadas, o implementar un modelo de *Soft-Delete* (borrado lógico). + +### 2. Cuellos de Botella (Consultas N+1) +Supabase (y las bases de datos en la nube en general) son muy sensibles a la latencia de red. El código actual realiza demasiadas consultas ocultas a la base de datos: +- **`project_list.html`**: La vista hace el trabajo correcto al usar `.annotate(total_expenses=Sum(...))` para calcular los gastos totales de un proyecto en una sola consulta. Sin embargo, **el template HTML ignora esta anotación** y llama a `{{ project.total_expenses_clp }}`, el cual es un `@property` del modelo que dispara un `.aggregate()` por cada proyecto en la pantalla. Si hay 50 proyectos, se hacen 100 consultas SQL a Supabase en lugar de 1. +- **CSV Export**: Falta hacer `select_related('vendor')`, lo que dispara consultas N+1 al exportar los gastos. + +### 3. Excepciones Silenciosas (Código Traga-Errores) +En `expenses/views.py` y `expenses/forms.py` se abusa de `except Exception: pass`. +- **Riesgo**: Si falla la eliminación de un archivo en S3 o si hay un error de validación, el código falla silenciosamente. Será imposible encontrar el error porque no quedará registrado en ningún Log. +- **Solución**: Capturar excepciones específicas y utilizar el módulo `logging`. + +--- + +## 🟡 Deuda Técnica (Refactorización) + +### 1. Desorden en la Raíz del Proyecto +La carpeta raíz del proyecto tiene mucha "basura" (`seed_all.py`, `patch_models.py`, `refactor_oop.py`). +- **Solución**: Mover todos los scripts de parcheo a una carpeta temporal, y los scripts de inicialización de datos (seeds) refactorizarlos hacia Comandos de Administración de Django (`management/commands/`). + +### 2. Plantillas Faltantes (Templates 404) +El módulo de Adquisiciones (`procurement/views.py`) intenta renderizar `requisition_detail.html` y `purchase_order_detail.html`, pero estos **archivos no existen**. Al navegar a esas rutas, la aplicación se caerá con un error `TemplateDoesNotExist`. + +### 3. Índices de Base de Datos +Falta añadir `db_index=True` a campos de búsqueda intensiva, como la `fecha` de los Gastos o el `status` de las órdenes. + +### 4. Falta de consistencia en Herencia +Algunos módulos (Nóminas y Adquisiciones) reescriben los campos `created_at` y `updated_at` manualmente en cada modelo, en lugar de heredar del `TimeStampedModel` base que ya se programó en la App de Gastos. diff --git a/requirements.txt b/requirements.txt index 390aa39..87a214d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -54,3 +54,4 @@ zope.interface==8.5 whitenoise==6.7.0 django-storages==2.14.2 boto3==1.34.69 +requests==2.31.0