import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime, timedelta
import numpy as np
import time
def show_ml_features(client, sheet_name):
# Fonction helper pour charger les données
def get_data_from_sheet(sheet_name_tab):
try:
# Assurez-vous que l'objet 'client' et 'sheet_name' sont définis en amont dans votre script
sh = client.open(sheet_name)
ws = sh.worksheet(sheet_name_tab)
return pd.DataFrame(ws.get_all_records())
except:
return pd.DataFrame()
# Chargement des données nécessaires
# Note: 'client' et 'sheet_name' doivent être définis avant ce bloc
df_prets_master = get_data_from_sheet("Prets_Master")
df_prets_update = get_data_from_sheet("Prets_Update")
df_capital_invest = get_data_from_sheet("Capital_Investissement")
df_clients = get_data_from_sheet("Clients_KYC")
# === En-tête ===
st.header("OBJECT EXPLORER")
# Note: 'sheet_name' doit être défini
st.success(f"✅ Liaison Directe établie")
# === CALCULS POUR LES MÉTRIQUES ===
# 1. Capital de l'entreprise (somme de Capital_Investissement)
capital_entreprise = 0
capital_variation = 0
if not df_capital_invest.empty and 'Capital' in df_capital_invest.columns:
df_capital_invest['Capital_Num'] = pd.to_numeric(
df_capital_invest['Capital'].astype(str).str.replace('FCFA', '').str.replace(' ', '').str.strip(),
errors='coerce'
).fillna(0)
capital_entreprise = df_capital_invest['Capital_Num'].sum()
# Variation = dernier vs précédent
if len(df_capital_invest) > 1:
derniere_entree = df_capital_invest.iloc[-1]['Capital_Num']
avant_derniere = df_capital_invest.iloc[-2]['Capital_Num']
if avant_derniere > 0:
capital_variation = ((derniere_entree - avant_derniere) / avant_derniere) * 100
# 2. Capital dehors (prêts non remboursés)
capital_dehors = 0
if not df_prets_master.empty and 'Montant_Capital' in df_prets_master.columns:
df_prets_master['Montant_Capital_Num'] = pd.to_numeric(df_prets_master['Montant_Capital'], errors='coerce').fillna(0)
capital_dehors = df_prets_master[df_prets_master['Statut'] != 'TERMINE']['Montant_Capital_Num'].sum()
# 3. Flux attendu (Montant_Total des prêts non remboursés)
flux_attendu = 0
flux_variation = 0
if not df_prets_master.empty and 'Montant_Total' in df_prets_master.columns:
df_prets_master['Montant_Total_Num'] = pd.to_numeric(df_prets_master['Montant_Total'], errors='coerce').fillna(0)
flux_attendu = df_prets_master[df_prets_master['Statut'] != 'TERMINE']['Montant_Total_Num'].sum()
# Variation = différence avec capital dehors
if capital_dehors > 0:
flux_variation = ((flux_attendu - capital_dehors) / capital_dehors) * 100
# 4. Score de liquidité
score_liquidite = 0
score_tendance = "Stable"
if capital_entreprise > 0:
score_liquidite = (capital_dehors / capital_entreprise) * 10
score_liquidite = min(score_liquidite, 10)
# Tendance basée sur le ratio
ratio = (capital_dehors / capital_entreprise) * 100
if ratio > 70:
score_tendance = "▲ Élevé"
elif ratio > 40:
score_tendance = "→ Moyen"
else:
score_tendance = "▼ Faible"
# 5. Bénéfices nets 2026
benefices_nets = 0
benefices_variation = 0
if not df_prets_master.empty and 'Cout_Credit' in df_prets_master.columns:
df_prets_master['Cout_Credit_Num'] = pd.to_numeric(df_prets_master['Cout_Credit'], errors='coerce').fillna(0)
benefices_nets = df_prets_master['Cout_Credit_Num'].sum()
# Simulation variation (peut être calculée vs mois précédent si date disponible)
benefices_variation = 5.2 # Placeholder - à calculer avec historique
# 6. Objectif 2026
objectif_2026 = 2_200_000
progression_objectif = (benefices_nets / objectif_2026) * 100 if objectif_2026 > 0 else 0
# 7. Reste à générer
reste_a_generer = max(0, objectif_2026 - benefices_nets)
reste_variation = -((reste_a_generer / objectif_2026) * 100) if objectif_2026 > 0 else 0
# 8. Capital total sorti
capital_total_sorti = 0
nb_prets_total = 0
if not df_prets_master.empty and 'Montant_Capital' in df_prets_master.columns:
# Convertir Montant_Capital en numérique si pas déjà fait
if 'Montant_Capital_Num' not in df_prets_master.columns:
df_prets_master['Montant_Capital_Num'] = pd.to_numeric(df_prets_master['Montant_Capital'], errors='coerce').fillna(0)
# Prêts NON UPDATED - on prend de Prets_Master
prets_non_updated = df_prets_master[df_prets_master['Statut'] != 'UPDATED']
nb_prets_total = len(prets_non_updated)
capital_total_sorti = prets_non_updated['Montant_Capital_Num'].sum()
# Prêts UPDATED - on prend depuis Prets_Update
if not df_prets_update.empty and 'ID_Pret' in df_prets_update.columns:
df_prets_update['Montant_Capital_Num'] = pd.to_numeric(df_prets_update['Montant_Capital'], errors='coerce').fillna(0)
prets_updated_ids = df_prets_master[df_prets_master['Statut'] == 'UPDATED']['ID_Pret'].tolist()
prets_updated_montants = df_prets_update[df_prets_update['ID_Pret'].isin(prets_updated_ids)]
capital_total_sorti += prets_updated_montants['Montant_Capital_Num'].sum()
nb_prets_total += len(prets_updated_montants)
# Ajouter aussi les prêts qui sont UNIQUEMENT dans Prets_Update (nouveaux prêts)
prets_update_nouveaux = df_prets_update[~df_prets_update['ID_Pret'].isin(df_prets_master['ID_Pret'].tolist())]
capital_total_sorti += prets_update_nouveaux['Montant_Capital_Num'].sum()
nb_prets_total += len(prets_update_nouveaux)
# Ajoutez le ration bénéfice net sur total sortie
# === AFFICHAGE DES MÉTRIQUES (2 lignes de 4) ===
# Ligne 1
col1, col2, col3, col4 = st.columns(4)
col1.metric(
"CAPITAL D'INVESTISSEMENT",
f"{capital_entreprise:,.0f} XOF".replace(',', ' '),
delta=f"{'▲' if capital_variation > 0 else '▼'} {abs(capital_variation):.1f}%" if capital_variation != 0 else "Stable"
)
col2.metric(
"CAPITAL DEHORS",
f"{capital_dehors:,.0f} XOF".replace(',', ' '),
delta=f"{(capital_dehors/capital_entreprise*100 if capital_entreprise > 0 else 0):.1f}% du capital investi"
)
col3.metric(
"FLUX ATTENDU",
f"{flux_attendu:,.0f} XOF".replace(',', ' '),
delta=f"{'▲' if flux_variation > 0 else '▼'} {abs(flux_variation):.1f}% vs capital" if flux_variation != 0 else "Stable"
)
col4.metric(
"LIQUIDITÉ UTILISÉE",
f"{score_liquidite:.1f}/10",
delta=score_tendance
)
# Ligne 2
col5, col6, col7, col8 = st.columns(4)
col5.metric(
"BÉNÉFICES NETS 2026",
f"{benefices_nets:,.0f} XOF".replace(',', ' '),
delta=f"▲ {benefices_variation:.1f}%" if benefices_variation > 0 else "Stable"
)
col6.metric(
"OBJECTIF 2026",
f"{objectif_2026:,.0f} XOF".replace(',', ' '),
delta=f"{progression_objectif:.1f}% atteint"
)
col7.metric(
"RESTE À GÉNÉRER",
f"{reste_a_generer:,.0f} XOF".replace(',', ' '),
delta=f"▼ {abs(reste_variation):.1f}%" if reste_a_generer > 0 else "✓ Objectif atteint !"
)
# Affichage de la métrique
col8.metric(
"CAPITAL TOTAL SORTI",
f"{capital_total_sorti:,.0f} XOF".replace(',', ' '),
delta=f"{nb_prets_total} prêt{'s' if nb_prets_total > 1 else ''} tot{'aux' if nb_prets_total > 1 else 'al'}"
)
#======> ANALYSE MENSUELLE DES BÉNÉFICES <=====
st.divider()
st.subheader("ANALYSE MENSUELLE DES BÉNÉFICES 2026")
# Préparation des données mensuelles
if not df_prets_master.empty and 'Date_Deblocage' in df_prets_master.columns and 'Cout_Credit' in df_prets_master.columns:
# Conversion des dates et montants
df_prets_master['Date_Deblocage_dt'] = pd.to_datetime(df_prets_master['Date_Deblocage'], format='%d/%m/%Y', errors='coerce')
df_prets_master['Cout_Credit_Num'] = pd.to_numeric(df_prets_master['Cout_Credit'], errors='coerce').fillna(0)
# Filtrer uniquement l'année 2026
df_2026 = df_prets_master[df_prets_master['Date_Deblocage_dt'].dt.year == 2026].copy()
if not df_2026.empty:
# Créer la colonne Mois (numérique)
df_2026['Mois'] = df_2026['Date_Deblocage_dt'].dt.month
# CRÉER d'abord benefices_mensuels
benefices_mensuels = df_2026.groupby('Mois')['Cout_Credit_Num'].sum().reset_index()
benefices_mensuels.columns = ['Mois', 'Benefice']
# Ajouter les noms de mois
mois_noms = {1: 'Janvier', 2: 'Février', 3: 'Mars', 4: 'Avril',
5: 'Mai', 6: 'Juin', 7: 'Juillet', 8: 'Août',
9: 'Septembre', 10: 'Octobre', 11: 'Novembre', 12: 'Décembre'}
benefices_mensuels['Mois_Nom'] = benefices_mensuels['Mois'].map(mois_noms)
# Calculer les variations mensuelles (% vs mois précédent)
benefices_mensuels['Variation'] = benefices_mensuels['Benefice'].pct_change() * 100
benefices_mensuels['Variation'] = benefices_mensuels['Variation'].fillna(0)
# Calculer le capital mensuel sorti (Montant_Capital)
df_2026['Montant_Capital_Num'] = pd.to_numeric(df_2026['Montant_Capital'], errors='coerce').fillna(0)
capital_mensuel = df_2026.groupby('Mois')['Montant_Capital_Num'].sum().reset_index()
capital_mensuel.columns = ['Mois', 'Capital_Sorti']
# Fusionner avec les bénéfices mensuels
benefices_mensuels = benefices_mensuels.merge(capital_mensuel, on='Mois', how='left')
benefices_mensuels['Capital_Sorti'] = benefices_mensuels['Capital_Sorti'].fillna(0)
# Graphique en barres groupées avec Plotly (pleine largeur)
fig_mensuel = go.Figure()
# Barres des bénéfices
fig_mensuel.add_trace(go.Bar(
x=benefices_mensuels['Mois_Nom'],
y=benefices_mensuels['Benefice'],
name='Bénéfices',
marker=dict(
color='#58a6ff',
line=dict(color='rgba(139, 148, 158, 0.3)', width=1.5)
),
text=benefices_mensuels['Benefice'].apply(lambda x: f"{x:,.0f}".replace(',', ' ')),
textposition='outside',
textfont=dict(size=11, color='#c9d1d9', family='Space Grotesk'),
opacity=0.85,
hovertemplate='%{x}
Bénéfice: %{y:,.0f} XOF
Capital Sorti: %{y:,.0f} XOF