Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Nieto2020/portalhub/llms.txt

Use this file to discover all available pages before exploring further.

The reports module (modules/reportes/) gives advisors a structured way to compose and publish financial analyses for their clients. Every report is typed (Monthly, Quarterly, Annual, or Special), follows a three-stage editorial lifecycle, and is permanently linked to the asesor who authored it. Admins have full read access across all reports, while advisors see only their own work.

Report Fields

ColumnTypeDescription
id_reporteintAuto-increment primary key
id_asesorint (FK)The advisor who created the report — ON DELETE CASCADE
titulostringReport title
descripcionstringShort summary / abstract
contenidotextFull report body
tipoenumMensual, Trimestral, Anual, or Especial
estadoenumBorrador, Publicado, or Archivado
fecha_creaciondatetimeSet to NOW() on insert
fecha_actualizaciondatetimeUpdated on every edit
The id_asesor foreign key is defined with ON DELETE CASCADE. If an advisor’s user account is removed from the system, all reports they authored are automatically deleted with it. Archive important reports before deactivating an asesor account.

Report Types

Mensual

Monthly accounting summary — income, expenses, and tax obligations for a single calendar month.

Trimestral

Quarterly review covering a three-month fiscal period.

Anual

Year-end annual report, often aligned with the SAT fiscal year.

Especial

Ad-hoc or one-off analysis outside the regular reporting calendar.

Report Lifecycle (State Machine)

Reports follow a linear editorial workflow:
StateDescription
BorradorDefault on creation; report is being drafted and is not yet visible to clients
PublicadoReport has been reviewed and released; visible to relevant clients
ArchivadoReport has been superseded or retired; preserved for audit purposes
When creating a report via crear.php you may set the initial estado to either Borrador or Publicado. The Archivado state is only assignable through the update/edit endpoint — it cannot be set at creation time.

Creating a Report

Endpoint: POST modules/reportes/crear.php Only ROL_ASESOR may create reports. The id_asesor is taken directly from the session — advisors cannot create reports on behalf of other advisors. titulo and descripcion are required; contenido, tipo, and estado fall back to safe defaults if omitted. Required fields:
FieldTypeNotes
titulostringCannot be empty after trim
descripcionstringCannot be empty after trim
Optional fields:
FieldTypeDefault
contenidostring"" (empty)
tipoenum"Mensual"
estadoenum"Borrador"
{
  "titulo": "Análisis Fiscal Q2 2025 – Empresa ABC",
  "descripcion": "Revisión de ingresos, deducciones y saldo a favor del segundo trimestre.",
  "contenido": "Durante el segundo trimestre...",
  "tipo": "Trimestral",
  "estado": "Borrador"
}
$stmt = $conexion->prepare("
    INSERT INTO reportes (id_asesor, titulo, descripcion, contenido, tipo, estado, fecha_creacion)
    VALUES (?, ?, ?, ?, ?, ?, NOW())
");
$stmt->execute([$id_asesor, $titulo, $descripcion, $contenido, $tipo, $estado]);

Listing Reports

Endpoint: GET modules/reportes/listar.php Returns reports joined with usuarios (advisor email) and perfiles (advisor full name), ordered by fecha_creacion DESC.
RoleFilter Applied
ROL_ASESOR (2)Only reports where r.id_asesor = id_usuario
ROL_ADMIN (1)All reports, all advisors
ROL_CLIENTE (3)Published reports linked to the client’s assigned asesor
Response item shape:
{
  "id_reporte": 33,
  "id_asesor": 5,
  "titulo": "Análisis Fiscal Q2 2025 – Empresa ABC",
  "descripcion": "Revisión de ingresos, deducciones y saldo a favor del segundo trimestre.",
  "contenido": "Durante el segundo trimestre...",
  "tipo": "Trimestral",
  "estado": "Borrador",
  "fecha_creacion": "2025-07-18 14:22:05",
  "fecha_actualizacion": null,
  "correo_asesor": "asesor@consultoria.mx",
  "nombre_asesor": "Lic. María García"
}
$sql = "
    SELECT
        r.id_reporte,
        r.id_asesor,
        r.titulo,
        r.descripcion,
        r.contenido,
        r.tipo,
        r.estado,
        r.fecha_creacion,
        r.fecha_actualizacion,
        u.correo  AS correo_asesor,
        p.nombre_completo AS nombre_asesor
    FROM reportes r
    JOIN usuarios u ON r.id_asesor = u.id_usuario
    LEFT JOIN perfiles p ON u.id_usuario = p.id_usuario
";

if ($rol == ROL_ASESOR) {
    $sql .= " WHERE r.id_asesor = ?";
    $params[] = $id_usuario;
}

$sql .= " ORDER BY r.fecha_creacion DESC";

Report Detail View

Endpoint: GET modules/reportes/detalle.php?id={id_reporte} Returns the complete record for a single report, including all fields. Subject to the same ownership rules as the list endpoint — an advisor cannot retrieve another advisor’s report.

Dashboard KPIs

Endpoint: GET modules/reportes/dashboard.php The dashboard endpoint is accessible to any authenticated user (checkAuth()) and aggregates platform-wide counts across users, appointments, accounting services, and payments into a single response.

Users

Total, active, and inactive user counts, broken down by client and advisor roles.

Appointments

Total appointment count with separate counts for Programada and Cancelada states.

Accounting Services

Total services with counts for Pendiente, En proceso, and Completado states.

Payments

Total payments with counts for Pendiente and Aprobado states, plus total monto_total.
GET /modules/reportes/dashboard.php
{
  "status": 200,
  "message": "Reporte dashboard obtenido correctamente",
  "data": {
    "usuarios": {
      "total": 52,
      "activos": 47,
      "inactivos": 5,
      "clientes": 40,
      "asesores": 10
    },
    "citas": {
      "total": 128,
      "programadas": 34,
      "canceladas": 12
    },
    "servicios": {
      "total": 95,
      "pendientes": 18,
      "en_proceso": 30,
      "completados": 47
    },
    "pagos": {
      "total": 110,
      "pendientes": 22,
      "aprobados": 75,
      "monto_total": "312500.00"
    }
  }
}

Build docs developers (and LLMs) love