import streamlit as st import pandas as pd import gspread from google.oauth2.service_account import Credentials import os import json import sys # Ajout du chemin pour trouver les modules sys.path.append(os.path.join(os.path.dirname(__file__), 'modules')) # IMPORT DU NOUVEAU MODULE try: from modules import kyc_form, map_dashboard, loans_engine, ml_dashboard, notifications, ontology_graph, repayments except ImportError: # Fallback si l'import direct Ă©choue (structure de dossier simple) import kyc_form import map_dashboard import loans_engine import ml_dashboard import notifications import ontology_graph import repayments # ============================================================================== # 1. CONFIGURATION DU "DIRECT DRIVER" & DESIGN # ============================================================================== st.set_page_config( page_title="Vortex-Flux | Ontology", page_icon="đŸ”ș", layout="wide", initial_sidebar_state="expanded" ) # Nom exact de votre fichier Google Sheets (Doit ĂȘtre partagĂ© avec l'email du bot) SHEET_NAME = "Vortex-Flux" # Scopes requis pour l'accĂšs Google Drive/Sheets SCOPES = [ "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive" ] # ============================================================================== # 2. INJECTION CSS GOTHAM SURVEILLANCE - STYLE GLOBAL # ============================================================================== st.markdown(""" """, unsafe_allow_html=True) # ============================================================================== # 3. MOTEUR DE CONNEXION (GSPREAD PUR) # ============================================================================== @st.cache_resource def get_gspread_client(): """Authentification robuste via gspread sans passer par st.connection""" raw_json = os.environ.get("GSHEETS_JSON") if not raw_json: st.error("🛑 SECRET MANQUANT : 'GSHEETS_JSON' est introuvable.") return None try: # CrĂ©ation du fichier temporaire sĂ©curisĂ© creds_dict = json.loads(raw_json) with open("temp_creds.json", "w") as f: json.dump(creds_dict, f) # Authentification Google credentials = Credentials.from_service_account_file("temp_creds.json", scopes=SCOPES) client = gspread.authorize(credentials) return client except Exception as e: st.error(f"⚠ Erreur d'authentification GSpread : {e}") return None def get_data_from_sheet(worksheet_name): """RĂ©cupĂšre les donnĂ©es d'un onglet sous forme de DataFrame""" client = get_gspread_client() if not client: return pd.DataFrame() try: # Ouverture du classeur par son nom sh = client.open(SHEET_NAME) # SĂ©lection de l'onglet worksheet = sh.worksheet(worksheet_name) # Lecture des donnĂ©es data = worksheet.get_all_records() return pd.DataFrame(data) except gspread.WorksheetNotFound: # Si l'onglet n'existe pas encore, on renvoie vide sans planter return pd.DataFrame() except gspread.SpreadsheetNotFound: st.error(f"⚠ Fichier Google Sheet '{SHEET_NAME}' introuvable. VĂ©rifiez le nom et le partage.") return pd.DataFrame() except Exception as e: st.error(f"Erreur de lecture : {e}") return pd.DataFrame() # ============================================================================== # 4. LOGIQUE ONTOLOGIQUE (IDs) # ============================================================================== def generate_ontology_id(prefix, sheet_tab): df = get_data_from_sheet(sheet_tab) # Calcul ID : Nombre de lignes + 1 next_id = len(df) + 1 return f"{prefix}-2026-{next_id:04d}" #2026 a changĂ© pour 2027 plus tard # ============================================================================== # 5. FONCTION DE RÉINITIALISATION COMPLÈTE # ============================================================================== def reset_application(): """ RĂ©initialise complĂštement l'application : - Vide le session_state - Vide tous les caches - Force un rechargement complet """ # 1. Sauvegarder les clĂ©s essentielles (si nĂ©cessaire) # Par exemple, si vous voulez garder certaines variables # keys_to_keep = [] # 2. Vider complĂštement le session_state for key in list(st.session_state.keys()): del st.session_state[key] # 3. Vider tous les caches de Streamlit st.cache_data.clear() st.cache_resource.clear() # 4. Force un rechargement complet st.rerun() # ============================================================================== # 6. INTERFACE UTILISATEUR # ============================================================================== client = get_gspread_client() if client: # --- BARRE LATÉRALE --- st.sidebar.title("đŸ”ș VORTEX-FLUX") st.sidebar.caption("Jumeau NumĂ©rique & Ontologie") st.sidebar.divider() st.sidebar.markdown("### System") menu = st.sidebar.radio("Module", ["Dashboard", "Ontology Model", "Tracking Metrics","Actor Onboarding", "Init Loan", "Repayments"] ) st.sidebar.divider() # --- BOUTON DE RÉINITIALISATION --- st.sidebar.markdown("### Rerunning") col1, col2 = st.sidebar.columns([3, 1]) with col1: st.markdown("RĂ©initialiser l'application", unsafe_allow_html=True) with col2: # Utilisation d'une clĂ© unique et d'une classe CSS personnalisĂ©e if st.button("reset", key="reset_app_btn", help="RĂ©initialiser l'application Ă  son Ă©tat initial"): reset_application() # Version alternative avec un bouton plus visible : # st.sidebar.markdown("---") # if st.sidebar.button("🔄 RESET APPLICATION", key="reset_full", help="RĂ©initialiser complĂštement l'application"): # reset_application() # --- A. TABLEAU DE BORD --- if menu == "Dashboard": # --- AJOUTS VORTEX-FLUX (ML & NOTIFICATIONS) --- # 1.Appel direct du Dashboard ML (Le "Nouveau" Tableau de Bord) ml_dashboard.show_ml_features(client, SHEET_NAME) st.divider() # 2. Module de Notification (Bouton de vĂ©rification) notifications.verifier_et_notifier_echeances(client, SHEET_NAME) # --- B. CODE DU MODULE ONTOLOGY --- elif menu == "Ontology Model": ontology_graph.show_ontology_graph(client, SHEET_NAME) # --- C. CODE DU MODULE CARTE TACTIQUE --- elif menu == "Tracking Metrics": # Appel du nouveau module map_dashboard.show_map_dashboard(client, SHEET_NAME) # --- D. CODE DU MODULE KYC --- elif menu == "Actor Onboarding": # APPEL DU MODULE EXTERNE kyc_form.show_kyc_form(client, SHEET_NAME, generate_ontology_id) # --- E. CODE DU MODULE LOANS --- elif menu == "Init Loan": loans_engine.show_loans_engine(client, SHEET_NAME) # --- F. CODE DU MODULE Repayment --- elif menu == "Repayments": repayments.show_repayments_module(client, SHEET_NAME) else: st.error("🛑 Impossible de se connecter Ă  Google Sheets. VĂ©rifiez vos credentials.")