Help & User Guide
A complete reference for the Ledger accounting system.
Core concepts
| Double-entry | Every transaction has at least one debit line and one credit line that sum to the same amount. |
| Normal balance | Assets & Expenses increase with Debit. Liabilities, Equity & Revenue increase with Credit. |
| Reference | Auto-generated ID for each entry (e.g. JUR-20250315-001). Used for searching and linking. |
| Project | Tag entries to a construction project for cost-tracking. Projects can be nested (sub-projects). |
| Document | Group imported entries under a source statement, invoice, or receipt. |
Trial Balance
Home dashboard — quick health check of all accounts.
The Trial Balance lists every account with its debit and credit totals for the selected period. The bottom of the page shows whether the ledger is in balance (debits = credits). An imbalance means a posting error exists somewhere.
How to use
- Open the app — Trial Balance is the home page.
- Optionally set a From and To date to view a period subset.
- Click any account code or name to drill into its full Ledger.
- If totals show Out of balance, check recent entries in the Journal.
Journal
Complete chronological log of all posted transactions.
What you see
Each row shows: date, reference, description, debit total, credit total, source badge (MANUAL or POS), and any linked document / project. 50 entries per page.
Actions
- Expand a row — click the reference to see all line items. Account names are clickable links that jump to that account's ledger.
- Search — type a reference, description, or account name in the search box.
- Filter by date / source — use the filter controls at the top.
- Edit — click the pencil icon to change date, description, or lines (entry must remain balanced).
- Assign Document / Project — use the dropdown fields in the expanded row. You can also assign a project to each individual line item — useful when a single payment covers multiple projects (see Projects).
- Reverse — creates a new offsetting entry (original is kept).
- Delete — permanently removes the entry.
New Entry
Manually post a journal entry from scratch.
Step-by-step
- Click New Entry in the sidebar.
- Set the Date (defaults to today).
- Optionally add a Description / memo.
- Optionally link to a Document and/or Project.
- Add at least two line items:
— Select an account
— Enter either a Debit or Credit amount (not both)
— Add a line memo if needed - Keep adding lines until debits = credits. The balance indicator turns green when the entry is balanced.
- Click Post Entry.
Ledger (Account Drill-Down)
All transactions for a single account with running balance.
Access the ledger by clicking any account code in the Trial Balance, Journal, or Chart of Accounts.
Features
- Running balance — each row shows the cumulative balance after that transaction.
- Date & text filter — narrow to a period or search by reference / description.
- Pagination — 100 transactions per page. Use « First, ← Prev, Next →, Last » in the top bar to navigate. The date range of the current page is shown alongside the page counter.
- Breadcrumb navigation — the account heading shows its full path (e.g. Bank › Savings › Sampath Coll 3887). Click any ancestor segment to see a dropdown of its immediate child accounts and jump to one without going back to the menu.
- Expand a row — click any row to see the full entry. Account links in the expanded detail (code and name) jump to that account's ledger and land on the exact page and transaction automatically.
- Counter accounts inline — each row shows the counter-account names in the empty column (debit row → counter names in credit column, and vice versa). Click any counter-account name to jump directly to its ledger at the correct page and transaction.
- Quick entry — click + New Entry at the top to open a mini form. Enter date, DR/CR side, amount, counter-account, and optional description without leaving the ledger.
- Edit & Delete — expand a row, then use Edit to change date, description, or lines (must stay balanced), or Delete to permanently remove the entry.
- Breakdown by account — the collapsible panel above the table shows which counter-accounts appear most. Click any card to jump to that account's ledger.
Chart of Accounts
Define the structure of your ledger.
Account types
| Type | Normal Balance | Examples |
|---|---|---|
| ASSET | Debit | Cash, Bank, Accounts Receivable |
| LIABILITY | Credit | Accounts Payable, Loans |
| EQUITY | Credit | Owner's Capital, Retained Earnings (3900) |
| REVENUE | Credit | Contract Income, Service Revenue |
| EXPENSE | Debit | Materials, Labour, Subcontractors |
Creating an account
- Click Chart of Accounts in the sidebar.
- Click + New Account.
- Enter a unique Code (e.g.
1010), a Name, and select the Type. - Optionally set a Parent account to create a sub-account hierarchy.
- Click Create.
Moving accounts
To relocate an account — and its entire subtree of sub-accounts — to a different parent, click the Move button on the account row. A panel opens below the row with a searchable parent selector. Pick the new parent and click Move Here. To promote the account to top-level (no parent), clear the selector and click Move Here. The system prevents circular moves (e.g. moving a parent into one of its own descendants).
Full hierarchical names
Account names are always shown with their full path from the root of the tree, separated by ›. For example, a sub-account named Salaries under Operating under Expenses displays as Expenses › Operating › Salaries everywhere in the app — in dropdowns, journal entry lines, ledger rows, and project entries. This makes it unambiguous which account you are looking at without needing to know the code.
Customising the default account list
The default Chart of Accounts is defined in apps/api/prisma/accounts.ts. Edit that file to add, remove, or rename accounts for a new deployment, then run pnpm db:seed to apply changes (safe to re-run — existing accounts are upserted, not duplicated). See New Business Instance for the full deployment guide.
Import
Bulk-import transactions from bank exports, PDFs, receipts, or GnuCash files.
Import modes
AI_API_KEY to be configured. Works with Gemini, Groq, or any OpenAI-compatible endpoint.Review step (CSV / PDF / AI)
- After upload the parsed rows are shown. Check dates and amounts look correct.
- Set a default debit account (e.g. your main expense account) for unrecognised rows.
- Click Apply Rules to auto-assign accounts based on your Category Rules.
- For each row, verify or change the debit account. Check/uncheck rows to include or exclude.
- Optionally attach to a Document (name, type, issuer) for record-keeping.
- Click Post Entries.
Documents
Group journal entries under a source document for filing and reference.
A Document represents a real-world paper: a bank statement, a supplier invoice, a receipt. Entries imported together in one batch are automatically attached to a single Document if you choose during import. You can also create Documents manually and link entries via the Journal.
Document types
- Statement — bank or credit card statement
- Receipt — proof of payment
- Invoice — supplier or customer invoice
- Other — anything else
Click a document name to see all its entries and totals. Documents with linked entries cannot be deleted.
Projects
Track costs by construction project, stage, or cost centre — hierarchically.
Hierarchy
Projects can be nested to any depth. Example: Phase 1 — Foundation
└ Excavation
└ Concrete Works
Phase 2 — Structure
The project detail page shows a Cost Breakdown that rolls up all direct and descendant entries — so "Phase 1" total includes Excavation + Concrete Works.
Creating and managing projects
- Click Projects in the sidebar.
- Click + New Project.
- Enter a name, optional description, optional parent, status (Active / Completed), and start/end dates.
Dates are required for Smart Assign Stage 1 (date-range matching). - Click Create.
Assigning entries to a project
There are five ways:
- At posting — select the project in the New Entry or Import form (assigns the whole entry).
- In the Journal — expand an entry and use the Project dropdown (assigns the whole entry).
- Per line — in the New Entry form or Journal edit view, each individual line can carry its own project. This is ideal when a single payment (e.g. a supplier invoice) covers work for two different projects. The project detail page shows the attributed amount — only the lines assigned to that project — marked with an asterisk (*) when it differs from the full entry total.
- From the Project page — use the "Assign Entries" search panel to find entries by keyword and add them.
- Smart Assign — bulk AI-assisted assignment (see below).
Editing & deleting projects
- Click a project to open its detail page, then click Edit.
- A project can only be deleted if it has no direct entries and no sub-projects. Remove or re-assign those first.
Category Rules
Keyword-based rules to automatically categorise entries during import and batch auto-assign.
Three rule types
| Type | When applied | What it does |
|---|---|---|
| Account | Import review screen | If description contains keyword → pre-select that expense account for the row |
| Project | Run Auto-Assign | If description or account names contain keyword → assign entry to named project |
| Document | Run Auto-Assign | If description or account names contain keyword → assign entry to named document |
Managing rules
- Add — select the tab (Account / Project / Document), fill in the keyword and target, click Add Rule. Keywords are case-insensitive.
- Edit — click the ✎ pencil icon on any rule row to edit the keyword or target inline. Press Enter to save or Escape to cancel.
- Delete — click the ✕ button on the rule row.
- Run a single rule — click ▶ Run on any rule to apply just that rule immediately. For Account rules, choose DR or CR to specify which side of the matching entries to update. Tick Override to reassign entries that already have an account assigned.
How Auto-Assign works
Clicking ▶ Run Auto-Assign runs a batch pass over all journal entries. Here is exactly what happens:
- Which entries are scanned — every entry that is missing a project or missing a document. Entries that already have both are skipped entirely.
- What is matched against — for each entry the system builds a search text from the entry's description plus the account names of all its lines, joined together. Matching is case-insensitive substring (e.g. keyword "wool" matches "WOOLWORTHS").
- First rule wins — rules are tested in the order they were created. The first rule whose keyword appears anywhere in the search text is applied. Later rules are not tested for that field once a match is found.
- Project assignment — if the entry has no project and a project rule matches, the entry is linked to the named project. If no project with that name exists yet, it is created automatically.
- Document assignment — same logic independently for documents. A single run can assign both a project and a document to the same entry if separate rules match.
- Never overwrites — existing project or document assignments are never changed. Only null fields are filled.
The result banner shows N tagged to projects, N tagged to documents (N entries scanned). You can run Auto-Assign as many times as you like — it is safe to re-run after adding new rules.
Smart Assign
Bulk project assignment using date-range matching and AI classification — ideal for years of historical data.
Two-stage process
If an entry's date falls within exactly one project's start/end date range, it is auto-matched with certainty. No AI required. Prerequisite: projects must have Start Date and End Date set.
Entries that fall in a period where multiple projects overlap are sent to the AI model in batches. The AI reads the entry description, account names, and candidate project names/descriptions, then returns a project assignment with a confidence rating (High / Medium / Low) and brief reasoning. Prerequisite: AI_API_KEY must be configured.
Workflow
- Set project start/end dates on all projects (Project detail → Edit).
- Open Smart Assign from the sidebar.
- Set the Limit (how many unassigned entries to analyse at once; default 200).
- Click Analyze.
- Review Stage 1 (auto-matched) and Stage 2 (AI suggestions). Uncheck any you disagree with.
- Click Apply Selected. The page re-analyses and shows remaining unassigned entries.
- Repeat until satisfied. Unmatched entries can be assigned manually via the Journal or Project pages.
Fiscal Years
Year-end closing — zero Revenue & Expense accounts and transfer net income to Retained Earnings.
Why close a year?
In standard accounting, Revenue and Expense accounts are reset to zero at the end of each year. The net profit (or loss) is posted to Retained Earnings (account 3900) in Equity. This lets you see each year's performance cleanly on an Income Statement without prior years' figures mixing in.
Closing workflow
- Ensure all entries for the year are posted and correct.
- Click Fiscal Years in the sidebar.
- Create the fiscal year if it doesn't exist (year number, start date, end date).
- Click Preview Close to see the closing entry that will be posted — debits each Revenue account, credits each Expense account, and posts the net to Retained Earnings.
- Click Close Year (or Confirm & Post from the preview panel) to post the entry.
- The year is now marked Closed. The closing entry reference (e.g.
CLOSE-2024) is shown as a link to the Journal.
Re-opening a closed year
If you find missing records after closing, click Re-open on the year. This posts a reversal of the closing entry (restoring all Revenue and Expense balances), lets you add the missing transactions, then you close again. Re-open is safe — it never deletes anything.
Effect on project costs
Year-end closing does not affect project cost reports. Project costs are accumulated across all years regardless of fiscal periods.
Reports
Income Statement and Balance Sheet.
POS Sync
Automatic polling from a Point of Sale system.
The POS Sync panel lives in the bottom-left corner of every page. It polls the configured POS server at regular intervals and imports new sales transactions automatically.
Status indicators
- ● Connected — polling is active and last poll succeeded.
- ● POS Offline — polling active but POS server unreachable. Shows last attempt time and error.
- ○ Connecting… — enabled but first poll not yet complete.
- ○ Sync disabled — polling is off. Click Enable to start.
Controls
- Enable / Disable — toggle automatic polling on or off.
- Sync Now — trigger an immediate poll without waiting for the next interval.
Imported POS entries appear in the Journal with a POS source badge and can be assigned to projects and documents like any other entry.
New Business Instance
How to run a completely separate copy of the app for a second business.
Each business needs its own database, its own .env, and its own Chart of Accounts. The app is stateless in code — only the database and environment files differ between instances.
Step-by-step
- Set the business name — add
NUXT_PUBLIC_BUSINESS_NAME="Acme Corp"toapps/web/.env. The name appears at the top of the sidebar so you can instantly tell which business you are looking at. - Configure the API — copy
apps/api/.env.exampletoapps/api/.envand set a uniqueDATABASE_URLandPORT(e.g.3004). - Configure the web app — set
NUXT_PUBLIC_API_BASE=http://localhost:3004inapps/web/.envto point at the new API port. - Start a separate database — pass different env vars to Docker Compose:
Both Postgres containers run independently because the host port and database name are different.DB_PORT=5437 POSTGRES_DB=acme docker-compose up -d - Apply schema and seed:
pnpm db:push pnpm db:seed - Customise the Chart of Accounts — edit
apps/api/prisma/accounts.tsto add, remove, or rename accounts for the new business, then re-runpnpm db:seed. Seeding is idempotent — existing accounts are updated, not duplicated. - Start the app — run
pnpm dev(choose a different web port if running both at once).
What each config file controls
| File | What to change |
|---|---|
| apps/web/.env | NUXT_PUBLIC_BUSINESS_NAME and NUXT_PUBLIC_API_BASE |
| apps/api/.env | DATABASE_URL and PORT |
| docker-compose.yml env | DB_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD |
| apps/api/prisma/accounts.ts | Default Chart of Accounts seeded on first pnpm db:seed |
.env files and the running database differ. Use dotenv-cli or shell variable prefixes to switch between environments without editing files.