# para argumentos
import sys
# para tiempo a esperar
import time
# para csv leer y escribir
import csv
# importar modulo para trabajar con postgresql
import pg8000
# para obtener hora del sistema
from datetime import datetime
# para carpetas crear y acceder
from pathlib import Path
# para levantar navegador chrome
import undetected_chromedriver as uc
# import undetected_chromedriver.v2 as uc
from selenium.webdriver.common.by import By
# para hacer select a elementos
from selenium.webdriver.support.ui import Select
# para esperar en una consulta web
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Función para validar formato AAAA-MM
def valformat_periodo(periodo):
	try:
		# Intenta convertirlo a fecha
		datetime.strptime(periodo, "%Y-%m")
		# si se pudo convertir retornamos true
		return True
	# o si no se pudo la exepcion
	except ValueError:
		# retornamos false
		return False

# declaramos variable de debug vacia
d=''

# Verifica si se proporciono el argumento, recordar que el primer argumento
# por defecto es el nombre del script y el segundo tendria que ser el parametro
# que estamos proporcionando, por lo tanto evaluamos si el largo de los argumentos
# pasados al script es igual a 2
if len(sys.argv) == 2:
	# establecemos el primer argumento en variable 
	arg1 = sys.argv[1]
	# dejamos el segundo argumento en vacio
	arg2 = None
# de lo contrario si, se proporcionaron 3 argumentos
elif len(sys.argv) == 3:
	# establecemos el primer argumento en variable
	arg1 = sys.argv[1]
	# establecemos el segundo argumento en variable debug
	d = sys.argv[2]
# de lo contrario si no se proporciono parametros
else:
	# establecemos el primer argumento en vacio
	arg1 = None
	# dejamos el segundo argumento en vacio
	arg2 = None

# validamos los parametros, primero para valor de debug
if d and d != "d" and d != "debug":
	# desplegamos error de reconocimiento de parametro
	print(f"error. parametro para debug debe ser 'd' o 'debug', parametro evaluado fue: d=\"{d}\"", file=sys.stderr)
	# salimos del script
	sys.exit(1)

if d: print(f"DEBUG ## ARGUMENTOS RECIVIDOS SON:")
if d: print(f"DEBUG ## argV1=|{sys.argv[1]}|")
if d: print(f"DEBUG ## argV2=|{sys.argv[2]}|")
 
# obtenemos la fecha del sistema y almacenamos en variable temporal
tfechs = datetime.now().strftime("%Y-%m")
# obtenemos ano y mes del sistema y almacenamos en variables
# obtenemos el año y el mes por separado del periodo
anio1, mes1 = tfechs.split("-")
# imprimimos mensaje con año y mes obtenidos del sistema
if d: print(f"DEBUG ## PERIODO OBTENIDO DEL SISTEMA (AAAA-MM) ES")
if d: print(f"DEBUG ## tfechs=|{tfechs}|")
if d: print(f"DEBUG ## ANIO ES")
if d: print(f"DEBUG ## anio1=|{anio1}|")
if d: print(f"DEBUG ## MES ES")
if d: print(f"DEBUG ## mes1=|{mes1}|")
#if len(sys.argv) == 2:
if arg1:
	# si se proporciono el argumento lo almacenamos en variable
	periodo_arg = sys.argv[1]
	# imprimimos el argumento obtenido
	if d: print(f"DEBUG ## SE PROPORCIONO PERIODO COMO ARGUMENTO, SE VALIDA FORMATO")
	# validamos el formato
	if valformat_periodo(periodo_arg):
		# establecemos valor para periodo
		per = periodo_arg
		# si es correcto obtenemos el año y el mes por separado
		anio, mes = per.split("-")
		if d: print(f"DEBUG ## FORMATO VALIDO, SE ESTABLECEN VARIABLES DESDE ARGUMENTO")
		if d: print(f"DEBUG ## per=|{per}|")
		if d: print(f"DEBUG ## ANIO ES")
		if d: print(f"DEBUG ## anio=|{anio}|")
		if d: print(f"DEBUG ## MES ES")
		if d: print(f"DEBUG ## mes=|{mes}|")		
	# de lo contrario
	else:
		# establecemos los valores para el periodo año y mes desde la fecha obtenida
		# del sistema
		anio = anio1
		mes = mes1
		per = tfechs
		# desplegamos mensaje de periodo proporcionado como argumento invalido
		if d: print(f"DEBUG ## FORMATO NO VALIDO, NO CUMPLE CON 'AAAA-MM' SE ESTABLECEN VARIABLES DESDE FECHA DEL SISTEMA")
		if d: print(f"DEBUG ## per=|{per}|")
		if d: print(f"DEBUG ## ANIO ES")
		if d: print(f"DEBUG ## anio=|{anio}|")
		if d: print(f"DEBUG ## MES ES")
		if d: print(f"DEBUG ## mes=|{mes}|")	
