klydekushy commited on
Commit
e04cb0b
·
verified ·
1 Parent(s): 6abc775

Create repayments.py

Browse files
Files changed (1) hide show
  1. src/modules/repayments.py +110 -0
src/modules/repayments.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from datetime import datetime, date
4
+
5
+ def show_repayments_module(client, sheet_name):
6
+ st.header("💰 GUICHET DE RECOUVREMENT (CASHFLOW IN)")
7
+
8
+ try:
9
+ sh = client.open(sheet_name)
10
+ ws_prets = sh.worksheet("Prets_Master")
11
+ ws_remb = sh.worksheet("Remboursements")
12
+
13
+ # Chargement des données
14
+ df_prets = pd.DataFrame(ws_prets.get_all_records())
15
+
16
+ # On ne garde que les prêts ACTIFS ou EN RETARD (pas ceux déjà clos)
17
+ # On filtre aussi pour s'assurer qu'on a bien des IDs
18
+ if not df_prets.empty and 'ID_Pret' in df_prets.columns:
19
+ active_loans = df_prets[df_prets['Statut'].isin(["ACTIF", "EN_RETARD", "LITIGE"])]
20
+ else:
21
+ st.warning("Aucun prêt actif trouvé.")
22
+ return
23
+
24
+ except Exception as e:
25
+ st.error(f"Erreur de connexion : {e}")
26
+ return
27
+
28
+ # --- 1. SÉLECTION DU PRÊT ---
29
+ st.subheader("1. Identifier le Dossier")
30
+
31
+ # On crée une liste de choix lisible : "ID - Nom Client (Reste à payer...)"
32
+ # Note: Pour le "Reste à payer" exact, il faudrait sommer les remboursements précédents.
33
+ # Pour cette V1, on affiche le Montant Total initial pour info.
34
+
35
+ choices = active_loans.apply(
36
+ lambda x: f"{x['ID_Pret']} - {x['Nom_Complet']} (Total dû: {x['Montant_Total']} XOF)",
37
+ axis=1
38
+ ).tolist()
39
+
40
+ selected_choice = st.selectbox("Sélectionnez le prêt à rembourser", [""] + choices)
41
+
42
+ if selected_choice:
43
+ # Extraction de l'ID Prêt
44
+ loan_id = selected_choice.split(" - ")[0]
45
+ loan_data = active_loans[active_loans['ID_Pret'] == loan_id].iloc[0]
46
+
47
+ # Affichage rapide du contexte
48
+ with st.expander("📄 Détails du contrat", expanded=True):
49
+ c1, c2, c3 = st.columns(3)
50
+ c1.metric("Capital Prêté", f"{loan_data['Montant_Capital']} XOF")
51
+ c2.metric("Montant Total Dû", f"{loan_data['Montant_Total']} XOF")
52
+ c3.metric("Échéance Prévue", f"{loan_data['Montant_Versement']} XOF / période")
53
+
54
+ # --- 2. SAISIE DU PAIEMENT ---
55
+ st.divider()
56
+ st.subheader("2. Enregistrement du Paiement")
57
+
58
+ with st.form("repayment_form", clear_on_submit=True):
59
+ col_a, col_b = st.columns(2)
60
+ with col_a:
61
+ date_paiement = st.date_input("Date du paiement", value=date.today())
62
+ montant_verse = st.number_input("Montant Versé (XOF)", min_value=1000, step=5000)
63
+ with col_b:
64
+ moyen = st.selectbox("Moyen de Paiement", ["Espèces", "Mobile Money (Wave/OM)", "Virement", "Chèque"])
65
+ commentaire = st.text_input("Référence / Commentaire", placeholder="Ex: Transaction ID Wave...")
66
+
67
+ # Checkbox pour clore le dossier
68
+ cloture = st.checkbox("✅ Ce paiement solde la totalité du prêt (Clôturer le dossier)")
69
+
70
+ submit = st.form_submit_button("VALIDER L'ENCAISSEMENT")
71
+
72
+ if submit:
73
+ try:
74
+ # Génération ID Transaction
75
+ existing_remb = ws_remb.get_all_values()
76
+ next_id = len(existing_remb) # Compte les lignes (incluant header)
77
+ trans_id = f"TRX-2025-{next_id:04d}"
78
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
79
+
80
+ # 1. Écriture dans la feuille Remboursements
81
+ new_row = [
82
+ trans_id,
83
+ loan_id,
84
+ str(date_paiement),
85
+ montant_verse,
86
+ moyen,
87
+ commentaire,
88
+ timestamp
89
+ ]
90
+ ws_remb.append_row(new_row)
91
+
92
+ # 2. Mise à jour du Statut dans Prets_Master (Si demandé)
93
+ if cloture:
94
+ # Trouver la ligne du prêt dans le Sheet (C'est un peu technique avec gspread)
95
+ # On cherche la cellule qui contient l'ID
96
+ cell = ws_prets.find(loan_id)
97
+ # On suppose que la colonne Statut est la colonne 15 (O) ou 9 (I) selon votre fichier.
98
+ # Mieux : on cherche l'entête "Statut"
99
+ header = ws_prets.row_values(1)
100
+ col_statut_idx = header.index("Statut") + 1
101
+
102
+ # Update de la cellule
103
+ ws_prets.update_cell(cell.row, col_statut_idx, "CLOTURE")
104
+ st.success(f"Dossier {loan_id} CLÔTURÉ avec succès.")
105
+
106
+ st.success(f"✅ Paiement de {montant_verse} XOF enregistré (Ref: {trans_id})")
107
+ st.balloons()
108
+
109
+ except Exception as e:
110
+ st.error(f"Erreur d'écriture : {e}")