udistrital / polux_cliente

Cliente angular del proyecto Polux
0 stars 0 forks source link

Complementar reportes con peticiones de JBPM #672

Closed diagutierrezro closed 1 month ago

diagutierrezro commented 1 month ago

Se requiere realizar la continuación de los reportes, esta vez se debe iniciar a buscar la información de las peticiones que se hacen hacia JBPM para verificar si allí se encuentra la información requerida en las columnas faltantes e implementar las peticiones para complementar las columnas. En dado caso de que no existan hacer la respectiva investigación con Jhon para verificar si ya existe algún enpoint que cuente con dicha información o si es necesario realizar una.

Sub Tareas

Criterios de aceptación

Dependencias @diagutierrezro debe preguntar al equipo DBA si es posible que se otorgue permisos de lectura a las bases de datos de Oracle para facilitas la busqueda de la información requerida.

Requerimientos

No aplica

Definition of Ready - DoR

Definition of Done - DoD - Desarrollo

CrisEs2506 commented 1 month ago

http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services

CrisEs2506 commented 1 month ago

SubTarea N°1: Verificar endpoints JBPM existentes para comprobar si existen peticiones útiles, revisar especialmente las peticiones que traen los datos de los estudiantes y docentes, en caso de que el endpoint funcione implementarlo en el mid y SubTarea N°2: Revisar si en otros endpoints existentes existe información que nos pueda ser útil e implementarla.

URL: http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/datos_basicos_estudiante/20142020001

Respuesta:

image

URL: http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/get_docentes_tg

Respuesta:

image

URL: http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/carrera/20

Respuesta

image

URL: http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/get_coordinador_carrera

URL: http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/consulta_coordinador_carrera

Respuesta

Con ninguna de las URL se logró hacer que funcionará y la documentación no es clara, por lo que se pedirá asesoría a Jhon (persona quien se encargo de realizar los endpoints).

CrisEs2506 commented 1 month ago

SubTarea N°1: Verificar endpoints JBPM existentes para comprobar si existen peticiones útiles, revisar especialmente las peticiones que traen los datos de los estudiantes y docentes, en caso de que el endpoint funcione implementarlo en el mid.

POLUX_CRUD

  1. reporte_general
package models

import (
    "strconv"
    "time"

    "github.com/astaxie/beego/orm"
)

type ReporteGeneral struct {
    Id                      int
    TrabajoGrado            int    `orm:"column(trabajo_grado)"`
    Titulo                  string `orm:"column(titulo)"`
    Modalidad               string `orm:"column(modalidad)"`
    EstadoTrabajoGrado      string `orm:"column(estado)"`
    IdEstudiante            string `orm:"column(id_estudiante)"`
    NombreEstudiante        string
    IdCoestudiante          string `orm:"column(id_coestudiante)"`
    NombreCoestudiante      string
    ProgramaAcademico       string
    AreaConocimiento        string `orm:"column(area_conocimiento)"`
    DocenteDirector         int    `orm:"column(docente_director)"`
    NombreDocenteDirector   string
    DocenteCodirector       int `orm:"column(docente_codirector)"`
    NombreDocenteCodirector string
    Evaluador               int `orm:"column(evaluador)"`
    NombreEvaluador         string
    FechaInicio             time.Time `orm:"column(fecha_inicio);type(timestamp without time zone)"`
    FechaFin                time.Time `orm:"column(fecha_fin);type(timestamp without time zone);null"`
    CalificacionUno         float32   `orm:"column(calificacion_1)"`
    CalificacionDos         float32   `orm:"column(calificacion_2)"`
}

func init() {
    orm.RegisterModel(new(ReporteGeneral))
}