# de lo contrario
else:
	# establecemos los valores para el periodo año y mes desde la fecha obtenida
	# del sistema
	anio = anio1
	mes = mes1
	per = tfechs
	# imprimimos mensaje informando que no se proporciono argumento para periodo
	if d: print(f"DEBUG ## NO SE PROPORCIONO PERIODO COMO ARGUMENTO, SE ESTABLECEN VARIABLES DESDE FECHA DEL SISTEMA")
	if d: print(f"DEBUG ## per=|{per}|")
	if d: print(f"DEBUG ## ANIO ES")
	if d: print(f"DEBUG ## anio=|{anio}|")
	if d: print(f"DEBUG ## MES ES")
	if d: print(f"DEBUG ## mes=|{mes}|")

# definimos la ruta base donde guardaremos los datos
ruta_base = Path("/var/www/html/efn/efnconsultor/SBS/COMISIONES-PRIMAS-SPP")
# definimos las sub-rutas hasta el archivo
ruta_completa = ruta_base / anio / mes
# Crear las carpetas si no existen
ruta_completa.mkdir(parents=True, exist_ok=True)
# definimos archivo de salida
arch_sal = ruta_completa / "consulta.txt"
# obtenemos fecha y hora
now = datetime.now()
# formateamos la fecha y asignamos a variable
fechahora = now.strftime("%Y-%m-%d %H:%M:%S")
# definimos variables para opciones del navegador
opc1="--no-sandbox"
opc2="--disable-blink-features=AutomationControlled"
opc3="--disable-extensions"
opc4="--disable-dev-shm-usage"
opc5="--start-maximized"
opc6="user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
# para definir la version de chromium
chrom_ver=120
# para definir la ruta al driver
chrom_drv="./chromedriver"
# establecemos variable para identificador de control html
url="https://www.sbs.gob.pe/app/spp/empleadores/comisiones_spp/Paginas/comision_prima.aspx"
# establecemos variable con nombre de identificador generico para controles tipo selector
# en formulario html
idgen="id"
# establecemos variable con nombre del selector en el formulario html
selperiodo_id="cboPeriodo"
# establecemos variable con nombre de identificador para valores del selector en el
# formulario html
selperiodo_val="value"
# establecemos variable con nombre del boton de consulta en el formulario html
btnconsul_id="btnConsultar"
# establecemos el identificador generico de columnas
divisorclm="tr"
# establecemos variable con nombre de las columnas del titulo que devuelve la consulta
# del formulario html
trtitulo="JER_filaTitulo"
# establecemos variable con nombre de las columnas del contenido que devuelve la consulta
# del formulario html
trcontenido="JER_filaContenido"
# establecemos variable con nombre de identificador de celdas para el contenido que
# devuelve la consulta del formulario html
tdcel="td"
# establecemos variable para tiempo de espera en segundos de carga de documento html
esp=5
# establecemos codificador para csv
codif="utf-8"
# definimos usuario para db postgresql
usuario="postgres"
# definimos contraseña para  postgresql
contra="DW3bBs1#m"
# definimos ip servidor postsgresql
servidor="localhost"
# definimos puerto del servidor postgresql
puerto="5432"
# definimos database deseada
basedatos="webservicelyz"
# imprimimos ruta y variables obtenidas
if d: print(f"DEBUG ## RUTA BASE ES")
if d: print(f"DEBUG ## ruta_base=|{ruta_base}|")
if d: print(f"DEBUG ## RUTA COMPLETA PARA EXTRACCION ES")
if d: print(f"DEBUG ## ruta_completa=|{ruta_completa}|")
if d: print(f"DEBUG ## ARCHIVO PARA RESULTADO DE EXTRACCION ES")
if d: print(f"DEBUG ## arch_sal=|{arch_sal}|")
if d: print(f"DEBUG ## FECHA COMPLETA DEL SISTEMA OBTENIDO ES")
if d: print(f"DEBUG ## fechahora=|{fechahora}|")
if d: print(f"DEBUG ## SE CREO LA RUTA COMPLETA")
if d: print(f"DEBUG ## OPCIONES DEFINIDAS PARA EL NAVEGADOR")
if d: print(f"DEBUG ## options.headless = False")
if d: print(f"DEBUG ## opc1=|{opc1}|")
if d: print(f"DEBUG ## opc2=|{opc2}|")
if d: print(f"DEBUG ## opc3=|{opc3}|")
if d: print(f"DEBUG ## opc4=|{opc4}|")
if d: print(f"DEBUG ## opc5=|{opc5}|")
if d: print(f"DEBUG ## opc6=|{opc6}|")
if d: print(f"DEBUG ## RUTA AL DRIVER DE CHROME")
if d: print(f"DEBUG ## chrom_drv=|{chrom_drv}|")
if d: print(f"DEBUG ## VERSION DE CHROME DE CHROME")
if d: print(f"DEBUG ## chrom_ver=|{chrom_ver}|")
if d: print(f"DEBUG ## URL BASE")
if d: print(f"DEBUG ## url=|{url}|")
if d: print(f"DEBUG ## IDENTIFICADOR GENERICO HTML")
if d: print(f"DEBUG ## idgen=|{idgen}|")
if d: print(f"DEBUG ## NOMBRE DE SELECTOR DE DESPLEGABLE DE FORMULARIO")
if d: print(f"DEBUG ## selperiodo_id=|{selperiodo_id}|")
if d: print(f"DEBUG ## VALOR DE SELECTOR DE DESPLEGABLE DE FORMULARIO")
if d: print(f"DEBUG ## selperiodo_val=|{selperiodo_val}|")
if d: print(f"DEBUG ## NOMBRE DE BOTON PARA CONSULTA")
if d: print(f"DEBUG ## btnconsul_id=|{btnconsul_id}|")
if d: print(f"DEBUG ## NOMBRE DE DIVISOR GENERICO DE COLUMNAS")
if d: print(f"DEBUG ## divisorclm=|{divisorclm}|")
if d: print(f"DEBUG ## NOMBRE DE COLUMNAS TITULOS")
if d: print(f"DEBUG ## trtitulo=|{trtitulo}|")
if d: print(f"DEBUG ## NOMBRE DE COLUMNAS CONTENIDO")
if d: print(f"DEBUG ## trcontenido=|{trcontenido}|")
if d: print(f"DEBUG ## NOMBRE DE IDENTIFICADOR GENERICO DE CELDAS")
if d: print(f"DEBUG ## tdcel=|{tdcel}|")
if d: print(f"DEBUG ## TIEMPO DE ESPERA PARA CARGA DE URL")
if d: print(f"DEBUG ## esp=|{esp}|")
if d: print(f"DEBUG ## CODIFICACION PARA CSV")
if d: print(f"DEBUG ## codif=|{codif}|")
if d: print(f"DEBUG ## VARIABLES PARA BASE DE DATOS POSTGRESQL")
if d: print(f"DEBUG ## usuario=|{usuario}|")
if d: print(f"DEBUG ## contra=|{contra}|")
if d: print(f"DEBUG ## servidor=|{servidor}|")
if d: print(f"DEBUG ## puerto=|{puerto}|")
if d: print(f"DEBUG ## basedatos=|{basedatos}|")
if d: print(f"DEBUG ## INICIANDO PRIMERA EXTRACCION DE DATOS")
if d: print(f"DEBUG ## ...")
# configuramos el navegador
options = uc.ChromeOptions()
# para levantar el navegador en segundo plano, sin interfaz grafica (opcional)
options.headless = False
options.add_argument(opc1)
options.add_argument(opc2)
options.add_argument(opc3)
options.add_argument(opc4)
options.add_argument(opc5)
options.add_argument(opc6)
# Ruta al chromedriver manual
driver = uc.Chrome(
	options=options,
	# ruta al driver de chromium
	driver_executable_path=chrom_drv,
	version_main=chrom_ver
)
# establecemos la pagina para obtener los resulados
#driver.get("https://www.sbs.gob.pe/app/spp/empleadores/comisiones_spp/Paginas/comision_prima.aspx")
driver.get(url)
# driver.get("https://www.google.com")
# imprime el titulo de la pagina
#print(driver.title)
# esperamos 5 segundos para que cargue la pagina
time.sleep(esp)
# seleccionamos el combo que tiene los periodos
#select = Select(driver.find_element("id", "cboPeriodo"))
select = Select(driver.find_element(idgen, selperiodo_id))
# ovtenemos todas las opciones
#options = select.find_elements(By.TAG_NAME, "option")
# Obtener el primer valor (ignorando el primero si es "Seleccione Periodo")
#ultimo_valor = options[-1].get_attribute("value")
#sel_valor2 = select.options[1].get_attribute("value")
sel_valor2 = select.options[1].get_attribute(selperiodo_val)
# imprimimos el segundo valor obtenido del selector
print(f"Segundo valor obtenido del combo {selperiodo_id} es: {sel_valor2}")
# obtenemos el año y el mes por separado del valor obtenido
anio2, mes2 = sel_valor2.split("-")
# imprimimos mensaje con año y mes obtenidos del combo
print(f"Datos obtenidos del sistema anio: {anio2} y el mes: {mes2}")
# imprimimos resultado de primera extraccion y variables obtenidas
if d: print(f"DEBUG ## ...")
if d: print(f"DEBUG ## FINALIZA PRIMERA EXTRACCION, DATOS OBTENIDOS SON:")
if d: print(f"DEBUG ## SEGUNDO VALOR DEL SELECTOR ES")
if d: print(f"DEBUG ## sel_valor2=|{sel_valor2}|")
if d: print(f"DEBUG ## PERIODO POR SEPARADO ES")
if d: print(f"DEBUG ## ANIO")
if d: print(f"DEBUG ## anio2=|{anio2}|")
if d: print(f"DEBUG ## MES")
if d: print(f"DEBUG ## mes2=|{mes2}|")
# validamos si el año y mes obtenidos superan los valores para mes y año del combo
if int(anio) > int(anio2) or int(mes) > int(mes2):
	# desplegamos mensaje informado que el año y mes proporcionados superan los valores actuales
	print(f"El anio: {anio} o el mes: {mes} proporcionados o obtenidos del sistema superan los valores maximos del combo: anio2: {anio2} y mes2: {mes2} se usaran los valores maximos del combo")
	if d: print(f"DEBUG ## anio={anio} o mes={mes} PROPORCIONADOS O OBTENIDOS DEL SISTEMA SUPERAN VALORES MAXIMOS DEL SELECTOR: anio2={anio2} y/o mes2={mes2} SE USA VALOR MAXIMO DEL SELECTOR")
	# establecemos los valores nuevamente para periodo, año y mes
	per = tfechs
	anio = anio2
	mes = mes2
