FullBagAccounting
Cloud accounting for small businesses and the accounting firms that keep their books, from quotation and VAT invoice to balance sheet, in Nepali (Bikram Sambat) and English dates.
Full stack developer, on the team from the beginning
- Role
- Full stack developer, on the team from the beginning
- Platform
- Web app
- Users
- Retail, trading and service businesses, and accounting firms managing several companies
- Stack
- TypeScript, React, Vite, Node.js, Express, Prisma, PostgreSQL, decimal.js, Docker
The problem
Small businesses in Nepal need VAT-ready invoices, books that follow the Nepali fiscal year from Shrawan to Asar, and reports their accountant can work from. Accounting firms keep books for several client companies at once.
FullBagAccounting covers the whole cycle, from quotation to balance sheet, with separate books for each company and dates in both Bikram Sambat and AD.
What it does
Sales and invoicing
Quotations, VAT-ready tax invoices, credit notes, recurring bills, partial payments, credit limits and overdue reminders.
Purchases and expenses
Supplier bills, expenses and payments, with payables tracked by supplier.
Vouchers
Cash/Bank, Journal, Contra and Debit/Credit Note entry, with post-dated cheques, registers, drafts and voids.
Voucher series
Numbers like PV-2083/084-0001 per voucher type, starting again every Shrawan 1. A number is given when a voucher is saved and never changes.
Ledgers
Chart of accounts, ledgers and sub-ledgers. Ledgers are never deleted, only deactivated.
Inventory
Items, units, batches and multiple warehouses, with stock moving automatically with each bill.
Banking
Statement import, reconciliation and cheques.
Currencies
Every ISO 4217 currency the company trades in, at Nepal Rastra Bank's published buying and selling rates.
Financial reports
Profit and loss, balance sheet, trial balance, cash flow, day book, ledgers and receivable/payable ageing, exported to Excel or PDF.
VAT
VAT summaries and sales and purchase registers.
Companies and branches
Accounting firms manage several companies from one login, each with separate books, branches and consolidated reporting.
Control
Roles and permissions, approval steps, a full audit trail, and import of opening balances, customers, suppliers and items from Excel or older software.



School, staff and student names are removed from these screenshots.
How it works
A React app built with Vite and served by nginx talks to an Express API written in TypeScript.
The API uses the same pattern as FullBagERP: a central database that knows every client company, and a separate PostgreSQL database for each one's books, reached through Prisma.
Money is handled with decimal.js rather than floating-point numbers. Exchange rates come from Nepal Rastra Bank's public API and are cached per day.
Hard problems and decisions
Voucher numbers that never repeat
- Problem
- Every voucher needs a number like PV-2083/084-0001: its type, its Nepali financial year, and a sequence. Two people saving vouchers at the same moment must never get the same number.
- What I chose
- The voucher's date picks the financial year. The next number comes from a single INSERT … ON CONFLICT DO UPDATE … RETURNING inside the voucher's transaction. Closed years and full series are refused with a message that says what to do.
- Why
- The database does the increment in one statement, so there is no read-then-write gap for two requests to fall into. Unit, integration and end-to-end tests cover it.
A connection pool deadlock
- Problem
- Under load, the API froze. Each request held a database connection while its handler also queried through Prisma, and both drew from one pool. With enough parallel requests, every connection was held by a request waiting for a second one.
- What I chose
- Prisma now gets its own pool for each company's database, and the API checks at startup that the worst-case number of connections fits the server's budget.
- Why
- A request can always get its second connection. An integration test reproduces the original deadlock, so it can't quietly come back.
Reading Nepal Rastra Bank's rates
- Problem
- NRB publishes official buying and selling rates, but quotes some currencies per 10 or 100 units, and its API answers HTTP 200 even when something went wrong.
- What I chose
- Rates are normalised to one unit. The response body decides the outcome: an empty day is a 404, a refused or unreachable call is a 502. Each day's rates are cached for an hour.
- Why
- Accountants see either the real rate or a clear error, never a silently wrong number.