func GetReporteGeneral() (map[string]interface{}, error) {
    o := orm.NewOrm()

    var results []orm.Params

    _, err := o.Raw(`
        WITH estudiantes AS (
            SELECT
                trabajo_grado,
                MAX(CASE WHEN row_number = 1 THEN estudiante ELSE NULL END) AS id_estudiante,
                MAX(CASE WHEN row_number = 2 THEN estudiante ELSE NULL END) AS id_coestudiante
            FROM (
                SELECT
                    trabajo_grado,
                    estudiante,
                    ROW_NUMBER() OVER (PARTITION BY trabajo_grado ORDER BY estudiante) AS row_number
                FROM
                    academica.estudiante_trabajo_grado
            ) sub
            GROUP BY
                trabajo_grado
        ),
        usuarios AS (
            SELECT
                trabajo_grado,
                MAX(CASE WHEN rol_trabajo_grado = 4593 THEN usuario ELSE NULL END) AS docente_director,
                MAX(CASE WHEN rol_trabajo_grado = 4594 THEN usuario ELSE NULL END) AS docente_codirector,
                MAX(CASE WHEN rol_trabajo_grado = 4595 THEN usuario ELSE NULL END) AS evaluador
            FROM
                academica.vinculacion_trabajo_grado
            GROUP BY
                trabajo_grado
        ),
        notas AS (
            SELECT
                trabajo_grado,
                MAX(CASE WHEN row_number = 1 THEN calificacion ELSE NULL END) AS nota2,
                MAX(CASE WHEN row_number = 2 THEN calificacion ELSE NULL END) AS nota1
            FROM (
                SELECT
                    trabajo_grado,
                    calificacion,
                    ROW_NUMBER() OVER (PARTITION BY trabajo_grado ORDER BY calificacion) AS row_number
                FROM
                    academica.asignatura_trabajo_grado
            ) sub
            GROUP BY
                trabajo_grado
        )

        SELECT
            tg.id AS trabajo_grado,
            tg.titulo,
            tg.modalidad,
            tg.estado_trabajo_grado,
            est.id_estudiante,
            est.id_coestudiante,
            atg.area_conocimiento,
            usr.docente_director,
            usr.docente_codirector,
            usr.evaluador,
            vtg.fecha_inicio,
            vtg.fecha_fin,
            notas.nota1 AS calificacion_1,
            notas.nota2 AS calificacion_2
        FROM
            academica.trabajo_grado tg
        LEFT JOIN
            estudiantes est ON tg.id = est.trabajo_grado
        LEFT JOIN
            academica.areas_trabajo_grado atg ON tg.id = atg.trabajo_grado
        LEFT JOIN
            academica.vinculacion_trabajo_grado vtg ON tg.id = vtg.trabajo_grado
        LEFT JOIN
            usuarios usr ON tg.id = usr.trabajo_grado
        LEFT JOIN
            notas ON tg.id = notas.trabajo_grado
        GROUP BY
            tg.id, tg.titulo, tg.modalidad, tg.estado_trabajo_grado, est.id_estudiante, est.id_coestudiante, atg.area_conocimiento, usr.docente_director, usr.docente_codirector, usr.evaluador, vtg.fecha_inicio, vtg.fecha_fin, notas.nota1, notas.nota2
        ORDER BY
            tg.id DESC`).Values(&results)

    if err != nil {
        return nil, err
    }

    if len(results) == 0 {
        return map[string]interface{}{
            "Success": false,
            "Data":    []interface{}{},
            "Message": "No se encontraron Resultados",
        }, nil
    }

    var reporteGeneral []ReporteGeneral
    contador := 0

    for _, result := range results {
        v := ReporteGeneral{
            Id: contador,
        }

        if val, ok := result["trabajo_grado"].(string); ok {
            v.TrabajoGrado, _ = strconv.Atoi(val)
        }

        if val, ok := result["titulo"].(string); ok && val != "" {
            v.Titulo = val
        }

        if val, ok := result["modalidad"].(string); ok {
            v.Modalidad = val
        }

        if val, ok := result["estado_trabajo_grado"].(string); ok {
            v.EstadoTrabajoGrado = val
        }

        if val, ok := result["id_estudiante"].(string); ok && val != "" {
            v.IdEstudiante = val
        }

        if val, ok := result["id_coestudiante"].(string); ok && val != "" {
            v.IdCoestudiante = val
        }

        if val, ok := result["area_conocimiento"].(string); ok {
            v.AreaConocimiento = val
        }

        if val, ok := result["docente_director"].(string); ok {
            v.DocenteDirector, _ = strconv.Atoi(val)
        }

        if val, ok := result["docente_codirector"].(string); ok && val != "" {
            v.DocenteCodirector, _ = strconv.Atoi(val)
        }

        if val, ok := result["evaluador"].(string); ok && val != "" {
            v.Evaluador, _ = strconv.Atoi(val)
        }

        if val, ok := result["fecha_inicio"].(string); ok {
            fechaInicio, _ := time.Parse(time.RFC3339, val)
            v.FechaInicio = fechaInicio
        }

        if val, ok := result["fecha_fin"].(string); ok && val != "" {
            fechaFin, _ := time.Parse(time.RFC3339, val)
            v.FechaFin = fechaFin
        }

        if val, ok := result["calificacion_1"].(string); ok && val != "" {
            floatVal, _ := strconv.ParseFloat(val, 32)
            v.CalificacionUno = float32(floatVal)
        }

        if val, ok := result["calificacion_2"].(string); ok && val != "" {
            floatVal, _ := strconv.ParseFloat(val, 32)
            v.CalificacionDos = float32(floatVal)
        }

        reporteGeneral = append(reporteGeneral, v)
        contador++
    }

    return map[string]interface{}{
        "Success": true,
        "Data":    reporteGeneral,
    }, nil
}
  1. reporte_solicitud
package models

import (
    "strconv"
    "time"

    "github.com/astaxie/beego/orm"
)