# activar para depurar
if d: print(f"DEBUG ## SELECCIONANDO PERIODO {per} EN SELECTOR {selperiodo_id}:")
if d: print(f"DEBUG ## ENVIANDO CLICK A BOTON {btnconsul_id}:")
# dentro del combo seleccionamos el periodo obtenido
#select.select_by_value("2025-07")
select.select_by_value(per)
# damos click en el boton consultar
driver.find_element(idgen, btnconsul_id).click()
# esperamos 5 segundos que cargue la consulta
time.sleep(esp)
# activar para depurar
if d: print(f"DEBUG ## ESPERANDO {esp} SEGUNDOS:")
if d: print(f"DEBUG ## ...")
# Esperar a que aparezcan las filas de datos (timeout 10 segundos)
WebDriverWait(driver, 10).until(
	#EC.presence_of_all_elements_located((By.CSS_SELECTOR, "tr.JER_filaContenido"))
	EC.presence_of_all_elements_located((By.CSS_SELECTOR, f"{divisorclm}.{trcontenido}"))
)
# activar para depurar
if d: print(f"DEBUG ## DATOS OBTENIDOS, PROCESANDO DATOS OBTENIDOS")
if d: print(f"DEBUG ## PROCESANDO ENCABEZADOS")
if d: print(f"DEBUG ## ...")

