Capstone 9 · Backend

Susu

A susu, also called a tontine, an ajo or a partner hand, is a rotating savings association: a group contributes a fixed amount each period, and each period one member receives the pot. It has funded businesses, homes and passages across West Africa and the Caribbean for generations, entirely on trust and record-keeping. Build the record-keeping as a service. Groups, members, a contribution schedule, a payout order, and a complete audit trail. No frontend required; this is an API and a data model. The difficulty is correctness. Money must never be represented as a floating point number. A contribution recorded twice must not count twice, which means idempotency. Two requests arriving at the same moment must not both take the same payout slot, which means the database has to enforce it rather than your code remembering to check. Every balance must be derivable from the ledger rather than stored and hoped for, so any disagreement is detectable. If you can demonstrate that your service survives duplicate requests and simultaneous ones without ever producing a wrong balance, you have built something most working developers would take seriously.

Concepts used

Data modelingTransactions and isolationIdempotencyMoney handlingAudit trailsAuthorizationAPI designTesting

Your dataset

Seeded groups and members, plus a generated history long enough to test a full rotation.

Milestones

1Model groups, members, contributions and payouts, with money as integer minor units or a decimal type.
2Make every balance a derivation from the ledger, never a stored total.
3Add idempotency keys, so a repeated contribution request is recorded once.
4Enforce one payout per period per group in the database, not in application code.
5Prove it: fire the same request twice concurrently and show exactly one takes effect.
6Add authorization, so a member sees only their groups and only an organizer can record a payout.
7Build the audit trail: who did what, when, and what the balance was afterwards.
8Write the API documentation, and a reconciliation endpoint that recomputes every balance from scratch and reports any disagreement.

The graded core

The rest of this project is yours to shape. This one function is the piece everything else depends on, so it runs against hidden tests to prove it is right before you build outward.

◈ Graded Challenge

Balances are derived, never stored. Write balance(entries) returning a member's balance in minor units from a list of ledger entries, each a dictionary with kind and amount. A "contribution" adds, a "payout" subtracts, and a "fee" subtracts. Any other kind is ignored rather than raising, because a ledger gains new entry kinds over time and an old reader must not fall over. An empty ledger balances zero.

Name it exactly: balance(entries)

Python3 visible + 4 hidden
loading editor…

Your workspace

Build the full project here. Work through the milestones in order, in both languages.

SANKOFA SANDBOX
loading editor…
Your turn → Build it in Python first, then rebuild it in JavaScript. The logic transfers, only the syntax changes.
← All projectsNext: The Switchboard →