SaraSoft
A commerce and inventory ERP, built for merchants whose network drops for days at a time, then reframed as an international SaaS product. Three deployments over a single database: Django/DRF backend, management application, online storefront. Roughly 60,000 lines of backend, 48,000 of management, 10,000 of storefront, 176 migrations and 107 test files.
Nothing to configure
The intended users are uneasy with a phone, sometimes unable to read: everything is inferred from the data rather than set up. A single-site customer never sees the word “site”. And no individual customer decision is frozen into the code — currency, timezone, VAT and numbering are attributes whose defaults reproduce the existing behaviour.
Functional scope
Twelve Django applications: catalogue and packaging, multi-site inventory with batches, transfers and stock counts, the full sales chain (quote → order → delivery note → invoice → payment → credit note), procurement, customers, expenses, treasury, OHADA accounting (fiscal years, journals, entries, reconciliation), and the product’s own subscription with Orange Money / MTN mobile payment.
Three axes of access, never conflated
Am I allowed? Which records concern me? Has the company paid? Three distinct questions, three mechanisms, three answers: 403 for a denied permission, 404 or a filtered list for scope, 402 for a module outside the plan. Answering 403 for an unsubscribed module would send the administrator ticking boxes that change nothing. Scope applies to writes as much as to reads, and an empty scope grants nothing.
Four locks on tenant isolation
A manager that filters by company, a refusal to write outside the company, row-level security applied through a PostgreSQL migration, and a surface test that walks from every route to the model it serves and demands the company key. The fourth exists because a model lacking that key gave the first three nothing to hold on to — and none of them objected.
Offline without asking anything
The data key is drawn at 256 bits, never derived from a password, and wrapped by a non-extractable device key: a copied browser profile yields nothing but ciphertext. Twenty-two resources are replicated encrypted on the device, and the user is asked for nothing to work offline — the protection must cost them nothing. The fingerprint is a gateway, not an identifier.
A queue of intents, not states
The sync queue carries what the user meant to do: creating then deleting a record offline cancels itself out, the document number acts as the idempotency key, a rejection waits for a human decision, and network silence is never read as a refusal.
A storefront without a cart
The storefront handles neither cart nor order: it connects buyer and seller through a pre-filled WhatsApp link, and the transaction is settled in the conversation. The buyer’s number therefore never reaches the server — no buyer personal data exists in this product. What gets counted is the gesture: viewed, then contacted. A connection is not a sale, and no screen suggests otherwise.