# === 1. EXTRAER ENCABEZADO ===
# Busca todos los elementos <tr> (filas de tabla) con la clase JER_filaTitulo y
# devuelve una lista de filas y con [1] accede a la segunda fila, que contiene
# los encabezados de columna (la primera tiene el título: "Al mes de devengue...").
#encabezado_fila = driver.find_elements(By.CSS_SELECTOR, "tr.JER_filaTitulo")[1]
encabezado_fila = driver.find_elements(By.CSS_SELECTOR, f"{divisorclm}.{trtitulo}")[1]
# Encuentra todas las celdas <td> dentro de esa fila, devuelve una lista con las
# celdas de encabezado y lo asigna a variable
#celdas_encabezado = encabezado_fila.find_elements(By.TAG_NAME, "td")
celdas_encabezado = encabezado_fila.find_elements(By.TAG_NAME, tdcel)
# encabezados es una lista por comprensión ([]) que: Extrae el texto (.text) de cada
# celda, elimina espacios extra alrededor (.strip()) y Reemplaza saltos de línea (\n)
# por un espacio (" "), para que los encabezados sean legibles y finalmente
# los asigna a variable encabezados
encabezados = [celda.text.strip().replace("\n", " ") for celda in celdas_encabezado]
# activar para depurar
if d: print(f"DEBUG ## PROCESANDO CONTENIDO")
if d: print(f"DEBUG ## ...")

