* feat: delete last voucher, notes field, schema cache fix
Address three customer feedback items from William (wigu.se):
1. Delete last voucher per series (Fortnox model):
- New `delete_last_voucher` RPC with full safety checks (last-in-series,
open period, no references, owner/admin only)
- Session variable bypass for immutability/retention/line triggers
- Full JSONB audit trail (BFNAR 2013:2 behandlingshistorik)
- DELETE endpoint + UI with confirmation dialogs
- Storno restoration when deleting a reversal entry
2. Notes/comment field on vouchers:
- `notes` column on journal_entries (always-editable internal metadata)
- Immutability trigger updated to allow notes-only updates on posted entries
- PATCH endpoint, inline-edit UI on detail page, form textarea
3. Schema cache fix:
- NOTIFY pgrst applied to production (immediate fix)
- Retroactive migration + CLAUDE.md migration rule added
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Greptile review — tighten trigger, lock voucher sequence
P1: The notes-only exception in enforce_journal_entry_immutability was
too broad — it only checked 7 verifikation fields, allowing silent
mutation of correction_of_id, reverses_id, reversed_by_id, committed_at,
and user_id on posted entries. Now guards all metadata fields; only
notes and updated_at may differ.
P2: Lock voucher_sequences row FOR UPDATE before the MAX(voucher_number)
check in delete_last_voucher to serialise against concurrent
commit_journal_entry calls, preventing voucher number gaps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Implement company and account deletion features
- Add event types for company and account deletion to CoreEvent.
- Enhance Supabase middleware to handle company context resolution and cookie management for archived companies.
- Create API routes for deleting accounts and companies, including necessary validations and event emissions.
- Implement tests for account and company deletion endpoints to ensure proper functionality and error handling.
- Add retention notice component to inform users about bookkeeping data retention during destructive actions.
- Create database migrations to support soft deletion of companies and anonymization of user accounts, ensuring compliance with retention laws.
* feat: enhance account deletion process and update user notifications
* Add service client for onboarding completion check and update escape hatch visibility
* Enhance invite flow and email handling for company members
* Refactor company context and RLS policies for active company isolation
- Update `switchCompany` to remove unnecessary revalidation as client handles navigation.
- Revise `getActiveCompanyId` to prioritize `user_preferences` and validate against non-archived memberships.
- Modify `setActiveCompany` to ensure `user_preferences` is the authoritative source while maintaining cookie compatibility.
- Enhance middleware to resolve active company using `user_preferences` and fallback to first non-archived membership.
- Introduce new API route `/api/company/current` to fetch the active company ID for cross-tab synchronization.
- Implement `CompanyTabSync` component for real-time active company enforcement across tabs.
- Create migration for RLS policies to enforce single-active-company isolation using `current_active_company_id()`.
* feat: implement viewer role enforcement for write permissions
- Added `useCanWrite` hook to determine if the current user has write permissions based on their role in the active company.
- Updated various components (JournalEntryForm, CustomerForm, DeadlineForm, etc.) to disable write actions and show a lock icon with a tooltip for users without write permissions.
- Introduced `requireWritePermission` function to enforce write permissions at the API level, returning a 403 response for viewers.
- Created tests to verify the behavior of the viewer role and write permissions.
- Added database migration to enforce read-only access for viewers at the database level.
* feat: multi-tenant company refactor (GNU-19)
Introduce companies table, company_members, and user_preferences to
support multiple companies per user. All data scoping changes from
user_id to company_id across the entire codebase.
Key changes:
- Database migration: new tables, company_id on 40+ tables, backfill,
RLS rewrite from user_id to company-member-based, updated RPCs
- Types: Company, CompanyMember, CompanyRole, UserPreferences types;
company_id added to all entity interfaces; companyId on all events
- Engine: all 7 core functions take companyId; storno, period, year-end
services updated; 16 report generators updated
- Middleware: company context resolution (cookie → prefs → first company)
- API routes: ~120 routes updated with requireCompanyId()
- Frontend: CompanyProvider context, layout/dashboard/onboarding updated
- Extensions: context factory, 9 extensions, all lib files updated
- Tests: 1880 tests passing, all helpers updated with company_id defaults
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add database migrations for multi-tenant company and team system (GNU-19)
Adds company_invitations, company creation RPC, team_members, account
deletion RPC, and teams table refactor migrations. Updates base
multi-tenant migration with cascading FKs and onboarding_step column.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add team types and update core infrastructure for multi-tenancy (GNU-19)
Adds TeamRole, MemberSource, and Team types. Refactors Supabase service
client to be stateless, updates middleware for team-aware routing, extends
CompanyContext with team/role fields, and updates extension service types
to accept companyId.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: thread company_id through business logic functions (GNU-19)
Replaces user_id scoping with company_id across all lib modules:
bookkeeping, documents, transactions, invoices, reconciliation, tax,
deadlines, and import. Updates corresponding tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: thread company_id through API routes and extensions (GNU-19)
Updates all existing API routes to extract and pass companyId. Updates
enable-banking and arcim-migration extensions for company-scoped
transaction ingestion and sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add company and team management API routes (GNU-19)
Adds CRUD endpoints for company members, company invitations, team
members, and team invitations. Includes invite token utilities, email
templates, and company switch server action.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add team/company UI components, pages, and dashboard updates (GNU-19)
Adds CompanySwitcher, ConsultantEmptyState, Step0RoleChoice, company
members and team management panels. Updates dashboard layout for
team-aware routing, onboarding for multi-step role choice, and auth
callback for team invite acceptance. Ignores supabase/.branches/.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add null guards for company in import page (GNU-19)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move appUrl declaration to outer scope in invite route (GNU-19)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add optional chaining for company.name in members section (GNU-19)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add optional chaining for second company.name in members section (GNU-19)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add null guards for company in extension components (GNU-19)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass companyId to executeSIEImport in arcim-migration extension (GNU-19)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: update tests to use companyId instead of userId and improve type handling
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: separate AR/AP/accounting into distinct nav groups (#92)
Split the flat "Finans" sidebar group into three visually distinct
sections — Försäljning (AR), Inköp (AP), and Redovisning — so users
coming from Fortnox immediately find customer invoicing and supplier
invoices as top-level concepts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: journal entry detail view, correction chain, and account name display
- Add journal entry detail page at /bookkeeping/[id] with full entry view
- Add correction chain API and component showing storno relationships
- Add JournalEntryStatusBadge component for entry status display
- Show debit/credit account names in template picker and review dialogs
- Expand client-side BAS account name mapping with additional accounts
- Show account codes on transaction inbox suggestion buttons
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review feedback — N+1 query, duplicate name, nav dedup
- Batch reverse-lookup into single query per BFS iteration (was N+1)
- Differentiate account 2393 from 2893 in display names
- Extract shared loop for desktop/mobile nav group rendering
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: add date sorting support to journal entries API
Add sort_date query parameter (asc/desc) that orders results by
entry_date instead of the default voucher_series + voucher_number.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add date sort toggle to journal entry list
Add ascending/descending sort button next to the missing attachment
filter. Defaults to newest first, toggles between nyast/äldst först.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add date range filter inputs to journal entry list
Add Från/Till text inputs (YYYY-MM-DD) for filtering entries by date
range. Applies on blur or Enter, with an X button to clear both fields.
Both fields are optional and work independently of the sort toggle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Update BAS account catalog with comprehensive SRU codes and K2 flags
- Add currency revaluation service with tests and API route
- Add expenses page and account deletion API
- Enhance booking templates with new patterns and improved tests
- Improve transaction categorization with template picker and description matching
- Polish dashboard, onboarding, import, and transaction UIs
- Refactor year-end service for multi-step closing
- Move SRU generator to ne-bilaga, remove standalone SRU export
- Remove unused dev docs, mock data, and extension hooks
- Add invoice delivery note sequences migration
Co-Authored-By: Claude Opus 4.6 <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>
- 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>
Add rollback logic to storno-service correctEntry to restore ledger
consistency if step 2 fails after reversal. Add correction API route at
/api/bookkeeping/journal-entries/[id]/correct. Add CorrectionEntryDialog
component and correction button to JournalEntryList.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add test coverage for invoices, transactions, bookkeeping, and supplier
invoice API routes. Includes test helpers (createMockRequest,
parseJsonResponse, createMockRouteParams, createQueuedMockSupabase) and
fixture factories (makeInvoice, makeCustomer, makeSupplier,
makeSupplierInvoice, makeCompanySettings).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>