Article technique · Tontini
Tontini : les places, le calendrier et le journal d’une tontine
Tontini est une application de tenue de tontine, dans laquelle un organisateur constitue son cercle, fixe la cotisation et l’ordre des tours, puis suit le calendrier des versements et l’historique des opérations.
- Rôle
- Auteur unique de l’API et de l’application
- Période
- De juin 2024 à décembre 2025, pour l’essentiel en juillet 2025
- État
- Prototype. Prototype non publié, sans paiement intégré
- Technologies
- Django 4.2, Django REST Framework, PostgreSQL 15, Flutter, flutter_bloc
- Dépôts
- Deux
Contexte
Une tontine est un cercle d’épargne tournant : chaque membre verse la même cotisation à échéance fixe, et la somme réunie revient à l’un d’eux, à tour de rôle. Tontini en assure la tenue, avec le montant de la cotisation, sa périodicité, l’ordre des bénéficiaires et l’historique de ce qui a été versé.
Une première version, écrite en juin 2024, n’était qu’une maquette alimentée par des données simulées. L’API a été développée en juillet 2025, en quatre journées de travail, et l’application lui a été raccordée dans le même temps.
Problème
L’organisateur connaît les membres de son cercle avant qu’aucun d’eux n’ait installé l’application, et il doit pouvoir préparer la tontine entière sans les attendre. L’ordre des tours change par ailleurs souvent avant le premier versement, lorsqu’un membre s’ajoute ou demande à passer plus tôt, et le calendrier doit suivre sans que personne ait à le corriger date par date.
Réponse apportée
Une place plutôt qu’un compte
Un membre est d’abord une place dans le cercle, qui porte un nom, une position et un code d’invitation, et qui n’est rattachée à un compte que plus tard. L’organisateur crée ainsi toutes les places d’emblée, puis transmet à chacun son code, sous la forme d’un texte, d’un code QR ou d’un lien. L’adhésion se fait en deux appels : le premier montre le groupe correspondant au code, le second rattache le compte à la place.
Un calendrier reconstruit à chaque changement
Le calendrier des versements est conservé en base, à raison d’une ligne par bénéficiaire, et il est supprimé puis recréé après chaque modification du groupe ou de ses membres. La date de chaque versement se déduit de la position du membre et de la périodicité, et son montant du produit de la cotisation par le nombre de membres. Dès qu’un premier versement est confirmé, le calendrier n’est plus régénéré.
members = Member.objects.filter(group=group).order_by('position')
amount = group.contribution * members.count()
try:
paid_distribution = Distribution.objects.get(is_paid=True, round=current_round, group=group)
except Distribution.DoesNotExist:
distributions = Distribution.objects.filter(round=current_round, group=group)
distributions.delete()
for member in members:
distribution_date = current_round.start_date + get_interval_duration(group.interval, member.position)
Distribution.objects.create(
amount=amount,
date=distribution_date,
currency_code=group.currency_code,
is_paid=False,
position=member.position,
round=current_round,
group=group,
member=member
)Un journal écrit à la confirmation
Lorsque l’organisateur confirme un versement, le serveur écrit le journal d’un seul geste : une opération de distribution pour le bénéficiaire et une opération de cotisation pour chaque membre. L’application ne suit donc pas les cotisations une à une.