# === 2. EXTRAER CONTENIDO ===
# Extraer datos segun los elementos "tr.JER_filaContenido" que son las filas de la tabla
filas = driver.find_elements(By.CSS_SELECTOR, f"{divisorclm}.{trcontenido}")
# declaramos un array vacio
datos_array = []
# realizamos un bucle que obtenga los valores y lo almacene en el array
for fila in filas:
    celdas = fila.find_elements(By.TAG_NAME, tdcel)
    fila_datos = [celda.text.strip() for celda in celdas]
    datos_array.append(fila_datos)
# Imprimir datos
#for fila in datos:
#    print(fila)
# imprimimos mensaje informando lo que obtuvimos del portal web
if d: print(f"DEBUG ## DATOS OBTENIDOS DE PORTAL WEB SON:")
# imprimimos los datos obtenidos
if d: print(datos_array)

# para guardar en un archivo txt donde cada dato este separado por tabulacion
# abrimos el archivo de datos para escritura con una nueva linea
#with open(arch_sal, "w", encoding="utf-8") as f:
	# realizamos un bucle para cada fila en en array
#	for fila in datos_array:
		# asignamos la linea del array separadas en columnas por tabulador
#		linea = "\t".join(fila)
		# escribimos la linea al archivo
#		f.write(linea + "\n")

# para guardar todo el archivo html
#html = driver.page_source
#with open("resultado_afp.html", "w", encoding="utf-8") as f:
#	f.write(html)
# cerramos el driver
#driver.quit()

# activar para depurar
if d: print(f"DEBUG ## GUARDANDO EN CSV...")
# para guardar en un archivo csv donde cada dato este separado por punto y coma abrimos
# el archivo de datos para escritura con el parametro newline que significa que vita que
# se agreguen líneas en blanco extra en algunos sistemas (como Windows).
# with se usa para abrir y cerrar automáticamente el archivo.
#with open(arch_sal, "w", newline="", encoding="utf-8") as f:
with open(arch_sal, "w", newline="", encoding=codif) as f:
	# Crea un objeto writer que permite escribir líneas en formato CSV dentro del archivo f
	writer = csv.writer(f)
	# Escribe una línea en el CSV con los nombres de columna (los encabezados).
	writer.writerow(encabezados)
	# Escribe todas las filas de datos (las que están en el array tabla_array) una debajo de otra.
	writer.writerows(datos_array)

