V2.0: Refonte système bancaire - DB SQLite, RIB FR, TVA auto, multi-banques
- Remplace JSON par SQLite (aiosqlite) pour atomicité et intégrité - Nouveau format RIB français avec checksum modulo 97 - Chaque banque a son propre rôle Discord (isolation par serveur) - TVA automatique Particulier -> Entreprise, redirection au Fisc - Institutions gouvernementales avec droit d'audit optionnel - Commandes: /gouv, /banque, /audit, /mes-ribs - Supprime: 16 anciens fichiers (entreprises, FBM, URSAFF, etc.) - Reset complet des données, repart de zéro
This commit is contained in:
parent
2e38d05152
commit
c9ad155bf6
38 changed files with 3689 additions and 5106 deletions
31
__main__.py
31
__main__.py
|
|
@ -33,7 +33,7 @@ permissions.update(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Initialisation du bot
|
# Initialisation du bot
|
||||||
bot = commands.Bot(command_prefix="!", application_id="1310235313461002241", intents=intents)
|
bot = commands.Bot(command_prefix="!", application_id="1337733859814543410", intents=intents)
|
||||||
|
|
||||||
async def load_cogs():
|
async def load_cogs():
|
||||||
"""Charge toutes les commandes."""
|
"""Charge toutes les commandes."""
|
||||||
|
|
@ -42,38 +42,25 @@ async def load_cogs():
|
||||||
"commandes.identite",
|
"commandes.identite",
|
||||||
"commandes.voir_carte_identite",
|
"commandes.voir_carte_identite",
|
||||||
"commandes.virement",
|
"commandes.virement",
|
||||||
"commandes.transactions",
|
"commandes.compte",
|
||||||
"commandes.ajouter_argent",
|
"commandes.mes_ribs",
|
||||||
|
"commandes.gouv",
|
||||||
|
"commandes.banque",
|
||||||
|
"commandes.audit",
|
||||||
"commandes.ticket",
|
"commandes.ticket",
|
||||||
"commandes.restranscription_staff",
|
"commandes.restranscription_staff",
|
||||||
"utils.welcome_message",
|
"utils.welcome_message",
|
||||||
"commandes.permis",
|
"commandes.permis",
|
||||||
"commandes.ouvrir_compte",
|
|
||||||
"commandes.compte",
|
|
||||||
"commandes.change_nickname",
|
"commandes.change_nickname",
|
||||||
"commandes.rename_all_on_join",
|
"commandes.rename_all_on_join",
|
||||||
"commandes.message_tous",
|
"commandes.message_tous",
|
||||||
"commandes.retirer_argent",
|
|
||||||
"commandes.ouvrir_comptes_entreprises",
|
|
||||||
"commandes.compte_gouvernement",
|
|
||||||
"commandes.comptes_entreprises",
|
|
||||||
"commandes.compte_urssaf",
|
|
||||||
"commandes.compte_banque_nationale",
|
|
||||||
"commandes.virement_entreprise",
|
|
||||||
"commandes.virement_gouvernement",
|
|
||||||
"commandes.valider_visite_médicale",
|
"commandes.valider_visite_médicale",
|
||||||
"commandes.abonnement",
|
|
||||||
"commandes.virement_banquier",
|
|
||||||
"commandes.virement_banquier_entreprise",
|
|
||||||
"commandes.compte_fbm",
|
|
||||||
"commandes.virement_fbm",
|
|
||||||
"commandes.virement_ursaff",
|
|
||||||
"commandes.stats_commandes",
|
"commandes.stats_commandes",
|
||||||
"commandes.roll",
|
"commandes.roll",
|
||||||
"commandes.annonces_sessions",
|
"commandes.annonces_sessions",
|
||||||
"commandes.retrait_gouv",
|
|
||||||
"commandes.counting",
|
"commandes.counting",
|
||||||
"commandes.config"
|
"commandes.config",
|
||||||
|
"commandes.panel"
|
||||||
]
|
]
|
||||||
|
|
||||||
for ext in extensions:
|
for ext in extensions:
|
||||||
|
|
@ -89,7 +76,7 @@ async def on_ready():
|
||||||
log_info(f"Connecté en tant que {bot.user}")
|
log_info(f"Connecté en tant que {bot.user}")
|
||||||
await load_cogs()
|
await load_cogs()
|
||||||
await bot.tree.sync()
|
await bot.tree.sync()
|
||||||
await bot.change_presence(activity=discord.Game(name="la V1.8")) # Ajout du status
|
await bot.change_presence(activity=discord.Game(name="la V2.0"))
|
||||||
log_info("Commandes synchronisées.")
|
log_info("Commandes synchronisées.")
|
||||||
|
|
||||||
# Gère les erreurs de commandes classiques
|
# Gère les erreurs de commandes classiques
|
||||||
|
|
|
||||||
218
abonnements.json
218
abonnements.json
|
|
@ -1,218 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"nom": "Test",
|
|
||||||
"rib_emetteur": "22144 59424 87742058459 72",
|
|
||||||
"rib_receveur": "66427 49104 57218570654 78",
|
|
||||||
"montant": 1.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "samedi"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "36495 80083 39542816185 27",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "26384 93370 75890178377 91",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "22144 59424 87742058459 72",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "85047 60626 80894743346 94",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "28777 24580 29765721710 42",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "24483 98056 61791340797 80",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "10009 40554 56452790470 78",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "76644 32901 90493249064 16",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "15563 69899 51361446295 84",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "22128 86524 35982837421 58",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "55868 11389 89049343014 38",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "93266 82343 74845298309 22",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "10234 24218 10477731114 78",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "50970 51336 33017058086 50",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "87292 81104 84784268868 12",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "51229 80290 86979675797 93",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "28794 77878 41312953164 71",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "78740 15751 70195185799 30",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "92871 52823 19649316403 70",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frais_bancaire_et_de_gestion_1",
|
|
||||||
"rib_emetteur": "73834 54818 11833486819 17",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 5.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Frog",
|
|
||||||
"rib_emetteur": "48003 84424 36961155485 64",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 700.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Di regia",
|
|
||||||
"rib_emetteur": "10009 40554 56452790470 78",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 4000.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Leonardo",
|
|
||||||
"rib_emetteur": "24756 54403 68357307735 95",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 4000.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Correa",
|
|
||||||
"rib_emetteur": "28794 77878 41312953164 71",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 4300.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "jose",
|
|
||||||
"rib_emetteur": "87292 81104 84784268868 12",
|
|
||||||
"rib_receveur": "15156 38436 35920 54357",
|
|
||||||
"montant": 800.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nom": "Paye_de_Salvatore_Di_Regia",
|
|
||||||
"rib_emetteur": "15156 38436 35920 54357",
|
|
||||||
"rib_receveur": "10009 40554 56452790470 78",
|
|
||||||
"montant": 5000.0,
|
|
||||||
"banque": "NGC Bank",
|
|
||||||
"jour": "dimanche"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{}
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands, tasks
|
|
||||||
import json
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
ABONNEMENTS_FILE = "abonnements.json"
|
|
||||||
|
|
||||||
BANQUES_DISPONIBLES = [
|
|
||||||
"Victoria's Credit Bank",
|
|
||||||
"NGC Bank"
|
|
||||||
]
|
|
||||||
|
|
||||||
JOURS_SEMAINE = [
|
|
||||||
"lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"
|
|
||||||
]
|
|
||||||
|
|
||||||
class Abonnement(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
self.abonnements = self.load_abonnements()
|
|
||||||
self.executer_abonnements.start()
|
|
||||||
|
|
||||||
def load_abonnements(self):
|
|
||||||
try:
|
|
||||||
with open(ABONNEMENTS_FILE, 'r', encoding='utf-8') as f:
|
|
||||||
return json.load(f)
|
|
||||||
except (FileNotFoundError, json.JSONDecodeError):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def save_abonnements(self):
|
|
||||||
with open(ABONNEMENTS_FILE, 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(self.abonnements, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
# 🎯 Auto-complétion pour les banques
|
|
||||||
async def autocomplete_banque(self, interaction: discord.Interaction, current: str):
|
|
||||||
return [
|
|
||||||
app_commands.Choice(name=b, value=b)
|
|
||||||
for b in BANQUES_DISPONIBLES if current.lower() in b.lower()
|
|
||||||
]
|
|
||||||
|
|
||||||
# 🎯 Auto-complétion pour les jours
|
|
||||||
async def autocomplete_jour(self, interaction: discord.Interaction, current: str):
|
|
||||||
return [
|
|
||||||
app_commands.Choice(name=day.capitalize(), value=day)
|
|
||||||
for day in JOURS_SEMAINE if current.lower() in day
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="abonnement", description="Crée un abonnement bancaire hebdomadaire.")
|
|
||||||
@app_commands.describe(
|
|
||||||
nom="Nom de l'abonnement",
|
|
||||||
rib_emetteur="RIB de l'expéditeur",
|
|
||||||
montant="Montant à envoyer",
|
|
||||||
rib_receveur="RIB du bénéficiaire",
|
|
||||||
banque="Nom de la banque",
|
|
||||||
jour="Jour de la semaine du virement"
|
|
||||||
)
|
|
||||||
@app_commands.autocomplete(banque=autocomplete_banque, jour=autocomplete_jour)
|
|
||||||
async def abonnement(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
nom: str,
|
|
||||||
rib_emetteur: str,
|
|
||||||
montant: float,
|
|
||||||
rib_receveur: str,
|
|
||||||
banque: str,
|
|
||||||
jour: str
|
|
||||||
):
|
|
||||||
if jour.lower() not in JOURS_SEMAINE:
|
|
||||||
await interaction.response.send_message("❌ Jour invalide. Choisissez un jour valide de la semaine.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
abonnement = {
|
|
||||||
"nom": nom,
|
|
||||||
"rib_emetteur": rib_emetteur,
|
|
||||||
"rib_receveur": rib_receveur,
|
|
||||||
"montant": montant,
|
|
||||||
"banque": banque,
|
|
||||||
"jour": jour.lower()
|
|
||||||
}
|
|
||||||
|
|
||||||
self.abonnements.append(abonnement)
|
|
||||||
self.save_abonnements()
|
|
||||||
|
|
||||||
await interaction.response.send_message(f"✅ Abonnement **{nom}** enregistré. Virement automatique tous les **{jour}**.", ephemeral=True)
|
|
||||||
|
|
||||||
@tasks.loop(minutes=60)
|
|
||||||
async def executer_abonnements(self):
|
|
||||||
today = datetime.datetime.now().strftime("%A").lower()
|
|
||||||
try:
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
except:
|
|
||||||
comptes = {}
|
|
||||||
|
|
||||||
updated = False
|
|
||||||
for abonnement in self.abonnements:
|
|
||||||
if abonnement["jour"] != today:
|
|
||||||
continue
|
|
||||||
|
|
||||||
banque = abonnement["banque"]
|
|
||||||
rib_emetteur = abonnement["rib_emetteur"]
|
|
||||||
rib_receveur = abonnement["rib_receveur"]
|
|
||||||
montant = abonnement["montant"]
|
|
||||||
|
|
||||||
destinataire_id = None
|
|
||||||
emetteur_id = None
|
|
||||||
|
|
||||||
for user_id, data in comptes.get(banque, {}).items():
|
|
||||||
if data.get("rib") == rib_emetteur:
|
|
||||||
emetteur_id = user_id
|
|
||||||
if data.get("rib") == rib_receveur:
|
|
||||||
destinataire_id = user_id
|
|
||||||
|
|
||||||
if not emetteur_id or not destinataire_id:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if comptes[banque][emetteur_id]["solde"] < montant:
|
|
||||||
continue
|
|
||||||
|
|
||||||
comptes[banque][emetteur_id]["solde"] -= montant
|
|
||||||
comptes[banque][emetteur_id]["transactions"].append({
|
|
||||||
"date": datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement automatique (abonnement)",
|
|
||||||
"source": f"Vers RIB {rib_receveur}",
|
|
||||||
"montant": -montant
|
|
||||||
})
|
|
||||||
|
|
||||||
comptes[banque][destinataire_id]["solde"] += montant
|
|
||||||
comptes[banque][destinataire_id]["transactions"].append({
|
|
||||||
"date": datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement reçu (abonnement)",
|
|
||||||
"source": f"{rib_emetteur}",
|
|
||||||
"montant": montant
|
|
||||||
})
|
|
||||||
|
|
||||||
updated = True
|
|
||||||
|
|
||||||
if updated:
|
|
||||||
with open("comptes_bancaires.json", 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(comptes, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
@executer_abonnements.before_loop
|
|
||||||
async def before_abonnement_loop(self):
|
|
||||||
await self.bot.wait_until_ready()
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(Abonnement(bot))
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class AjouterArgent(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
# Choix de banques automatiques
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(
|
|
||||||
name="ajouter_argent",
|
|
||||||
description="Ajoute de l'argent à un compte (réservé aux banquiers)."
|
|
||||||
)
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
@app_commands.describe(
|
|
||||||
rib="Le RIB du compte",
|
|
||||||
montant="Montant à ajouter",
|
|
||||||
banque="Banque cible (facultatif)"
|
|
||||||
)
|
|
||||||
async def ajouter_argent(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
rib: str,
|
|
||||||
montant: float,
|
|
||||||
banque: app_commands.Choice[str] = None
|
|
||||||
):
|
|
||||||
# Vérification du rôle
|
|
||||||
if not has_role(interaction.user, "banquier"):
|
|
||||||
await interaction.response.send_message(
|
|
||||||
"❌ Vous n'avez pas la permission d'utiliser cette commande.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
if montant <= 0:
|
|
||||||
await interaction.response.send_message(
|
|
||||||
"❌ Le montant doit être supérieur à zéro.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
banque_nom = banque.value if banque else None
|
|
||||||
|
|
||||||
# Chargement des fichiers
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
entreprises = json.load(f)
|
|
||||||
|
|
||||||
cible_data = None
|
|
||||||
user_id = None
|
|
||||||
is_entreprise = False
|
|
||||||
|
|
||||||
# Recherche dans la banque spécifiée (si précisée)
|
|
||||||
if banque_nom and banque_nom in comptes:
|
|
||||||
for uid, info in comptes[banque_nom].items():
|
|
||||||
if info.get("rib") == rib:
|
|
||||||
cible_data = comptes
|
|
||||||
user_id = uid
|
|
||||||
break
|
|
||||||
|
|
||||||
if not user_id and banque_nom and banque_nom in entreprises:
|
|
||||||
for nom_entreprise, info in entreprises[banque_nom].items():
|
|
||||||
if info.get("rib") == rib:
|
|
||||||
cible_data = entreprises
|
|
||||||
user_id = nom_entreprise
|
|
||||||
is_entreprise = True
|
|
||||||
break
|
|
||||||
|
|
||||||
# Si banque non précisée ou compte non trouvé, recherche dans toutes les banques
|
|
||||||
if not user_id and not banque_nom:
|
|
||||||
# Recherche dans toutes les banques utilisateurs
|
|
||||||
for banque_courante, comptes_banque in comptes.items():
|
|
||||||
for uid, info in comptes_banque.items():
|
|
||||||
if info.get("rib") == rib:
|
|
||||||
cible_data = comptes
|
|
||||||
user_id = uid
|
|
||||||
banque_nom = banque_courante
|
|
||||||
break
|
|
||||||
if user_id:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not user_id and not is_entreprise:
|
|
||||||
# Recherche dans toutes les banques entreprises
|
|
||||||
for banque_courante, entreprises_banque in entreprises.items():
|
|
||||||
for nom_entreprise, info in entreprises_banque.items():
|
|
||||||
if info.get("rib") == rib:
|
|
||||||
cible_data = entreprises
|
|
||||||
user_id = nom_entreprise
|
|
||||||
banque_nom = banque_courante
|
|
||||||
is_entreprise = True
|
|
||||||
break
|
|
||||||
if user_id:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not user_id:
|
|
||||||
await interaction.response.send_message(
|
|
||||||
"❌ Aucun compte trouvé avec ce RIB.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Ajout du montant
|
|
||||||
cible_data[banque_nom][user_id]["solde"] += montant
|
|
||||||
transaction = {
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": montant,
|
|
||||||
"emetteur": interaction.user.id,
|
|
||||||
"destinataire": user_id
|
|
||||||
}
|
|
||||||
cible_data[banque_nom][user_id]["transactions"].append(transaction)
|
|
||||||
|
|
||||||
# Sauvegarde
|
|
||||||
if is_entreprise:
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(entreprises, f, ensure_ascii=False, indent=4)
|
|
||||||
else:
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes, f, ensure_ascii=False, indent=4)
|
|
||||||
# Envoyer un MP à l'utilisateur (sauf entreprise)
|
|
||||||
try:
|
|
||||||
user = await self.bot.fetch_user(int(user_id))
|
|
||||||
await user.send(
|
|
||||||
f"💰 Un dépôt de **{montant:.2f}€** a été effectué sur votre compte dans **{banque_nom}**."
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass # Si l'utilisateur a désactivé les MP
|
|
||||||
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"✅ **{montant:.2f}€** ajoutés avec succès au compte `{rib}` dans la banque **{banque_nom}**.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(AjouterArgent(bot))
|
|
||||||
75
commandes/audit.py
Normal file
75
commandes/audit.py
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import discord
|
||||||
|
from discord import app_commands
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from utils.guild_config import has_role, get_guild_role
|
||||||
|
from utils.bank_manager import BankManager
|
||||||
|
|
||||||
|
bank_manager = BankManager()
|
||||||
|
|
||||||
|
|
||||||
|
class Audit(commands.Cog):
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
audit_group = app_commands.Group(name="audit", description="Audit bancaire (institutions)")
|
||||||
|
|
||||||
|
@audit_group.command(name="consulter-banque", description="Consulter les comptes d'une banque (institutions avec audit)")
|
||||||
|
@app_commands.describe(nom_banque="Nom de la banque à auditer")
|
||||||
|
async def consulter_banque(self, interaction: discord.Interaction, nom_banque: str):
|
||||||
|
user_roles = [r.id for r in interaction.user.roles]
|
||||||
|
institutions = await bank_manager.lister_institutions(interaction.guild.id)
|
||||||
|
|
||||||
|
authorized = None
|
||||||
|
for inst in institutions:
|
||||||
|
if inst["role_id"] and inst["role_id"] in user_roles and inst["can_audit_all"]:
|
||||||
|
authorized = inst
|
||||||
|
break
|
||||||
|
|
||||||
|
if not authorized:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas le droit d'audit. Réservé aux institutions avec le droit d'audit activé.",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
banque = await bank_manager.get_banque_by_name(interaction.guild.id, nom_banque)
|
||||||
|
if not banque:
|
||||||
|
banques = await bank_manager.lister_banques(interaction.guild.id)
|
||||||
|
noms = ", ".join(b["name"] for b in banques) or "aucune"
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"❌ Banque **{nom_banque}** introuvable. Banques disponibles : {noms}",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
comptes = await bank_manager.get_comptes_banque(interaction.guild.id, banque["id"])
|
||||||
|
if not comptes:
|
||||||
|
await interaction.response.send_message("Aucun compte dans cette banque.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=f"🔍 Audit : {banque['name']}",
|
||||||
|
description=f"Effectué par l'institution **{authorized['name']}**",
|
||||||
|
color=discord.Color.orange(),
|
||||||
|
)
|
||||||
|
|
||||||
|
for c in comptes:
|
||||||
|
member = interaction.guild.get_member(c["user_id"])
|
||||||
|
name = member.display_name if member else f"User#{c['user_id']}"
|
||||||
|
tva_text = f" | TVA: {c['tva_rate']}%" if c["account_type"] == "entreprise" else ""
|
||||||
|
embed.add_field(
|
||||||
|
name=f"{name} ({c['account_type']})",
|
||||||
|
value=(
|
||||||
|
f"**RIB :** `{c['rib']}`\n"
|
||||||
|
f"**Solde :** `{c['solde']:.2f}€`{tva_text}"
|
||||||
|
),
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
embed.set_footer(text=f"Total : {len(comptes)} compte(s) | Réserve banque : {banque['vault_balance']:.2f}€")
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot):
|
||||||
|
await bot.add_cog(Audit(bot))
|
||||||
245
commandes/banque.py
Normal file
245
commandes/banque.py
Normal file
|
|
@ -0,0 +1,245 @@
|
||||||
|
import discord
|
||||||
|
from discord import app_commands
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from utils.guild_config import has_role, get_guild_role
|
||||||
|
from utils.bank_manager import BankManager
|
||||||
|
from utils.rib import decoder_rib
|
||||||
|
|
||||||
|
bank_manager = BankManager()
|
||||||
|
|
||||||
|
|
||||||
|
class Banque(commands.Cog):
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
banque_group = app_commands.Group(name="banque", description="Opérations bancaires")
|
||||||
|
|
||||||
|
async def _get_user_bank(self, interaction: discord.Interaction) -> dict:
|
||||||
|
banques = await bank_manager.lister_banques(interaction.guild.id)
|
||||||
|
for b in banques:
|
||||||
|
role = interaction.guild.get_role(b["role_id"])
|
||||||
|
if role and role in interaction.user.roles:
|
||||||
|
return b
|
||||||
|
return None
|
||||||
|
|
||||||
|
@banque_group.command(name="ouvrir-compte", description="Ouvrir un compte pour un membre")
|
||||||
|
@app_commands.describe(
|
||||||
|
membre="Le membre qui recevra le compte",
|
||||||
|
type_compte="Type de compte",
|
||||||
|
taux_tva="Taux TVA (entreprises uniquement, défaut 0%)"
|
||||||
|
)
|
||||||
|
@app_commands.choices(
|
||||||
|
type_compte=[
|
||||||
|
app_commands.Choice(name="Particulier", value="particulier"),
|
||||||
|
app_commands.Choice(name="Entreprise", value="entreprise"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
async def ouvrir_compte(
|
||||||
|
self,
|
||||||
|
interaction: discord.Interaction,
|
||||||
|
membre: discord.Member,
|
||||||
|
type_compte: app_commands.Choice[str],
|
||||||
|
taux_tva: float = 0.0,
|
||||||
|
):
|
||||||
|
bank = await self._get_user_bank(interaction)
|
||||||
|
if not bank:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas de rôle de banquier sur ce serveur.", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if type_compte.value == "entreprise" and taux_tva < 0:
|
||||||
|
await interaction.response.send_message("❌ Le taux TVA ne peut pas être négatif.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = await bank_manager.ouvrir_compte(
|
||||||
|
guild_id=interaction.guild.id,
|
||||||
|
bank_id=bank["id"],
|
||||||
|
user_id=membre.id,
|
||||||
|
account_type=type_compte.value,
|
||||||
|
tva_rate=taux_tva if type_compte.value == "entreprise" else 0.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="💳 Compte ouvert",
|
||||||
|
description=(
|
||||||
|
f"**Banque :** {bank['name']}\n"
|
||||||
|
f"**Membre :** {membre.mention}\n"
|
||||||
|
f"**Type :** {type_compte.value.title()}\n"
|
||||||
|
f"**RIB :** `{result['rib']}`\n"
|
||||||
|
),
|
||||||
|
color=discord.Color.green(),
|
||||||
|
)
|
||||||
|
if type_compte.value == "entreprise":
|
||||||
|
embed.add_field(name="Taux TVA", value=f"{taux_tva}%")
|
||||||
|
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await membre.send(
|
||||||
|
f"💳 Votre compte **{type_compte.value}** chez **{bank['name']}** a été ouvert.\n"
|
||||||
|
f"**RIB :** `{result['rib']}`"
|
||||||
|
)
|
||||||
|
except discord.Forbidden:
|
||||||
|
pass
|
||||||
|
|
||||||
|
except ValueError as e:
|
||||||
|
await interaction.response.send_message(f"❌ {e}", ephemeral=True)
|
||||||
|
|
||||||
|
@banque_group.command(name="modifier-tva", description="Modifier le taux TVA d'une entreprise")
|
||||||
|
@app_commands.describe(
|
||||||
|
rib="RIB de l'entreprise",
|
||||||
|
nouveau_taux="Nouveau taux TVA (ex: 5.5, 20)"
|
||||||
|
)
|
||||||
|
async def modifier_tva(self, interaction: discord.Interaction, rib: str, nouveau_taux: float):
|
||||||
|
bank = await self._get_user_bank(interaction)
|
||||||
|
if not bank:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas de rôle de banquier sur ce serveur.", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if nouveau_taux < 0 or nouveau_taux > 100:
|
||||||
|
await interaction.response.send_message("❌ Le taux doit être entre 0 et 100%.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
compte = await bank_manager.get_compte_by_rib(interaction.guild.id, rib)
|
||||||
|
if not compte:
|
||||||
|
await interaction.response.send_message("❌ Compte introuvable.", ephemeral=True)
|
||||||
|
return
|
||||||
|
if compte["bank_id"] != bank["id"]:
|
||||||
|
await interaction.response.send_message("❌ Ce RIB n'appartient pas à votre banque.", ephemeral=True)
|
||||||
|
return
|
||||||
|
if compte["account_type"] != "entreprise":
|
||||||
|
await interaction.response.send_message("❌ La TVA ne s'applique qu'aux comptes entreprise.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
ok = await bank_manager.modifier_tva(interaction.guild.id, rib, nouveau_taux)
|
||||||
|
if ok:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"✅ Taux TVA mis à jour : **{nouveau_taux}%** pour `{rib}`.", ephemeral=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message("❌ Erreur lors de la mise à jour.", ephemeral=True)
|
||||||
|
|
||||||
|
@banque_group.command(name="consulter-clients", description="Voir tous les comptes de votre banque")
|
||||||
|
async def consulter_clients(self, interaction: discord.Interaction):
|
||||||
|
bank = await self._get_user_bank(interaction)
|
||||||
|
if not bank:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas de rôle de banquier sur ce serveur.", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
comptes = await bank_manager.get_comptes_banque(interaction.guild.id, bank["id"])
|
||||||
|
if not comptes:
|
||||||
|
await interaction.response.send_message("Aucun compte dans cette banque.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=f"🏦 Clients de {bank['name']}",
|
||||||
|
color=discord.Color.blue(),
|
||||||
|
)
|
||||||
|
|
||||||
|
for c in comptes:
|
||||||
|
member = interaction.guild.get_member(c["user_id"])
|
||||||
|
name = member.display_name if member else f"<@{c['user_id']}>"
|
||||||
|
tva_text = f" | TVA: {c['tva_rate']}%" if c["account_type"] == "entreprise" else ""
|
||||||
|
embed.add_field(
|
||||||
|
name=f"{name} ({c['account_type']})",
|
||||||
|
value=(
|
||||||
|
f"**RIB :** `{c['rib']}`\n"
|
||||||
|
f"**Solde :** `{c['solde']:.2f}€`{tva_text}"
|
||||||
|
),
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
embed.set_footer(text=f"{len(comptes)} compte(s)")
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
@banque_group.command(name="info", description="Informations sur votre banque")
|
||||||
|
async def info_banque(self, interaction: discord.Interaction):
|
||||||
|
bank = await self._get_user_bank(interaction)
|
||||||
|
if not bank:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas de rôle de banquier sur ce serveur.", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
role = interaction.guild.get_role(bank["role_id"])
|
||||||
|
comptes = await bank_manager.get_comptes_banque(interaction.guild.id, bank["id"])
|
||||||
|
nb_particuliers = sum(1 for c in comptes if c["account_type"] == "particulier")
|
||||||
|
nb_entreprises = sum(1 for c in comptes if c["account_type"] == "entreprise")
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=f"🏦 {bank['name']}",
|
||||||
|
color=discord.Color.blue(),
|
||||||
|
)
|
||||||
|
embed.add_field(name="Rôle", value=role.mention if role else "Inconnu", inline=True)
|
||||||
|
embed.add_field(name="Code établissement", value=f"`{bank['establishment_code']}`", inline=True)
|
||||||
|
embed.add_field(name="Solde propre (réserve)", value=f"`{bank['vault_balance']:.2f}€`", inline=True)
|
||||||
|
embed.add_field(name="Encours clients", value=f"`{bank['clients_total_balance']:.2f}€`", inline=True)
|
||||||
|
embed.add_field(name="Comptes particuliers", value=str(nb_particuliers), inline=True)
|
||||||
|
embed.add_field(name="Comptes entreprises", value=str(nb_entreprises), inline=True)
|
||||||
|
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
@banque_group.command(name="depot", description="Déposer de l'argent sur un compte")
|
||||||
|
@app_commands.describe(rib="RIB du compte", montant="Montant à déposer")
|
||||||
|
async def depot(self, interaction: discord.Interaction, rib: str, montant: float):
|
||||||
|
bank = await self._get_user_bank(interaction)
|
||||||
|
if not bank:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas de rôle de banquier sur ce serveur.", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
compte = await bank_manager.get_compte_by_rib(interaction.guild.id, rib)
|
||||||
|
if not compte:
|
||||||
|
await interaction.response.send_message("❌ Compte introuvable.", ephemeral=True)
|
||||||
|
return
|
||||||
|
if compte["bank_id"] != bank["id"]:
|
||||||
|
await interaction.response.send_message("❌ Ce RIB n'appartient pas à votre banque.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = await bank_manager.depot_banquier(interaction.guild.id, rib, montant, interaction.user.id)
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"✅ Dépôt de **{montant:.2f}€** sur `{rib}`. Nouveau solde : **{result['nouveau_solde']:.2f}€**",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
await interaction.response.send_message(f"❌ {e}", ephemeral=True)
|
||||||
|
|
||||||
|
@banque_group.command(name="retrait", description="Retirer de l'argent d'un compte")
|
||||||
|
@app_commands.describe(rib="RIB du compte", montant="Montant à retirer")
|
||||||
|
async def retrait(self, interaction: discord.Interaction, rib: str, montant: float):
|
||||||
|
bank = await self._get_user_bank(interaction)
|
||||||
|
if not bank:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas de rôle de banquier sur ce serveur.", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
compte = await bank_manager.get_compte_by_rib(interaction.guild.id, rib)
|
||||||
|
if not compte:
|
||||||
|
await interaction.response.send_message("❌ Compte introuvable.", ephemeral=True)
|
||||||
|
return
|
||||||
|
if compte["bank_id"] != bank["id"]:
|
||||||
|
await interaction.response.send_message("❌ Ce RIB n'appartient pas à votre banque.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = await bank_manager.retrait_banquier(interaction.guild.id, rib, montant, interaction.user.id)
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"✅ Retrait de **{montant:.2f}€** sur `{rib}`. Nouveau solde : **{result['nouveau_solde']:.2f}€**",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
await interaction.response.send_message(f"❌ {e}", ephemeral=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot):
|
||||||
|
await bot.add_cog(Banque(bot))
|
||||||
|
|
@ -1,93 +1,62 @@
|
||||||
import discord
|
import discord
|
||||||
from discord import app_commands
|
from discord import app_commands
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from utils.banque_manager import BanqueManager
|
|
||||||
|
|
||||||
banque_manager = BanqueManager()
|
from utils.bank_manager import BankManager
|
||||||
|
|
||||||
|
bank_manager = BankManager()
|
||||||
|
|
||||||
|
|
||||||
class Compte(commands.Cog):
|
class Compte(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
@app_commands.command(
|
@app_commands.command(name="compte", description="Afficher vos comptes bancaires et vos dernières transactions")
|
||||||
name="compte",
|
async def compte(self, interaction: discord.Interaction):
|
||||||
description="Afficher vos comptes bancaires et vos 3 dernières transactions"
|
comptes = await bank_manager.get_comptes_user(interaction.guild.id, interaction.user.id)
|
||||||
)
|
|
||||||
@app_commands.describe(
|
|
||||||
membre="Afficher le compte d'un autre membre (réservé au gouvernement)"
|
|
||||||
)
|
|
||||||
async def compte(self, interaction: discord.Interaction, membre: discord.Member = None):
|
|
||||||
"""Affiche les soldes et dernières transactions de l'utilisateur ou d'un autre membre (si gouvernement)"""
|
|
||||||
|
|
||||||
banque_manager.load_data()
|
if not comptes:
|
||||||
|
await interaction.response.send_message(
|
||||||
# Par défaut, on cible l'utilisateur qui exécute la commande
|
"❌ Vous n'avez aucun compte bancaire. Utilisez `/mes-ribs` pour voir vos RIBs.",
|
||||||
cible = interaction.user
|
ephemeral=True,
|
||||||
user_id = str(cible.id)
|
)
|
||||||
|
return
|
||||||
# Si un autre membre est précisé, on vérifie le rôle
|
|
||||||
if membre and membre != interaction.user:
|
|
||||||
role_gouv = discord.utils.get(interaction.guild.roles, name="🌍│Gouvernement")
|
|
||||||
if role_gouv not in interaction.user.roles:
|
|
||||||
await interaction.response.send_message(
|
|
||||||
"❌ Vous devez avoir le rôle **gouvernement** pour consulter le compte d'un autre membre.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
|
||||||
cible = membre
|
|
||||||
user_id = str(membre.id)
|
|
||||||
|
|
||||||
comptes = banque_manager.comptes
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title=f"💳 Comptes bancaires de {cible.display_name}",
|
title=f"💳 Comptes de {interaction.user.display_name}",
|
||||||
color=discord.Color.blue()
|
color=discord.Color.blue(),
|
||||||
)
|
)
|
||||||
|
|
||||||
banques_trouvees = False
|
for c in comptes:
|
||||||
|
transactions = await bank_manager.get_transactions(interaction.guild.id, c["rib"], limit=5)
|
||||||
|
tva_text = f" | TVA: {c['tva_rate']}%" if c["account_type"] == "entreprise" else ""
|
||||||
|
|
||||||
for banque, data in comptes.items():
|
tx_lines = []
|
||||||
if not isinstance(data, dict) or user_id not in data:
|
for tx in transactions:
|
||||||
continue # Ce n'est pas une banque valide pour cet utilisateur
|
is_outgoing = tx["emetteur_rib"] == c["rib"]
|
||||||
|
direction = "→" if is_outgoing else "←"
|
||||||
compte = data[user_id]
|
other_rib = tx["destinataire_rib"] if is_outgoing else tx["emetteur_rib"]
|
||||||
rib = compte.get("rib", "Non défini")
|
signe = "-" if is_outgoing else "+"
|
||||||
solde = compte.get("solde", 0)
|
tx_type = tx["type"]
|
||||||
transactions = compte.get("transactions", [])
|
if tx_type == "tva_prelevee":
|
||||||
|
tx_lines.append(f"- {direction} **TVA** : `{signe}{tx['montant']:.2f}€`")
|
||||||
# Récupérer les 3 dernières transactions avec date
|
|
||||||
last_transactions = transactions[-3:] if transactions else []
|
|
||||||
|
|
||||||
tx_str = ""
|
|
||||||
for tx in last_transactions:
|
|
||||||
date = tx.get("date", "Date inconnue")
|
|
||||||
tx_type = tx.get("type", "Inconnu")
|
|
||||||
montant = tx.get("montant", 0)
|
|
||||||
source = tx.get("emetteur", tx.get("source", "Inconnu"))
|
|
||||||
dest = tx.get("destinataire", "Inconnu")
|
|
||||||
|
|
||||||
if tx_type.lower() == "virement" or tx_type.lower().startswith("virement"):
|
|
||||||
tx_str += f"- 🕒 {date} : **{tx_type}** de **{montant}€** à <@{dest}>\n"
|
|
||||||
elif tx_type.lower() == "virement reçu":
|
|
||||||
tx_str += f"- 🕒 {date} : **{tx_type}** de **{montant}€** de <@{source}>\n"
|
|
||||||
else:
|
else:
|
||||||
tx_str += f"- 🕒 {date} : **{tx_type}** de **{montant}€**\n"
|
tx_lines.append(f"- {direction} **{tx_type}** : `{signe}{tx['montant']:.2f}€` vers `{other_rib or '?'}`")
|
||||||
|
|
||||||
if not tx_str:
|
tx_text = "\n".join(tx_lines) if tx_lines else "*Aucune transaction récente.*"
|
||||||
tx_str = "*Aucune transaction.*"
|
|
||||||
|
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name=f"🏦 {banque}",
|
name=f"🏦 {c['bank_name']} ({c['account_type']}){tva_text}",
|
||||||
value=f"💳 **RIB** : `{rib}`\n💰 **Solde** : `{solde}€`\n📜 **Transactions récentes :**\n{tx_str}",
|
value=(
|
||||||
inline=False
|
f"**RIB :** `{c['rib']}`\n"
|
||||||
|
f"**Solde :** `{c['solde']:.2f}€`\n\n"
|
||||||
|
f"**Transactions récentes :**\n{tx_text}"
|
||||||
|
),
|
||||||
|
inline=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
banques_trouvees = True
|
|
||||||
|
|
||||||
if not banques_trouvees:
|
|
||||||
embed.description = "❌ Aucun compte bancaire trouvé dans les banques enregistrées pour cet utilisateur."
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
await bot.add_cog(Compte(bot))
|
await bot.add_cog(Compte(bot))
|
||||||
|
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class CompteBanqueNationale(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
def get_banque_nationale_data(self):
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r+", encoding="utf-8") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
# Crée la section si elle n'existe pas
|
|
||||||
if "banque_nationale" not in data:
|
|
||||||
data["banque_nationale"] = {
|
|
||||||
"BANQUE": {
|
|
||||||
"rib": "11111 22222 33333333333 44",
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": [{
|
|
||||||
"date": "Création automatique",
|
|
||||||
"type": "Création de compte",
|
|
||||||
"source": "Système",
|
|
||||||
"montant": 0.0
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.seek(0)
|
|
||||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
|
||||||
f.truncate()
|
|
||||||
|
|
||||||
banque_data = data["banque_nationale"].get("BANQUE", {})
|
|
||||||
return banque_data.get("solde", 0.0), banque_data.get("transactions", [])
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Erreur lecture ou création banque_nationale : {e}")
|
|
||||||
return 0.0, []
|
|
||||||
|
|
||||||
@app_commands.command(name="voir_banque_nationale", description="Voir solde et transactions du compte banque nationale")
|
|
||||||
async def voir_banque_nationale(self, interaction: discord.Interaction):
|
|
||||||
if not has_role(interaction.user, "banque_nationale"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission d'accéder à ce compte.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
solde, transactions = self.get_banque_nationale_data()
|
|
||||||
|
|
||||||
if not transactions:
|
|
||||||
await interaction.response.send_message("📄 Aucune transaction trouvée sur le compte banque nationale.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Pagination
|
|
||||||
pages = []
|
|
||||||
per_page = 5
|
|
||||||
total_pages = math.ceil(len(transactions) / per_page)
|
|
||||||
|
|
||||||
for i in range(total_pages):
|
|
||||||
start = i * per_page
|
|
||||||
end = start + per_page
|
|
||||||
chunk = transactions[start:end]
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="🏦 Banque Nationale - Historique",
|
|
||||||
description=f"Page {i+1}/{total_pages}",
|
|
||||||
color=discord.Color.blue()
|
|
||||||
)
|
|
||||||
embed.add_field(name="💰 Solde", value=f"{solde:.2f}€", inline=False)
|
|
||||||
|
|
||||||
for tx in chunk:
|
|
||||||
description = (
|
|
||||||
f"**Date**: {tx.get('date', 'N/A')}\n"
|
|
||||||
f"**Type**: {tx.get('type', 'N/A')}\n"
|
|
||||||
f"**Montant**: {tx.get('montant', 0)}€\n"
|
|
||||||
f"**Source**: {tx.get('source', 'N/A')}"
|
|
||||||
)
|
|
||||||
embed.add_field(name="📄 Transaction", value=description, inline=False)
|
|
||||||
|
|
||||||
pages.append(embed)
|
|
||||||
|
|
||||||
class Pagination(discord.ui.View):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(timeout=None)
|
|
||||||
self.current = 0
|
|
||||||
|
|
||||||
@discord.ui.button(label="⬅️", style=discord.ButtonStyle.grey)
|
|
||||||
async def previous(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current > 0:
|
|
||||||
self.current -= 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
@discord.ui.button(label="➡️", style=discord.ButtonStyle.grey)
|
|
||||||
async def next(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current < len(pages) - 1:
|
|
||||||
self.current += 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=pages[0], view=Pagination(), ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(CompteBanqueNationale(bot))
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class CompteFBM(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
def get_all_transactions(self):
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
fbm_data = data.setdefault("fbm", {}).setdefault("FBM", {
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
})
|
|
||||||
return fbm_data["solde"], fbm_data["transactions"]
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Erreur lecture comptes_entreprises.json : {e}")
|
|
||||||
return 0.0, []
|
|
||||||
|
|
||||||
@app_commands.command(name="compte_fbm", description="Affiche le solde et l'historique du compte FBM (réservé au personnel FBM).")
|
|
||||||
async def compte_fbm(self, interaction: discord.Interaction):
|
|
||||||
if not has_role(interaction.user, "fbm"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission d'accéder à ce compte.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
solde, transactions = self.get_all_transactions()
|
|
||||||
|
|
||||||
if not transactions:
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="📄 Compte FBM",
|
|
||||||
description="Aucune transaction enregistrée.",
|
|
||||||
color=discord.Color.orange()
|
|
||||||
)
|
|
||||||
embed.add_field(name="💰 Solde actuel", value=f"{solde:.2f}€", inline=False)
|
|
||||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Pagination
|
|
||||||
pages = []
|
|
||||||
per_page = 5
|
|
||||||
total_pages = math.ceil(len(transactions) / per_page)
|
|
||||||
|
|
||||||
for i in range(total_pages):
|
|
||||||
start = i * per_page
|
|
||||||
end = start + per_page
|
|
||||||
chunk = transactions[start:end]
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="📄 Historique FBM",
|
|
||||||
description=f"Page {i+1}/{total_pages}",
|
|
||||||
color=discord.Color.orange()
|
|
||||||
)
|
|
||||||
embed.add_field(name="💰 Solde actuel", value=f"{solde:.2f}€", inline=False)
|
|
||||||
|
|
||||||
for tx in chunk:
|
|
||||||
desc = (
|
|
||||||
f"**Date**: {tx.get('date', 'N/A')}\n"
|
|
||||||
f"**Type**: {tx.get('type', 'N/A')}\n"
|
|
||||||
f"**Montant**: {tx.get('montant', 0)}€\n"
|
|
||||||
f"**Source**: {tx.get('source', 'N/A')}"
|
|
||||||
)
|
|
||||||
embed.add_field(name="🔸 Transaction", value=desc, inline=False)
|
|
||||||
|
|
||||||
pages.append(embed)
|
|
||||||
|
|
||||||
class Pagination(discord.ui.View):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(timeout=None)
|
|
||||||
self.current = 0
|
|
||||||
|
|
||||||
@discord.ui.button(label="⬅️", style=discord.ButtonStyle.grey)
|
|
||||||
async def previous(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current > 0:
|
|
||||||
self.current -= 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
@discord.ui.button(label="➡️", style=discord.ButtonStyle.grey)
|
|
||||||
async def next(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current < len(pages) - 1:
|
|
||||||
self.current += 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=pages[0], view=Pagination(), ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(CompteFBM(bot))
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class CompteGouvernement(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
def get_gouv_data(self):
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
gouv_data = data.get("Gouvernement", {}).get("GOUV", {})
|
|
||||||
return gouv_data.get("solde", 0.0), gouv_data.get("transactions", [])
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Erreur lecture comptes_entreprises.json : {e}")
|
|
||||||
return 0.0, []
|
|
||||||
|
|
||||||
@app_commands.command(name="compte_gouvernement", description="Affiche le solde et les transactions du compte Gouvernement.")
|
|
||||||
async def compte_gouvernement(self, interaction: discord.Interaction):
|
|
||||||
if not has_role(interaction.user, "gouvernement"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission d'accéder à ce compte.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
solde, transactions = self.get_gouv_data()
|
|
||||||
|
|
||||||
if not transactions:
|
|
||||||
await interaction.response.send_message("📄 Aucune transaction trouvée pour le gouvernement.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Pagination setup
|
|
||||||
pages = []
|
|
||||||
per_page = 5
|
|
||||||
total_pages = math.ceil(len(transactions) / per_page)
|
|
||||||
|
|
||||||
for i in range(total_pages):
|
|
||||||
start = i * per_page
|
|
||||||
end = start + per_page
|
|
||||||
chunk = transactions[start:end]
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="🏛️ Compte Gouvernement",
|
|
||||||
description=f"Page {i+1}/{total_pages}",
|
|
||||||
color=discord.Color.dark_gold()
|
|
||||||
)
|
|
||||||
embed.add_field(name="💰 Solde", value=f"{solde:.2f}€", inline=False)
|
|
||||||
|
|
||||||
for tx in chunk:
|
|
||||||
desc = (
|
|
||||||
f"**Date**: {tx.get('date', 'N/A')}\n"
|
|
||||||
f"**Type**: {tx.get('type', 'N/A')}\n"
|
|
||||||
f"**Montant**: {tx.get('montant', 0)}€\n"
|
|
||||||
f"**Source**: {tx.get('source', 'N/A')}"
|
|
||||||
)
|
|
||||||
embed.add_field(name="📄 Transaction", value=desc, inline=False)
|
|
||||||
|
|
||||||
pages.append(embed)
|
|
||||||
|
|
||||||
# Vue de pagination
|
|
||||||
class Pagination(discord.ui.View):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(timeout=None)
|
|
||||||
self.current = 0
|
|
||||||
|
|
||||||
@discord.ui.button(label="⬅️", style=discord.ButtonStyle.grey)
|
|
||||||
async def previous(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current > 0:
|
|
||||||
self.current -= 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
@discord.ui.button(label="➡️", style=discord.ButtonStyle.grey)
|
|
||||||
async def next(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current < len(pages) - 1:
|
|
||||||
self.current += 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=pages[0], view=Pagination(), ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(CompteGouvernement(bot))
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class CompteUrssaf(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
def get_all_transactions(self):
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Erreur lecture comptes_entreprises.json : {e}")
|
|
||||||
return 0.0, []
|
|
||||||
|
|
||||||
# Si URSAFF n'existe pas, on le crée
|
|
||||||
if "ursaff" not in data:
|
|
||||||
data["ursaff"] = {
|
|
||||||
"URSSAFF": {
|
|
||||||
"rib": "00000 00000 00000000000 01",
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
ursaff_data = data.get("ursaff", {}).get("URSAFF", {})
|
|
||||||
return ursaff_data.get("solde", 0.0), ursaff_data.get("transactions", [])
|
|
||||||
|
|
||||||
@app_commands.command(name="compte_ursaff", description="Affiche le solde et l'historique complet du compte URSAFF (réservé aux membres URSAFF).")
|
|
||||||
async def compte_ursaff(self, interaction: discord.Interaction):
|
|
||||||
# Vérifie que l'utilisateur a le rôle URSAFF
|
|
||||||
if not has_role(interaction.user, "ursaff"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission d'accéder à ce compte.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
solde, transactions = self.get_all_transactions()
|
|
||||||
|
|
||||||
# Pagination setup
|
|
||||||
pages = []
|
|
||||||
per_page = 5
|
|
||||||
total_pages = max(1, math.ceil(len(transactions) / per_page))
|
|
||||||
|
|
||||||
for i in range(total_pages):
|
|
||||||
start = i * per_page
|
|
||||||
end = start + per_page
|
|
||||||
chunk = transactions[start:end]
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="📄 Historique URSSAF",
|
|
||||||
description=f"Page {i+1}/{total_pages}",
|
|
||||||
color=discord.Color.dark_purple()
|
|
||||||
)
|
|
||||||
embed.add_field(name="💼 Solde actuel", value=f"{solde:.2f}€", inline=False)
|
|
||||||
|
|
||||||
if chunk:
|
|
||||||
for tx in chunk:
|
|
||||||
description = (
|
|
||||||
f"**Date**: {tx.get('date', 'N/A')}\n"
|
|
||||||
f"**Type**: {tx.get('type', 'N/A')}\n"
|
|
||||||
f"**Montant**: {tx.get('montant', 0)}€\n"
|
|
||||||
f"**Source**: {tx.get('source', 'N/A')}"
|
|
||||||
)
|
|
||||||
embed.add_field(name="🔹 Transaction", value=description, inline=False)
|
|
||||||
else:
|
|
||||||
embed.add_field(name="📄 Transactions", value="Aucune transaction récente.", inline=False)
|
|
||||||
|
|
||||||
pages.append(embed)
|
|
||||||
|
|
||||||
class Pagination(discord.ui.View):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(timeout=None)
|
|
||||||
self.current = 0
|
|
||||||
|
|
||||||
@discord.ui.button(label="⬅️", style=discord.ButtonStyle.grey)
|
|
||||||
async def previous(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current > 0:
|
|
||||||
self.current -= 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
@discord.ui.button(label="➡️", style=discord.ButtonStyle.grey)
|
|
||||||
async def next(self, interaction_btn: discord.Interaction, button: discord.ui.Button):
|
|
||||||
if self.current < len(pages) - 1:
|
|
||||||
self.current += 1
|
|
||||||
await interaction_btn.response.edit_message(embed=pages[self.current], view=self)
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=pages[0], view=Pagination(), ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(CompteUrssaf(bot))
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
|
|
||||||
class CompteEntreprise(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="compte_entreprise", description="Consulte le solde et les transactions d'une entreprise.")
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
async def compte_entreprise(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
banque: app_commands.Choice[str],
|
|
||||||
nom_entreprise: str,
|
|
||||||
mot_de_passe: str
|
|
||||||
):
|
|
||||||
banque_nom = banque.value
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
await interaction.response.send_message("❌ Erreur de lecture des données bancaires.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if banque_nom not in comptes or nom_entreprise not in comptes[banque_nom]:
|
|
||||||
await interaction.response.send_message("❌ Ce compte entreprise n'existe pas.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
compte = comptes[banque_nom][nom_entreprise]
|
|
||||||
|
|
||||||
# 🔐 Vérification du mot de passe avec la bonne clé
|
|
||||||
mdp_stocke = compte.get("mdp", "").strip()
|
|
||||||
mdp_fournit = mot_de_passe.strip()
|
|
||||||
|
|
||||||
if mdp_stocke != mdp_fournit:
|
|
||||||
await interaction.response.send_message("❌ Mot de passe incorrect.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
solde = compte.get("solde", 0)
|
|
||||||
transactions = compte.get("transactions", [])
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
title=f"🏢 Compte Entreprise : {nom_entreprise}",
|
|
||||||
color=discord.Color.teal()
|
|
||||||
)
|
|
||||||
embed.add_field(name="🏦 Banque", value=banque_nom, inline=True)
|
|
||||||
embed.add_field(name="💰 Solde", value=f"{solde:.2f}€", inline=False)
|
|
||||||
|
|
||||||
if transactions:
|
|
||||||
last_transactions = transactions[-3:]
|
|
||||||
for tx in reversed(last_transactions):
|
|
||||||
desc = (
|
|
||||||
f"**Date**: {tx.get('date', 'N/A')}\n"
|
|
||||||
f"**Type**: {tx.get('type', 'N/A')}\n"
|
|
||||||
f"**Montant**: {tx.get('montant', 0)}€\n"
|
|
||||||
f"**Source**: {tx.get('source', 'N/A')}"
|
|
||||||
)
|
|
||||||
embed.add_field(name="📄 Transaction", value=desc, inline=False)
|
|
||||||
else:
|
|
||||||
embed.add_field(name="📄 Transactions", value="Aucune transaction récente.", inline=False)
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(CompteEntreprise(bot))
|
|
||||||
194
commandes/gouv.py
Normal file
194
commandes/gouv.py
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
import discord
|
||||||
|
from discord import app_commands
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from utils.guild_config import has_role
|
||||||
|
from utils.bank_manager import BankManager
|
||||||
|
|
||||||
|
bank_manager = BankManager()
|
||||||
|
|
||||||
|
|
||||||
|
class Gouv(commands.Cog):
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
gouv_group = app_commands.Group(name="gouv", description="Commandes gouvernementales")
|
||||||
|
|
||||||
|
def _check_gouv(self, interaction: discord.Interaction) -> bool:
|
||||||
|
return has_role(interaction.user, "gouvernement")
|
||||||
|
|
||||||
|
@gouv_group.command(name="creer-banque", description="Créer une nouvelle banque commerciale")
|
||||||
|
@app_commands.describe(
|
||||||
|
nom="Nom de la banque (ex: NGC Bank)",
|
||||||
|
role="Le rôle Discord des banquiers de cette banque"
|
||||||
|
)
|
||||||
|
async def creer_banque(self, interaction: discord.Interaction, nom: str, role: discord.Role):
|
||||||
|
if not self._check_gouv(interaction):
|
||||||
|
await interaction.response.send_message("❌ Réservé au rôle **Gouvernement**.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = await bank_manager.creer_banque(interaction.guild.id, nom, role.id)
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="🏦 Banque créée",
|
||||||
|
description=(
|
||||||
|
f"**{nom}** a été créée avec succès.\n\n"
|
||||||
|
f"**Rôle banquiers :** {role.mention}\n"
|
||||||
|
f"**Code établissement :** `{result['establishment_code']}`\n"
|
||||||
|
f"**ID banque :** `{result['id']}`"
|
||||||
|
),
|
||||||
|
color=discord.Color.green(),
|
||||||
|
)
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
except Exception as e:
|
||||||
|
await interaction.response.send_message(f"❌ Erreur : {e}", ephemeral=True)
|
||||||
|
|
||||||
|
@gouv_group.command(name="creer-institution", description="Créer une institution (Fisc, URSAFF, etc.)")
|
||||||
|
@app_commands.describe(
|
||||||
|
nom="Nom de l'institution",
|
||||||
|
role="Le rôle Discord qui gère cette institution",
|
||||||
|
audit="Peut-elle consulter les comptes de toutes les banques ?"
|
||||||
|
)
|
||||||
|
async def creer_institution(
|
||||||
|
self,
|
||||||
|
interaction: discord.Interaction,
|
||||||
|
nom: str,
|
||||||
|
role: discord.Role,
|
||||||
|
audit: bool = False,
|
||||||
|
):
|
||||||
|
if not self._check_gouv(interaction):
|
||||||
|
await interaction.response.send_message("❌ Réservé au rôle **Gouvernement**.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = await bank_manager.creer_institution(
|
||||||
|
interaction.guild.id, nom, role.id, audit
|
||||||
|
)
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="🏛️ Institution créée",
|
||||||
|
description=(
|
||||||
|
f"**{nom}** a été créée.\n\n"
|
||||||
|
f"**Rôle :** {role.mention}\n"
|
||||||
|
f"**Droit d'audit :** {'✅ Oui' if audit else '❌ Non'}\n"
|
||||||
|
f"**ID :** `{result['id']}`"
|
||||||
|
),
|
||||||
|
color=discord.Color.blue(),
|
||||||
|
)
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
except Exception as e:
|
||||||
|
await interaction.response.send_message(f"❌ Erreur : {e}", ephemeral=True)
|
||||||
|
|
||||||
|
@gouv_group.command(name="config-fisc", description="Définir quelle institution reçoit la TVA")
|
||||||
|
@app_commands.describe(
|
||||||
|
institution="L'institution qui servira de Fisc"
|
||||||
|
)
|
||||||
|
async def config_fisc(self, interaction: discord.Interaction, institution: str):
|
||||||
|
if not self._check_gouv(interaction):
|
||||||
|
await interaction.response.send_message("❌ Réservé au rôle **Gouvernement**.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
institutions = await bank_manager.lister_institutions(interaction.guild.id)
|
||||||
|
target = None
|
||||||
|
for inst in institutions:
|
||||||
|
if inst["name"].lower() == institution.lower():
|
||||||
|
target = inst
|
||||||
|
break
|
||||||
|
|
||||||
|
if not target:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"❌ Institution **{institution}** introuvable. Institutions disponibles : {', '.join(i['name'] for i in institutions) or 'aucune'}",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
ok = await bank_manager.configurer_fisc(interaction.guild.id, target["id"])
|
||||||
|
if ok:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="🏛️ Fisc configuré",
|
||||||
|
description=f"**{target['name']}** reçoit désormais la TVA de tous les virements Particulier → Entreprise.",
|
||||||
|
color=discord.Color.green(),
|
||||||
|
)
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message("❌ Erreur lors de la configuration.", ephemeral=True)
|
||||||
|
|
||||||
|
@gouv_group.command(name="lister-banques", description="Lister toutes les banques du serveur")
|
||||||
|
async def lister_banques(self, interaction: discord.Interaction):
|
||||||
|
if not self._check_gouv(interaction):
|
||||||
|
await interaction.response.send_message("❌ Réservé au rôle **Gouvernement**.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
banques = await bank_manager.lister_banques(interaction.guild.id)
|
||||||
|
if not banques:
|
||||||
|
await interaction.response.send_message("Aucune banque configurée.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
embed = discord.Embed(title="🏦 Banques du serveur", color=discord.Color.blue())
|
||||||
|
for b in banques:
|
||||||
|
role = interaction.guild.get_role(b["role_id"])
|
||||||
|
role_text = role.mention if role else f"`{b['role_id']}` introuvable"
|
||||||
|
embed.add_field(
|
||||||
|
name=b["name"],
|
||||||
|
value=(
|
||||||
|
f"**Rôle :** {role_text}\n"
|
||||||
|
f"**Code établissement :** `{b['establishment_code']}`\n"
|
||||||
|
f"**Réserve :** `{b['vault_balance']:.2f}€`\n"
|
||||||
|
f"**Encours clients :** `{b['clients_total_balance']:.2f}€`"
|
||||||
|
),
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
@gouv_group.command(name="lister-institutions", description="Lister toutes les institutions du serveur")
|
||||||
|
async def lister_institutions(self, interaction: discord.Interaction):
|
||||||
|
if not self._check_gouv(interaction):
|
||||||
|
await interaction.response.send_message("❌ Réservé au rôle **Gouvernement**.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
institutions = await bank_manager.lister_institutions(interaction.guild.id)
|
||||||
|
if not institutions:
|
||||||
|
await interaction.response.send_message("Aucune institution configurée.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
fisc_config = await bank_manager.get_fisc_config(interaction.guild.id)
|
||||||
|
fisc_id = fisc_config["institution_id"] if fisc_config else None
|
||||||
|
|
||||||
|
embed = discord.Embed(title="🏛️ Institutions du serveur", color=discord.Color.blue())
|
||||||
|
for inst in institutions:
|
||||||
|
role = interaction.guild.get_role(inst["role_id"]) if inst["role_id"] else None
|
||||||
|
role_text = role.mention if role else "Non assigné"
|
||||||
|
is_fisc = " 💰 **(Fisc)**" if inst["id"] == fisc_id else ""
|
||||||
|
embed.add_field(
|
||||||
|
name=f"{inst['name']}{is_fisc}",
|
||||||
|
value=(
|
||||||
|
f"**Rôle :** {role_text}\n"
|
||||||
|
f"**Audit :** {'✅ Toutes les banques' if inst['can_audit_all'] else '❌ Non'}\n"
|
||||||
|
f"**ID :** `{inst['id']}`"
|
||||||
|
),
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
@gouv_group.command(name="supprimer-banque", description="Supprimer une banque")
|
||||||
|
@app_commands.describe(nom="Nom de la banque à supprimer")
|
||||||
|
async def supprimer_banque(self, interaction: discord.Interaction, nom: str):
|
||||||
|
if not self._check_gouv(interaction):
|
||||||
|
await interaction.response.send_message("❌ Réservé au rôle **Gouvernement**.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
banque = await bank_manager.get_banque_by_name(interaction.guild.id, nom)
|
||||||
|
if not banque:
|
||||||
|
await interaction.response.send_message(f"❌ Banque **{nom}** introuvable.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
ok = await bank_manager.supprimer_banque(interaction.guild.id, banque["id"])
|
||||||
|
if ok:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"✅ Banque **{nom}** supprimée avec tous ses comptes.", ephemeral=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message("❌ Erreur lors de la suppression.", ephemeral=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot):
|
||||||
|
await bot.add_cog(Gouv(bot))
|
||||||
44
commandes/mes_ribs.py
Normal file
44
commandes/mes_ribs.py
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import discord
|
||||||
|
from discord import app_commands
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from utils.bank_manager import BankManager
|
||||||
|
|
||||||
|
bank_manager = BankManager()
|
||||||
|
|
||||||
|
|
||||||
|
class MesRibs(commands.Cog):
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
@app_commands.command(name="mes-ribs", description="Afficher tous vos RIBs")
|
||||||
|
async def mes_ribs(self, interaction: discord.Interaction):
|
||||||
|
comptes = await bank_manager.get_comptes_user(interaction.guild.id, interaction.user.id)
|
||||||
|
|
||||||
|
if not comptes:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez aucun compte bancaire.", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=f"💳 RIBs de {interaction.user.display_name}",
|
||||||
|
color=discord.Color.blue(),
|
||||||
|
)
|
||||||
|
|
||||||
|
for c in comptes:
|
||||||
|
tva_text = f" | TVA: {c['tva_rate']}%" if c["account_type"] == "entreprise" else ""
|
||||||
|
embed.add_field(
|
||||||
|
name=f"{c['bank_name']} ({c['account_type']})",
|
||||||
|
value=(
|
||||||
|
f"**RIB :** `{c['rib']}`\n"
|
||||||
|
f"**Solde :** `{c['solde']:.2f}€`{tva_text}"
|
||||||
|
),
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot):
|
||||||
|
await bot.add_cog(MesRibs(bot))
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
from utils.banque_manager import BanqueManager
|
|
||||||
import random
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
# Liste des banques disponibles (id interne : nom affiché)
|
|
||||||
BANQUES = {
|
|
||||||
"Victoria's Credit Bank": "Victoria's Credit Bank",
|
|
||||||
"NGC Bank": "Nexus Global Corporation Bank"
|
|
||||||
}
|
|
||||||
|
|
||||||
banque_manager = BanqueManager()
|
|
||||||
|
|
||||||
class OuvrirCompte(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
@app_commands.command(name="ouvrir_compte", description="Ouvre un compte bancaire pour un utilisateur (banquier uniquement).")
|
|
||||||
@app_commands.choices(
|
|
||||||
banque=[app_commands.Choice(name=nom, value=id_banque) for id_banque, nom in BANQUES.items()]
|
|
||||||
)
|
|
||||||
async def ouvrir_compte(self, interaction: discord.Interaction, utilisateur: discord.Member, banque: app_commands.Choice[str]):
|
|
||||||
banque_id = banque.value
|
|
||||||
banque_nom = BANQUES[banque_id]
|
|
||||||
|
|
||||||
# Vérification du rôle de banquier
|
|
||||||
if not has_role(interaction.user, "banquier"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission d'ouvrir un compte.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
user_id = str(utilisateur.id)
|
|
||||||
banque_manager.load_data()
|
|
||||||
|
|
||||||
# Conversion automatique si l'ancien format est utilisé
|
|
||||||
if all(isinstance(v, dict) and 'rib' in v for v in banque_manager.comptes.values()):
|
|
||||||
banque_manager.comptes = {"vicynationale": banque_manager.comptes}
|
|
||||||
|
|
||||||
# Vérification si la banque existe dans les données
|
|
||||||
if banque_id not in banque_manager.comptes:
|
|
||||||
banque_manager.comptes[banque_id] = {}
|
|
||||||
|
|
||||||
# Vérification si l'utilisateur a déjà un compte dans cette banque
|
|
||||||
if user_id in banque_manager.comptes[banque_id]:
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"❌ {utilisateur.mention} possède déjà un compte à la {banque_nom} !",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Génération du RIB aléatoire
|
|
||||||
rib = f"{random.randint(10000, 99999)} {random.randint(10000, 99999)} {random.randint(10000000000, 99999999999)} {random.randint(10, 99)}"
|
|
||||||
|
|
||||||
# Création du compte
|
|
||||||
banque_manager.comptes[banque_id][user_id] = {
|
|
||||||
"rib": rib,
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
banque_manager.save_data()
|
|
||||||
|
|
||||||
# Envoi du RIB en MP à l'utilisateur cible
|
|
||||||
try:
|
|
||||||
await utilisateur.send(f"🏦 Un compte a été créé pour vous à la **{banque_nom}**.\nVoici votre RIB : `{rib}`")
|
|
||||||
except discord.Forbidden:
|
|
||||||
await interaction.response.send_message("❌ Impossible d'envoyer le RIB en message privé (l'utilisateur a les MP fermés).", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
await interaction.response.send_message(f"✅ Compte créé avec succès pour {utilisateur.mention} à la **{banque_nom}**.", ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(OuvrirCompte(bot))
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
import string
|
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
COMPTES_ENTREPRISES_PATH = "comptes_entreprises.json"
|
|
||||||
|
|
||||||
def generer_rib():
|
|
||||||
return " ".join(["".join(random.choices(string.digits, k=5)) for _ in range(4)])
|
|
||||||
|
|
||||||
def generer_mdp():
|
|
||||||
return "".join(random.choices(string.ascii_letters + string.digits, k=8))
|
|
||||||
|
|
||||||
class OuvrirCompteEntreprise(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choix = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
tva_choix = [
|
|
||||||
app_commands.Choice(name="2%", value=2),
|
|
||||||
app_commands.Choice(name="5%", value=5),
|
|
||||||
app_commands.Choice(name="10%", value=10),
|
|
||||||
app_commands.Choice(name="20%", value=20),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="ouvrir_compte_entreprise", description="Ouvre un compte bancaire pour une entreprise")
|
|
||||||
@app_commands.choices(banque=banque_choix, tva=tva_choix)
|
|
||||||
async def ouvrir_compte_entreprise(self, interaction: discord.Interaction, entreprise: str, banque: app_commands.Choice[str], tva: app_commands.Choice[int]):
|
|
||||||
# ✅ Vérifie que l'utilisateur est banquier
|
|
||||||
if not has_role(interaction.user, "banquier"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission d'exécuter cette commande.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
banque_name = banque.value
|
|
||||||
entreprise = entreprise.strip()
|
|
||||||
|
|
||||||
# ✅ Chargement sécurisé du fichier
|
|
||||||
if os.path.exists(COMPTES_ENTREPRISES_PATH):
|
|
||||||
try:
|
|
||||||
with open(COMPTES_ENTREPRISES_PATH, "r", encoding="utf-8") as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
comptes = {}
|
|
||||||
else:
|
|
||||||
comptes = {}
|
|
||||||
|
|
||||||
if banque_name not in comptes:
|
|
||||||
comptes[banque_name] = {}
|
|
||||||
|
|
||||||
if entreprise in comptes[banque_name]:
|
|
||||||
await interaction.response.send_message(f"❌ Un compte existe déjà pour l'entreprise **{entreprise}** dans la banque **{banque_name}**.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
rib = generer_rib()
|
|
||||||
mdp = generer_mdp()
|
|
||||||
|
|
||||||
comptes[banque_name][entreprise] = {
|
|
||||||
"rib": rib,
|
|
||||||
"solde": 0,
|
|
||||||
"mdp": mdp,
|
|
||||||
"tva": tva.value,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
with open(COMPTES_ENTREPRISES_PATH, "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
# ✅ MP à l'utilisateur avec le RIB et le mot de passe
|
|
||||||
try:
|
|
||||||
await interaction.user.send(
|
|
||||||
f"🏦 Compte de l'entreprise **{entreprise}** ouvert avec succès dans la banque **{banque_name}** !\n"
|
|
||||||
f"💳 RIB : `{rib}`\n"
|
|
||||||
f"🔐 Mot de passe : `{mdp}`\n"
|
|
||||||
f"💼 Taux de TVA : `{tva.value}%`\n\n"
|
|
||||||
f"Conservez bien ces informations."
|
|
||||||
)
|
|
||||||
except discord.Forbidden:
|
|
||||||
await interaction.response.send_message("⚠️ Impossible de vous envoyer un message privé avec les informations du compte.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
await interaction.response.send_message(f"✅ Le compte de l'entreprise **{entreprise}** a été créé avec succès.", ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(OuvrirCompteEntreprise(bot))
|
|
||||||
2389
commandes/panel.py
Normal file
2389
commandes/panel.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,74 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
from utils.banque_manager import BanqueManager
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
banque_manager = BanqueManager()
|
|
||||||
|
|
||||||
class Pret(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
@app_commands.command(name="calculer_pret", description="Accorde un prêt bancaire à un utilisateur (Réservé aux banquiers).")
|
|
||||||
async def calculer_pret(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
utilisateur: discord.Member,
|
|
||||||
banque: str,
|
|
||||||
montant: float,
|
|
||||||
duree_annees: int
|
|
||||||
):
|
|
||||||
"""Les banquiers peuvent accorder un prêt à un utilisateur si son solde le permet."""
|
|
||||||
|
|
||||||
# Vérification de si le joueur executant la commande est un banquier
|
|
||||||
if not has_role(interaction.user, "banquier"):
|
|
||||||
await interaction.response.send_message(
|
|
||||||
"❌ Vous n'avez pas la permission d'accorder un prêt.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
user_id = str(utilisateur.id)
|
|
||||||
success, result = banque_manager.ajouter_pret(user_id, banque, montant, duree_annees)
|
|
||||||
|
|
||||||
if not success:
|
|
||||||
await interaction.response.send_message(result, ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
total_a_rembourser = result
|
|
||||||
taux_interet = banque_manager.comptes[user_id]['prets'][-1]['taux_interet'] * 100
|
|
||||||
|
|
||||||
# Vérifier si l'utilisateur a assez d'argent pour rembourser
|
|
||||||
solde_utilisateur = banque_manager.comptes[user_id].get("solde", 0)
|
|
||||||
if solde_utilisateur < total_a_rembourser:
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"❌ {utilisateur.mention} n'a pas assez d'argent pour rembourser ce prêt.\n"
|
|
||||||
f"💰 **Solde actuel** : {solde_utilisateur}€\n"
|
|
||||||
f"💳 **Montant à rembourser** : {total_a_rembourser}€",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Débiter le solde de l'utilisateur
|
|
||||||
banque_manager.comptes[user_id]["solde"] -= total_a_rembourser
|
|
||||||
banque_manager.save_data()
|
|
||||||
|
|
||||||
# Création de l'embed
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="🏦 Prêt bancaire accordé",
|
|
||||||
description=f"Le prêt a été accordé par {interaction.user.mention} pour {utilisateur.mention}.",
|
|
||||||
color=discord.Color.green()
|
|
||||||
)
|
|
||||||
embed.set_thumbnail(url="https://cdn-icons-png.flaticon.com/512/2910/2910827.png") # Icône banque
|
|
||||||
embed.add_field(name="💰 Montant emprunté", value=f"{montant}€", inline=True)
|
|
||||||
embed.add_field(name="📅 Durée", value=f"{duree_annees} ans", inline=True)
|
|
||||||
embed.add_field(name="📈 Taux d'intérêt", value=f"{taux_interet}%", inline=True)
|
|
||||||
embed.add_field(name="💳 Montant total à rembourser", value=f"{total_a_rembourser}€", inline=False)
|
|
||||||
embed.add_field(name="💰 Solde après prêt", value=f"{banque_manager.comptes[user_id]['solde']}€", inline=True)
|
|
||||||
embed.set_footer(text="Prêt enregistré dans le compte bancaire ✅")
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=embed)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(Pret(bot))
|
|
||||||
|
|
@ -1,146 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class RetirerArgent(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(
|
|
||||||
name="retirer_argent",
|
|
||||||
description="Retire de l'argent d'un compte via son RIB (utilisateur ou entreprise)."
|
|
||||||
)
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
@app_commands.describe(
|
|
||||||
rib="Le RIB du compte",
|
|
||||||
montant="Montant à retirer",
|
|
||||||
banque="Banque cible (facultatif)"
|
|
||||||
)
|
|
||||||
async def retirer_argent(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
rib: str,
|
|
||||||
montant: float,
|
|
||||||
banque: app_commands.Choice[str] = None
|
|
||||||
):
|
|
||||||
if not has_role(interaction.user, "banquier"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission de faire cela.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if montant <= 0:
|
|
||||||
await interaction.response.send_message("❌ Le montant doit être supérieur à zéro.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
banque_nom = banque.value if banque else None
|
|
||||||
|
|
||||||
# Charger les fichiers
|
|
||||||
try:
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes_bancaires = json.load(f)
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes_entreprises = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
await interaction.response.send_message("❌ Erreur lors de la lecture des fichiers JSON.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
compte = None
|
|
||||||
source = None # "utilisateur" ou "entreprise"
|
|
||||||
user_id = None
|
|
||||||
|
|
||||||
# Recherche dans la banque spécifiée (si précisée)
|
|
||||||
if banque_nom and banque_nom in comptes_bancaires:
|
|
||||||
for uid, data in comptes_bancaires[banque_nom].items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
compte = data
|
|
||||||
source = "utilisateur"
|
|
||||||
user_id = uid
|
|
||||||
break
|
|
||||||
|
|
||||||
if not compte and banque_nom and banque_nom in comptes_entreprises:
|
|
||||||
for entreprise, data in comptes_entreprises[banque_nom].items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
compte = data
|
|
||||||
source = "entreprise"
|
|
||||||
user_id = entreprise
|
|
||||||
break
|
|
||||||
|
|
||||||
# Si banque non précisée ou compte non trouvé, recherche dans toutes les banques
|
|
||||||
if not compte and not banque_nom:
|
|
||||||
# Recherche dans toutes les banques utilisateurs
|
|
||||||
for banque_courante, comptes_banque in comptes_bancaires.items():
|
|
||||||
for uid, data in comptes_banque.items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
compte = data
|
|
||||||
source = "utilisateur"
|
|
||||||
user_id = uid
|
|
||||||
banque_nom = banque_courante
|
|
||||||
break
|
|
||||||
if compte:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not compte:
|
|
||||||
# Recherche dans toutes les banques entreprises
|
|
||||||
for banque_courante, entreprises_banque in comptes_entreprises.items():
|
|
||||||
for entreprise, data in entreprises_banque.items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
compte = data
|
|
||||||
source = "entreprise"
|
|
||||||
user_id = entreprise
|
|
||||||
banque_nom = banque_courante
|
|
||||||
break
|
|
||||||
if compte:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not compte:
|
|
||||||
await interaction.response.send_message("❌ Aucun compte trouvé avec ce RIB.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if compte["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Solde insuffisant pour retirer cette somme.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Appliquer le retrait
|
|
||||||
compte["solde"] -= montant
|
|
||||||
transaction = {
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Retrait",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": -montant,
|
|
||||||
"emetteur": interaction.user.id,
|
|
||||||
"destinataire": user_id
|
|
||||||
}
|
|
||||||
compte.setdefault("transactions", []).append(transaction)
|
|
||||||
|
|
||||||
# Sauvegarde dans le bon fichier
|
|
||||||
if source == "utilisateur":
|
|
||||||
comptes_bancaires[banque_nom][user_id] = compte
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes_bancaires, f, indent=4, ensure_ascii=False)
|
|
||||||
else:
|
|
||||||
comptes_entreprises[banque_nom][user_id] = compte
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes_entreprises, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
# Message de confirmation
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="💸 Retrait effectué",
|
|
||||||
description=f"💼 Banque : **{banque_nom}**\n📌 Type : **{source.capitalize()}**",
|
|
||||||
color=discord.Color.red()
|
|
||||||
)
|
|
||||||
embed.add_field(name="RIB", value=rib, inline=False)
|
|
||||||
embed.add_field(name="Montant retiré", value=f"{montant:.2f}€", inline=True)
|
|
||||||
embed.add_field(name="Effectué par", value=interaction.user.mention, inline=True)
|
|
||||||
embed.set_footer(text="Transaction enregistrée ✅")
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=embed, ephemeral=False)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(RetirerArgent(bot))
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
GOUV_BANQUE = "Gouvernement"
|
|
||||||
GOUV_COMPTE = "GOUV"
|
|
||||||
GOUV_RIB = "00000 00000 00000000000 00"
|
|
||||||
|
|
||||||
class GouvVirement(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
# Liste des banques à jour (ajoute ici toutes les banques possibles de ton système)
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(
|
|
||||||
name="gouv_virer",
|
|
||||||
description="Le Gouvernement vire de l'argent de son compte vers un autre RIB (entreprise ou particulier)."
|
|
||||||
)
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
@app_commands.describe(
|
|
||||||
rib="Le RIB destinataire",
|
|
||||||
montant="Montant à virer",
|
|
||||||
banque="Banque cible (facultatif)"
|
|
||||||
)
|
|
||||||
async def gouv_virer(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
rib: str,
|
|
||||||
montant: float,
|
|
||||||
banque: app_commands.Choice[str] = None
|
|
||||||
):
|
|
||||||
# Vérification du rôle Gouvernement
|
|
||||||
if not has_role(interaction.user, "gouvernement"):
|
|
||||||
await interaction.response.send_message("❌ Seul le Gouvernement peut utiliser cette commande.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if montant <= 0:
|
|
||||||
await interaction.response.send_message("❌ Le montant doit être supérieur à zéro.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
banque_nom = banque.value if banque else None
|
|
||||||
|
|
||||||
# Charger les fichiers
|
|
||||||
try:
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes_bancaires = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
comptes_bancaires = {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes_entreprises = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
await interaction.response.send_message("❌ Erreur lors de la lecture des fichiers JSON.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Récupérer le compte du Gouvernement
|
|
||||||
try:
|
|
||||||
gouv_compte = comptes_entreprises[GOUV_BANQUE][GOUV_COMPTE]
|
|
||||||
except KeyError:
|
|
||||||
await interaction.response.send_message("❌ Compte Gouvernement introuvable.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if gouv_compte["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Le Gouvernement n'a pas assez de fonds.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Chercher le destinataire
|
|
||||||
destinataire_compte = None
|
|
||||||
destinataire_banque = None
|
|
||||||
destinataire_nom = None
|
|
||||||
destinataire_type = None
|
|
||||||
|
|
||||||
# Si banque précisée, chercher d'abord dans cette banque (entreprises puis particuliers)
|
|
||||||
if banque_nom:
|
|
||||||
# Entreprises
|
|
||||||
if banque_nom in comptes_entreprises:
|
|
||||||
for nom, data in comptes_entreprises[banque_nom].items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
destinataire_compte = data
|
|
||||||
destinataire_banque = banque_nom
|
|
||||||
destinataire_nom = nom
|
|
||||||
destinataire_type = "entreprise"
|
|
||||||
break
|
|
||||||
# Particuliers
|
|
||||||
if not destinataire_compte and banque_nom in comptes_bancaires:
|
|
||||||
for uid, data in comptes_bancaires[banque_nom].items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
destinataire_compte = data
|
|
||||||
destinataire_banque = banque_nom
|
|
||||||
destinataire_nom = uid
|
|
||||||
destinataire_type = "particulier"
|
|
||||||
break
|
|
||||||
# Si banque non précisée, chercher dans toutes les banques
|
|
||||||
else:
|
|
||||||
# Entreprises
|
|
||||||
for banque_courante, entreprises in comptes_entreprises.items():
|
|
||||||
for nom, data in entreprises.items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
destinataire_compte = data
|
|
||||||
destinataire_banque = banque_courante
|
|
||||||
destinataire_nom = nom
|
|
||||||
destinataire_type = "entreprise"
|
|
||||||
break
|
|
||||||
if destinataire_compte:
|
|
||||||
break
|
|
||||||
# Particuliers
|
|
||||||
if not destinataire_compte:
|
|
||||||
for banque_courante, comptes in comptes_bancaires.items():
|
|
||||||
for uid, data in comptes.items():
|
|
||||||
if data.get("rib") == rib:
|
|
||||||
destinataire_compte = data
|
|
||||||
destinataire_banque = banque_courante
|
|
||||||
destinataire_nom = uid
|
|
||||||
destinataire_type = "particulier"
|
|
||||||
break
|
|
||||||
if destinataire_compte:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not destinataire_compte:
|
|
||||||
await interaction.response.send_message("❌ Aucun compte trouvé avec ce RIB dans la banque spécifiée." if banque_nom else "❌ Aucun compte trouvé avec ce RIB.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Effectuer le virement
|
|
||||||
gouv_compte["solde"] -= montant
|
|
||||||
destinataire_compte["solde"] += montant
|
|
||||||
|
|
||||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
|
||||||
|
|
||||||
# Transaction côté Gouvernement (sortant)
|
|
||||||
gouv_compte.setdefault("transactions", []).append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement",
|
|
||||||
"source": "Gouvernement",
|
|
||||||
"montant": -montant,
|
|
||||||
"emetteur": "Gouvernement",
|
|
||||||
"destinataire": destinataire_nom
|
|
||||||
})
|
|
||||||
|
|
||||||
# Transaction côté destinataire (entrant)
|
|
||||||
destinataire_compte.setdefault("transactions", []).append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement",
|
|
||||||
"source": "Gouvernement",
|
|
||||||
"montant": montant,
|
|
||||||
"emetteur": "Gouvernement",
|
|
||||||
"destinataire": destinataire_nom
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sauvegarde
|
|
||||||
comptes_entreprises[GOUV_BANQUE][GOUV_COMPTE] = gouv_compte
|
|
||||||
if destinataire_type == "entreprise":
|
|
||||||
comptes_entreprises[destinataire_banque][destinataire_nom] = destinataire_compte
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes_entreprises, f, indent=4, ensure_ascii=False)
|
|
||||||
else:
|
|
||||||
comptes_bancaires[destinataire_banque][destinataire_nom] = destinataire_compte
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes_entreprises, f, indent=4, ensure_ascii=False)
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes_bancaires, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
# Message de confirmation
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="🏛️ Virement Gouvernemental effectué",
|
|
||||||
description=f"💼 Banque destinataire : **{destinataire_banque}**\n📌 Type : **{destinataire_type.capitalize()}**",
|
|
||||||
color=discord.Color.gold()
|
|
||||||
)
|
|
||||||
embed.add_field(name="RIB destinataire", value=rib, inline=False)
|
|
||||||
embed.add_field(name="Montant viré", value=f"{montant:.2f}€", inline=True)
|
|
||||||
embed.add_field(name="Effectué par", value=interaction.user.mention, inline=True)
|
|
||||||
embed.set_footer(text="Transaction enregistrée ✅")
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=embed, ephemeral=False)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(GouvVirement(bot))
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
from utils.banque_manager import BanqueManager
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
banque_manager = BanqueManager()
|
|
||||||
|
|
||||||
class Transactions(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
@app_commands.command(name="transactions", description="Affiche les transactions d'un utilisateur (réservé aux banquiers).")
|
|
||||||
async def transactions(self, interaction: discord.Interaction, utilisateur: discord.Member):
|
|
||||||
"""Affiche l'historique des transactions d'un utilisateur (banquiers uniquement)."""
|
|
||||||
|
|
||||||
# ✅ Récupération du vrai membre pour avoir les rôles
|
|
||||||
member = interaction.guild.get_member(interaction.user.id)
|
|
||||||
if not member:
|
|
||||||
await interaction.response.send_message("❌ Impossible de vérifier vos permissions.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# ✅ Vérification du rôle banquier
|
|
||||||
if not has_role(member, "banquier"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission de voir les transactions.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
banque_manager.load_data()
|
|
||||||
|
|
||||||
user_id = str(utilisateur.id)
|
|
||||||
|
|
||||||
# ✅ Vérification si l'utilisateur a des transactions
|
|
||||||
if user_id not in banque_manager.comptes or "transactions" not in banque_manager.comptes[user_id]:
|
|
||||||
await interaction.response.send_message(f"❌ {utilisateur.mention} n'a pas d'historique de transactions.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
transactions = banque_manager.comptes[user_id].get("transactions", [])
|
|
||||||
|
|
||||||
if not transactions:
|
|
||||||
await interaction.response.send_message(f"📜 {utilisateur.mention} n'a encore effectué aucune transaction.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# ✅ Création de l'embed
|
|
||||||
embed = discord.Embed(
|
|
||||||
title=f"📜 Historique des transactions de {utilisateur.name}",
|
|
||||||
color=discord.Color.gold()
|
|
||||||
)
|
|
||||||
|
|
||||||
for t in transactions[-10:]:
|
|
||||||
embed.add_field(
|
|
||||||
name=f"📅 {t['date']}",
|
|
||||||
value=(
|
|
||||||
f"**Type**: {t['type']}\n"
|
|
||||||
f"💰 **Montant**: {t['montant']}€\n"
|
|
||||||
f"📤 **Émetteur**: <@{t['emetteur']}>\n"
|
|
||||||
f"📥 **Destinataire**: <@{t['destinataire']}>"
|
|
||||||
),
|
|
||||||
inline=False
|
|
||||||
)
|
|
||||||
|
|
||||||
embed.set_footer(text="Seules les 10 dernières transactions sont affichées.")
|
|
||||||
|
|
||||||
await interaction.response.send_message(embed=embed)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(Transactions(bot))
|
|
||||||
|
|
@ -1,138 +1,71 @@
|
||||||
import json
|
|
||||||
import discord
|
import discord
|
||||||
from discord import app_commands
|
from discord import app_commands
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from datetime import datetime
|
|
||||||
|
from utils.bank_manager import BankManager
|
||||||
|
from utils.rib import decoder_rib
|
||||||
|
|
||||||
|
bank_manager = BankManager()
|
||||||
|
|
||||||
|
|
||||||
class Virement(commands.Cog):
|
class Virement(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
banque_choices = [
|
@app_commands.command(name="virement", description="Faire un virement à un autre compte via RIB")
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
@app_commands.describe(
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
rib_source="Votre RIB (compte source)",
|
||||||
]
|
rib_dest="RIB du destinataire",
|
||||||
|
montant="Montant à envoyer",
|
||||||
@app_commands.command(name="virement", description="Fait un virement bancaire à un autre membre via son RIB")
|
)
|
||||||
@app_commands.choices(banque=banque_choices)
|
async def virement(
|
||||||
@app_commands.describe(rib="Le RIB du destinataire", montant="Le montant à envoyer", banque="Banque d'où retirer l'argent")
|
self,
|
||||||
async def virement(self, interaction: discord.Interaction, rib: str, montant: float, banque: app_commands.Choice[str]):
|
interaction: discord.Interaction,
|
||||||
auteur_id = str(interaction.user.id)
|
rib_source: str,
|
||||||
banque_source = banque.value
|
rib_dest: str,
|
||||||
|
montant: float,
|
||||||
# Charger les comptes utilisateurs
|
):
|
||||||
with open('comptes_bancaires.json', 'r', encoding='utf-8') as f:
|
if montant <= 0:
|
||||||
comptes = json.load(f)
|
await interaction.response.send_message("❌ Le montant doit être supérieur à 0.", ephemeral=True)
|
||||||
|
|
||||||
# Charger les comptes entreprises
|
|
||||||
with open('comptes_entreprises.json', 'r', encoding='utf-8') as f:
|
|
||||||
entreprises = json.load(f)
|
|
||||||
|
|
||||||
# Vérifier que l'utilisateur a un compte dans cette banque
|
|
||||||
if banque_source not in comptes or auteur_id not in comptes[banque_source]:
|
|
||||||
await interaction.response.send_message(f"❌ Tu n'as pas de compte dans la banque **{banque_source}**.", ephemeral=True)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
compte_emetteur = comptes[banque_source][auteur_id]
|
compte_source = await bank_manager.get_compte_by_rib(interaction.guild.id, rib_source)
|
||||||
if compte_emetteur["solde"] < montant:
|
if not compte_source:
|
||||||
await interaction.response.send_message("❌ Ton solde est insuffisant pour effectuer ce virement.", ephemeral=True)
|
await interaction.response.send_message("❌ RIB source introuvable.", ephemeral=True)
|
||||||
|
return
|
||||||
|
if compte_source["user_id"] != interaction.user.id:
|
||||||
|
await interaction.response.send_message("❌ Ce RIB ne vous appartient pas.", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Rechercher le destinataire (utilisateur ou entreprise)
|
try:
|
||||||
destinataire_id = None
|
result = await bank_manager.virement(
|
||||||
banque_destinataire = None
|
guild_id=interaction.guild.id,
|
||||||
is_entreprise = False
|
rib_source=rib_source,
|
||||||
|
rib_dest=rib_dest,
|
||||||
|
montant=montant,
|
||||||
|
emetteur_id=interaction.user.id,
|
||||||
|
)
|
||||||
|
|
||||||
# Recherche dans comptes utilisateurs
|
msg = f"✅ Virement de **{result['montant_envoye']:.2f}€** effectué."
|
||||||
for bq_name, bq_data in comptes.items():
|
if result["tva_prelevee"] > 0:
|
||||||
if isinstance(bq_data, dict):
|
msg += f"\n💰 TVA prélevée : **{result['tva_prelevee']:.2f}€** → Fisc."
|
||||||
for user_id, info in bq_data.items():
|
msg += f"\n**Reçu par le destinataire :** {result['montant_recu']:.2f}€"
|
||||||
if isinstance(info, dict) and info.get("rib") == rib:
|
|
||||||
destinataire_id = user_id
|
|
||||||
banque_destinataire = bq_name
|
|
||||||
break
|
|
||||||
if destinataire_id:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Sinon, recherche dans les entreprises
|
await interaction.response.send_message(msg, ephemeral=True)
|
||||||
if not destinataire_id:
|
|
||||||
for bq_name, bq_data in entreprises.items():
|
|
||||||
if isinstance(bq_data, dict):
|
|
||||||
for ent_id, info in bq_data.items():
|
|
||||||
if isinstance(info, dict) and info.get("rib") == rib:
|
|
||||||
destinataire_id = ent_id
|
|
||||||
banque_destinataire = bq_name
|
|
||||||
is_entreprise = True
|
|
||||||
break
|
|
||||||
if destinataire_id:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not destinataire_id:
|
|
||||||
await interaction.response.send_message("❌ Aucun compte trouvé avec ce RIB.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Appliquer la TVA si entreprise
|
|
||||||
montant_net = montant
|
|
||||||
tva_envoyee = 0
|
|
||||||
if is_entreprise:
|
|
||||||
taux = entreprises[banque_destinataire][destinataire_id].get("tva", 0)
|
|
||||||
tva_envoyee = round(montant * taux / 100, 2)
|
|
||||||
montant_net = montant - tva_envoyee
|
|
||||||
|
|
||||||
# Ajouter la TVA au Gouvernement
|
|
||||||
if "Gouvernement" not in entreprises:
|
|
||||||
entreprises["Gouvernement"] = {}
|
|
||||||
if "GOUV" not in entreprises["Gouvernement"]:
|
|
||||||
entreprises["Gouvernement"]["GOUV"] = {
|
|
||||||
"rib": "00000 00000 00000000000 00",
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
entreprises["Gouvernement"]["GOUV"]["solde"] += tva_envoyee
|
|
||||||
entreprises["Gouvernement"]["GOUV"]["transactions"].append({
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": auteur_id,
|
|
||||||
"montant": tva_envoyee
|
|
||||||
})
|
|
||||||
|
|
||||||
# Déduire du compte émetteur
|
|
||||||
comptes[banque_source][auteur_id]["solde"] -= montant
|
|
||||||
comptes[banque_source][auteur_id]["transactions"].append({
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement",
|
|
||||||
"source": f"Vers RIB {rib}",
|
|
||||||
"montant": -montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# Ajouter au compte destinataire
|
|
||||||
cible_data = entreprises if is_entreprise else comptes
|
|
||||||
cible_data[banque_destinataire][destinataire_id]["solde"] += montant_net
|
|
||||||
cible_data[banque_destinataire][destinataire_id]["transactions"].append({
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": interaction.user.name,
|
|
||||||
"montant": montant_net
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sauvegarde
|
|
||||||
with open('comptes_bancaires.json', 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(comptes, f, ensure_ascii=False, indent=4)
|
|
||||||
with open('comptes_entreprises.json', 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(entreprises, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
# Envoi MP au destinataire si c'est un utilisateur
|
|
||||||
if not is_entreprise:
|
|
||||||
try:
|
try:
|
||||||
user_dest = await self.bot.fetch_user(int(destinataire_id))
|
dest_compte = await bank_manager.get_compte_by_rib(interaction.guild.id, rib_dest)
|
||||||
await user_dest.send(f"📥 Vous avez reçu un virement de **{montant:.2f}€** de la part de **{interaction.user.display_name}**.")
|
if dest_compte and dest_compte["account_type"] == "particulier":
|
||||||
except:
|
dest_user = await self.bot.fetch_user(dest_compte["user_id"])
|
||||||
pass # Si l'utilisateur a les MP désactivés
|
await dest_user.send(
|
||||||
|
f"📥 Vous avez reçu **{result['montant_recu']:.2f}€** de la part de **{interaction.user.display_name}**."
|
||||||
|
)
|
||||||
|
except (discord.Forbidden, Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
except ValueError as e:
|
||||||
|
await interaction.response.send_message(f"❌ {e}", ephemeral=True)
|
||||||
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"✅ Virement de **{montant:.2f}€** effectué.{' TVA de ' + str(tva_envoyee) + '€ envoyée au Gouvernement.' if is_entreprise else ''}",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
await bot.add_cog(Virement(bot))
|
await bot.add_cog(Virement(bot))
|
||||||
|
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
import json
|
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
from datetime import datetime
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class VirementBanquier(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="virement_banquier", description="Effectue un virement au nom d'un client (réservé aux banquiers).")
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
async def virement_banquier(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
rib_emetteur: str,
|
|
||||||
montant: float,
|
|
||||||
rib_destinataire: str,
|
|
||||||
banque: app_commands.Choice[str]
|
|
||||||
):
|
|
||||||
if not has_role(interaction.user, "banquier"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission d'utiliser cette commande.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
banque_nom = banque.value
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
except:
|
|
||||||
await interaction.response.send_message("❌ Erreur de lecture des comptes bancaires.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Trouver les ID à partir des RIB
|
|
||||||
emetteur_id = None
|
|
||||||
destinataire_id = None
|
|
||||||
|
|
||||||
for user_id, data in comptes.get(banque_nom, {}).items():
|
|
||||||
if data.get("rib") == rib_emetteur:
|
|
||||||
emetteur_id = user_id
|
|
||||||
if data.get("rib") == rib_destinataire:
|
|
||||||
destinataire_id = user_id
|
|
||||||
|
|
||||||
if not emetteur_id:
|
|
||||||
await interaction.response.send_message("❌ Le RIB émetteur est introuvable dans cette banque.", ephemeral=True)
|
|
||||||
return
|
|
||||||
if not destinataire_id:
|
|
||||||
await interaction.response.send_message("❌ Le RIB destinataire est introuvable dans cette banque.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Vérifier le solde
|
|
||||||
if comptes[banque_nom][emetteur_id]["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Le solde du compte émetteur est insuffisant.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Exécuter le virement
|
|
||||||
comptes[banque_nom][emetteur_id]["solde"] -= montant
|
|
||||||
comptes[banque_nom][emetteur_id]["transactions"].append({
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement manuel (par banquier)",
|
|
||||||
"source": f"Vers RIB {rib_destinataire}",
|
|
||||||
"montant": -montant
|
|
||||||
})
|
|
||||||
|
|
||||||
comptes[banque_nom][destinataire_id]["solde"] += montant
|
|
||||||
comptes[banque_nom][destinataire_id]["transactions"].append({
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement reçu (par banquier)",
|
|
||||||
"source": f"RIB {rib_emetteur}",
|
|
||||||
"montant": montant
|
|
||||||
})
|
|
||||||
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
await interaction.response.send_message(f"✅ Virement de **{montant:.2f}€** effectué de **{rib_emetteur}** vers **{rib_destinataire}** dans **{banque_nom}**.", ephemeral=True)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(VirementBanquier(bot))
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
from utils.guild_config import has_role
|
|
||||||
|
|
||||||
class VirementBanquierEntreprise(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banques = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank")
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="virement_banquier_entreprise", description="Fait un virement depuis une entreprise avec mot de passe (réservé aux banquiers).")
|
|
||||||
@app_commands.choices(banque=banques)
|
|
||||||
async def virement_banquier_entreprise(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
banque: app_commands.Choice[str],
|
|
||||||
nom_entreprise: str,
|
|
||||||
mot_de_passe: str,
|
|
||||||
rib_destinataire: str,
|
|
||||||
montant: float
|
|
||||||
):
|
|
||||||
if not has_role(interaction.user, "banquier"):
|
|
||||||
await interaction.response.send_message("❌ Vous n'avez pas la permission de faire cette commande.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
banque_nom = banque.value
|
|
||||||
|
|
||||||
# Chargement des fichiers
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
entreprises = json.load(f)
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
particuliers = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
await interaction.response.send_message("❌ Erreur de lecture des fichiers JSON.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Vérification de l'entreprise
|
|
||||||
if banque_nom not in entreprises or nom_entreprise not in entreprises[banque_nom]:
|
|
||||||
await interaction.response.send_message("❌ Compte entreprise introuvable.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
compte_entreprise = entreprises[banque_nom][nom_entreprise]
|
|
||||||
|
|
||||||
if compte_entreprise.get("mdp") != mot_de_passe:
|
|
||||||
await interaction.response.send_message("❌ Mot de passe incorrect.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if compte_entreprise["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Solde insuffisant pour ce virement.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Recherche du compte destinataire (entreprise ou particulier)
|
|
||||||
destinataire_id = None
|
|
||||||
banque_destinataire = None
|
|
||||||
is_entreprise = False
|
|
||||||
|
|
||||||
# Recherche dans entreprises
|
|
||||||
for bq, entreprises_data in entreprises.items():
|
|
||||||
for nom, infos in entreprises_data.items():
|
|
||||||
if infos.get("rib") == rib_destinataire:
|
|
||||||
destinataire_id = nom
|
|
||||||
banque_destinataire = bq
|
|
||||||
is_entreprise = True
|
|
||||||
break
|
|
||||||
if destinataire_id:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Sinon, recherche dans particuliers
|
|
||||||
if not destinataire_id:
|
|
||||||
for bq, clients in particuliers.items():
|
|
||||||
for user_id, infos in clients.items():
|
|
||||||
if infos.get("rib") == rib_destinataire:
|
|
||||||
destinataire_id = user_id
|
|
||||||
banque_destinataire = bq
|
|
||||||
is_entreprise = False
|
|
||||||
break
|
|
||||||
if destinataire_id:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not destinataire_id:
|
|
||||||
await interaction.response.send_message("❌ RIB destinataire introuvable.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Retrait du montant
|
|
||||||
compte_entreprise["solde"] -= montant
|
|
||||||
compte_entreprise["transactions"].append({
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement",
|
|
||||||
"source": f"Entreprise {nom_entreprise}",
|
|
||||||
"montant": -montant,
|
|
||||||
"destinataire": rib_destinataire
|
|
||||||
})
|
|
||||||
|
|
||||||
# Créditer le destinataire
|
|
||||||
compte_cible = entreprises if is_entreprise else particuliers
|
|
||||||
compte_data = compte_cible[banque_destinataire][destinataire_id]
|
|
||||||
compte_data["solde"] += montant
|
|
||||||
compte_data["transactions"].append({
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": nom_entreprise,
|
|
||||||
"montant": montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sauvegarde
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(entreprises, f, ensure_ascii=False, indent=4)
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(particuliers, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
await interaction.response.send_message(f"✅ Virement de **{montant:.2f}€** effectué depuis **{nom_entreprise}** vers **{rib_destinataire}**.")
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(VirementBanquierEntreprise(bot))
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
class VirementEntreprise(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="virement_entreprise", description="Effectuer un virement depuis une entreprise vers un RIB.")
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
async def virement_entreprise(
|
|
||||||
self,
|
|
||||||
interaction: discord.Interaction,
|
|
||||||
rib_entreprise: str,
|
|
||||||
montant: float,
|
|
||||||
mot_de_passe: str,
|
|
||||||
rib_destinataire: str,
|
|
||||||
banque: app_commands.Choice[str]
|
|
||||||
):
|
|
||||||
banque_nom = banque.value
|
|
||||||
|
|
||||||
# Chargement des données
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes_entreprises = json.load(f)
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes_bancaires = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
await interaction.response.send_message("❌ Erreur de lecture des données bancaires.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# 🔐 Vérification de l'émetteur
|
|
||||||
entreprise_id = None
|
|
||||||
for nom_entreprise, infos in comptes_entreprises.get(banque_nom, {}).items():
|
|
||||||
if infos.get("rib") == rib_entreprise:
|
|
||||||
if infos.get("mdp") != mot_de_passe:
|
|
||||||
await interaction.response.send_message("❌ Mot de passe incorrect.", ephemeral=True)
|
|
||||||
return
|
|
||||||
entreprise_id = nom_entreprise
|
|
||||||
break
|
|
||||||
|
|
||||||
if not entreprise_id:
|
|
||||||
await interaction.response.send_message("❌ Aucun compte entreprise trouvé avec ce RIB.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
compte_emetteur = comptes_entreprises[banque_nom][entreprise_id]
|
|
||||||
|
|
||||||
if compte_emetteur["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Solde insuffisant.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# 🔎 Recherche du destinataire
|
|
||||||
destinataire_data = None
|
|
||||||
destinataire_type = None
|
|
||||||
destinataire_nom = None
|
|
||||||
banque_dest = None
|
|
||||||
|
|
||||||
for banque_cible, comptes in comptes_entreprises.items():
|
|
||||||
for nom, infos in comptes.items():
|
|
||||||
if infos.get("rib") == rib_destinataire:
|
|
||||||
destinataire_data = infos
|
|
||||||
destinataire_type = "entreprise"
|
|
||||||
destinataire_nom = nom
|
|
||||||
banque_dest = banque_cible
|
|
||||||
break
|
|
||||||
if destinataire_data:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not destinataire_data:
|
|
||||||
for banque_cible, comptes in comptes_bancaires.items():
|
|
||||||
for uid, infos in comptes.items():
|
|
||||||
if infos.get("rib") == rib_destinataire:
|
|
||||||
destinataire_data = infos
|
|
||||||
destinataire_type = "particulier"
|
|
||||||
destinataire_nom = uid
|
|
||||||
banque_dest = banque_cible
|
|
||||||
break
|
|
||||||
if destinataire_data:
|
|
||||||
break
|
|
||||||
|
|
||||||
if not destinataire_data:
|
|
||||||
await interaction.response.send_message("❌ RIB destinataire introuvable.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# 📉 Débit du compte entreprise
|
|
||||||
compte_emetteur["solde"] -= montant
|
|
||||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
|
||||||
compte_emetteur.setdefault("transactions", []).append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement",
|
|
||||||
"source": f"Vers RIB {rib_destinataire}",
|
|
||||||
"montant": -montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# 📈 Crédit du destinataire (avec TVA si entreprise)
|
|
||||||
montant_net = montant
|
|
||||||
tva_envoyee = 0
|
|
||||||
|
|
||||||
if destinataire_type == "entreprise":
|
|
||||||
tva = destinataire_data.get("tva", 0)
|
|
||||||
tva_envoyee = round(montant * tva / 100, 2)
|
|
||||||
montant_net = montant - tva_envoyee
|
|
||||||
|
|
||||||
# Crédit TVA à l'État
|
|
||||||
if "Gouvernement" not in comptes_entreprises:
|
|
||||||
comptes_entreprises["Gouvernement"] = {}
|
|
||||||
if "GOUV" not in comptes_entreprises["Gouvernement"]:
|
|
||||||
comptes_entreprises["Gouvernement"]["GOUV"] = {
|
|
||||||
"rib": "00000 00000 00000000000 00",
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
comptes_entreprises["Gouvernement"]["GOUV"]["solde"] += tva_envoyee
|
|
||||||
comptes_entreprises["Gouvernement"]["GOUV"]["transactions"].append({
|
|
||||||
"date": now,
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": entreprise_id,
|
|
||||||
"montant": tva_envoyee
|
|
||||||
})
|
|
||||||
|
|
||||||
destinataire_data["solde"] += montant_net
|
|
||||||
destinataire_data.setdefault("transactions", []).append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": entreprise_id,
|
|
||||||
"montant": montant_net
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sauvegardes
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes_entreprises, f, ensure_ascii=False, indent=4)
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes_bancaires, f, ensure_ascii=False, indent=4)
|
|
||||||
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"✅ Virement effectué avec succès.{' TVA de ' + str(tva_envoyee) + '€ envoyée au Gouvernement.' if tva_envoyee else ''}",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(VirementEntreprise(bot))
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
class VirementFBM(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="virement_fbm", description="Fait un virement au compte indépendant FBM.")
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
@app_commands.describe(montant="Montant à transférer", banque="Banque à utiliser")
|
|
||||||
async def virement_fbm(self, interaction: discord.Interaction, montant: float, banque: app_commands.Choice[str]):
|
|
||||||
auteur_id = str(interaction.user.id)
|
|
||||||
banque_nom = banque.value
|
|
||||||
|
|
||||||
if montant <= 0:
|
|
||||||
await interaction.response.send_message("❌ Le montant doit être supérieur à 0.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Charger les fichiers
|
|
||||||
try:
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
await interaction.response.send_message("❌ Erreur lors de la lecture des comptes bancaires.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
entreprises = json.load(f)
|
|
||||||
except:
|
|
||||||
entreprises = {}
|
|
||||||
|
|
||||||
# Vérification du compte de l'utilisateur
|
|
||||||
if banque_nom not in comptes or auteur_id not in comptes[banque_nom]:
|
|
||||||
await interaction.response.send_message("❌ Tu n'as pas de compte dans cette banque.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
compte = comptes[banque_nom][auteur_id]
|
|
||||||
if compte["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Solde insuffisant pour effectuer le virement.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Initialiser FBM si nécessaire
|
|
||||||
if "fbm" not in entreprises:
|
|
||||||
entreprises["fbm"] = {}
|
|
||||||
if "FBM" not in entreprises["fbm"]:
|
|
||||||
entreprises["fbm"]["FBM"] = {
|
|
||||||
"rib": "00000 00000 00000000000 03",
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
|
||||||
|
|
||||||
# Mise à jour des soldes
|
|
||||||
compte["solde"] -= montant
|
|
||||||
entreprises["fbm"]["FBM"]["solde"] += montant
|
|
||||||
|
|
||||||
# Historique utilisateur
|
|
||||||
compte["transactions"].append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement",
|
|
||||||
"source": f"Vers FBM",
|
|
||||||
"montant": -montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# Historique FBM
|
|
||||||
entreprises["fbm"]["FBM"]["transactions"].append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": interaction.user.name,
|
|
||||||
"montant": montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sauvegarde
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(entreprises, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
# Confirmation
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"✅ Virement de **{montant:.2f}€** envoyé au compte **FBM** depuis **{banque_nom}**.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(VirementFBM(bot))
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
class VirementGouvernement(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="virement_gouvernement", description="Effectue un virement au Gouvernement.")
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
@app_commands.describe(montant="Le montant à envoyer", banque="Banque à utiliser pour le virement")
|
|
||||||
async def virement_gouvernement(self, interaction: discord.Interaction, montant: float, banque: app_commands.Choice[str]):
|
|
||||||
auteur_id = str(interaction.user.id)
|
|
||||||
banque_source = banque.value
|
|
||||||
|
|
||||||
if montant <= 0:
|
|
||||||
await interaction.response.send_message("❌ Le montant doit être supérieur à zéro.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Charger les fichiers
|
|
||||||
try:
|
|
||||||
with open('comptes_bancaires.json', 'r', encoding='utf-8') as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
with open('comptes_entreprises.json', 'r', encoding='utf-8') as f:
|
|
||||||
entreprises = json.load(f)
|
|
||||||
except Exception as e:
|
|
||||||
await interaction.response.send_message(f"❌ Erreur de lecture des fichiers : {e}", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if banque_source not in comptes or auteur_id not in comptes[banque_source]:
|
|
||||||
await interaction.response.send_message(f"❌ Tu n'as pas de compte dans la banque **{banque_source}**.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
compte_user = comptes[banque_source][auteur_id]
|
|
||||||
if compte_user["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Solde insuffisant pour effectuer ce virement.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Vérifier ou créer le compte Gouvernement
|
|
||||||
if "Gouvernement" not in entreprises:
|
|
||||||
entreprises["Gouvernement"] = {}
|
|
||||||
if "GOUV" not in entreprises["Gouvernement"]:
|
|
||||||
entreprises["Gouvernement"]["GOUV"] = {
|
|
||||||
"rib": "00000 00000 00000000000 00",
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Effectuer le virement
|
|
||||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
|
||||||
compte_user["solde"] -= montant
|
|
||||||
entreprises["Gouvernement"]["GOUV"]["solde"] += montant
|
|
||||||
|
|
||||||
compte_user["transactions"].append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement",
|
|
||||||
"source": f"Vers Gouvernement",
|
|
||||||
"montant": -montant
|
|
||||||
})
|
|
||||||
entreprises["Gouvernement"]["GOUV"]["transactions"].append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": interaction.user.name,
|
|
||||||
"montant": montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sauvegarde
|
|
||||||
with open('comptes_bancaires.json', 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(comptes, f, indent=4, ensure_ascii=False)
|
|
||||||
with open('comptes_entreprises.json', 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(entreprises, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"✅ Virement de **{montant:.2f}€** envoyé au Gouvernement avec succès.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(VirementGouvernement(bot))
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
import discord
|
|
||||||
from discord import app_commands
|
|
||||||
from discord.ext import commands
|
|
||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
class VirementUrssaf(commands.Cog):
|
|
||||||
def __init__(self, bot):
|
|
||||||
self.bot = bot
|
|
||||||
|
|
||||||
banque_choices = [
|
|
||||||
app_commands.Choice(name="Victoria's Credit Bank", value="Victoria's Credit Bank"),
|
|
||||||
app_commands.Choice(name="NGC Bank", value="NGC Bank"),
|
|
||||||
]
|
|
||||||
|
|
||||||
@app_commands.command(name="virement_ursaff", description="Fait un virement vers le compte indépendant URSAFF.")
|
|
||||||
@app_commands.choices(banque=banque_choices)
|
|
||||||
@app_commands.describe(montant="Montant à transférer", banque="Banque à utiliser")
|
|
||||||
async def virement_ursaff(self, interaction: discord.Interaction, montant: float, banque: app_commands.Choice[str]):
|
|
||||||
auteur_id = str(interaction.user.id)
|
|
||||||
banque_nom = banque.value
|
|
||||||
|
|
||||||
if montant <= 0:
|
|
||||||
await interaction.response.send_message("❌ Le montant doit être supérieur à 0.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open("comptes_bancaires.json", "r", encoding="utf-8") as f:
|
|
||||||
comptes = json.load(f)
|
|
||||||
except Exception:
|
|
||||||
await interaction.response.send_message("❌ Erreur lors de la lecture des comptes bancaires.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open("comptes_entreprises.json", "r", encoding="utf-8") as f:
|
|
||||||
entreprises = json.load(f)
|
|
||||||
except:
|
|
||||||
entreprises = {}
|
|
||||||
|
|
||||||
if banque_nom not in comptes or auteur_id not in comptes[banque_nom]:
|
|
||||||
await interaction.response.send_message("❌ Tu n'as pas de compte dans cette banque.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
compte = comptes[banque_nom][auteur_id]
|
|
||||||
if compte["solde"] < montant:
|
|
||||||
await interaction.response.send_message("❌ Solde insuffisant pour effectuer le virement.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Initialiser URSAFF si nécessaire
|
|
||||||
if "ursaff" not in entreprises:
|
|
||||||
entreprises["ursaff"] = {}
|
|
||||||
if "URSAFF" not in entreprises["ursaff"]:
|
|
||||||
entreprises["ursaff"]["URSAFF"] = {
|
|
||||||
"rib": "00000 00000 00000000000 02",
|
|
||||||
"solde": 0.0,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
|
|
||||||
|
|
||||||
# Mise à jour des soldes
|
|
||||||
compte["solde"] -= montant
|
|
||||||
entreprises["ursaff"]["URSAFF"]["solde"] += montant
|
|
||||||
|
|
||||||
# Historique utilisateur
|
|
||||||
compte["transactions"].append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement",
|
|
||||||
"source": "Vers URSAFF",
|
|
||||||
"montant": -montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# Historique URSAFF
|
|
||||||
entreprises["ursaff"]["URSAFF"]["transactions"].append({
|
|
||||||
"date": now,
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": interaction.user.name,
|
|
||||||
"montant": montant
|
|
||||||
})
|
|
||||||
|
|
||||||
# Sauvegarde
|
|
||||||
with open("comptes_bancaires.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(comptes, f, indent=4, ensure_ascii=False)
|
|
||||||
with open("comptes_entreprises.json", "w", encoding="utf-8") as f:
|
|
||||||
json.dump(entreprises, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
await interaction.response.send_message(
|
|
||||||
f"✅ Virement de **{montant:.2f}€** envoyé au compte **URSAFF** depuis **{banque_nom}**.",
|
|
||||||
ephemeral=True
|
|
||||||
)
|
|
||||||
|
|
||||||
async def setup(bot):
|
|
||||||
await bot.add_cog(VirementUrssaf(bot))
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,492 +0,0 @@
|
||||||
{
|
|
||||||
"ngc_bank": {},
|
|
||||||
"Gouvernement": {
|
|
||||||
"GOUV": {
|
|
||||||
"rib": "00000 00000 00000000000 00",
|
|
||||||
"solde": 10085849.01,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "26/04/2025 15:55:13",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "534003230435442690",
|
|
||||||
"montant": 0.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "27/04/2025 14:01:32",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "534003230435442690",
|
|
||||||
"montant": 0.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "28/04/2025 08:53:44",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1108087282692522105",
|
|
||||||
"montant": 8.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "28/04/2025 10:42:38",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1263573205268828231",
|
|
||||||
"montant": 7.6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "28/04/2025 15:37:27",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1244182195300601920",
|
|
||||||
"montant": 8.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "01/05/2025 08:56:08",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "914118793918312480",
|
|
||||||
"montant": 5.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "01/05/2025 13:08:59",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1321863072242995332",
|
|
||||||
"montant": 300.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "04/05/2025 16:51:20",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "971446412690722826",
|
|
||||||
"montant": 0.01
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "05/05/2025 16:09:39",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "353942721997832195",
|
|
||||||
"montant": 400.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "05/05/2025 16:23:40",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "828239898975666216",
|
|
||||||
"montant": 10.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "05/05/2025 16:24:07",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "534003230435442690",
|
|
||||||
"montant": 100.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "06/05/2025 10:49:55",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1263573205268828231",
|
|
||||||
"montant": 8.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "06/05/2025 18:19:03",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1263573205268828231",
|
|
||||||
"montant": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "07/05/2025 19:45:13",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "gameurpro12",
|
|
||||||
"montant": 1.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 17:23:13",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1200313720195264613",
|
|
||||||
"montant": 7.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 18:31:46",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1263573205268828231",
|
|
||||||
"montant": 7.6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 19:10:15",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "534003230435442690",
|
|
||||||
"montant": 100.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 19:15:25",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "534003230435442690",
|
|
||||||
"montant": 100.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "11/05/2025 13:06:24",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1321863072242995332",
|
|
||||||
"montant": 330.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "11/05/2025 14:49:46",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1072112886509473792",
|
|
||||||
"montant": 14000.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "11/05/2025 14:50:02",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "501080933282218005",
|
|
||||||
"montant": 2400.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "12/05/2025 18:35:06",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1263573205268828231",
|
|
||||||
"montant": 7.6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "18/05/2025 15:17:43",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1126995714552111215",
|
|
||||||
"montant": 2400.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "18/05/2025 15:34:58",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "376796341071773706",
|
|
||||||
"montant": 2400.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "18/05/2025 15:34:58",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "376796341071773706",
|
|
||||||
"montant": 2400.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "19/05/2025 11:55:01",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1200313720195264613",
|
|
||||||
"montant": 7.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "29/05/2025 13:51:53",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "376796341071773706",
|
|
||||||
"montant": 6000.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "29/05/2025 15:16:42",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "353942721997832195",
|
|
||||||
"montant": 27.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "06/06/2025 20:09:01",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "353942721997832195",
|
|
||||||
"montant": 42.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "20/06/2025 19:06:14",
|
|
||||||
"type": "TVA reçue",
|
|
||||||
"source": "1244372888702816458",
|
|
||||||
"montant": 2000.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "29/06/2025 12:31:17",
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": 15869.0,
|
|
||||||
"emetteur": 353942721997832195,
|
|
||||||
"destinataire": "GOUV"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"NGC Bank": {
|
|
||||||
"Journal en onde": {
|
|
||||||
"rib": "93884 11674 79519 40904",
|
|
||||||
"solde": 6031.0,
|
|
||||||
"mdp": "E96zM0Jj",
|
|
||||||
"tva": 2,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "05/05/2025 16:23:40",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "docteur_w.d_axolotl",
|
|
||||||
"montant": 490.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "05/05/2025 16:24:07",
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": 4900.0,
|
|
||||||
"emetteur": 534003230435442690,
|
|
||||||
"destinataire": "Journal en onde"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "06/05/2025 10:49:55",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "e.93130",
|
|
||||||
"montant": 392.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "06/05/2025 18:19:03",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "e.93130",
|
|
||||||
"montant": 49.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Milano Motors": {
|
|
||||||
"rib": "79307 68952 45977 60249",
|
|
||||||
"solde": 126400.0,
|
|
||||||
"mdp": "9YcjNvud",
|
|
||||||
"tva": 20,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "11/05/2025 14:49:46",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "lagrenouillebeka",
|
|
||||||
"montant": 56000.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "11/05/2025 14:50:02",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "justeme",
|
|
||||||
"montant": 9600.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "18/05/2025 15:17:43",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "jl_wesley.f1",
|
|
||||||
"montant": 9600.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "18/05/2025 15:34:58",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "bitehoven",
|
|
||||||
"montant": 9600.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "18/05/2025 15:34:58",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "bitehoven",
|
|
||||||
"montant": 9600.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "29/05/2025 13:51:53",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "bitehoven",
|
|
||||||
"montant": 24000.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "20/06/2025 19:06:14",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "oghacker1337",
|
|
||||||
"montant": 8000.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Sicilia mia": {
|
|
||||||
"rib": "19440 99822 26785 73807",
|
|
||||||
"solde": 108.0,
|
|
||||||
"mdp": "8sqmuoz4",
|
|
||||||
"tva": 20,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "29/05/2025 15:16:42",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "mg_studios_",
|
|
||||||
"montant": 108.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Domaine de vins": {
|
|
||||||
"rib": "96241 34733 44548 77079",
|
|
||||||
"solde": 1768.0,
|
|
||||||
"mdp": "hIJj81ci",
|
|
||||||
"tva": 20,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "05/05/2025 16:09:39",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "mg_studios_",
|
|
||||||
"montant": 1600.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "06/06/2025 20:09:01",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "mg_studios_",
|
|
||||||
"montant": 168.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Umbrella Assurances": {
|
|
||||||
"rib": "54201 75079 71658 35659",
|
|
||||||
"solde": 2969.4,
|
|
||||||
"mdp": "KDRQGd3R",
|
|
||||||
"tva": 2,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "28/04/2025 08:53:44",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "tricks212_zz",
|
|
||||||
"montant": 416.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "28/04/2025 10:42:38",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "e.93130",
|
|
||||||
"montant": 372.4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "28/04/2025 15:37:27",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "hvk_pompotfraicz",
|
|
||||||
"montant": 416.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "01/05/2025 08:56:08",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "neyzizz",
|
|
||||||
"montant": 254.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 17:23:13",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "agent_chaos_officiel",
|
|
||||||
"montant": 382.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 18:31:46",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "e.93130",
|
|
||||||
"montant": 372.4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "12/05/2025 18:35:06",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "e.93130",
|
|
||||||
"montant": 372.4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "19/05/2025 11:55:01",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "agent_chaos_officiel",
|
|
||||||
"montant": 382.2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Auto école": {
|
|
||||||
"rib": "11940 73588 95258 04768",
|
|
||||||
"solde": 15971.0,
|
|
||||||
"mdp": "zcEKe45Y",
|
|
||||||
"tva": 20,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "26/04/2025 15:55:13",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "nixfix06",
|
|
||||||
"montant": 0.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "27/04/2025 14:01:32",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "nixfix06",
|
|
||||||
"montant": 0.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "01/05/2025 13:08:59",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "sz94d",
|
|
||||||
"montant": 1200.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "11/05/2025 13:06:24",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "sz94d",
|
|
||||||
"montant": 1320.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Sicilia Mia": {
|
|
||||||
"rib": "68229 13765 90163 35585",
|
|
||||||
"solde": 1907.09,
|
|
||||||
"mdp": "6uTORm3r",
|
|
||||||
"tva": 10,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "04/05/2025 16:51:20",
|
|
||||||
"type": "Virement reçu",
|
|
||||||
"source": "gameurpro12",
|
|
||||||
"montant": 0.09000000000000001
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"NGC Bank": {
|
|
||||||
"rib": "15156 38436 35920 54357",
|
|
||||||
"solde": 1040900.0,
|
|
||||||
"mdp": "nxDcskg0",
|
|
||||||
"tva": 2,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 19:10:15",
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": 4900.0,
|
|
||||||
"emetteur": 534003230435442690,
|
|
||||||
"destinataire": "NGC Bank"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 19:15:25",
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": 4900.0,
|
|
||||||
"emetteur": 534003230435442690,
|
|
||||||
"destinataire": "NGC Bank"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "09/05/2025 19:15:51",
|
|
||||||
"type": "Retrait",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": -4900.0,
|
|
||||||
"emetteur": 534003230435442690,
|
|
||||||
"destinataire": "NGC Bank"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "24/05/2025 13:44:09",
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": 1000000.0,
|
|
||||||
"emetteur": 534003230435442690,
|
|
||||||
"destinataire": "NGC Bank"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"date": "04/06/2025 16:30:19",
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": 36000.0,
|
|
||||||
"emetteur": 534003230435442690,
|
|
||||||
"destinataire": "NGC Bank"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Agence immobilière.": {
|
|
||||||
"rib": "54044 32109 51269 69180",
|
|
||||||
"solde": 108000.0,
|
|
||||||
"mdp": "tCH7QK7G",
|
|
||||||
"tva": 20,
|
|
||||||
"transactions": [
|
|
||||||
{
|
|
||||||
"date": "03/07/2025 22:35:20",
|
|
||||||
"type": "Dépôt",
|
|
||||||
"source": "Banque",
|
|
||||||
"montant": 108000.0,
|
|
||||||
"emetteur": 353942721997832195,
|
|
||||||
"destinataire": "Agence immobilière."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"La Concordia": {
|
|
||||||
"rib": "09860 71327 12935 47361",
|
|
||||||
"solde": 0,
|
|
||||||
"mdp": "3vo66Wqu",
|
|
||||||
"tva": 10,
|
|
||||||
"transactions": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"identities": {
|
"identities": {
|
||||||
"353942721997832195": {
|
"353942721997832195": {
|
||||||
"nom": "RICCI",
|
"nom": "JOHN",
|
||||||
"prenom": "Aldo",
|
"prenom": "Marston",
|
||||||
"date_naissance": "22/05/1967",
|
"date_naissance": "22/05/2008",
|
||||||
"lieu_naissance": "Victoria's Vice",
|
"lieu_naissance": "Victorias",
|
||||||
"sexe": "Homme",
|
"sexe": "Homme",
|
||||||
"date_expiration": "01/12/2026"
|
"date_expiration": "17/08/2028"
|
||||||
},
|
},
|
||||||
"1096453463849828362": {
|
"1096453463849828362": {
|
||||||
"nom": "DE MONTROSE",
|
"nom": "DE MONTROSE",
|
||||||
|
|
|
||||||
500
utils/bank_manager.py
Normal file
500
utils/bank_manager.py
Normal file
|
|
@ -0,0 +1,500 @@
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
|
|
||||||
|
from utils.db import get_db
|
||||||
|
from utils.rib import generer_rib, valider_rib, decoder_rib
|
||||||
|
|
||||||
|
GUIICHET_PARTICULIER = 4
|
||||||
|
GUIICHET_ENTREPRISE = 3
|
||||||
|
GUIICHET_BANQUE = 2
|
||||||
|
GUIICHET_INSTITUTION = 1
|
||||||
|
|
||||||
|
|
||||||
|
class BankManager:
|
||||||
|
|
||||||
|
async def creer_banque(self, guild_id: int, name: str, role_id: int) -> dict:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT COALESCE(MAX(establishment_code), 9999) FROM banks WHERE guild_id = ?",
|
||||||
|
(guild_id,),
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
last_code = row[0]
|
||||||
|
new_code = last_code + 1
|
||||||
|
if new_code > 89999:
|
||||||
|
raise ValueError("Plus de codes d'établissement disponibles.")
|
||||||
|
|
||||||
|
cursor = await db.execute(
|
||||||
|
"INSERT INTO banks (guild_id, name, role_id, establishment_code) VALUES (?, ?, ?, ?)",
|
||||||
|
(guild_id, name, role_id, new_code),
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
bank_id = cursor.lastrowid
|
||||||
|
return {"id": bank_id, "name": name, "role_id": role_id, "establishment_code": new_code}
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def supprimer_banque(self, guild_id: int, bank_id: int) -> bool:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"DELETE FROM banks WHERE id = ? AND guild_id = ?", (bank_id, guild_id)
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
return cursor.rowcount > 0
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_banque(self, guild_id: int, bank_id: int) -> Optional[dict]:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM banks WHERE id = ? AND guild_id = ?", (bank_id, guild_id)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_banque_by_role(self, guild_id: int, role_id: int) -> Optional[dict]:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM banks WHERE guild_id = ? AND role_id = ?", (guild_id, role_id)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_banque_by_name(self, guild_id: int, name: str) -> Optional[dict]:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM banks WHERE guild_id = ? AND name = ?", (guild_id, name)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def lister_banques(self, guild_id: int) -> list:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM banks WHERE guild_id = ? ORDER BY name", (guild_id,)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [dict(r) for r in rows]
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def ouvrir_compte(
|
||||||
|
self,
|
||||||
|
guild_id: int,
|
||||||
|
bank_id: int,
|
||||||
|
user_id: int,
|
||||||
|
account_type: str,
|
||||||
|
tva_rate: float = 0.0,
|
||||||
|
password: str = None,
|
||||||
|
) -> dict:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM banks WHERE id = ? AND guild_id = ?", (bank_id, guild_id)
|
||||||
|
)
|
||||||
|
bank = await cursor.fetchone()
|
||||||
|
if not bank:
|
||||||
|
raise ValueError("Banque introuvable.")
|
||||||
|
|
||||||
|
guichet = GUIICHET_ENTREPRISE if account_type == "entreprise" else GUIICHET_PARTICULIER
|
||||||
|
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT COUNT(*) FROM accounts WHERE guild_id = ? AND bank_id = ? AND user_id = ? AND account_type = ?",
|
||||||
|
(guild_id, bank_id, user_id, account_type),
|
||||||
|
)
|
||||||
|
count = (await cursor.fetchone())[0]
|
||||||
|
if count > 0:
|
||||||
|
raise ValueError(f"Ce membre a déjà un compte {account_type} dans cette banque.")
|
||||||
|
|
||||||
|
rib = generer_rib(bank["establishment_code"], guichet)
|
||||||
|
|
||||||
|
cursor = await db.execute(
|
||||||
|
"INSERT INTO accounts (guild_id, bank_id, user_id, rib, account_type, tva_rate, password) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
(guild_id, bank_id, user_id, rib, account_type, tva_rate, password),
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
return {"id": cursor.lastrowid, "rib": rib, "account_type": account_type, "tva_rate": tva_rate}
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_compte_by_rib(self, guild_id: int, rib: str) -> Optional[dict]:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"""SELECT a.*, b.name as bank_name, b.establishment_code, b.role_id as bank_role_id
|
||||||
|
FROM accounts a JOIN banks b ON a.bank_id = b.id
|
||||||
|
WHERE a.rib = ? AND a.guild_id = ?""",
|
||||||
|
(rib, guild_id),
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_comptes_user(self, guild_id: int, user_id: int) -> list:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"""SELECT a.*, b.name as bank_name, b.establishment_code
|
||||||
|
FROM accounts a JOIN banks b ON a.bank_id = b.id
|
||||||
|
WHERE a.guild_id = ? AND a.user_id = ?
|
||||||
|
ORDER BY b.name, a.account_type""",
|
||||||
|
(guild_id, user_id),
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [dict(r) for r in rows]
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_comptes_banque(self, guild_id: int, bank_id: int) -> list:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"""SELECT a.*, b.name as bank_name
|
||||||
|
FROM accounts a JOIN banks b ON a.bank_id = b.id
|
||||||
|
WHERE a.guild_id = ? AND a.bank_id = ?
|
||||||
|
ORDER BY a.user_id, a.account_type""",
|
||||||
|
(guild_id, bank_id),
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [dict(r) for r in rows]
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def modifier_tva(self, guild_id: int, rib: str, nouveau_taux: float) -> bool:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE accounts SET tva_rate = ? WHERE rib = ? AND guild_id = ? AND account_type = 'entreprise'",
|
||||||
|
(nouveau_taux, rib, guild_id),
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
return cursor.rowcount > 0
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def virement(
|
||||||
|
self,
|
||||||
|
guild_id: int,
|
||||||
|
rib_source: str,
|
||||||
|
rib_dest: str,
|
||||||
|
montant: float,
|
||||||
|
emetteur_id: int = None,
|
||||||
|
destinataire_id: int = None,
|
||||||
|
) -> dict:
|
||||||
|
if montant <= 0:
|
||||||
|
raise ValueError("Le montant doit être supérieur à 0.")
|
||||||
|
if rib_source == rib_dest:
|
||||||
|
raise ValueError("Impossible de se virer à soi-même.")
|
||||||
|
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
source = await self._get_account(db, guild_id, rib_source)
|
||||||
|
if not source:
|
||||||
|
raise ValueError("Compte source introuvable.")
|
||||||
|
dest = await self._get_account(db, guild_id, rib_dest)
|
||||||
|
if not dest:
|
||||||
|
raise ValueError("Compte destination introuvable.")
|
||||||
|
|
||||||
|
if source["solde"] < montant:
|
||||||
|
raise ValueError(f"Solde insuffisant. Disponible : {source['solde']:.2f}€")
|
||||||
|
|
||||||
|
tva_montant = 0.0
|
||||||
|
montant_net = montant
|
||||||
|
|
||||||
|
if source["account_type"] == "particulier" and dest["account_type"] == "entreprise":
|
||||||
|
tva_rate = dest["tva_rate"] or 0.0
|
||||||
|
if tva_rate > 0:
|
||||||
|
tva_montant = round(montant * tva_rate / 100, 2)
|
||||||
|
montant_net = round(montant - tva_montant, 2)
|
||||||
|
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE accounts SET solde = solde - ? WHERE rib = ? AND guild_id = ?",
|
||||||
|
(montant, rib_source, guild_id),
|
||||||
|
)
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE accounts SET solde = solde + ? WHERE rib = ? AND guild_id = ?",
|
||||||
|
(montant_net, rib_dest, guild_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
if tva_montant > 0:
|
||||||
|
fisc_rib = await self._get_fisc_rib(db, guild_id)
|
||||||
|
if fisc_rib:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE accounts SET solde = solde + ? WHERE rib = ? AND guild_id = ?",
|
||||||
|
(tva_montant, fisc_rib, guild_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE banks SET clients_total_balance = clients_total_balance - ? WHERE id = ? AND guild_id = ?",
|
||||||
|
(montant, source["bank_id"], guild_id),
|
||||||
|
)
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE banks SET clients_total_balance = clients_total_balance + ? WHERE id = ? AND guild_id = ?",
|
||||||
|
(montant_net, dest["bank_id"], guild_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
await db.execute(
|
||||||
|
"""INSERT INTO transactions (guild_id, emetteur_rib, destinataire_rib, emetteur_id, destinataire_id, montant, type, date)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
|
(guild_id, rib_source, rib_dest, emetteur_id or source["user_id"], destinataire_id or dest["user_id"], montant, "virement", now),
|
||||||
|
)
|
||||||
|
if tva_montant > 0 and fisc_rib:
|
||||||
|
await db.execute(
|
||||||
|
"""INSERT INTO transactions (guild_id, destinataire_rib, montant, type, date, metadata)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?)""",
|
||||||
|
(guild_id, fisc_rib, tva_montant, "tva_prelevee", now, json.dumps({"source_rib": rib_source, "dest_rib": rib_dest})),
|
||||||
|
)
|
||||||
|
|
||||||
|
await db.commit()
|
||||||
|
|
||||||
|
result = {
|
||||||
|
"montant_envoye": montant,
|
||||||
|
"montant_recu": montant_net,
|
||||||
|
"tva_prelevee": tva_montant,
|
||||||
|
}
|
||||||
|
if tva_montant > 0:
|
||||||
|
result["tva_dest"] = fisc_rib
|
||||||
|
return result
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def depot_banquier(
|
||||||
|
self, guild_id: int, rib: str, montant: float, banquier_id: int
|
||||||
|
) -> dict:
|
||||||
|
if montant <= 0:
|
||||||
|
raise ValueError("Le montant doit être supérieur à 0.")
|
||||||
|
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
compte = await self._get_account(db, guild_id, rib)
|
||||||
|
if not compte:
|
||||||
|
raise ValueError("Compte introuvable.")
|
||||||
|
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE accounts SET solde = solde + ? WHERE rib = ? AND guild_id = ?",
|
||||||
|
(montant, rib, guild_id),
|
||||||
|
)
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE banks SET clients_total_balance = clients_total_balance + ? WHERE id = ? AND guild_id = ?",
|
||||||
|
(montant, compte["bank_id"], guild_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
await db.execute(
|
||||||
|
"""INSERT INTO transactions (guild_id, destinataire_rib, destinataire_id, montant, type, date, metadata)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)""",
|
||||||
|
(guild_id, rib, compte["user_id"], montant, "depot_banquier", now, json.dumps({"banquier_id": banquier_id})),
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
return {"nouveau_solde": compte["solde"] + montant}
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def retrait_banquier(
|
||||||
|
self, guild_id: int, rib: str, montant: float, banquier_id: int
|
||||||
|
) -> dict:
|
||||||
|
if montant <= 0:
|
||||||
|
raise ValueError("Le montant doit être supérieur à 0.")
|
||||||
|
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
compte = await self._get_account(db, guild_id, rib)
|
||||||
|
if not compte:
|
||||||
|
raise ValueError("Compte introuvable.")
|
||||||
|
if compte["solde"] < montant:
|
||||||
|
raise ValueError(f"Solde insuffisant. Disponible : {compte['solde']:.2f}€")
|
||||||
|
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE accounts SET solde = solde - ? WHERE rib = ? AND guild_id = ?",
|
||||||
|
(montant, rib, guild_id),
|
||||||
|
)
|
||||||
|
cursor = await db.execute(
|
||||||
|
"UPDATE banks SET clients_total_balance = clients_total_balance - ? WHERE id = ? AND guild_id = ?",
|
||||||
|
(montant, compte["bank_id"], guild_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
await db.execute(
|
||||||
|
"""INSERT INTO transactions (guild_id, emetteur_rib, emetteur_id, montant, type, date, metadata)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)""",
|
||||||
|
(guild_id, rib, compte["user_id"], montant, "retrait_banquier", now, json.dumps({"banquier_id": banquier_id})),
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
return {"nouveau_solde": compte["solde"] - montant}
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_transactions(self, guild_id: int, rib: str, limit: int = 10) -> list:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"""SELECT * FROM transactions
|
||||||
|
WHERE guild_id = ? AND (emetteur_rib = ? OR destinataire_rib = ?)
|
||||||
|
ORDER BY date DESC LIMIT ?""",
|
||||||
|
(guild_id, rib, rib, limit),
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [dict(r) for r in rows]
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def creer_institution(
|
||||||
|
self, guild_id: int, name: str, role_id: int = None, can_audit_all: bool = False
|
||||||
|
) -> dict:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"INSERT INTO institutions (guild_id, name, role_id, can_audit_all) VALUES (?, ?, ?, ?)",
|
||||||
|
(guild_id, name, role_id, int(can_audit_all)),
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
return {"id": cursor.lastrowid, "name": name, "can_audit_all": can_audit_all}
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_institution(self, guild_id: int, institution_id: int) -> Optional[dict]:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM institutions WHERE id = ? AND guild_id = ?",
|
||||||
|
(institution_id, guild_id),
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_institution_by_role(self, guild_id: int, role_id: int) -> Optional[dict]:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM institutions WHERE guild_id = ? AND role_id = ?",
|
||||||
|
(guild_id, role_id),
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def lister_institutions(self, guild_id: int) -> list:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM institutions WHERE guild_id = ? ORDER BY name", (guild_id,)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [dict(r) for r in rows]
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def configurer_fisc(self, guild_id: int, institution_id: int) -> bool:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
inst = await self.get_institution(guild_id, institution_id)
|
||||||
|
if not inst:
|
||||||
|
return False
|
||||||
|
|
||||||
|
guichet = GUIICHET_INSTITUTION
|
||||||
|
bank = await self._get_gouvernement_bank(db, guild_id)
|
||||||
|
if not bank:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"INSERT INTO banks (guild_id, name, role_id, establishment_code) VALUES (?, ?, ?, ?)",
|
||||||
|
(guild_id, "Gouvernement", 0, 1),
|
||||||
|
)
|
||||||
|
bank_id = cursor.lastrowid
|
||||||
|
bank = {"id": bank_id, "establishment_code": 1}
|
||||||
|
else:
|
||||||
|
bank_id = bank["id"]
|
||||||
|
|
||||||
|
rib = generer_rib(bank["establishment_code"], guichet)
|
||||||
|
|
||||||
|
existing = await db.execute(
|
||||||
|
"SELECT rib FROM accounts WHERE guild_id = ? AND bank_id = ? AND user_id = ? AND account_type = 'entreprise'",
|
||||||
|
(guild_id, bank_id, institution_id),
|
||||||
|
)
|
||||||
|
existing_row = await existing.fetchone()
|
||||||
|
if existing_row:
|
||||||
|
rib = existing_row[0]
|
||||||
|
else:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"INSERT INTO accounts (guild_id, bank_id, user_id, rib, account_type, solde) VALUES (?, ?, ?, ?, 'entreprise', 0.0)",
|
||||||
|
(guild_id, bank_id, institution_id, rib),
|
||||||
|
)
|
||||||
|
|
||||||
|
await db.execute(
|
||||||
|
"INSERT OR REPLACE INTO fisc_config (guild_id, institution_id) VALUES (?, ?)",
|
||||||
|
(guild_id, institution_id),
|
||||||
|
)
|
||||||
|
await db.commit()
|
||||||
|
return True
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_fisc_config(self, guild_id: int) -> Optional[dict]:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"""SELECT fc.*, i.name as institution_name, i.role_id as institution_role_id
|
||||||
|
FROM fisc_config fc
|
||||||
|
JOIN institutions i ON fc.institution_id = i.id
|
||||||
|
WHERE fc.guild_id = ?""",
|
||||||
|
(guild_id,),
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def get_next_bank_codes(self, guild_id: int) -> list:
|
||||||
|
db = await get_db()
|
||||||
|
try:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT establishment_code FROM banks WHERE guild_id = ? ORDER BY establishment_code",
|
||||||
|
(guild_id,),
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [r[0] for r in rows]
|
||||||
|
finally:
|
||||||
|
await db.close()
|
||||||
|
|
||||||
|
async def _get_account(self, db: aiosqlite.Connection, guild_id: int, rib: str) -> Optional[dict]:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM accounts WHERE rib = ? AND guild_id = ?", (rib, guild_id)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
|
||||||
|
async def _get_fisc_rib(self, db: aiosqlite.Connection, guild_id: int) -> Optional[str]:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"""SELECT a.rib FROM accounts a
|
||||||
|
JOIN fisc_config fc ON a.user_id = fc.institution_id
|
||||||
|
WHERE fc.guild_id = ? AND a.account_type = 'entreprise'""",
|
||||||
|
(guild_id,),
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] if row else None
|
||||||
|
|
||||||
|
async def _get_gouvernement_bank(self, db: aiosqlite.Connection, guild_id: int) -> Optional[dict]:
|
||||||
|
cursor = await db.execute(
|
||||||
|
"SELECT * FROM banks WHERE guild_id = ? AND name = 'Gouvernement'",
|
||||||
|
(guild_id,),
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
import json
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
from .logger import log_error
|
|
||||||
|
|
||||||
class BanqueManager:
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
self.file_path = "comptes_bancaires.json"
|
|
||||||
self.comptes = {}
|
|
||||||
self.load_data()
|
|
||||||
|
|
||||||
def load_data(self):
|
|
||||||
"""Charge les données bancaires depuis un fichier JSON."""
|
|
||||||
if os.path.exists(self.file_path):
|
|
||||||
try:
|
|
||||||
with open(self.file_path, "r", encoding="utf-8") as f:
|
|
||||||
data = f.read().strip()
|
|
||||||
self.comptes = json.loads(data) if data else {}
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
log_error("Erreur de lecture dans comptes_bancaires.json, réinitialisation...")
|
|
||||||
self.comptes = {}
|
|
||||||
self.save_data()
|
|
||||||
|
|
||||||
def save_data(self):
|
|
||||||
"""Sauvegarde les comptes et transactions dans comptes_bancaires.json."""
|
|
||||||
with open(self.file_path, "w", encoding="utf-8") as f:
|
|
||||||
json.dump(self.comptes, f, indent=4, ensure_ascii=False)
|
|
||||||
|
|
||||||
def enregistrer_transaction(self, emetteur_id, destinataire_id, montant, type_transaction):
|
|
||||||
"""
|
|
||||||
Enregistre une transaction dans l'historique et recharge les données en temps réel.
|
|
||||||
"""
|
|
||||||
self.load_data()
|
|
||||||
|
|
||||||
transaction = {
|
|
||||||
"date": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
|
|
||||||
"type": type_transaction,
|
|
||||||
"montant": montant,
|
|
||||||
"emetteur": emetteur_id,
|
|
||||||
"destinataire": destinataire_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if emetteur_id not in self.comptes:
|
|
||||||
self.comptes[emetteur_id] = {"solde": 0, "prets": [], "transactions": []}
|
|
||||||
elif "transactions" not in self.comptes[emetteur_id]:
|
|
||||||
self.comptes[emetteur_id]["transactions"] = []
|
|
||||||
|
|
||||||
self.comptes[emetteur_id]["transactions"].append(transaction)
|
|
||||||
|
|
||||||
if destinataire_id not in self.comptes:
|
|
||||||
self.comptes[destinataire_id] = {"solde": 0, "prets": [], "transactions": []}
|
|
||||||
elif "transactions" not in self.comptes[destinataire_id]:
|
|
||||||
self.comptes[destinataire_id]["transactions"] = []
|
|
||||||
|
|
||||||
self.comptes[destinataire_id]["transactions"].append(transaction)
|
|
||||||
|
|
||||||
self.save_data()
|
|
||||||
|
|
@ -16,7 +16,8 @@ class CardGenerator:
|
||||||
|
|
||||||
def create_template(self):
|
def create_template(self):
|
||||||
try:
|
try:
|
||||||
CI_path = "/home/discord/Bot/Vicy/ressources/assets/CIITAL.png"
|
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
CI_path = os.path.join(base_dir, "ressources", "assets", "CIITAL.png")
|
||||||
|
|
||||||
if not os.path.exists(CI_path):
|
if not os.path.exists(CI_path):
|
||||||
raise FileNotFoundError(f"Image de fond introuvable : {CI_path}")
|
raise FileNotFoundError(f"Image de fond introuvable : {CI_path}")
|
||||||
|
|
|
||||||
82
utils/db.py
Normal file
82
utils/db.py
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
import aiosqlite
|
||||||
|
import os
|
||||||
|
|
||||||
|
DB_PATH = os.path.join(os.path.dirname(__file__), "..", "data", "bank_v2.db")
|
||||||
|
|
||||||
|
SCHEMA = """
|
||||||
|
CREATE TABLE IF NOT EXISTS banks (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
guild_id INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
role_id INTEGER NOT NULL,
|
||||||
|
establishment_code INTEGER NOT NULL,
|
||||||
|
vault_balance REAL DEFAULT 0.0,
|
||||||
|
clients_total_balance REAL DEFAULT 0.0,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE(guild_id, name),
|
||||||
|
UNIQUE(guild_id, establishment_code)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS accounts (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
guild_id INTEGER NOT NULL,
|
||||||
|
bank_id INTEGER NOT NULL,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
rib TEXT NOT NULL UNIQUE,
|
||||||
|
account_type TEXT NOT NULL CHECK(account_type IN ('particulier', 'entreprise')),
|
||||||
|
solde REAL DEFAULT 0.0,
|
||||||
|
tva_rate REAL DEFAULT 0.0,
|
||||||
|
password TEXT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (bank_id) REFERENCES banks(id) ON DELETE CASCADE,
|
||||||
|
UNIQUE(guild_id, bank_id, user_id, account_type)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS institutions (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
guild_id INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
role_id INTEGER,
|
||||||
|
can_audit_all INTEGER DEFAULT 0,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE(guild_id, name)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS fisc_config (
|
||||||
|
guild_id INTEGER PRIMARY KEY,
|
||||||
|
institution_id INTEGER,
|
||||||
|
FOREIGN KEY (institution_id) REFERENCES institutions(id) ON DELETE SET NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS transactions (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
guild_id INTEGER NOT NULL,
|
||||||
|
emetteur_rib TEXT,
|
||||||
|
destinataire_rib TEXT,
|
||||||
|
emetteur_id INTEGER,
|
||||||
|
destinataire_id INTEGER,
|
||||||
|
montant REAL NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
metadata TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_accounts_guild_user ON accounts(guild_id, user_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_accounts_rib ON accounts(rib);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_accounts_bank ON accounts(guild_id, bank_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_transactions_guild ON transactions(guild_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_transactions_ribs ON transactions(emetteur_rib, destinataire_rib);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_banks_guild ON banks(guild_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_institutions_guild ON institutions(guild_id);
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
async def get_db() -> aiosqlite.Connection:
|
||||||
|
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
|
||||||
|
db = await aiosqlite.connect(DB_PATH)
|
||||||
|
db.row_factory = aiosqlite.Row
|
||||||
|
await db.execute("PRAGMA journal_mode=WAL")
|
||||||
|
await db.execute("PRAGMA foreign_keys=ON")
|
||||||
|
await db.executescript(SCHEMA)
|
||||||
|
await db.commit()
|
||||||
|
return db
|
||||||
|
|
@ -18,9 +18,6 @@ DEFAULT_CONFIG = {
|
||||||
"visite_medicale": None,
|
"visite_medicale": None,
|
||||||
"permis": None,
|
"permis": None,
|
||||||
"auto_ecole": None,
|
"auto_ecole": None,
|
||||||
"fbm": None,
|
|
||||||
"banque_nationale": None,
|
|
||||||
"ursaff": None,
|
|
||||||
"session_reminders": None,
|
"session_reminders": None,
|
||||||
},
|
},
|
||||||
"channels": {
|
"channels": {
|
||||||
|
|
@ -47,9 +44,6 @@ ROLE_LABELS = {
|
||||||
"visite_medicale": "Visite Médicale",
|
"visite_medicale": "Visite Médicale",
|
||||||
"permis": "Permis",
|
"permis": "Permis",
|
||||||
"auto_ecole": "Auto-École",
|
"auto_ecole": "Auto-École",
|
||||||
"fbm": "FBM",
|
|
||||||
"banque_nationale": "Banque Nationale",
|
|
||||||
"ursaff": "URSAFF",
|
|
||||||
"session_reminders": "Session Reminders",
|
"session_reminders": "Session Reminders",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
55
utils/rib.py
Normal file
55
utils/rib.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
def _checksum(digits: str) -> int:
|
||||||
|
return (97 - (int(digits) % 97)) % 97
|
||||||
|
|
||||||
|
|
||||||
|
def generer_rib(establishment_code: int, guichet_code: int) -> str:
|
||||||
|
etab = str(establishment_code).zfill(5)
|
||||||
|
guichet = str(guichet_code).zfill(5)
|
||||||
|
numero = "".join(random.choices(string.digits, k=11))
|
||||||
|
checksum_digits = f"76{etab}{guichet}{numero}"
|
||||||
|
cle = str(_checksum(checksum_digits)).zfill(2)
|
||||||
|
return f"FR76 {etab} {guichet} {numero} {cle}"
|
||||||
|
|
||||||
|
|
||||||
|
def valider_rib(rib: str) -> bool:
|
||||||
|
parts = rib.replace("FR76 ", "").split()
|
||||||
|
if len(parts) != 3:
|
||||||
|
return False
|
||||||
|
etab, guichet, rest = parts
|
||||||
|
if len(etab) != 5 or len(guichet) != 5:
|
||||||
|
return False
|
||||||
|
if len(rest) != 13:
|
||||||
|
return False
|
||||||
|
numero = rest[:11]
|
||||||
|
cle = rest[11:]
|
||||||
|
if not etab.isdigit() or not guichet.isdigit() or not numero.isdigit() or not cle.isdigit():
|
||||||
|
return False
|
||||||
|
checksum_digits = f"76{etab}{guichet}{numero}"
|
||||||
|
return _checksum(checksum_digits) == int(cle)
|
||||||
|
|
||||||
|
|
||||||
|
def decoder_rib(rib: str) -> dict:
|
||||||
|
parts = rib.replace("FR76 ", "").split()
|
||||||
|
if len(parts) != 3:
|
||||||
|
return None
|
||||||
|
etab, guichet, rest = parts
|
||||||
|
numero = rest[:11]
|
||||||
|
cle = rest[11:]
|
||||||
|
etab_int = int(etab)
|
||||||
|
guichet_int = int(guichet)
|
||||||
|
|
||||||
|
TYPE_MAP = {4: "particulier", 3: "entreprise", 2: "banque", 1: "institution"}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"etablissement": etab_int,
|
||||||
|
"guichet": guichet_int,
|
||||||
|
"numero": numero,
|
||||||
|
"cle": int(cle),
|
||||||
|
"type_compte": TYPE_MAP.get(guichet_int, "inconnu"),
|
||||||
|
"est_gouvernement": etab_int < 100,
|
||||||
|
"valide": valider_rib(rib),
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue