How the per-line ledger and the document numbering are designed
The core record in the plan is a Line: one item from the master, placed in one project. A supplier PO, a consignment, a site receipt, a daily report and a measurement are all events that happen to lines.
The ledger
| Column | Moves when |
|---|---|
| Sold | the client's PO or an amendment PO is captured |
| Ordered | a supplier PO is sent or amended |
| Dispatched | a consignment leaves a vendor |
| Received | the site engineer confirms it at the gate |
| Consumed | a daily report is filed |
| Invoiced | a client invoice is issued |
| Measured | the joint measurement sheet is signed |
None of these is stored by hand. One function, ledger.recompute(line), derives them from events and caches the result for the dashboards. The balances people ask about — to order, in transit, on site, to invoice — are computed on screen and never saved. Quantities are integer thousandths of the item's unit and rates are integer paise, so a line's value is always computed.
The model expects numbers that do not add up neatly: one line bought on two POs at two rates, a short receipt, a local purchase topping up consumption, a measured length longer than what was sold. Each is an event with a date, a person and a document.
Financial-year numbering and GST
Every outbound document is numbered FTX/<KIND>/<FY>/<NNNNN> from a sequence per kind per financial year (1 April to 31 March, Asia/Kolkata). A document takes the year of the moment it is sent, not drafted, and the number is taken atomically inside the send step, so a draft never holds one. A gap is acceptable; a duplicate never is. Offers and POs revise with an -R<n> suffix, and the as-sent PDF is kept with its hash.
GST is one module: the two parties' states decide CGST plus SGST or IGST per line, in paise, with the round-off as its own line. Legal e-invoicing stays outside: the invoice is exported and the IRN and QR are typed back in.

