# activar para depurar	
if d: print(f"DEBUG ## CSV GUARDADO EN LA RUTA")
if d: print(f"DEBUG ## {arch_sal}")
# Definimos conexión a la base de datos
conn = pg8000.connect(
	# usuario db
	user=usuario,
	# contra usuario db
	password=contra,
	# ip servidor postsgresql
	host=servidor,
	# puerto del servidor postgresql
	port=puerto,
	# database deseada
	database=basedatos,
)

# definimos consulta para regimen pensionario
sqlregpen="SELECT regpen.codregimenpensionario, regpen.descripcion FROM public.regimenpensionario regpen;"

# activar para depurar
if d: print(f"DEBUG ## ESTABLECIENDO CONEXION A BASE DE DATOS")
if d: print(f"DEBUG ## EJECUTANDO CONSULTA PARA OBTENER REGIMEN PENSIONARIO")
if d: print(f"DEBUG ## sqlregpen=|{sqlregpen}|")
# crear cursor
cursor = conn.cursor()
# ejecutar consulta para regimen pensionario
cursor.execute(sqlregpen)

# Obtener resultados de la tabla regimenpensionario como lista
regpen_array = cursor.fetchall()

# definimos consulta para detalle afp
afpdet = f"""SELECT afpdet.codafpdetalle, afpdet.seguro, afpdet.comision, afpdet.descuento, afpdet.anio, afpdet.mes, afpdet.actualizado, afpdet.codregimenpensionario, afpdet.codusuario
FROM public.afpdetalle afpdet WHERE afpdet.anio = '{anio}' AND afpdet.mes = '{mes}' AND afpdet.codusuario = 0;
"""
# activar para depurar
if d: print(f"DEBUG ## EJECUTANDO CONSULTA PARA OBTENER DETALLE AFP")
if d: print(f"DEBUG ## afpdet=|{afpdet}|")
# ejecutar consulta para detalle afp
cursor.execute(afpdet)

# Obtener resultados de la tabla afpdetalle como lista
afpdet_array = cursor.fetchall()

# activar para depurar
if d: print(f"DEBUG ## CREANDO DICCIONARIO DEL DETALLE AFP OBTENIDO")
# Crear un diccionario con afpdet por codregimenpensionario
afpdet_dict = { row[7]: row for row in afpdet_array }
# creamos llaves desde diccionario:
# obtenemos todos los valores de la columna 7 comenzando del cero para todas las filas
# que se encuentran en el array de afp detalle y lo asignamos a array con el objetivo de
# verificar si estamos usando la columna correcta para crear las llaves en el diccionario
# recordar que en un diccionario, la llave se usa para identificar a toda la fila de
# valores en la cual tambien encuentra y esta puede estar en cualquier columna, no es lo
# mismo que un indice que se usa para llegar a un valor especifico
val_llave = [row[7] for row in afpdet_array]

# cerramos cursor
#cursor.close()

print("Datos obtenidos para regimen pensionario de BD son")
# activar para depurar
if d: print(f"DEBUG ## DATOS OBTENIDOS DE REGIMEN PENSIONARIO DE DB SON")
# imprimimos mensaje informando los datos obtenidos para el regimen pensionario
# Mostramos resultados para regimen pensionario
if d:
	for fila in regpen_array:
	    print(fila)

# imprimimos mensaje informando los datos obtenidos para detalle afp
print("Datos obtenidos para detalle AFP de BD son")
# activar para depurar
if d: print(f"DEBUG ## DATOS OBTENIDOS PARA DETALLE AFP DE DB SON")
# Mostramos resultados para afpdet
if d:
	for fila in afpdet_array:
	    print(fila)