type ReporteSolicitud struct {
    Id                      int    `orm:"column(id)"`
    TrabajoGrado            int    `orm:"column(trabajo_grado)"`
    Titulo                  string `orm:"column(titulo)"`
    Modalidad               string `orm:"column(modalidad)"`
    EstadoTrabajoGrado      string `orm:"column(estado_trabajo_grado)"`
    IdEstudiante            string `orm:"column(id_estudiante)"`
    NombreEstudiante        string
    IdCoestudiante          string `orm:"column(id_coestudiante)"`
    NombreCoestudiante      string
    ProgramaAcademico       string
    Coordinador             int
    NombreCoordinador       string
    DocenteDirector         int `orm:"column(docente_director)"`
    NombreDocenteDirector   string
    DocenteCodirector       int `orm:"column(docente_codirector)"`
    NombreDocenteCodirector string
    Evaluador               int `orm:"column(evaluador)"`
    NombreEvaluador         string
    FechaSolicitud          time.Time `orm:"column(fecha_solicitud);type(timestamp without time zone)"`
    FechaRevision           time.Time `orm:"column(fecha_revision);type(timestamp without time zone);null"`
    Solicitud               string    `orm:"column(tipo_solicitud)"`
    Observacion             string    `orm:"column(justificacion)"`
    Respuesta               string    `orm:"column(estado_solicitud)"`
}

func init() {
    orm.RegisterModel(new(ReporteSolicitud))
}

func GetReporteSolicitud() (map[string]interface{}, error) {
    o := orm.NewOrm()

    var results []orm.Params

    _, err := o.Raw(`
        WITH estudiantes AS (
            SELECT
                trabajo_grado,
                MAX(CASE WHEN row_number = 1 THEN estudiante ELSE NULL END) AS id_estudiante,
                MAX(CASE WHEN row_number = 2 THEN estudiante ELSE NULL END) AS id_coestudiante
            FROM (
                SELECT
                    trabajo_grado,
                    estudiante,
                    ROW_NUMBER() OVER (PARTITION BY trabajo_grado ORDER BY estudiante) AS row_number
                FROM
                    academica.estudiante_trabajo_grado
            ) sub
            GROUP BY
                trabajo_grado
        ),
        usuarios AS (
            SELECT
                trabajo_grado,
                MAX(CASE WHEN rol_trabajo_grado = 4593 THEN usuario ELSE NULL END) AS docente_director,
                MAX(CASE WHEN rol_trabajo_grado = 4594 THEN usuario ELSE NULL END) AS docente_codirector,
                MAX(CASE WHEN rol_trabajo_grado = 4595 THEN usuario ELSE NULL END) AS evaluador
            FROM
                academica.vinculacion_trabajo_grado
            GROUP BY
                trabajo_grado
        )

        SELECT 
            stg.id,
            stg.trabajo_grado,
            tg.titulo,
            mts.modalidad,
            tg.estado_trabajo_grado,
            e.id_estudiante,
            e.id_coestudiante,
            u.docente_director,
            u.docente_codirector,
            u.evaluador,
            stg.fecha AS fecha_solicitud,
            rs.fecha AS fecha_revision,
            mts.tipo_solicitud,
            rs.justificacion,
            rs.estado_solicitud
        FROM 
            academica.solicitud_trabajo_grado stg
        JOIN 
            academica.modalidad_tipo_solicitud mts
            ON stg.modalidad_tipo_solicitud = mts.id
        JOIN 
            academica.trabajo_grado tg
            ON stg.trabajo_grado = tg.id
        LEFT JOIN 
            academica.respuesta_solicitud rs
            ON stg.id = rs.solicitud_trabajo_grado
        LEFT JOIN 
            estudiantes e
            ON stg.trabajo_grado = e.trabajo_grado
        LEFT JOIN 
            usuarios u
            ON stg.trabajo_grado = u.trabajo_grado
        ORDER BY
            stg.id DESC`).Values(&results)

    if err != nil {
        return nil, err
    }

    if len(results) == 0 {
        return map[string]interface{}{
            "Success": false,
            "Data":    []interface{}{},
            "Message": "No se encontraron Resultados",
        }, nil
    }

    var reporteSolicitud []ReporteSolicitud

    for _, result := range results {
        v := ReporteSolicitud{}

        if val, ok := result["id"].(string); ok {
            v.Id, _ = strconv.Atoi(val)
        }

        if val, ok := result["trabajo_grado"].(string); ok {
            v.TrabajoGrado, _ = strconv.Atoi(val)
        }

        if val, ok := result["titulo"].(string); ok && val != "" {
            v.Titulo = val
        }

        if val, ok := result["modalidad"].(string); ok && val != "" {
            v.Modalidad = val
        }

        if val, ok := result["estado_trabajo_grado"].(string); ok && val != "" {
            v.EstadoTrabajoGrado = val
        }

        if val, ok := result["id_estudiante"].(string); ok && val != "" {
            v.IdEstudiante = val
        }

        if val, ok := result["id_coestudiante"].(string); ok && val != "" {
            v.IdCoestudiante = val
        }

        v.ProgramaAcademico = ""

        v.Coordinador = 0

        if val, ok := result["docente_director"].(string); ok {
            v.DocenteDirector, _ = strconv.Atoi(val)
        }

        if val, ok := result["docente_codirector"].(string); ok && val != "" {
            v.DocenteCodirector, _ = strconv.Atoi(val)
        }

        if val, ok := result["evaluador"].(string); ok && val != "" {
            v.Evaluador, _ = strconv.Atoi(val)
        }

        if val, ok := result["fecha_solicitud"].(string); ok {
            fechaSolicitud, _ := time.Parse(time.RFC3339, val)
            v.FechaSolicitud = fechaSolicitud
        }

        if val, ok := result["fecha_revision"].(string); ok && val != "" {
            fechaRevision, _ := time.Parse(time.RFC3339, val)
            v.FechaRevision = fechaRevision
        }

        if val, ok := result["tipo_solicitud"].(string); ok && val != "" {
            v.Solicitud = val
        }

        if val, ok := result["justificacion"].(string); ok && val != "" {
            v.Observacion = val
        }

        if val, ok := result["estado_solicitud"].(string); ok && val != "" {
            v.Respuesta = val
        }

        reporteSolicitud = append(reporteSolicitud, v)
    }

    return map[string]interface{}{
        "Success": true,
        "Data":    reporteSolicitud,
    }, nil
}

