Mo3anمُعانLead Engineer2024 · built from scratch · Saudi Arabia · Arabic-first
An installment-financing back office on Next.js, Node.js and PostgreSQL with role-based access control. It carries the cycle from client file to contract, schedule, collections and treasury in one Arabic-first system.
Stack: Next.js, React, TypeScript, Node.js, Express, PostgreSQL, Prisma, Socket.io, Docker

A financing office that ran on its employees’ memory
The problem
A client signs a contract, the contract becomes monthly installments, and each installment is either paid on time or slips. Before Mo3an the whole cycle was manual.
The bet was one system for the whole cycle, where every number on screen is the outcome of an accounting entry and not a manual input. That rule is easy to state and expensive to keep. The three decisions below are where it was kept.
| Contracts | Kept in spreadsheets. |
|---|---|
| Collections | Kept in notebooks. |
| Treasury | Nobody knew the real balance without a hand tally. |
| Arrears | Surfaced only when someone asked. |
Three choices, and what each one cost
Decisions
Balances are computed, never typed
| Chose | The treasury has no editable balance. Each payment method’s balance is the running result of its entries: opening capital, collected payments, expenses, transfers between methods, and adjustments recorded with who changed what and why. |
|---|---|
| Over | A stored balance field on each payment method that staff or code update directly. Simpler to build and to read, but once it drifts from the real cash nothing explains the difference. |
| Cost | Nothing can be corrected by typing a new number. Every fix is another entry, and every payment, expense and transfer has to post its own entry rather than adjust a total. |
Contract terms lock when the contract is created
| Chose | Entering the amount, margin, installment count and collection day generates the full schedule with dates and amounts. From then on the financial fields are read-only, because changing them would corrupt the schedule the client committed to and break consistency with recorded payments. |
|---|---|
| Over | Editable contracts that regenerate the schedule on every change, which is friendlier to staff but has to reconcile a new schedule against payments already recorded. |
| Cost | Terms cannot be corrected in place on an active contract. Only the guarantor, notes and status stay editable, and a reduction in what the client owes goes through an approved discount that adjusts the remainder without touching the original schedule. |
Permissions enforced on the server, mirrored in the interface
| Chose | Fine-grained permissions, granted per user from the settings screen and checked in dedicated middleware at every endpoint. The interface hides what a user lacks, but it is a convenience and never the guard. |
|---|---|
| Over | A few fixed roles such as collector, accountant and manager, with the interface deciding what each one sees. Quicker to build and to administer, but any signed-in user who calls the API directly gets past it. |
| Cost | Each permission exists in two places, the endpoint and the screen, and both have to be kept in step. Setting up a new user means granting permissions one by one instead of picking a role. |
One installment, four states
The unit of everything
Clients rarely pay an exact installment. The payment service takes an amount and a method, walks the open installments in order, and can close one while partially opening the next. All of it happens inside one transaction that fully succeeds or fully fails.
Lateness is never recorded by hand. Only the nightly job can mark an installment overdue.
| Moved by payments |
|
|---|---|
| Set by the nightly job only | OverdueCreates an arrears record with the days-late count and updates the client’s risk class. |
Three months in production
Result
| 3M+ SAR ($800K+) | In transactions supported over the first three months of deploymentnote 1 |
|---|---|
| 500+ | Documents generated daily by automated reporting, as PDF and Excel outputnote 2 |
The treasury balance, the arrears list and the client-risk classes are all derived from recorded entries. Every operation leaves an audit entry with the user, the module and the before and after values.
The production system
Real screenshots, all Arabic RTL
From client file to collected installment




Treasury, reports and oversight




By the numbers
Counted from the source
| 71 | REST endpoints in 15 modules |
|---|---|
| 23 | Data models |
| 35 | Permissions |
| 13 | Screens, all Arabic RTL |
Notes
How each figure on this page is defined
- 1Transactions the platform supported in its first three months of deployment. A transaction total, not revenue.
- 2Documents the platform’s automated reporting generates each day, as PDF and Excel output.