# imprimimos mensaje informando el diccionario para el regimen pensionario
print("Diccionario para AFP detalle es")
# activar para depurar
if d: print(f"DEBUG ## DICCIONARIO CREADO PARA DETALLE AFP ES")
# imprimimos el dicionario
if d: print (afpdet_dict)
if d: print(f"DEBUG ## DICCIONARIO CREADO PARA DETALLE AFP ES")
if d: print(f"DEBUG ## VALORES USUARIOS COMO LLAVE SON:")
if d: print(val_llave)
if d: print(f"DEBUG ## CONJUNTO DE LLAVES UNICAS SIN REPETIDOS SON:")
if d: print(set(val_llave))
if d: print(f"DEBUG ## LLAVES ASIGNADAS AL DICCIONARIO SON:")
if d: print(list(afpdet_dict.keys()))
if d: print(f"DEBUG ## DETALLE DE LLAVES CON SU VALOR SON:")
if d:
	# Mostrar cada llave y su valor completo
	for llave, valor in afpdet_dict.items():
		print(f"llave: {llave}, Valor: {valor}")
	# otra forma de mostrar cada clave y su valor completo
	#for llave, valor in afpdet_dict.items():
	#	print("llave:", llave, "Valor:", valor)

# imprimimos array con valores que se asignaran como llaves de diccionario
print("Valores usados como llave:", val_llave)
# imprimimos las llaves pero sin duplicados, si es que hubieran
print("Conjunto de llaves único sin repetidos:", set(val_llave))
# para ver todas las claves asignadas al diccionario
print("llaves del diccionario:", list(afpdet_dict.keys()))


# Creamos array para sentencias en base a coincidencias
sqls = []