POLUX_MID

  1. reporte_general
package models

import (
    "encoding/xml"
    "time"
)

type ReporteGeneral struct {
    Id                      int
    TrabajoGrado            int    `orm:"column(trabajo_grado)"`
    Titulo                  string `orm:"column(titulo)"`
    Modalidad               string `orm:"column(modalidad)"`
    EstadoTrabajoGrado      string `orm:"column(estado)"`
    IdEstudiante            string `orm:"column(id_estudiante)"`
    NombreEstudiante        string
    IdCoestudiante          string `orm:"column(id_coestudiante)"`
    NombreCoestudiante      string
    ProgramaAcademico       string
    AreaConocimiento        string `orm:"column(area_conocimiento)"`
    DocenteDirector         int    `orm:"column(docente_director)"`
    NombreDocenteDirector   string
    DocenteCodirector       int `orm:"column(docente_codirector)"`
    NombreDocenteCodirector string
    Evaluador               int `orm:"column(evaluador)"`
    NombreEvaluador         string
    FechaInicio             time.Time `orm:"column(fecha_inicio);type(timestamp without time zone)"`
    FechaFin                time.Time `orm:"column(fecha_fin);type(timestamp without time zone);null"`
    CalificacionUno         float32   `orm:"column(calificacion_1)"`
    CalificacionDos         float32   `orm:"column(calificacion_2)"`
}

type DatosBasicosEstudiante struct {
    Nombre  string `xml:"nombre"`
    Carrera string `xml:"carrera"`
}

type DatosEstudianteCollection struct {
    XMLName                xml.Name                 `xml:"datosEstudianteCollection"`
    DatosBasicosEstudiante []DatosBasicosEstudiante `xml:"datosBasicosEstudiante"`
}
  1. reporte_solicitud
package models

import (
    "time"
)

type ReporteSolicitud struct {
    Id                      int    `orm:"column(id)"`
    TrabajoGrado            int    `orm:"column(trabajo_grado)"`
    Titulo                  string `orm:"column(titulo)"`
    Modalidad               string `orm:"column(modalidad)"`
    EstadoTrabajoGrado      string `orm:"column(estado_trabajo_grado)"`
    IdEstudiante            string `orm:"column(id_estudiante)"`
    NombreEstudiante        string
    IdCoestudiante          string `orm:"column(id_coestudiante)"`
    NombreCoestudiante      string
    ProgramaAcademico       string
    Coordinador             int
    NombreCoordinador       string
    DocenteDirector         int `orm:"column(docente_director)"`
    NombreDocenteDirector   string
    DocenteCodirector       int `orm:"column(docente_codirector)"`
    NombreDocenteCodirector string
    Evaluador               int `orm:"column(evaluador)"`
    NombreEvaluador         string
    FechaSolicitud          time.Time `orm:"column(fecha_solicitud);type(timestamp without time zone)"`
    FechaRevision           time.Time `orm:"column(fecha_revision);type(timestamp without time zone);null"`
    Solicitud               string    `orm:"column(tipo_solicitud)"`
    Observacion             string    `orm:"column(justificacion)"`
    Respuesta               string    `orm:"column(estado_solicitud)"`
}
  1. reporte_general
package helpers

import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "net/http"
    "strconv"

    "github.com/astaxie/beego/logs"
    "github.com/udistrital/polux_mid/models"
    "github.com/xuri/excelize/v2"
)

