import os import json from pathlib import Path from dotenv import load_dotenv from logger_manager import get_logger # ============================================================================ load_dotenv() logger = get_logger("hana") CONFIG_FILE = Path(__file__).parent / "config.json" _conn = None _cfg_hana = None # ============================================================================ def _cargar_config(): global _cfg_hana if _cfg_hana is None: with open(CONFIG_FILE, encoding="utf-8") as f: data = json.load(f) _cfg_hana = data["hana"] return _cfg_hana # ============================================================================ def get_connection(): global _conn if _conn is None: try: cfg = _cargar_config() from hdbcli import dbapi _conn = dbapi.connect( address=cfg["host"], port=cfg["port"], user=cfg["user"], password=cfg["password"] ) except Exception as e: logger.error(f" โŒ Error conectando a HANA: {e}") return None return _conn # ============================================================================ def _nombres_rucs(rucs) -> str: if not rucs: return "" return ",".join(f"'{r}'" for r in rucs) # ============================================================================ def obtener_pendientes(schema: str, rucs: list[str], days: int = 240) -> list[dict]: conn = get_connection() if not conn: return [] filtro_rucs = _nombres_rucs(rucs) cond_rucs = f"AND T0.\"LicTradNum\" IN ({filtro_rucs})" if filtro_rucs else "" try: query = f""" SELECT T0."DocNum", T0."DocEntry", TO_VARCHAR(T0."DocDate",'YYYY-MM-DD') "DocDate" , TO_VARCHAR(T0."TaxDate",'YYYY-MM-DD') "TaxDate", T0."CardName", T0."FolioPref", T0."FolioNum", T0."Indicator", T0."DocCur" , CASE T0."DocCur" WHEN 'SOL' THEN T0."DocTotal" ELSE T0."DocTotalFC" END "DocTotal" , T0."U_PGX_REPIMP" "urlPDF" , T0."U_PGX_PDF" "tienePDF" , T0."U_PGX_REPIMPXML" "urlXML" , T0."U_PGX_XML" "tieneXML" , T0."LicTradNum" FROM "{schema}".OPCH T0 WHERE T0."CANCELED" = 'N' {cond_rucs} AND T0."Indicator" IN ('01', '02','08') AND (IFNULL(T0."U_PGX_PDF",'N') = 'N' OR IFNULL(T0."U_PGX_XML",'N') = 'N') AND T0."CreateDate" >= ADD_DAYS(CURRENT_DATE, -{days}); """ cursor = conn.cursor() cursor.execute(query) columns = [desc[0] for desc in cursor.description] rows = cursor.fetchall() cursor.close() result = [dict(zip(columns, row)) for row in rows] for d in result: d["schema"] = schema return result except Exception as e: logger.error(f" โŒ Error en query HANA: {e}") return [] # ============================================================================ def marcar_pdf_descargado(schema: str, docentry: int, url: str, ruta: str): conn = get_connection() if not conn: return False try: cursor = conn.cursor() cursor.execute(f""" UPDATE "{schema}".OPCH SET "U_PGX_PDF" = 'Y' WHERE "DocEntry" = ? """, (docentry,)) conn.commit() cursor.close() return True except Exception as e: logger.error(f" โŒ Error actualizando PDF HANA: {e}") return False # ============================================================================ def marcar_xml_descargado(schema: str, docentry: int, url: str, ruta: str): conn = get_connection() if not conn: return False try: cursor = conn.cursor() cursor.execute(f""" UPDATE "{schema}".OPCH SET "U_PGX_XML" = 'Y' WHERE "DocEntry" = ? """, (docentry,)) conn.commit() cursor.close() return True except Exception as e: logger.error(f" โŒ Error actualizando XML HANA: {e}") return False # ============================================================================ def cerrar_conexion(): global _conn if _conn: try: _conn.close() except: pass _conn = None # ============================================================================ if __name__ == "__main__": logger.info("=" * 60) logger.info("๐Ÿ“‹ HANA MANAGER - Prueba") logger.info("=" * 60) with open(CONFIG_FILE, encoding="utf-8") as f: cfg = json.load(f) for emp in cfg["empresas"]: logger.info(f"\n๐Ÿข Empresa: {emp['nombre']} (schema={emp['schema']})") docs = obtener_pendientes(emp["schema"], cfg.get("rucs", []), cfg.get("consulta", {}).get("dias", 240)) logger.info(f" ๐Ÿ“„ Documentos pendientes: {len(docs)}") for d in docs[:5]: logger.info(f" DocEntry={d['DocEntry']} DocNum={d['DocNum']} " f"DocDate={d['DocDate']} Indicator={d['Indicator']} " f"Folio={d['FolioPref']}-{d['FolioNum']} " f"PDF={d['tienePDF']} XML={d['tieneXML']}") if len(docs) > 5: logger.info(f" ... y {len(docs) - 5} mรกs") # ============================================================================