klydekushy commited on
Commit
e056231
·
verified ·
1 Parent(s): 1ee6705

Update src/modules/repayments.py

Browse files
Files changed (1) hide show
  1. src/modules/repayments.py +93 -47
src/modules/repayments.py CHANGED
@@ -549,14 +549,14 @@ def show_repayments_module(client, sheet_name):
549
  # Affichage du scénario sélectionné
550
  if 'selected_scenario' in st.session_state:
551
  selected = st.session_state['selected_scenario']
552
- st.success(f"Scénario sélectionné : {selected['label']} ({selected['taux']}% de pénalités)")
553
  st.info(f"Montant total à encaisser : **{selected['total_a_encaisser']:,.0f} XOF**")
554
  else:
555
  # Pas de retard
556
  if jours_retard < 0:
557
- st.success(f"Paiement anticipé de {abs(jours_retard)} jours")
558
  else:
559
- st.success("Paiement dans les délais")
560
 
561
  st.session_state['selected_scenario'] = {
562
  'taux': 0.0,
@@ -599,7 +599,7 @@ def show_repayments_module(client, sheet_name):
599
  help="Informations complémentaires"
600
  )
601
 
602
- submit = st.form_submit_button("VALIDER L'ENCAISSEMENT", use_container_width=True)
603
 
604
  if submit:
605
  if montant_verse <= 0:
@@ -709,7 +709,7 @@ def show_repayments_module(client, sheet_name):
709
 
