Food import and wholesale trade — the local market · Deployed and running
Zad Al-Khair
An Arabic web system that follows an imported shipment from the order until its price is collected, and holds trade debt in gold instead of pounds so inflation does not eat it.
- System type
- Internal operations system (imports · inventory · credit sales · treasury · reports)
- Our role
- Full build — operations discovery, engineering, deployment

An internal operations system covering imports, inventory, credit sales, cash accounts and reports as a single chain: every clearing expense is posted as a ledger entry and immediately raises the landed unit cost, goods are sold out of a named inventory batch, and each invoice is measured in gold grams on its issue day and settled at the gold rate of each payment day. The interface is Arabic and right-to-left in its structure, and runs with the same capabilities on desktop and phone.
- 18
- screens
- 21
- database tables
- 44
- server actions
- 39
- indexes and unique constraints
- 11
- database CHECK constraints
- 27
- automated tests, all passing
- 12,318
- lines of code
- Sector
- Food import and wholesale trade — the local market
- System type
- Internal operations system (imports · inventory · credit sales · treasury · reports)
- Coverage
- 18 screens, 7 API routes, 21 tables
- Users
- Two roles: owner (all permissions) and staff (daily operation)
- Language and direction
- Fully Arabic, right to left (RTL) — not a translation layer over an English interface
- Devices
- Desktop and phone — the same system, with no cut-down version
- Currency and time
- Local currency · local time zone · Gregorian dates DD/MM/YYYY
The problem before the system
The trader imports 18 products — beans, rice, oils, spices and salt — from overseas suppliers as well as local ones. The problem was never selling. It was three gaps that cost him real money.
Read the detailHide the detail3 points
- The real cost of a shipment was unknown until it ended.
- — A single shipment passes through customs, the port quay, the chamber of commerce, the food safety authority and transport — each expense paid on a different day and recorded on a different sheet or spreadsheet. The true price per kilo only appeared once the papers were added up by hand, usually after the goods had already been sold at a price set by guesswork.
- The books were spread across separate notebooks and spreadsheets.
- — One notebook for customers, one file for shipments, another for expenses — and figures moved between them by hand. Every transfer was a chance to make a mistake, and there was no single truthful copy.
- Selling on credit lost its value silently.
- — The trader sells on 30 to 90 day terms. When the exchange rate and inflation move during the term, the same amount comes back with less purchasing power. His workaround was to convert the invoice into its gold equivalent on a calculator, write the number in the margin of the notebook, and redo the arithmetic by hand with every partial payment. The idea was right, but it was slow, error-prone, and nobody could audit it later.
Understanding the trade before writing the code
Read the detailHide the detail
We started from one question: what makes this business profit or lose? The answer was two numbers — the landed unit cost after every expense, and the value of a receivable on the day it is collected rather than the day it was issued.
So we built the system around those two numbers rather than around data-entry screens. Every structural decision serves one of them: shipment expenses are real financial entries attached to the shipment, so they appear in the cost and in the ledger at once with no double counting; and every gold conversion is stored at the rate in force the moment it happened, so today's price never changes a past effect.
The system is not a set of independent screens but one chain in which each link feeds the next: the shipment is ordered, clears the port, leaves it, enters the warehouse — each clearing expense being posted and added to the cost. Landed unit cost = (purchase price + all expenses) ÷ quantity. It becomes an inventory batch at that cost; a sale is made from a specific batch and the quantity leaves stock immediately; the invoice is measured in gold at issue — invoice grams = total ÷ the price of a gram of 24k that day; each payment settles at its own day's price — grams settled = amount paid ÷ the gram price on the payment day; and what remains is remaining grams, valued in pounds at today's rate.
The practical consequence: an invoice may be settled with more pounds than it was issued for, and that is correct. In the demo data shown, an invoice issued at EGP 297,500 was settled by two payments totalling EGP 305,800 — the difference is not a surcharge on the customer, it is the same weight of gold he took on the purchase day, priced on the payment day.
Engineering decisions
The rules the core enforces, and the choices that follow from them.
Read the detailHide the detail11 points
- 01
No selling out of thin air
Every sale line is tied to a real inventory batch, the quantity leaves stock the moment the invoice is issued, and it returns in full if the invoice is cancelled.
- 02
The rate used is stored, never recomputed
The gold price on the invoice's issue day, and the price on the day of each payment, are both fixed records. A change in today's price does not touch a letter of the past.
- 03
Amounts are never computed in floating point
All money and gram arithmetic runs through exact Decimal: money to two places, grams to three.
- 04
An invoice with payments cannot be deleted
Deletion is available only for what nothing has touched yet, so an existing financial trace cannot be wiped out.
- 05
A shipment expense is a single entry
It appears on the shipment page and in the ledger at the same time — not two records that can drift apart, and no double counting in the totals.
- 06
Paying the supplier does not enter the import cost
The purchase price is already recorded on the shipment — a decision that stops the same money being counted twice.
- 07
Units carry a physical dimension
Mass (kg/tonne) and volume (litre) never mix; an unknown unit returns 'no measure' instead of assuming kilograms — a missing number is safer than a wrong one that looks right.
- 08
Weight is shown in tonnes above a tonne and in kilograms below it
The trader's language, not the database's.
- 09
The gold price comes from the local market
With an automatic fallback to the global price if the source fails, and then to the last known price — the service never blocks the issuing of an invoice.
- 10
A sudden-jump valve
Any price reading more than 15% away from the last known price is rejected automatically — protection against a faulty scrape that looks plausible after the source's markup changes.
- 11
An honest 'live' indicator
It only goes green when the price really is local and current, and it tells the user plainly when the price is global or stale.
Platform-level guarantees
Protection sits in the layer that cannot be bypassed, not in the interface alone.
Read the detailHide the detail7 points
Constraints in the database itself
11 CHECK constraints prevent negative quantities and amounts.
Idempotency keys
They stop an invoice or a shipment being created twice on a double click or a weak connection.
Session invalidation at the root
A session version number lives in the database; incrementing it drops every previously issued token on every device at once.
A limit on sign-in attempts
A time window applied to the identifier and to the network address together.
Indexing built for the queries that exist
39 indexes and unique constraints on the columns that are actually searched and sorted, plus a permanent serial number for the ledger that is displayed without an expensive recount on every view.
Automatic daily backup
To cloud storage, keeping the last 60 copies, with restore from inside the system and a full export at the press of a button.
An audit log
It records who performed any sensitive operation, when, and on which entity — on a best-effort basis, so a failure to record never blocks the operation itself.
Arabic, RTL and responsiveness
The interface is fully Arabic and right-to-left in its structure, not by visual mirroring — and the system runs on a phone with the same capabilities.
Read the detailHide the detail4 points
- Navigation, tables, forms and printed documents are all built on dir="rtl" and logical properties (padding-inline-start rather than padding-left).
- Numbers, dates and codes are forced into Latin direction inside Arabic text so they do not flip.
- Wide tables scroll inside their own container instead of breaking the page, and navigation becomes a sliding side menu.
- A dark mode (the default) and a light mode are built on colour variables, and the choice is saved for the user.
Sales on the phone
Governance and traceability
Read the detailHide the detail
Two roles with different permissions: the owner holds deletion, restore, user management and transfers between cash accounts; staff run the day (selling, collecting, shipments, expenses) and hold none of those. The same URL yields two different interfaces — the permission governs what is built, not what is visually hidden.
The activity log shows the time, the user, the type of operation and a short summary.
Every number can be traced back to its source: from the debt to the invoice, from the invoice to the inventory batch, from the batch to the shipment, and from the shipment to its clearing expenses.
The screens
32 screensThe software is real; the data shown in the screenshots is not. Every name and figure in these images is generated demo data: suppliers, customers, warehouses, bank accounts, phone numbers, tax numbers, amounts and gold prices are all invented, created on a completely isolated local database with no connection to the production database — which was never read. What is real: the software itself (a production build, with its screens, calculations and behaviour unchanged), the business name and logo, the product names taken from the business's real catalogue, the system-size figures measured from the repository, and the test results.
The full cycle — from order to collection
Importing and shipments
Selling linked to gold
Customers and suppliers
The ledger and the cash accounts
Governance and permissions
Printed documents
Signing in
Light mode
What changed
| Before | After |
|---|---|
| A shipment's cost was added up by hand after it ended | The landed unit cost appears instantly with every expense posted |
| Linking an invoice to gold on a calculator, redone with every payment | Conversion and settlement happen automatically, and every rate used is kept as a fixed record |
| Data spread across separate notebooks and spreadsheets | One truthful copy: 21 linked tables behind 18 screens |
| Knowing who was late meant going through the notebook | Late accounts are flagged automatically with the number of days late and sorted first |
| The cash balance was a mental estimate | A balance derived from the movements themselves, with a running statement that can be checked line by line |
| A backup whenever someone remembered | An automatic copy every dawn, keeping the last 60 |
This table describes a change in capability — what the system is now able to do — not measured gains. There is no documented before/after measurement of time saved or errors avoided, so no percentage is claimed.
The numbers
System size
- Screens
- 18
- API routes
- 7
- Database tables
- 21
- Migrations applied
- 8
- Indexes and unique constraints
- 39
- CHECK constraints in the database
- 11
- Server actions (across 10 files)
- 44
- UI components
- 19
- Lines of application code
- 12,318
- Lines in the data model
- 424
- Unique Arabic strings in the interface
- 898
- Automated tests, all passing (across 4 files)
- 27
Measured from the repository with re-runnable commands, not estimated. Date of measurement: 30 July 2026.
Test run
- goldProvider
- 5
- goldSettlement
- 7
- landedCost
- 9
- formatQty
- 6
- Run time
- 679 ms
npx vitest run, 30 July 2026: 4 files passed, 27 tests passed. Coverage: the import cost engine, the gold linking and settlement engine, the gold price provider, and quantity formatting.
Size of the demo dataset
- Suppliers
- 6
- Customers
- 14
- Warehouses
- 3
- Cash accounts (cash and bank)
- 3
- Shipments
- 14
- Inventory batches
- 10
- Inventory movements
- 53
- Supplier invoices
- 14
- Sales invoices
- 28
- Sale lines
- 41
- Customer payments
- 30
- Ledger entries
- 127
- Days of gold prices
- 151
- Audit log entries
- 20
- Categories
- 25
These are not real operating figures. They are the size of the generated data that appears in the screenshots, listed for transparency only, and counted with SELECT count(*) on the local demo database.
Next




