* fix(transaction): enforce valid date range for transactions and add database constraint
* fix(transaction): implement server-side validation for transaction dates and enhance error handling
* feat: add user locale preference to user_preferences table
- Introduced a new column 'locale' in the user_preferences table to store per-user UI language preferences.
- Added a CHECK constraint to ensure only supported locales ('sv', 'en') are allowed.
- Triggered a schema reload notification for the changes.
chore: declare CSS module support in TypeScript
- Added a declaration for CSS modules in globals.d.ts to enable TypeScript support for importing CSS files.
* feat: add Swish as an invoice payment method in company settings
* fix: consolidate commit_journal_entry to single 4-arg signature
Replaces the phantom-overload drop migration with an idempotent consolidation
that leaves only the 4-arg-with-defaults signature, callable with either 2 or
4 named args. Fixes the "Could not choose the best candidate function"
ambiguity caused when the commit-metadata migration CREATE OR REPLACE'd a
4-arg version alongside the existing 2-arg one.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: preserve SIE source voucher identity on journal entries
Adds source_voucher_series / source_voucher_number columns to journal_entries
so per-verifikat traceability survives the importer's skip-empty-voucher
logic. The SIE importer populates the original series/number even when
skipped vouchers cause gnubok's target numbering to drift from the source
file's sequence. Required for BFNAR 2013:2 kap 8 behandlingshistorik.
- Migration adds columns + partial index + extends immutability trigger
- importVouchers() records rawSeries/rawNumber per voucher
- JournalEntry type + test fixtures gain the new fields
- Bookkeeping detail page surfaces "Ursprungligt verifikat" when present
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: polish invoice-inbox workspace for production use
- Bedrock image fit: shrink images > 5 MB via sharp before Bedrock upload
so HEIC/high-res phone photos don't fail with the 5 MB cap
- Swedish error mapping: toSwedishInboxError translates Bedrock /
infrastructure errors to Swedish sentences stored in error_message
- History timeline endpoint (GET /items/:id/history) returns the
processing_history events correlated to the inbox item
- Workspace UI: inline diagnostic timeline inside the convert dialog,
same-email row grouping ("+N dokument" chip), inferred-VAT affordance
with "needs review" signalling, Riksbanken exchange-rate prefill for
foreign-currency invoices so the supplier-invoice create path populates
*_sek audit columns
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: extend inbox-smart-match to supplier invoices
Both receipts and supplier invoices expose structurally identical match
anchors (date, amount, currency, counterparty name) so the matcher can
reuse the same narrowing + LLM prompt. Adds getMatchAnchors() as a shared
extractor across ReceiptExtractionResult / InvoiceExtractionResult, and
updates the event handlers to process supplier_invoice items alongside
receipts. LLM prompt re-phrased as "dokument" rather than "kvitto" and
loosened the date-window heuristic since invoice payments can lag behind
the invoice date by weeks.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: drop unused category selector from TransactionForm
The manual "Lägg till transaktion" dialog predates the current categorization
flow (SwipeCategorizationView, BatchCategorySelector, AI suggestions). The
category dropdown here never drove journal-entry creation — onSubmit fanned
it out to CreateTransactionInput.category, which is optional. Removes the
dropdown, the unused watch() hook, and the categories lookup table.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(migrations): restore drop-phantom file and rebump timestamps
Supabase branch DB failed with PK violation on schema_migrations because
my two migrations collided with timestamps already on main:
20260421120000 → journal_entries_with_related_rpc (PR #298)
20260421130000 → drop_legacy_supplier_invoice_user_id_uniqueness (PR #296)
Rebumped to 20260421140000 and 20260421150000 so each migration has a
unique version (Supabase uses only the 14-digit prefix as the PK).
Also restored the 20260420130000_drop_phantom_commit_journal_entry_overload
migration I had deleted — CLAUDE.md rule #5 forbids modifying existing
migrations. My consolidate migration is still compatible: drop_phantom
drops the 4-arg overload (no-op where absent), then consolidate recreates
it with defaults.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(inbox-smart-match): anchor invoices on dueDate with wider window
The original ±7d window around invoiceDate filtered out all real payments
for invoices with standard 30–60 day terms — the matcher would see zero
candidates before the LLM was called, making the supplier-invoice matcher
effectively dead.
New anchor selection:
- Receipts: receipt date ±7 days (unchanged; paid on the spot)
- Invoices with dueDate: dueDate ±14 days (covers early/late payments)
- Invoices without dueDate: invoiceDate -7/+45 days (covers 30-day terms)
MatchAnchors now carries windowDaysBefore/After so the window can vary per
document shape. Added three getMatchAnchors tests asserting window sizes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: MCP OAuth 303 redirect, send dialog auto-close, bank details null payload
- OAuth authorize: use 303 See Other instead of default 307, which
preserved POST method and caused Claude's callback to return 405
- SendInvoiceDialog: close dialog and show toast after email send
instead of leaving a success message that requires manual close
- BankDetailsSetupDialog: omit empty fields from payload instead of
sending null, which fails Zod validation on non-nullable schema fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: remove dead sentMessage state and fix stale comment
Remove sentMessage state, its success banner JSX, and the CheckCircle2
import — all unreachable after the dialog now auto-closes on email send.
Fix stale "to null" comment in BankDetailsSetupDialog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: support Nordea Business CSV variants, polish API keys UI, fix transaction categorization
- Extend Nordea Business bank file parser to handle three CSV export
formats (classic, Betalare/Mottagare variant, Bokföringsdatum variant)
with proper detection guards against SEB/LF misidentification
- Rework ApiKeysPanel: add CopyBlock component, destructive confirm on
revoke, collapsible API-key-based connection methods, Claude.ai OAuth
instructions as recommended path, simplified scope badges
- Stop deriving is_business from category on manual transaction creation;
set null so categorization flow handles it correctly
- Show categorize button when journal_entry_id is missing regardless of
is_business value
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review — await clipboard, fix zero-scope label, simplify condition
- Await navigator.clipboard.writeText and catch failures
- Change zero-scope label from "Enbart läs" to "Inga behörigheter"
- Simplify redundant ternary condition in TransactionHistoryList
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: repair broken ternary in TransactionHistoryList JSX
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: mobile UX improvements across dashboard pages
- Responsive layouts with stacked mobile forms and grid desktop views
- Safe area handling (viewportFit cover, bottom nav insets, main padding)
- Touch-friendly dialogs, tabs, and page headers
- Mobile nav drawer open/close animation
- Dashboard layout parallel Supabase queries
- SIE parser: handle quoted VER/TRANS fields
- Skip account override for template-based transaction booking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR review feedback from Greptile
- Fix nav drawer close timer race condition with useRef + clearTimeout
- Show locked VAT rate as read-only label on mobile instead of hiding it
- Remove dead bottom-16 class overridden by inline style
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Remove influencer-specific features (campaigns, TikTok, gifts, shadow ledger,
contracts, briefings) and consolidate into a clean ERP foundation with core
bookkeeping, invoicing, receipts, tax reporting, and calendar functionality.
Reorganize database migrations into a clean numbered sequence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>