* fix: include reversed entries in all reports (general ledger, trial balance, VAT, SIE, NE, INK2)
Reversed entries (storno) must appear alongside their original posted entries
in reports for a complete audit trail. Previously, filtering by status='posted'
excluded them, causing discrepancies when corrections had been made.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: semi-manual invoice payment booking with editable journal lines
When marking an invoice as paid, users now see a dialog where they can:
- Choose which bank/cash account the payment goes to (1910, 1920, 1930, etc.)
- Review and edit the proposed journal entry lines before committing
- The happy path remains fast — lines are pre-filled correctly
Implementation:
- Pure proposePaymentLines() function for line computation (accrual + cash)
- PaymentBookingDialog with AccountCombobox, balance validation, date picker
- API accepts optional custom lines, falls back to auto-generation without them
- 18 tests (8 unit + 10 API) all passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Greptile review — validation fallback, balance check, error handling
- P1: Return 400 on invalid body instead of silently falling back to
auto-generated lines (split JSON parse from schema validation)
- P1: Add server-side balance check for custom lines before committing
(debit must equal credit, totalDebit > 0)
- P2: Wrap PaymentBookingDialog init() in try/catch with toast on
failure and auto-close instead of silent empty state
- Add 2 new tests: unbalanced lines → 400, invalid schema → 400
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: OAuth callback redirect for local dev and timeout resilience
- Pass redirectUri dynamically from NEXT_PUBLIC_APP_URL so OAuth
callbacks work on localhost (not just production)
- Encode consentId/provider in OAuth state (base64url JSON) so the
callback doesn't depend on session storage
- Add skipAuth flag to extension API routes for OAuth callbacks
(external provider redirects have no user session cookie)
- Wrap AbortError in descriptive timeout messages in arcim-client
- Make preview endpoint resilient to partial failures (company info
and SIE fetch are individually non-blocking)
- Simplify login page (remove unused magic link auth mode)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: create journal entry before marking invoice as paid
Move journal entry creation before the invoice status update so that
if accounting fails, the invoice is not permanently marked paid without
a corresponding entry. Previously the error was silently swallowed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: update mark-paid tests for journal-first ordering
Reorder mock queue to match new flow (settings before update), update
failure test to expect 500 instead of silent success, add try-catch
with proper error response in route handler.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add reverse charge VAT (ruta 20-32) and improve mobile UX across dashboard
Add full reverse charge (omvänd skattskyldighet) support to the VAT declaration:
- Map accounts 2614/2624/2634 to ruta 30/31/32 for self-assessed output VAT
- Calculate purchase bases (ruta 20-24) from supplier invoices by supplier type
- Include ruta 30-32 in ruta 49 formula and totalOutputVat summary
- Display reverse charge section in reports UI and composition chart
- Add comprehensive test coverage for all reverse charge scenarios
Improve mobile UX across the app:
- Convert nav drawer to bottom sheet with drag handle and safe area padding
- Add mobile card layout for PaymentBookingDialog journal lines
- Replace settings tab pills with dropdown selector on mobile
- Make wizard step indicators responsive (collapsed on mobile)
- Ensure all dialog footers stack buttons full-width on mobile
- Add 44px minimum touch targets throughout
- Make onboarding buttons full-width on mobile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Greptile review — indentation, query efficiency, tab dedup
- Fix misleading try-block indentation in mark-paid route
- Filter reversed entries at DB level (.eq('status', 'posted')) instead
of fetching then discarding in memory
- Extract shared settingsTabs array so mobile Select and desktop
TabsList stay in sync automatically
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add resilience fallbacks, Arcim retry logic, and client tests
Add FallbackPrompt component and integrate it across banking and migration
error states so users always have a manual import escape hatch. Add retry
with exponential backoff to Arcim API client for transient failures (429,
502, 503, 504) and timeouts. Expand import page deep-linking with ?mode=
parameter. Add persistent error banner on settings page for bank connection
failures. Include 18 new tests for the Arcim client covering retry, backoff,
pagination, timeout, env validation, and singleton resource unwrapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Greptile review — setActiveTab, test cleanup, redundant clearTimeout
- Add missing setActiveTab('banking') when handling bank_error query
param so the error banner is actually visible (P1)
- Guard env-var cleanup with try/finally in arcim-client tests to
prevent state leakage on assertion failure (P2)
- Only mock retry-range setTimeout delays in backoff test, letting
AbortController timers pass through real setTimeout (P2)
- Remove redundant clearTimeout in catch block — finally handles it (P2)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add BFL-compliant counterparty names to journal descriptions and cancelled entry status
Journal descriptions now include customer/supplier names for traceability
(e.g. "Kundfaktura 1001, Foretag AB"). Failed draft entries are marked as
'cancelled' instead of deleted, respecting immutability constraints.
Includes DB migration for the new journal_entries status value.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Greptile review — Swedish typos, missing source type, trigger and reversal cleanup
- Fix Swedish spelling: leverantor → leverantör in all supplier description prefixes
- Add supplier_credit_note to supplierSourceTypes in VAT declaration so credit
notes correctly reduce reverse-charge bases (ruta 20–24)
- Mark orphaned concurrent reversals as cancelled instead of attempting deletion
that the immutability trigger blocks
- Allow posted → cancelled transition in trigger for orphaned reversal cleanup
- Restrict cancelled entry line trigger to DELETE-only (block INSERT/UPDATE)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use main's Step3TaxRegistration (onboarding restructured in PR #54)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: retrigger Greptile review
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Change missing extension env vars from throw to log.warn (graceful degradation)
- Move initialized flag after all init steps complete
- Add error.tsx and loading.tsx for dashboard error boundaries
- Fix cron route auth header checks
- Add ensureInitialized() to journal entry reverse and invoice mark-paid/sent routes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add currency-utils module for SEK conversion with exchange rates
- Refactor createJournalEntry to use draft+commit flow preventing voucher number gaps (BFL 5 kap. 7§)
- Add foreign currency support to invoice entries with per-line SEK conversion
- Centralize category-to-account mapping into single source of truth
- Refactor invoice inbox to use shared document analyzer with document type classification (receipt, supplier invoice, government letter)
- Update mapping engine, supplier invoice entries, and transaction entries
- Fix report component rendering issues
- Add new validation schemas and tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove all sector-specific extensions (construction, ecommerce, export,
hotel, restaurant, tech) — only general-purpose extensions remain
- Move NE-bilaga and SRU export from extensions to core reports (lib/reports/)
- Move moms-box-mapping from extensions/export/shared to lib/vat/
- Replace per-extension API routes with catch-all dispatcher
(app/api/extensions/ext/[...path]/route.ts)
- Add manifest.json for each extension with metadata, env vars, and deps
- Add api-routes.ts pattern for extension-defined API endpoints
- Add code generation scripts (generate-extension-registry, create-extension)
- Add extensions.config.json for opt-in extension loading
- Add extensions.schema.json for config validation
- Add email service interface with noop default (lib/email/service.ts)
- Add CI workflow (core-build.yml) to verify core builds with zero extensions
- Add migration 045: expand account_type CHECK for untaxed_reserves
- Update CLAUDE.md with comprehensive extension system documentation
- Update all report engines and bookkeeping services for new imports
- Clean up extensions.schema.json to only list existing extensions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reduce booking template library to eliminate duplicate suggestions when
users describe transactions. Templates with identical accounting treatment
(same account + VAT) are merged, keywords consolidated, and the entire
subscriptions group is eliminated. Also includes prior work on reports,
extensions, and transaction improvements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix buildLineInserts() using wrong DB column names (cost_center_id → cost_center,
project_id → project) and add missing tax_code field
- Replace transaction-based dashboard income/expense with journal-entry-based
calculation using account classes (3xxx revenue, 4-7xxx expenses)
- Add email/phone fields to CompanySettings type, validate RESEND_FROM_EMAIL
in isResendConfigured(), remove unsafe type casts in invoice send/reminders
- Always auto-fill line description from account name in JournalEntryForm
- Reorder expense lines in TransactionBookingDialog so 1930 is always first row
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>