# activar para depurar
if d: print(f"DEBUG ## INICIO BUCLE PARA DATOS DE LA WEB")
# realizamos un bucle que recorra todos las filas obtenidas por el scraping
for filadatos in datos_array:
	# tomamos el valor de la primera columna ejem: 'HABITAT', 'INTEGRA', etc.
	afp_nombre = filadatos[0]
	# activar para depurar
	if d: print(f"DEBUG ## VALOR OBTENIDO PARA NOMBRE AFP_ES")
	if d: print(f"DEBUG ## afp_nombre=|{afp_nombre}|")
	if d: print(f"DEBUG ## INICIO BUCLE PARA DATOS DE REGIMEN PENSIONARIO")
	# realizamos otro bucle que recorra cada fila del array obtenido de regimen
	# pensionario de postgresql y buscamos coincidencia en descripción del régimen
	#for codigo, descripcion in regpen_array:
	for filaregpen in regpen_array:
		# obtenemos el valor para el codigo  y descripcion de regimen pensionario
		codigo = filaregpen[0]
		descripcion = filaregpen[1]
		# activar para depurar
		if d: print(f"DEBUG ## VALOR OBTENIDO PARA CODIGO REGIMEN PENSIONARIO ES")
		if d: print(f"DEBUG ## filaregpen[0]=|{filaregpen[0]}|")
		if d: print(f"DEBUG ## VALOR OBTENIDO PARA DESCRIPCION REGIMEN PENSIONARIO ES")
		if d: print(f"DEBUG ## filaregpen[0]=|{filaregpen[1]}|")
		if d: print(f"DEBUG ## VALIDANDO SI afp_nombre=|{afp_nombre.upper()}| = regpen_descripcion=|{descripcion.upper()}|")
		# si el valor de la primera columna que obtuvimos del array del scraping
		# y que lo asignamos a afp_nombre esta incluido en descripcion ignorando
		# mayusculas gracias a upper, es decir si hay coincidencia:
		# afp_nombre = 'HABITAT' | descripcion = 'AFP Habitat' | entonces | 'HABITAT' in 'AFP HABITAT'  # True
		if afp_nombre.upper() in descripcion.upper():
			# imprimimos la coincidencia
			print(f"Coincidencia: {afp_nombre} con {descripcion}")
			# activar para depurar
			if d: print(f"DEBUG ## COINCIDENCIA afp_nombre=|{afp_nombre}| CON descripcion=|{descripcion}|")
			# esablecemos los valores segun nos combiene
			# comision sera la fila 1, reemplazando porcentaje por nada y cambiando , por punto
			comision = filadatos[1].replace("%", "").replace(",", ".").strip()
			# anual_saldo la fila 2 (no lo uso por el momento)
			anual_saldo = filadatos[2]
			# seguro la fila 3, reemplazando porcentaje por nada y cambiando , por punto
			seguro = filadatos[3].replace("%", "").replace(",", ".").strip()
			# descuento la fila 4, reemplazando porcentaje por nada y cambiando , por punto
			descuento = filadatos[4].replace("%", "").replace(",", ".").strip()
			# remuneracion la fila 5 (no lo uso por el momento)
			remuneracion = filadatos[5]
			# activar para depurar
			if d: print(f"DEBUG ## DATOS OBTENIDOS SON")
			if d: print(f"DEBUG ## comision=|{comision}|")
			if d: print(f"DEBUG ## anual_saldo=|{anual_saldo}|")
			if d: print(f"DEBUG ## seguro=|{seguro}|")
			if d: print(f"DEBUG ## descuento=|{descuento}|")
			if d: print(f"DEBUG ## remuneracion=|{remuneracion}|")
			if d: print(f"DEBUG ## VALIDANDO SI codigo=|{codigo}| ESTA EN DICCIONARIO")
			# Buscamos si el regimen pensionario tiene detalle
			if codigo in afpdet_dict:
				# si es asi obtenemos el valor del regimen
				fila_afpdet = afpdet_dict
				# Usás fila_inventario como necesites
				print(f"Regimen pensionario tiene detalle en afpdetalle, codigo evaluado fue: {codigo}")
				# activar para depurar
				if d: print(f"DEBUG ## codigo=|{codigo}| ESTA EN DICCIONARIO")
				if d: print(f"DEBUG ## FILA OBTENIDA ES")
				if d: print(f"DEBUG ## fila_afpdet=|{fila_afpdet}|")
				if d: print(f"DEBUG ## SE GENERA CONSULTA PARA UPDATE")
				# creamos variable con la sentencia sql a insertar
				update_sql = f"""
				UPDATE afpdetalle
				SET seguro = {seguro},
					comision = {comision},
					descuento = {descuento},
					anio = {anio},
					mes = {mes},
					actualizado = '{fechahora}',
					codusuario = 0
				WHERE codregimenpensionario = {codigo};
				"""
				# guardamos la sentencia en una lista
				sqls.append(update_sql)
			# de lo contrario si no tiene
			else:
				# Producto no está en inventario aún
				print(f"Regimen pensionario no tiene detalle en afpdetalle, codigo evaluado fue: {codigo}")
				# activar para depurar
				if d: print(f"DEBUG ## codigo=|{codigo}| NO ESTA EN DICCIONARIO")
				if d: print(f"DEBUG ## SE GENERA CONSULTA PARA INSERT")
				# creamos variable con la sentencia sql a insertar
				insert_sql = f"""
				INSERT INTO afpdetalle (seguro, comision, descuento, anio, mes, actualizado, codregimenpensionario, codusuario)
				VALUES ('{seguro}', '{comision}', '{descuento}', '{anio}', '{mes}', '{fechahora}', '{codigo}', 0);
				"""
				# guardamos la sentencia en una lista
				sqls.append(insert_sql)
			# detener el loop si encontró coincidencia
			break

# activar para depurar
if d: print(f"DEBUG ## SENTENCIAS OBTENIDAS SON")
if d:
# recorremos la lista creada e imprimimos los inserts o ejecutar los inserts
	for sentencia in sqls:
		print(sentencia)

# activar para depurar
if d: print(f"DEBUG ## EJECUTANDO SENTENCIAS...")
for sentencia in sqls:
	cursor.execute(sentencia)
# guardar cambios en db
conn.commit()
# activar para depurar
if d: print(f"DEBUG ## SENTENCIAS EJECUTADAS")
# cerramos el cursor
cursor.close()

# Cerramos la conexión
conn.close()

# imprimimos mensaje informando que se guardaron los datos
print("datos guardados")
# activar para depurar
if d: print(f"DEBUG ## FINALIZA SCRIPT")
sys.exit(1)