Who can use this: Owner can do everything; Manager can view but is denied
tax.edit_rateandtax.archive; Accountant can view tax rates and apply taxes to documents but cannot edit rates or archive. URL / Route:
- Tax rates —
/finance/tax-rates(finance.tax-rates.index). Detail:finance.tax-rates.show,edit,update,create,store,destroy,quick-create,toggle.- Tax codes —
/finance/settings/tax-codes(finance.settings.tax-codes.index).- Tax overview —
/finance/settings/taxes(finance.settings.taxes.index).- VAT returns —
/finance/vat-returns(finance.vat-returns.index). Actions:finance.vat-returns.create,store,show,finalize,post-reporting,settle,carry-forward. Plan / feature gates:feature:vat_enabledis the master switch (default: enabled). Reverse charge needsfeature:reverse_charge_enabled(default: off). VAT returns also needfeature:tracker.vat_returns(default: enabled). Permissions:tax.view,tax.apply,tax.edit_rate,tax.archive,tax.codes.view,tax.codes.manage,tax.rates.view,tax.rates.manage. VAT-return permissions:vat_returns.view,vat_returns.create,vat_returns.finalize,vat_returns.post_reporting,vat_returns.settle,vat_returns.carry_forward. Reverse-charge use needstax.reverse_charge. All of the above also requirefeature:vat_enabled(andreverse_charge_enabledfor reverse charge).
Purpose
Solabooks has three layers in its tax model:
- Tax codes — the policy entries (Standard rate, Zero-rated, Exempt, Reverse-charge). Codes group rates and decide how a tax line interacts with the VAT return.
- Tax rates — the actual percentages associated with codes. A "Standard" tax code may carry a 5% rate today and a 10% rate from a future date.
- VAT returns — the periodic reporting cycle where you sum the tax codes by period and produce the return amount due to / claimable from your authority.
Database note: in this build the underlying tables for
Tax,TaxCode, andTaxRateare unified — all three model classes alias the sametaxestable. You do not need to maintain separate tables; older guides that mention three distinct tables refer to a previous schema.
Step by step
Tax codes
Route: /finance/settings/tax-codes. Permissions: tax.codes.view, tax.codes.manage.
- Open the page to see all tax codes.
- Click New tax code to add one. Fields: name, type (Output / Input / Both), behaviour (Standard / Zero-rated / Exempt / Reverse-charge / Out-of-scope), recoverability percentage, default account.
- Edit or toggle visibility from each row.
The setup wizard installs the country's default tax codes. You only need this page for unusual configurations.
Tax rates
Route: /finance/tax-rates. Permissions: tax.rates.view, tax.rates.manage.
- Open
/finance/tax-rates. Each row shows code, label, rate %, effective from, effective to, status. - New rate: click New tax rate. Pick a code, enter the rate %, the effective-from date, and an optional end date.
- Quick create:
finance.tax-rates.quick-createis used by inline pickers when you create an item or invoice and need a rate that does not yet exist. - Edit: click a row. Permission
tax.edit_rateis required (Manager is denied this). - Toggle / archive:
finance.tax-rates.toggle. Permissiontax.archive(Manager denied).
Apply tax on a transaction
Permission: tax.apply. Available on every line of a quote, sales order, invoice, sales receipt, credit note, bill, expense, debit note, refund, and journal entry. Picking a tax code (and the active rate inside it) attaches a tax line to the document; totals recompute live.
Reverse charge
Permission: tax.reverse_charge. Feature flags: vat_enabled AND reverse_charge_enabled.
When reverse-charge is on, a "Reverse-charge" tax code can be picked on supplier bills. The bill posts both an output and an input VAT line in equal amounts so the net to the authority is zero, satisfying the standard reverse-charge mechanism.
VAT return lifecycle
Routes: /finance/vat-returns/*.
- Create a return:
finance.vat-returns.create/store. Permission:vat_returns.create. Pick the period (from a list of un-returned closed periods). - Show the return:
finance.vat-returns.show. Each line shows turnover by tax code, output VAT, input VAT, and the net payable / claimable. Source documents are linked. - Finalize:
finance.vat-returns.finalize. Permission:vat_returns.finalize. Locks the figures so further postings into the period do not change them. The return becomes "Finalized". - Post reporting:
finance.vat-returns.post-reporting. Permission:vat_returns.post_reporting. Records that you have submitted the return externally (e.g. uploaded to your tax authority's portal). Optionally writes the receivable / payable journal. - Settle:
finance.vat-returns.settle. Permission:vat_returns.settle. Records the actual payment made or refund received against the VAT control account, closing out the return. - Carry forward:
finance.vat-returns.carry-forward. Permission:vat_returns.carry_forward. If the period closed in net credit, you can roll the credit into the next period instead of claiming a refund.
VAT detail report
Route: /finance/reports/vat-detail-by-rate (finance.reports.vat-detail-by-rate). Permission: gated on vat_enabled (per the permission map). PDF: finance.reports.pdf.vat-detail-by-rate. Use this to see every tax-bearing line by rate for a date range.
Worked examples
Standard 17% VAT on a JOD 100 sale:
| Account | Debit | Credit |
|---|---|---|
| AR — Customer control | 117.00 | |
| Revenue — Sales | 100.00 | |
| VAT Output | 17.00 |
The JOD 17 contributes to "Output VAT" on the VAT return.
Standard 17% VAT on a JOD 100 purchase, fully recoverable:
| Account | Debit | Credit |
|---|---|---|
| Expense | 100.00 | |
| VAT Input (Recoverable) | 17.00 | |
| AP — Supplier control | 117.00 |
The JOD 17 contributes to "Input VAT" on the VAT return and reduces the net payable.
Zero-rated sale of JOD 100 (e.g. export): no VAT lines at all — the sale still appears on the return as zero-rated turnover for reporting, but there is no Output VAT to remit.
| Account | Debit | Credit |
|---|---|---|
| AR — Customer control | 100.00 | |
| Revenue — Sales | 100.00 |
Exempt sale of JOD 100 (e.g. some financial services): like zero-rated, no VAT collected, but the sale is reported in a different box and input VAT on related purchases is NOT recoverable.
Partially-recoverable VAT — JOD 100 expense + JOD 17 VAT, only 50% recoverable:
| Account | Debit | Credit |
|---|---|---|
| Expense | 100.00 | |
| VAT Input (Recoverable) | 8.50 | |
| Expense (non-recoverable VAT gross-up) | 8.50 | |
| AP — Supplier control | 117.00 |
The non-recoverable half is added back to the expense account — the full JOD 117 hits P&L.
Reverse charge on a JOD 100 imported service (output and input cancel out, net payable to authority = zero):
| Account | Debit | Credit |
|---|---|---|
| Expense | 100.00 | |
| VAT Input (Recoverable, reverse charge) | 17.00 | |
| VAT Output (reverse charge) | 17.00 | |
| AP — Supplier control | 100.00 |
Both VAT lines show on the VAT return — output in the reverse-charge box, input in the recoverable box — netting to zero cash impact.
A VAT-return period summary (illustration):
| Box | Amount (JOD) |
|---|---|
| Standard-rated sales (Output VAT) | 1,700.00 |
| Zero-rated sales | 0.00 |
| Exempt sales (reporting only) | 0.00 |
| Reverse-charge output | 17.00 |
| Total Output VAT | 1,717.00 |
| Standard purchases (Input VAT, recoverable) | 850.00 |
| Reverse-charge input | 17.00 |
| Total Input VAT | 867.00 |
| Net payable to authority | 850.00 |
Common mistakes
- "Tax line doesn't appear on a document." Check the line's tax code is set — every line carries its own. A blank tax code means "no tax". If new documents always miss tax, set a default on the customer / supplier record.
- "Reverse-charge isn't an option." Reverse charge needs both
feature:vat_enabledANDfeature:reverse_charge_enabledon for the org. Check at Settings. - "VAT return is locked but I need to add a transaction in that period." Finalized returns block new postings in their period. Either edit the return back to Draft (with
vat_returns.finalizepermission), or post in a later period and accept it in the next return. - Rate change mid-period. Tax codes don't expire — rates do. When a rate changes (e.g. 16% → 17%), add a new rate with the new effective-from date; existing documents keep their original rate.
- Non-recoverable VAT confusion. Non-recoverable VAT is added back into the expense account, not the recoverable VAT account. Check the tax code's Recoverability % if a bill's input-VAT figure doesn't match what you expected.
- Negative VAT return ("you're owed money"). Don't claim a refund every period — use Carry forward to roll the credit into the next period instead, especially if you expect output VAT to outweigh input VAT soon.
Tips
- The VAT Detail by Rate report under Reports breaks down every tax line by code for a date range — use it before finalizing a return to spot misclassifications.
- For a reverse-charge bill, the output and input VAT cancel out to zero cash impact — the bill itself doesn't ask for a separate VAT payment.
Behaviour and rules
- Tax codes don't expire. Rates do — a code carries multiple rates with effective-from/to dates.
- VAT-return blocking. Once a return covers a period and is Finalized, postings into that period are blocked unless the period is unlocked first.
- Reverse charge lines do not contribute to the tax payable but do show on the VAT return for the relevant boxes.
vat_enabledglobal gate. Withvat_enabledoff for the org, alltax.*,tax.codes.*,tax.rates.*,vat_returns.*, andreports.vat.*permissions are denied via the permission map. The org can still use the app, but no tax lines are produced.- Multiple tax authorities. Not currently supported in this build — there is one VAT regime per organization.
- Tax archive vs delete. Use Archive (toggle) to hide a rate. Hard delete is allowed only when no transaction has used the rate.
Permissions / restrictions
- View tax pages:
tax.view,tax.codes.view,tax.rates.view. - Apply tax on a document:
tax.apply. - Edit a rate:
tax.edit_rate(Manager denied). - Manage codes:
tax.codes.manage. - Manage rates:
tax.rates.manage. - Archive a rate:
tax.archive(Manager denied). - Reverse charge:
tax.reverse_charge(requires both flags). - VAT-return actions:
vat_returns.view/create/finalize/post_reporting/settle/carry_forward.
Related
- Setup wizard — initial tax setup
- Invoices, Bills, Expenses — where tax lines actually post
- Reports — Tax, VAT Detail by Rate
- Fiscal years and lock dates — how periods interact with returns
- Settings