first commit

This commit is contained in:
Eidan T.
2026-05-09 14:00:04 -04:00
commit e0ec11977c
42 changed files with 4596 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
#from .etl_service import *
+23
View File
@@ -0,0 +1,23 @@
# Servicio API: endpoints GET para descarga
from flask import Flask, request, jsonify
from App.Services.logic_service import run_etl # O importa db_utils directamente
import pandas as pd
import logging
app = Flask(__name__)
logging.basicConfig(filename='Logs/api.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
@app.route('/api/download', methods=['GET'])
def download_data():
try:
project = request.args.get('project')
task = request.args.get('task')
# Lógica: query DB y devolver JSON/CSV
conn = get_db_connection() # Importa de Utils
query = f"SELECT * FROM {task} WHERE project = '{project}'"
df = pd.read_sql(query, conn)
conn.close()
return jsonify(df.to_dict(orient='records'))
except Exception as e:
logging.error(f"API falló: {str(e)}")
return jsonify({"error": "Error interno del servidor"}), 500 # Devuelve error, pero Flask sigue vivo
+339
View File
@@ -0,0 +1,339 @@
import sys
import os
from typeguard import config
# subir 2 niveles hasta la raíz (donde está App)
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
from App.Utils.db_utils import DatabaseManager # Reutilizado de db_utils.py
from App.Config.GeneralConfig import GeneralConfig # Reutilizado de GeneralConfig.py
from App.Config.pgConfig import PGConfig # Reutilizado de PGConfig.py
from App.Config.version import APP_NAME, VERSION, AUTHOR # Reutilizado de version.py
from App.Utils.report_utils import ReportGenerator # Nueva utilidad para generar reportes (ej. Excel)
import logging
from datetime import datetime
# Configura logging
logging.basicConfig(filename='Logs/etl.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
def run_etl(config, data_report, target_date_report):
'''Función principal para ejecutar ETL.
Lee los datos desde la base de datos, los transforma en un excel y los sube a SharePoint.
Args:
config: Configuración general de la aplicación.
database: Instancia de la clase DatabaseManager.
data_report: Diccionario con la información del reporte a generar.
target_date_report: Fecha objetivo para filtrar datos (str, formato 'YYYY-MM-DD')
Returns:
Tuple[bool, str]: Una tupla con el resultado de la operación y un mensaje informativo.
'''
date_execution = datetime.now(GeneralConfig.zoneTime)
target_date_report_format = target_date_report.strftime('%Y-%m-%d')
result = {
"errors": []
} # Lista para almacenar errores y mensajes informativos
################################## INICIANDO REPORTE ##################################
config.database.log_execution(procedure_id=str(config.database.db_databaseID)+str('0003')+str('0189')+str(data_report['reportID']),
procedure_name='Trasmision Datos '+str(data_report['project_name'])+' '+str(data_report['report_name']),
status='STARTING',
message='Inicializando la trasmision de reporte: '+str(data_report['report_name']),
executed_by=str(config.database.db_user),
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=str(date_execution))
################################ OBTENIENDO DATOS DE LA BASE DE DATOS ##################################
try:
query = f"SELECT * FROM {data_report['Table_Name']} WHERE Fecha = '{target_date_report_format}'"
print(query)
data_sql_report = config.database.get_execute_query(query)
if not data_sql_report:
print(f"No se encontraron datos para el reporte {data_report['report_name']} en la fecha {target_date_report_format}")
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'WARNING',
message=f"No se encontraron datos para el reporte {data_report['report_name']} en la fecha {target_date_report_format}",
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=f'{date_execution}')
return {
"status": "WARNING",
"report": data_report["report_name"],
"message": "Sin datos en la base de datos"
}
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'SUCCESS',
message=f'Lectura de la base datos para crear reporte :{data_report["report_name"]}',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=f'{date_execution}')
except Exception as e:
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'FAILED',
message=f'Error en la lectura de la base datos para crear reporte :{data_report["report_name"]}',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=str(e),
target_date=target_date_report_format,
date=f'{date_execution}')
return {
"status": "FAILED",
"report": data_report["report_name"],
"message": f"Error lectura BD {str(e)}"
}
################################ CREANDO REPORTE EN EXCEL ##################################
try:
doc_report = ReportGenerator(target_date_report,**data_report)
doc_report.createReportData(data_sql_report)
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'SUCCESS',
message=f'Creación del reporte :{data_report["report_name"] } en formato Excel',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=f'{date_execution}')
except Exception as e:
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'FAILED',
message=f'Error en la creación del reporte :{data_report["report_name"] } en formato Excel',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=str(e),
target_date=target_date_report_format,
date=f'{date_execution}')
return {
"status": "FAILED",
"report": data_report["report_name"],
"message": f"Error creación del reporte {str(e)}"
}
################################ SUBIR REPORTE A FTP ###############################
if data_report.get('FTP', False):
try:
ftp_path = f"/www/TranferData_APP_PYTHON/{config.project_name}/{data_report['report_name']}/"
#print(ftp_path)
config.ftpdatabase.uploadFile(ftp_path, doc_report.docsend_Path) # Asegúrate de que la configuración FTP esté presente en el config general
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'SUCCESS',
message=f'Subida del reporte :{data_report["report_name"] } a FTP',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=f'{date_execution}')
except Exception as e:
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'FAILED',
message=f'Error en la subida del reporte :{data_report["report_name"] } a FTP',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=str(e),
target_date=target_date_report_format,
date=f'{date_execution}')
result["errors"].append(f"Error subir reporte a FTP {str(e)}")
#return {
# "status": "FAILED",
# "report": data_report["report_name"],
# "message": f"Error subir reporte a FTP {str(e)}"
#}
############################### SUBIR REPORTA A SFTP ##################################
if data_report.get('SFTP', False):
try:
# Lógica para subir a SFTP (puedes usar paramiko o alguna librería similar)
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'SUCCESS',
message=f'Subida del reporte :{data_report["report_name"] } a SFTP',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=f'{date_execution}')
except Exception as e:
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'FAILED',
message=f'Error en la subida del reporte :{data_report["report_name"] } a SFTP',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=str(e),
target_date=target_date_report_format,
date=f'{date_execution}')
result["errors"].append(f"Error subir reporte a SFTP {str(e)}")
#return {
# "status": "FAILED",
# "report": data_report["report_name"],
# "message": f"Error subir reporte a SFTP {str(e)}"
#}
################################ SUBIR REPORTE A SHAREPOINT PYTHON ##################################
if data_report.get('SharePoint', False):
try:
sharepoint_folder = config.sharepointPath.get(data_report['reportID'])
if not sharepoint_folder:
raise Exception(f"No existe ruta SharePoint para reportID {data_report['reportID']}")
config.sharepoint.uploadFile(doc_report, sharepoint_folder)
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'SUCCESS',
message=f'Subida del reporte :{data_report["report_name"] } a SharePoint usando Python',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=f'{date_execution}')
except Exception as e:
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'FAILED',
message=f'Error en la subida del reporte :{data_report["report_name"] } a SharePoint usando Python',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=str(e),
target_date=target_date_report_format,
date=f'{date_execution}')
result["errors"].append(f"Error subir reporte a SharePoint usando Python {str(e)}" )
#return {
# "status": "FAILED",
# "report": data_report["report_name"],
# "message": f"Error subir reporte a SharePoint usando Python {str(e)}"
#}
################################ SUBIR REPORTE A SHAREPOINT N8N ##################################
if data_report.get('N8N', False):
try:
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'SUCCESS',
message=f'Subida del reporte :{data_report["report_name"] } a SharePoint usando N8N',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=None,
target_date=target_date_report_format,
date=f'{date_execution}')
except Exception as e:
config.database.log_execution(procedure_id=f'{config.database.db_databaseID}00030189{data_report["reportID"]}',
procedure_name=f'Trasmision Datos {data_report["project_name"]} {data_report["report_name"]}',
status=f'FAILED',
message=f'Error en la subida del reporte :{data_report["report_name"] } a SharePoint usando N8N',
executed_by=f'{config.database.db_user}',
source= f'{APP_NAME}_{VERSION}',
extra_info=str(e),
target_date=target_date_report_format,
date=f'{date_execution}')
result["errors"].append(f"Error subir reporte a SharePoint usando N8N {str(e)}")
#return {
# "status": "FAILED",
# "report": data_report["report_name"],
# "message": f"Error subir reporte a SharePoint usando N8N {str(e)}"
#}
#################################################################################################
if result["errors"]:
return {
"status": "COMPLETED_WITH_ERRORS",
"report": data_report["report_name"],
"message": " | ".join(result["errors"])
}
else:
return {
"status": "SUCCESS",
"report": data_report["report_name"],
"message": "ETL ejecutado exitosamente"
}
# Aquí va la lógica de ETL específica para cada proyecto y reporte
# Por simplicidad, loggea que se ejecutó
#logging.info(f"ETL ejecutado para proyecto: {project}, reporte: {report_name}, usando config: {config.project_name}")
"""
pg_config = PGConfig()
database = DatabaseManager(pg_config.database, pg_config.databaseID)
data_report = {
'project_name': 'PG',
'report_name': 'Cobertura',
'Table_Name': 'ReportCobertura',
'nowTime': GeneralConfig.nowTime,
'nowTimeFormat': GeneralConfig.nowTimeFormat,
'project_name': pg_config.project_name,
'current_time': GeneralConfig.execution_time,
'reportID': '0001'
}
run_etl(pg_config, database, data_report, target_date_report='2026-03-26')"""
+13
View File
@@ -0,0 +1,13 @@
# Servicio UI: manejo de forms web
from flask import render_template, request
from App.Services.logic_service import run_etl
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
project = request.form['project']
task = request.form['task']
# Trigger ETL manual
run_etl(project, task)
return "ETL ejecutado"
return render_template('index.html')