func BuildReporteGeneral() error {
    var reporteGeneral []models.ReporteGeneral

    //Se traen todos los datos de reporte general
    url := "/v1/reporte_general"
    if err := GetRequestNew("PoluxCrudUrl", url, &reporteGeneral); err != nil {
        logs.Error("Error al obtener ReporteGeneral: ", err.Error())
        return err
    }

    var parametros []models.Parametro

    //Se trae los Estados, la Modalidad del Trabajo de Grado y las Areas de Conocimiento
    url = "parametro?query=TipoParametroId__in:73|76|3|4&limit=0"
    if err := GetRequestNew("UrlCrudParametros", url, &parametros); err != nil {
        logs.Error("Error al obtener Parametros: ", err.Error())
        return err
    }

    //Crear un mapa de parámetros para facilitar la búsqueda
    parametroMap := make(map[int]string)
    for _, parametro := range parametros {
        parametroMap[parametro.Id] = parametro.Nombre
    }

    // Mapa para almacenar los nombres y carreras de estudiantes ya consultados
    nombresCache := make(map[string]models.DatosBasicosEstudiante)

    //Iterar sobre reporteGeneral y modificar los campos necesarios
    for i, rg := range reporteGeneral {
        if modalidadID, err := strconv.Atoi(rg.Modalidad); err == nil {
            if nombre, ok := parametroMap[modalidadID]; ok {
                reporteGeneral[i].Modalidad = nombre
            }
        }

        if estadoID, err := strconv.Atoi(rg.EstadoTrabajoGrado); err == nil {
            if nombre, ok := parametroMap[estadoID]; ok {
                reporteGeneral[i].EstadoTrabajoGrado = nombre
            }
        }

        if areaID, err := strconv.Atoi(rg.AreaConocimiento); err == nil {
            if nombre, ok := parametroMap[areaID]; ok {
                reporteGeneral[i].AreaConocimiento = nombre
            }
        }

        // Procesar IdEstudiante
        if rg.IdEstudiante != "" {
            if datos, exists := nombresCache[rg.IdEstudiante]; exists {
                // Si el nombre y carrera ya están en el cache, usarlos directamente
                reporteGeneral[i].NombreEstudiante = datos.Nombre
                reporteGeneral[i].ProgramaAcademico = datos.Carrera
            } else {
                // Si no están en el cache, obtenerlos y guardarlos
                datos, err := obtenerDatosEstudiante(rg.IdEstudiante)
                if err != nil {
                    logs.Error("Error al obtener datos del estudiante: ", err.Error())
                } else {
                    reporteGeneral[i].NombreEstudiante = datos.Nombre
                    reporteGeneral[i].ProgramaAcademico = datos.Carrera
                    nombresCache[rg.IdEstudiante] = datos // Guardar en el cache
                }
            }
        }

        // Procesar IdCoestudiante (sin modificar ProgramaAcademico)
        if rg.IdCoestudiante != "" {
            if datos, exists := nombresCache[rg.IdCoestudiante]; exists {
                // Si el nombre ya está en el cache, usarlo directamente
                reporteGeneral[i].NombreCoestudiante = datos.Nombre
            } else {
                // Si no están en el cache, obtenerlos y guardarlos
                datos, err := obtenerDatosEstudiante(rg.IdCoestudiante)
                if err != nil {
                    logs.Error("Error al obtener datos del coestudiante: ", err.Error())
                } else {
                    reporteGeneral[i].NombreCoestudiante = datos.Nombre
                    nombresCache[rg.IdCoestudiante] = datos // Guardar en el cache
                }
            }
        }
    }

    // Traer docentes
    docenteMap, err := obtenerDocentes()
    if err != nil {
        logs.Error("Error al obtener docentes: ", err.Error())
        return err
    }

    // Mapa para almacenar los nombres de carreras ya consultadas
    carreraCache := make(map[string]string)

    //Hubo la necesidad de iterar nuevamente sobre reporteGeneral, ya que se necesitaba que se añadiera primero el id de la carrera a ProgramaAcademico a través del anterior for, para luego obtener el nombre de la carrera y está fue la única manera (aunque a mi parecer no tan óptima)
    for i, rg := range reporteGeneral {
        // Obtener nombre de la carrera a partir del ID almacenado en ProgramaAcademico
        if rg.ProgramaAcademico != "" {
            if nombreCarrera, exists := carreraCache[rg.ProgramaAcademico]; exists {
                // Si el nombre de la carrera ya está en el cache, usarlo directamente
                reporteGeneral[i].ProgramaAcademico = nombreCarrera
            } else {
                // Si no está en el cache, obtenerlo y guardarlo
                nombreCarrera, err := obtenerNombreCarrera(rg.ProgramaAcademico)
                if err != nil {
                    logs.Error("Error al obtener el nombre de la carrera: ", err.Error())
                } else {
                    reporteGeneral[i].ProgramaAcademico = nombreCarrera
                    carreraCache[rg.ProgramaAcademico] = nombreCarrera // Guardar en el cache
                }
            }
        }

        // Asignar nombres de docentes
        if nombre, exists := docenteMap[rg.DocenteDirector]; exists {
            reporteGeneral[i].NombreDocenteDirector = nombre
        }
        if nombre, exists := docenteMap[rg.DocenteCodirector]; exists {
            reporteGeneral[i].NombreDocenteCodirector = nombre
        }
        if nombre, exists := docenteMap[rg.Evaluador]; exists {
            reporteGeneral[i].NombreEvaluador = nombre
        }
    }

    //Título de las Columnas del Excel
    headers := map[string]string{
        "A1": "Trabajo Grado",
        "B1": "Título",
        "C1": "Modalidad",
        "D1": "Estado",
        "E1": "ID Estudiante",
        "F1": "Nombre Estudiante",
        "G1": "ID Estudiante",
        "H1": "Nombre Estudiante",
        "I1": "Programa Academico",
        "J1": "Area Conocimiento",
        "K1": "ID Docente Director",
        "L1": "Nombre Docente Director",
        "M1": "ID Docente Codirector",
        "N1": "Nombre Docente Codirector",
        "O1": "ID Evaluador",
        "P1": "Nombre Evaluador",
        "Q1": "Fecha Inicio",
        "R1": "Fecha Fin",
        "S1": "Calificación 1",
        "T1": "Calificación 2",
    }

    //Creación e Inicialización del Excel
    file := excelize.NewFile()

    //Definir el estilo para los Encabezados
    style := &excelize.Style{
        Fill: excelize.Fill{
            Type:    "pattern",
            Color:   []string{"#FFFF00"},
            Pattern: 1,
        },
        Border: []excelize.Border{
            {Type: "left", Color: "000000", Style: 1},
            {Type: "top", Color: "000000", Style: 1},
            {Type: "bottom", Color: "000000", Style: 1},
            {Type: "right", Color: "000000", Style: 1},
        },
    }

    //Precargar los estilos a la hoja de calculo
    styleID, err := file.NewStyle(style)
    if err != nil {
        fmt.Println(err)
        return err
    }

    //Recorrer los headers y añadir a la hoja de cálculo del Excel
    for k, v := range headers {
        file.SetCellValue("Sheet1", k, v)
        file.SetCellStyle("Sheet1", k, k, styleID) // Aplicar el estilo de fondo amarillo
    }

    //Recorrer cada elemento del Slice de ReporteGeneral y escribir en cada fila del Excel su respectiva información
    for i := 0; i < len(reporteGeneral); i++ {
        rowCount := i + 2

        file.SetCellValue("Sheet1", fmt.Sprintf("A%v", rowCount), reporteGeneral[i].TrabajoGrado)
        file.SetCellValue("Sheet1", fmt.Sprintf("B%v", rowCount), reporteGeneral[i].Titulo)
        file.SetCellValue("Sheet1", fmt.Sprintf("C%v", rowCount), reporteGeneral[i].Modalidad)
        file.SetCellValue("Sheet1", fmt.Sprintf("D%v", rowCount), reporteGeneral[i].EstadoTrabajoGrado)
        file.SetCellValue("Sheet1", fmt.Sprintf("E%v", rowCount), reporteGeneral[i].IdEstudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("F%v", rowCount), reporteGeneral[i].NombreEstudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("G%v", rowCount), reporteGeneral[i].IdCoestudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("H%v", rowCount), reporteGeneral[i].NombreCoestudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("I%v", rowCount), reporteGeneral[i].ProgramaAcademico)
        file.SetCellValue("Sheet1", fmt.Sprintf("J%v", rowCount), reporteGeneral[i].AreaConocimiento)
        file.SetCellValue("Sheet1", fmt.Sprintf("K%v", rowCount), reporteGeneral[i].DocenteDirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("L%v", rowCount), reporteGeneral[i].NombreDocenteDirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("M%v", rowCount), reporteGeneral[i].DocenteCodirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("N%v", rowCount), reporteGeneral[i].NombreDocenteCodirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("O%v", rowCount), reporteGeneral[i].Evaluador)
        file.SetCellValue("Sheet1", fmt.Sprintf("P%v", rowCount), reporteGeneral[i].NombreEvaluador)
        file.SetCellValue("Sheet1", fmt.Sprintf("Q%v", rowCount), reporteGeneral[i].FechaInicio.Format("2006-01-02"))
        file.SetCellValue("Sheet1", fmt.Sprintf("R%v", rowCount), reporteGeneral[i].FechaFin.Format("2006-01-02"))
        file.SetCellValue("Sheet1", fmt.Sprintf("S%v", rowCount), reporteGeneral[i].CalificacionUno)
        file.SetCellValue("Sheet1", fmt.Sprintf("T%v", rowCount), reporteGeneral[i].CalificacionDos)
    }

    //Guardar el archivo Excel en este caso en la raíz del proyecto
    if err := file.SaveAs("ReporteGeneral.xlsx"); err != nil {
        fmt.Println(err)
    }

    return nil
}

