Closed diagutierrezro closed 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.
Respuesta:
Respuesta:
Respuesta
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).
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
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
}
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
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"`
}
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)"`
}
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, ¶metros); 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
}
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, ¶metros); 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
}
Resultado Reporte General - Excel
Falta información de coordinadores, se debe buscar dicha información en las bases de datos de oracle, se manejará en otro issue.
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