5a8dd21931 feat(reconciliation): page-owned window, automatic matching, and a way out for unbookable rows (#1742)
Second half of the reconciliation redesign, on top of the bridge in #1737.

**Toolbar.** The view hosted its own "Datum från / Datum till" inputs behind a
Filtrera button: a second period control competing with the header's
räkenskapsår picker (convention 8), and the source of a "typed but not applied"
state that needed its own attention line to explain. The window is now owned by
the page, narrowed through the shared ReportDateRange like every other report,
and applied on change. The view holds no date state at all, which also removes
the ref-synchronisation dance and the off-by-one it existed to prevent (a year
switch fetching the previous year's window because the refs updated a commit
late).

Reconciliation opens on the FULL year, not the family default of YTD, and keeps
its own preset memory: a reconciliation runs over a whole räkenskapsår, and
inheriting a "Denna månad" last used on Resultatrapport would show an alarming
difference for a window nobody chose here. ReportDateRange gained defaultPreset
and storageKeyPrefix for that; every existing caller keeps its behaviour.

**Automatic matching.** "Förhandsgranska" told the user nothing about what it
did, and the ochre line above it existed only to point at it: people matched a
whole migration row by row next to a button they never found. The matcher now
runs by itself, once per window+account, whenever there is unmatched work. It is
a dry run, so nothing is written and Tillämpa still requires an explicit click.
The button stays as a re-run and is renamed to what it does. ?autorun=1 keeps a
distinct meaning (run even on a clean window) so the transactions-inbox deep
link still produces a result rather than silence.

**A way out for rows that cannot be paired.** An unmatched bank row that no
voucher on the account could settle is not reconciliation work, it is an unbooked
affärshändelse, and the match picker held nothing for it. Those rows now offer
"Bokför" into /transactions?highlight=<id>, with a bulk link in the section
header. The rule (direction-compatible and equal to the öre) is extracted to
lib/reconciliation/voucher-candidate.ts so it is testable and so the component
never imports the server-only reconciliation module. Deliberately strict: a false
negative offers booking on a row that could also have been paired, which is a
legitimate outcome, while a false positive sends the user into an empty picker.

11 new tests for the candidate rule, covering direction, öre equality, float
noise, PostgREST numeric strings and the foreign-account case where the
candidate RPC projects no FX amount and no match may be claimed.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 13:14:31 +02:00
2026-07-21 23:00:15 +02:00
2026-06-12 16:35:30 +02:00
2026-07-21 23:00:15 +02:00
2026-07-24 15:03:50 +02:00
2026-07-21 23:00:15 +02:00
2026-07-05 03:05:09 +02:00
2026-07-24 15:03:50 +02:00
2026-07-23 16:16:55 +02:00
2026-07-05 03:05:09 +02:00
2026-07-05 03:05:09 +02:00

Accounted

Open-source Swedish accounting software for sole traders (enskild firma) and limited companies (aktiebolag). Double-entry bookkeeping that complies with Swedish accounting law, built to be operated by you or by your AI agent.

License: AGPL-3.0-or-later Core Build pg-real tests Docker

Website · Hosted app · Documentation

Why Accounted?

Compliant by construction. Accounted implements double-entry bookkeeping under Swedish accounting law (Bokföringslagen). Voucher immutability, sequential voucher numbering, period locks, and 7-year document retention are enforced by database triggers, not by convention. Corrections are made the legal way, with reversal entries (storno), never by editing history. See ARCHITECTURE.md for how.

Agent-native. The full bookkeeping engine is exposed as 100+ MCP (Model Context Protocol) tools with scoped API keys, so an AI agent can do the books in Accounted: categorize transactions, draft vouchers, reconcile periods, and prepare declarations. Posting is staged for human approval, so the agent proposes and you decide.

Yours to run. AGPL-3.0 licensed and fully self-hostable with Docker and Supabase. Use the hosted version at app.gnubok.se or run your own.

Features

  • Double-entry bookkeeping -- BAS 2026 chart of accounts, draft/commit workflow, sequential voucher numbering
  • Invoicing -- Create, send, and track invoices with mixed VAT rates and PDF generation
  • Bank reconciliation -- PSD2 bank connection via Enable Banking, 4-pass automatic matching
  • VAT declaration -- SKV 4700 form mapping, per-rate breakdown, EU/export handling
  • Tax reports -- NE-bilaga, INK2, SRU export for Skatteverket
  • Payroll -- Salary runs, payslips, and AGI (arbetsgivardeklaration) employer declarations
  • Supplier invoices -- Registration, payment tracking, input VAT deduction
  • Document archive -- SHA-256 integrity, 7-year retention enforcement, full archive ZIP export
  • SIE import/export -- Standard Swedish accounting interchange format
  • Agent access (MCP) -- 100+ bookkeeping tools over the Model Context Protocol, with scoped API keys and staged approvals
  • Extension system -- Opt-in plugins for AI categorization, receipt OCR, email, calendar, and more

Self-Hosting

git clone https://github.com/erp-mafia/accounted.git
cd accounted
./setup.sh              # Prompts for Supabase credentials, generates .env
docker compose up -d

You need a Supabase project and must apply the database migrations before first use. See docs/SELF-HOSTING.md for the full step-by-step guide, including Supabase setup, auth configuration, optional features (AI, email, push notifications), and troubleshooting.

Development Setup

Prerequisites: Node.js 20+, a Supabase project.

npm install
npm run dev       # Start dev server (auto-generates extension registry)
npm test          # Run tests
npm run build     # Production build
npm run lint      # ESLint

See CONTRIBUTING.md for the full development workflow.

Tech Stack

  • Framework: Next.js 16 (App Router), React 19, TypeScript (strict)
  • Database: Supabase (PostgreSQL + Row Level Security + email/password auth + TOTP MFA)
  • Styling: Tailwind CSS 4 + shadcn/ui
  • Integrations: Enable Banking (PSD2), Anthropic SDK, LangChain, OpenAI, Resend, JSZip

Documentation

Community

Contributing

Contributions are welcome. See CONTRIBUTING.md for the full guide.

All commits require a DCO sign-off (git commit -s).

License

AGPL-3.0-or-later with an extension exception: third-party extensions that interact solely through the documented Extension API may be licensed under any terms, including proprietary. See LICENSE for details and NOTICE for third-party attributions.

S
Description
Accounted — svensk bokföringsmotor (AGPL, BAS 2026, BFL-compliant, 150+ MCP tools). Finance-kapacitet brevet ERPNext. ADR-ENGAGEMENT-001-tillägg.
Readme AGPL-3.0
56 MiB
Languages
TypeScript 93%
PLpgSQL 5.8%
JavaScript 0.4%
HTML 0.3%
MDX 0.2%
Other 0.1%