func obtenerDatosEstudiante(idEstudiante string) (models.DatosBasicosEstudiante, error) {
    url := fmt.Sprintf("http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/datos_basicos_estudiante/%s", idEstudiante)

    resp, err := http.Get(url)
    if err != nil {
        return models.DatosBasicosEstudiante{}, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return models.DatosBasicosEstudiante{}, fmt.Errorf("Error al realizar la solicitud: %s", resp.Status)
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return models.DatosBasicosEstudiante{}, err
    }

    var datos models.DatosEstudianteCollection
    if err := xml.Unmarshal(body, &datos); err != nil {
        return models.DatosBasicosEstudiante{}, err
    }

    if len(datos.DatosBasicosEstudiante) > 0 {
        return datos.DatosBasicosEstudiante[0], nil
    }

    return models.DatosBasicosEstudiante{}, fmt.Errorf("No se encontraron datos para el estudiante %s", idEstudiante)
}

func obtenerNombreCarrera(idCarrera string) (string, error) {
    url := fmt.Sprintf("http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/carrera/%s", idCarrera)

    resp, err := http.Get(url)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return "", fmt.Errorf("error al realizar la solicitud: %s", resp.Status)
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }

    var carreraCollection struct {
        Carrera struct {
            Nombre string `xml:"nombre"`
        } `xml:"carrera"`
    }

    if err := xml.Unmarshal(body, &carreraCollection); err != nil {
        return "", err
    }

    return carreraCollection.Carrera.Nombre, nil
}

func obtenerDocentes() (map[int]string, error) {
    url := "http://busservicios.intranetoas.udistrital.edu.co:8282/wso2eiserver/services/servicios_academicos/get_docentes_tg"

    resp, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("error al realizar la solicitud: %s", resp.Status)
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    var docentes struct {
        Docentes []struct {
            ID     int    `xml:"id"`
            Nombre string `xml:"NOMBRE"`
        } `xml:"docente"`
    }

    if err := xml.Unmarshal(body, &docentes); err != nil {
        return nil, err
    }

    docenteMap := make(map[int]string)
    for _, docente := range docentes.Docentes {
        docenteMap[docente.ID] = docente.Nombre
    }

    return docenteMap, nil
}
  1. reporte_solicitud

Se encuentra en espera, ya que se necesita de los endpoints para traer la información de los coordinadores, sin embargo, la implementación del restante es igual al anterior informe (reporte_general) por lo que el avance de este helper es del 85%.

package helpers

import (
    "fmt"
    "strconv"

    "github.com/astaxie/beego/logs"
    "github.com/udistrital/polux_mid/models"
    "github.com/xuri/excelize/v2"
)

func BuildReporteSolicitud() error {
    var reporteSolicitud []models.ReporteSolicitud

    //Se traen todos los datos de reporte solicitud del CRUD
    url := "/v1/reporte_solicitud"
    if err := GetRequestNew("PoluxCrudUrl", url, &reporteSolicitud); err != nil {
        logs.Error("Error al obtener ReporteSolicitud: ", err.Error())
        return err
    }

    var parametros []models.Parametro

    //Se trae los Estados, la Modalidades, los Tipo Solicitud y los Estados de Solicitud de Trabajo de Grado de Parametros
    url = "parametro?query=TipoParametroId__in:73|76|77|78&limit=0"
    if err := GetRequestNew("UrlCrudParametros", url, &parametros); err != nil {
        logs.Error("Error al obtener Parametros: ", err.Error())
        return err
    }

    //Crear un mapa de parámetros para facilitar la búsqueda
    parametroMap := make(map[int]string)
    for _, parametro := range parametros {
        parametroMap[parametro.Id] = parametro.Nombre
    }

    //Iterar sobre reporteSolicitud y modificar los campos necesarios
    for i, rs := range reporteSolicitud {
        if modalidadID, err := strconv.Atoi(rs.Modalidad); err == nil {
            if nombre, ok := parametroMap[modalidadID]; ok {
                reporteSolicitud[i].Modalidad = nombre
            }
        }

        if estadoID, err := strconv.Atoi(rs.EstadoTrabajoGrado); err == nil {
            if nombre, ok := parametroMap[estadoID]; ok {
                reporteSolicitud[i].EstadoTrabajoGrado = nombre
            }
        }

        if tipoSolicitudID, err := strconv.Atoi(rs.Solicitud); err == nil {
            if nombre, ok := parametroMap[tipoSolicitudID]; ok {
                reporteSolicitud[i].Solicitud = nombre
            }
        }

        if estadoSolicitudID, err := strconv.Atoi(rs.Respuesta); err == nil {
            if nombre, ok := parametroMap[estadoSolicitudID]; ok {
                reporteSolicitud[i].Respuesta = nombre
            }
        }
    }

    //Título de las Columnas del Excel
    headers := map[string]string{
        "A1": "ID Solicitud",
        "B1": "Trabajo Grado",
        "C1": "Título",
        "D1": "Modalidad",
        "E1": "Estado Trabajo Grado",
        "F1": "ID Estudiante",
        "G1": "Nombre Estudiante",
        "H1": "ID Estudiante",
        "I1": "Nombre Estudiante",
        "J1": "Programa Academico",
        "K1": "ID Coordinador",
        "L1": "Nombre Coordinador",
        "M1": "ID Docente Director",
        "N1": "Nombre Docente Director",
        "O1": "ID Docente Codirector",
        "P1": "Nombre Docente Codirector",
        "Q1": "ID Evaluador",
        "R1": "Nombre Evaluador",
        "S1": "Fecha Solicitud",
        "T1": "Fecha Revision",
        "U1": "Concepto de Revision",
        "V1": "Observaciones",
        "W1": "Respuesta",
    }

    //Creación e Inicialización del Excel
    file := excelize.NewFile()

    //Definir el estilo para los Encabezados
    style := &excelize.Style{
        Fill: excelize.Fill{
            Type:    "pattern",
            Color:   []string{"#FFFF00"},
            Pattern: 1,
        },
        Border: []excelize.Border{
            {Type: "left", Color: "000000", Style: 1},
            {Type: "top", Color: "000000", Style: 1},
            {Type: "bottom", Color: "000000", Style: 1},
            {Type: "right", Color: "000000", Style: 1},
        },
    }

    //Precarsar los estilos a la hoja de calculo
    styleID, err := file.NewStyle(style)
    if err != nil {
        fmt.Println(err)
        return err
    }

    //Recorrer los headers y añadir a la hoja de cálculo del Excel
    for k, v := range headers {
        file.SetCellValue("Sheet1", k, v)
        file.SetCellStyle("Sheet1", k, k, styleID) // Aplicar el estilo de fondo amarillo
    }

    //Recorrer cada elemento del Slice de ReporteSolicitud y escribir en cada fila del Excel su respectiva información
    for i := 0; i < len(reporteSolicitud); i++ {
        rowCount := i + 2

        file.SetCellValue("Sheet1", fmt.Sprintf("A%v", rowCount), reporteSolicitud[i].Id)
        file.SetCellValue("Sheet1", fmt.Sprintf("B%v", rowCount), reporteSolicitud[i].TrabajoGrado)
        file.SetCellValue("Sheet1", fmt.Sprintf("C%v", rowCount), reporteSolicitud[i].Titulo)
        file.SetCellValue("Sheet1", fmt.Sprintf("D%v", rowCount), reporteSolicitud[i].Modalidad)
        file.SetCellValue("Sheet1", fmt.Sprintf("E%v", rowCount), reporteSolicitud[i].EstadoTrabajoGrado)
        file.SetCellValue("Sheet1", fmt.Sprintf("F%v", rowCount), reporteSolicitud[i].IdEstudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("G%v", rowCount), reporteSolicitud[i].NombreEstudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("H%v", rowCount), reporteSolicitud[i].IdCoestudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("I%v", rowCount), reporteSolicitud[i].NombreCoestudiante)
        file.SetCellValue("Sheet1", fmt.Sprintf("J%v", rowCount), reporteSolicitud[i].ProgramaAcademico)
        file.SetCellValue("Sheet1", fmt.Sprintf("K%v", rowCount), reporteSolicitud[i].Coordinador)
        file.SetCellValue("Sheet1", fmt.Sprintf("L%v", rowCount), reporteSolicitud[i].NombreCoordinador)
        file.SetCellValue("Sheet1", fmt.Sprintf("M%v", rowCount), reporteSolicitud[i].DocenteDirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("N%v", rowCount), reporteSolicitud[i].NombreDocenteDirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("O%v", rowCount), reporteSolicitud[i].DocenteCodirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("P%v", rowCount), reporteSolicitud[i].NombreDocenteCodirector)
        file.SetCellValue("Sheet1", fmt.Sprintf("Q%v", rowCount), reporteSolicitud[i].Evaluador)
        file.SetCellValue("Sheet1", fmt.Sprintf("R%v", rowCount), reporteSolicitud[i].NombreEvaluador)
        file.SetCellValue("Sheet1", fmt.Sprintf("S%v", rowCount), reporteSolicitud[i].FechaSolicitud.Format("2006-01-02"))
        file.SetCellValue("Sheet1", fmt.Sprintf("T%v", rowCount), reporteSolicitud[i].FechaRevision.Format("2006-01-02"))
        file.SetCellValue("Sheet1", fmt.Sprintf("U%v", rowCount), reporteSolicitud[i].Solicitud)
        file.SetCellValue("Sheet1", fmt.Sprintf("V%v", rowCount), reporteSolicitud[i].Observacion)
        file.SetCellValue("Sheet1", fmt.Sprintf("W%v", rowCount), reporteSolicitud[i].Respuesta)
    }

    //Guardar el archivo Excel en este caso en la raíz del proyecto
    if err := file.SaveAs("ReporteSolicitud.xlsx"); err != nil {
        fmt.Println(err)
    }

    return nil
}
CrisEs2506 commented 1 month ago

Resultado Reporte General - Excel

ReporteGeneral.xlsx

diagutierrezro commented 1 month ago

Falta información de coordinadores, se debe buscar dicha información en las bases de datos de oracle, se manejará en otro issue.