710
  st.markdown(f"""
711
  <div class="repayment-success-badge">
712
- <h3>DOSSIER {loan_id} AUTOMATIQUEMENT CLÔTURÉ</h3>
713
  <p style="color: #8b949e; margin: 8px 0 0 0;">
714
  Motif : {critere_messages.get(analyse_complete['critere_cloture'], 'Prêt terminé')}<br>
715
  Paiement de {montant_verse:,.0f} XOF enregistré | Ref: {trans_id}
@@ -719,15 +719,45 @@ def show_repayments_module(client, sheet_name):
719
 
720
  st.info(f"Détails : {analyse_complete['message_cloture']}")
721
  else:
722
- st.success(f"Paiement de **{montant_verse:,.0f} XOF** enregistré avec succès")
723
  st.info(f"Référence de transaction : **{trans_id}**")
724
 
725
  # Afficher l'état du prêt
726
  if analyse_complete['solde_apres'] > 0:
727
  st.info(f"Solde restant à rembourser : **{analyse_complete['solde_apres']:,.0f} XOF**")
728
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
729
  # Afficher un récapitulatif détaillé
730
- with st.expander("Récapitulatif de la transaction", expanded=True):
731
  recap_col1, recap_col2, recap_col3 = st.columns(3)
732
  with recap_col1:
733
  st.write(f"**ID Transaction :** {trans_id}")
@@ -744,43 +774,6 @@ def show_repayments_module(client, sheet_name):
744
  st.write(f"**Solde Après :** {analyse_complete['solde_apres']:,.0f} XOF")
745
  st.write(f"**Moyen :** {moyen}")
746
  st.write(f"**Statut :** {analyse_complete['statut_paiement']}")
747
-
748
- # Bouton pour générer le reçu
749
- st.divider()
750
- if st.button("Générer le Reçu", use_container_width=True):
751
- # Préparer les données pour le reçu
752
- client_data = df_clients[df_clients['ID_Client'] == analyse_complete['id_client']].iloc[0].to_dict()
753
-
754
- recu_data = {
755
- 'numero_recu': numero_recu,
756
- 'trans_id': trans_id,
757
- 'date_paiement': date_paiement,
758
- 'client': client_data,
759
- 'loan': loan_data.to_dict(),
760
- 'paiement': analyse_complete,
761
- 'moyen': moyen,
762
- 'reference': reference_externe
763
- }
764
-
765
- pdf_bytes = generer_recu(recu_data)
766
-
767
- if pdf_bytes:
768
- # Mise à jour de Recu_Emis dans Remboursements
769
- cell_trans = ws_remb.find(trans_id)
770
- header_remb = ws_remb.row_values(1)
771
- col_recu_idx = header_remb.index("Recu_Emis") + 1
772
- ws_remb.update_cell(cell_trans.row, col_recu_idx, "OUI")
773
-
774
- st.download_button(
775
- label="Télécharger le Reçu PDF",
776
- data=pdf_bytes,
777
- file_name=f"{numero_recu}_{loan_id}.pdf",
778
- mime="application/pdf",
779
- use_container_width=True
780
- )
781
- st.success("Reçu généré avec succès")
782
- else:
783
- st.error("❌ Erreur lors de la génération du reçu")
784
 
785
  except Exception as e:
786
  st.error(f"❌ Erreur lors de l'enregistrement : {e}")
@@ -817,8 +810,8 @@ def show_repayments_module(client, sheet_name):
817
  jours_avance = (premiere_echeance - date_paiement).days
818
  causes.append(f"Le paiement est effectué {jours_avance} jours AVANT la première échéance ({premiere_echeance.strftime('%d/%m/%Y')}). Ceci est autorisé comme paiement anticipé.")
819
  elif date_paiement > derniere_echeance:
820
- jours_retard = (date_paiement - derniere_echeance).days
821
- causes.append(f"Le paiement est effectué {jours_retard} jours APRÈS la dernière échéance ({derniere_echeance.strftime('%d/%m/%Y')})")
822
 
823
  # Vérifier si toutes les échéances sont payées
824
  if 'echeances' in locals() and len(echeances) > 0:
@@ -850,10 +843,63 @@ def show_repayments_module(client, sheet_name):
850
 
851
  if 'previous_payments' in locals():
852
  st.write(f"- Nombre de paiements enregistrés: {len(previous_payments)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
 
854
  else:
855
  # Instructions si aucun client sélectionné
856
- st.info("Veuillez sélectionner un client dans la liste ci-dessus pour commencer")
857
 
858
  # Afficher statistiques rapides
859
  if not active_loans.empty:
 
549
  # Affichage du scénario sélectionné
550
  if 'selected_scenario' in st.session_state:
551
  selected = st.session_state['selected_scenario']
552
+ st.success(f"Scénario sélectionné : {selected['label']} ({selected['taux']}% de pénalités)")
553
  st.info(f"Montant total à encaisser : **{selected['total_a_encaisser']:,.0f} XOF**")
554
  else:
555
  # Pas de retard
556
  if jours_retard < 0:
557
+ st.success(f"Paiement anticipé de {abs(jours_retard)} jours")
558
  else:
559
+ st.success("Paiement dans les délais")
560
 
561
  st.session_state['selected_scenario'] = {
562
  'taux': 0.0,
 
599
  help="Informations complémentaires"
600
  )
601
 
602
+ submit = st.form_submit_button("VALIDER L'ENCAISSEMENT", use_container_width=True)
603
 
604
  if submit:
605
  if montant_verse <= 0:
 
709
 
710
  st.markdown(f"""
711
  <div class="repayment-success-badge">
712
+ <h3>✅ DOSSIER {loan_id} AUTOMATIQUEMENT CLÔTURÉ</h3>
713
  <p style="color: #8b949e; margin: 8px 0 0 0;">
714
  Motif : {critere_messages.get(analyse_complete['critere_cloture'], 'Prêt terminé')}<br>
715
  Paiement de {montant_verse:,.0f} XOF enregistré | Ref: {trans_id}
 
719
 
720
  st.info(f"Détails : {analyse_complete['message_cloture']}")
721
  else:
722
+ st.success(f"Paiement de **{montant_verse:,.0f} XOF** enregistré avec succès")
723
  st.info(f"Référence de transaction : **{trans_id}**")
724
 
725
  # Afficher l'état du prêt
726
  if analyse_complete['solde_apres'] > 0:
727
  st.info(f"Solde restant à rembourser : **{analyse_complete['solde_apres']:,.0f} XOF**")
728
 
729
+ # === CORRECTION 4 : Préparer les données pour le reçu IMMÉDIATEMENT ===
730
+ client_data_dict = df_clients[df_clients['ID_Client'] == analyse_complete['id_client']].iloc[0].to_dict()
731
+
732
+ recu_data = {
733
+ 'numero_recu': numero_recu,
734
+ 'trans_id': trans_id,
735
+ 'date_paiement': date_paiement,
736
+ 'client': client_data_dict,
737
+ 'loan': loan_data.to_dict(),
738
+ 'paiement': analyse_complete,
739
+ 'moyen': moyen,
740
+ 'reference': reference_externe if reference_externe else "N/A"
741
+ }
742
+
743
+ # Vérification avant sauvegarde
744
+ print("=== VÉRIFICATION DES DONNÉES ===")
745
+ print(f"✓ Numéro reçu : {recu_data.get('numero_recu')}")
746
+ print(f"✓ Transaction ID : {recu_data.get('trans_id')}")
747
+ print(f"✓ Client ID : {recu_data['client'].get('ID_Client')}")
748
+ print(f"✓ Loan ID : {recu_data['loan'].get('ID_Pret')}")
749
+ print(f"✓ Montant versé : {recu_data['paiement'].get('montant_verse')}")
750
+
751
+ # Sauvegarder dans session_state pour persistance
752
+ st.session_state['derniere_transaction'] = {
753
+ 'recu_data': recu_data,
754
+ 'trans_id': trans_id,
755
+ 'numero_recu': numero_recu,
756
+ 'loan_id': loan_id
757
+ }
758
+
759
  # Afficher un récapitulatif détaillé
760
+ with st.expander("📋 Récapitulatif de la transaction", expanded=True):
761
  recap_col1, recap_col2, recap_col3 = st.columns(3)
762
  with recap_col1:
763
  st.write(f"**ID Transaction :** {trans_id}")
 
774
  st.write(f"**Solde Après :** {analyse_complete['solde_apres']:,.0f} XOF")
775
  st.write(f"**Moyen :** {moyen}")
776
  st.write(f"**Statut :** {analyse_complete['statut_paiement']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
 
778
  except Exception as e:
779
  st.error(f"❌ Erreur lors de l'enregistrement : {e}")
 
810
  jours_avance = (premiere_echeance - date_paiement).days
811
  causes.append(f"Le paiement est effectué {jours_avance} jours AVANT la première échéance ({premiere_echeance.strftime('%d/%m/%Y')}). Ceci est autorisé comme paiement anticipé.")
812
  elif date_paiement > derniere_echeance:
813
+ jours_retard_global = (date_paiement - derniere_echeance).days
814
+ causes.append(f"Le paiement est effectué {jours_retard_global} jours APRÈS la dernière échéance ({derniere_echeance.strftime('%d/%m/%Y')})")
815
 
816
  # Vérifier si toutes les échéances sont payées
817
  if 'echeances' in locals() and len(echeances) > 0:
 
843
 
844
  if 'previous_payments' in locals():
845
  st.write(f"- Nombre de paiements enregistrés: {len(previous_payments)}")
846
+
847
+ # === CORRECTION 2 : GÉNÉRATION DU REÇU (Section persistante) ===
848
+ if 'derniere_transaction' in st.session_state:
849
+ st.divider()
850
+ st.subheader("📄 Génération du Reçu")
851
+
852
+ trans_data = st.session_state['derniere_transaction']
853
+
854
+ st.info(f"✅ Transaction **{trans_data['trans_id']}** enregistrée avec succès")
855
+ st.caption(f"Reçu N° : **{trans_data['numero_recu']}**")
856
+
857
+ col_btn1, col_btn2 = st.columns(2)
858
+
859
+ with col_btn1:
860
+ if st.button("📥 Générer et Télécharger le Reçu PDF", use_container_width=True, type="primary"):
861
+ try:
862
+ pdf_bytes = generer_recu(trans_data['recu_data'])
863
+
864
+ if pdf_bytes:
865
+ # Mise à jour de Recu_Emis dans Remboursements
866
+ try:
867
+ cell_trans = ws_remb.find(trans_data['trans_id'])
868
+ header_remb = ws_remb.row_values(1)
869
+ col_recu_idx = header_remb.index("Recu_Emis") + 1
870
+ ws_remb.update_cell(cell_trans.row, col_recu_idx, "OUI")
871
+ except Exception as e_update:
872
+ st.warning(f"⚠️ Impossible de mettre à jour le statut du reçu : {e_update}")
873
+
874
+ # Téléchargement
875
+ st.download_button(
876
+ label="💾 Cliquer ici pour télécharger",
877
+ data=pdf_bytes,
878
+ file_name=f"{trans_data['numero_recu']}_{trans_data['loan_id']}.pdf",
879
+ mime="application/pdf",
880
+ use_container_width=True,
881
+ key="download_pdf"
882
+ )
883
+ st.success("✅ Reçu généré avec succès ! Cliquez sur le bouton ci-dessus pour télécharger.")
884
+ else:
885
+ st.error("❌ Erreur lors de la génération du PDF")
886
+
887
+ except Exception as e_pdf:
888
+ st.error(f"❌ Erreur lors de la génération : {e_pdf}")
889
+ st.exception(e_pdf)
890
+
891
+ with col_btn2:
892
+ if st.button("🔄 Nouvelle Transaction", use_container_width=True):
893
+ # Nettoyer la session
894
+ if 'derniere_transaction' in st.session_state:
895
+ del st.session_state['derniere_transaction']
896
+ if 'selected_scenario' in st.session_state:
897
+ del st.session_state['selected_scenario']
898
+ st.rerun()
899
 
900
  else:
901
  # Instructions si aucun client sélectionné
902
+ st.info("ℹ️ Veuillez sélectionner un client dans la liste ci-dessus pour commencer")
903
 
904
  # Afficher statistiques rapides
905
  if not active_loans.empty: