| import streamlit as st |
| import pandas as pd |
| import gspread |
| from google.oauth2.service_account import Credentials |
| import os |
| import json |
|
|
| |
| |
| |
|
|
| |
| if 'usuario_autenticado' not in st.session_state: |
| st.session_state['usuario_autenticado'] = False |
|
|
| |
| def verificar_login(usuario, contrasena): |
| usuario_correcto = os.environ.get("USUARIO") |
| contrasena_correcta = os.environ.get("PASSWORD") |
| |
| if usuario == usuario_correcto and contrasena == contrasena_correcta: |
| st.session_state['usuario_autenticado'] = True |
| st.success("¡Inicio de sesión exitoso!") |
| else: |
| st.error("Usuario o contraseña incorrectos.") |
|
|
| |
| |
| |
|
|
| |
| if not st.session_state['usuario_autenticado']: |
| st.title("🔒 Iniciar Sesión") |
| usuario_input = st.text_input("Nombre de Usuario") |
| contrasena_input = st.text_input("Contraseña", type="password") |
| |
| if st.button("Entrar"): |
| verificar_login(usuario_input, contrasena_input) |
|
|
| |
| else: |
| |
| if st.button("Cerrar Sesión"): |
| st.session_state['usuario_autenticado'] = False |
| st.rerun() |
| |
| st.divider() |
| st.title("💱 Gestor de Compra/Venta de Divisas") |
| |
| |
| @st.cache_resource |
| def init_connection(): |
| scopes = [ |
| "https://www.googleapis.com/auth/spreadsheets", |
| ] |
| |
| try: |
| |
| secreto_hf = os.environ.get("GCP_CREDENTIALS") |
| |
| if secreto_hf is None: |
| st.error("No se encontró el secreto 'GCP_CREDENTIALS'.") |
| st.stop() |
| |
| |
| credenciales_dict = json.loads(secreto_hf) |
| |
| |
| credentials = Credentials.from_service_account_info( |
| credenciales_dict, |
| scopes=scopes |
| ) |
| |
| client = gspread.authorize(credentials) |
| return client |
| except Exception as e: |
| st.error(f"Error de conexión: {e}") |
| st.stop() |
| |
| |
| gc = init_connection() |
| |
| |
| ID_DEL_DOCUMENTO = "1vYsYvo4LJERddrXGi4y-ugp-6vVM4xOo-D_ZPaxuMdI" |
| |
| |
| NOMBRE_DE_LA_HOJA = "Dol" |
| |
| try: |
| documento_completo = gc.open_by_key(ID_DEL_DOCUMENTO) |
| sheet = documento_completo.worksheet(NOMBRE_DE_LA_HOJA) |
| except gspread.exceptions.WorksheetNotFound: |
| st.error(f"Se encontró el documento, pero no existe una pestaña llamada '{NOMBRE_DE_LA_HOJA}'.") |
| st.stop() |
| except Exception as e: |
| st.error(f"No se pudo abrir el documento. Verifica el ID y los permisos. Error: {e}") |
| st.stop() |
| |
| |
| if 'compras' not in st.session_state: |
| st.session_state.compras = [] |
| if 'ventas' not in st.session_state: |
| st.session_state.ventas = [] |
| |
| |
| col1, col2 = st.columns(2) |
| |
| with col1: |
| st.header("🛒 Compras ($)") |
| with st.form("form_compra", clear_on_submit=True): |
| tasa_c = st.number_input("Tasa Compra", min_value=0.0, format="%.2f") |
| monto_c = st.number_input("Monto ($)", min_value=0.0, format="%.2f") |
| submit_c = st.form_submit_button("Agregar Compra") |
| |
| if submit_c and tasa_c > 0 and monto_c > 0: |
| total_bs_c = tasa_c * monto_c |
| st.session_state.compras.append({ |
| "Tipo": "Compra", "Tasa": tasa_c, "Monto ($)": monto_c, "Total (Bs)": total_bs_c |
| }) |
| st.success("¡Compra agregada temporalmente!") |
| |
| with col2: |
| st.header("💸 Ventas (USDT)") |
| with st.form("form_venta", clear_on_submit=True): |
| tasa_v = st.number_input("Tasa Venta", min_value=0.0, format="%.4f") |
| monto_v = st.number_input("Monto (USDT)", min_value=0.0, format="%.2f") |
| submit_v = st.form_submit_button("Agregar Venta") |
| |
| if submit_v and tasa_v > 0 and monto_v > 0: |
| total_bs_v = tasa_v * monto_v |
| st.session_state.ventas.append({ |
| "Tipo": "Venta", "Tasa": tasa_v, "Monto (USDT)": monto_v, "Total (Bs)": total_bs_v |
| }) |
| st.success("¡Venta agregada temporalmente!") |
| |
| |
| st.divider() |
| df_compras = pd.DataFrame(st.session_state.compras) |
| df_ventas = pd.DataFrame(st.session_state.ventas) |
| col_tabla1, col_tabla2 = st.columns(2) |
| |
| with col_tabla1: |
| st.subheader("Registros de Compra (Sin guardar)") |
| st.dataframe(df_compras, use_container_width=True) |
| |
| with col_tabla2: |
| st.subheader("Registros de Venta (Sin guardar)") |
| st.dataframe(df_ventas, use_container_width=True) |
| |
| |
| if st.button("🚀 Hacer Push a Google Sheets", use_container_width=True): |
| try: |
| datos_a_subir = [] |
| for row in st.session_state.compras: |
| datos_a_subir.append(["Compra", row["Tasa"], row["Monto ($)"], row["Total (Bs)"]]) |
| for row in st.session_state.ventas: |
| datos_a_subir.append(["Venta", row["Tasa"], row["Monto (USDT)"], row["Total (Bs)"]]) |
| |
| if datos_a_subir: |
| sheet.append_rows(datos_a_subir) |
| st.success("¡Datos enviados exitosamente!") |
| st.session_state.compras = [] |
| st.session_state.ventas = [] |
| st.rerun() |
| else: |
| st.warning("No hay datos nuevos para subir.") |
| |
| except Exception as e: |
| st.error(f"Error al subir a Google Sheets: {e}") |
| |
| |
| st.divider() |
| st.header("📈 Resumen Histórico y Ganancias") |
| |
| try: |
| datos_historicos = sheet.get_all_values() |
| |
| if len(datos_historicos) > 0: |
| df_hist = pd.DataFrame(datos_historicos, columns=["Tipo", "Tasa", "Monto", "Total (Bs)"]) |
| df_hist["Tasa"] = pd.to_numeric(df_hist["Tasa"], errors='coerce') |
| df_hist["Monto"] = pd.to_numeric(df_hist["Monto"], errors='coerce') |
| df_hist["Total (Bs)"] = pd.to_numeric(df_hist["Total (Bs)"], errors='coerce') |
| df_hist = df_hist.dropna(subset=['Total (Bs)']) |
| |
| hist_compras = df_hist[df_hist["Tipo"].str.contains("Compra", case=False, na=False)] |
| hist_ventas = df_hist[df_hist["Tipo"].str.contains("Venta", case=False, na=False)] |
| |
| h_total_bs_comprados = hist_compras["Total (Bs)"].sum() |
| h_total_usd_comprados = hist_compras["Monto"].sum() |
| h_tasa_prom_compra = h_total_bs_comprados / h_total_usd_comprados if h_total_usd_comprados > 0 else 0 |
| |
| h_total_bs_vendidos = hist_ventas["Total (Bs)"].sum() |
| h_total_usdt_vendidos = hist_ventas["Monto"].sum() |
| h_tasa_prom_venta = h_total_bs_vendidos / h_total_usdt_vendidos if h_total_usdt_vendidos > 0 else 0 |
| |
| h_diferencia_bs = h_total_bs_vendidos - h_total_bs_comprados |
| diferencia_divisas = h_total_usd_comprados - h_total_usdt_vendidos |
| valor_bs_sobrantes = h_diferencia_bs / h_tasa_prom_venta if h_tasa_prom_venta > 0 else 0 |
| ganancia_estimada_usd = diferencia_divisas + valor_bs_sobrantes |
| |
| col_m1, col_m2, col_m3, col_m4 = st.columns(4) |
| col_m1.metric("Total Invertido ($)", f"{h_total_usd_comprados:,.2f}") |
| col_m2.metric("Total Vendido (USDT)", f"{h_total_usdt_vendidos:,.2f}") |
| col_m3.metric("Diferencia (Bs)", f"{h_diferencia_bs:,.2f}") |
| col_m4.metric("Ganancia Neta Estimada (USD)", f"{ganancia_estimada_usd:,.2f}") |
| |
| st.write(f"**Tasa Promedio Compra:** {h_tasa_prom_compra:,.2f} Bs | **Tasa Promedio Venta:** {h_tasa_prom_venta:,.2f} Bs") |
| |
| else: |
| st.info("La hoja de cálculo está vacía o aún no tiene registros válidos.") |
| |
| except Exception as e: |
| st.error(f"Error al leer la hoja histórica: {e}") |
|
|