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), }