* feat(reports,settings): report library + focused report routes, settings modal
Reports
- Replace the monolithic /reports tab-switcher with a calm, grouped report
library landing (ReportLibrary + RecentReportsShelf) driven by a new
lib/reports/catalog.ts.
- Each report opens a focused /reports/[slug] route (FocusedReport) with a
shared fiscal-year selector, optional date-range, and URL-based account
drill-down into the general ledger.
- Extract every report view into components/reports/views, add a reusable
ReportExportMenu, and remove the old ReportsNav.
Settings
- Add an intercepting @settingsModal parallel route so in-app navigation to
/settings opens as a modal over the current page; hard loads still resolve
to the full page.
- Share one SettingsShell (rail + content) between page and modal, extract each
section into components/settings/sections/*Content, add a settings hotkey and
command-palette entry, and remove the old SettingsSidebar.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(reports,settings): remove dead salary-journal entry, fix border token
Addresses PR review feedback (#629):
- Remove the unreachable `salary-journal` report from the catalog. It had
needsEmployees + no route + no FocusedView handler and `hasEmployees` was
never plumbed through, so it never appeared in the library and a direct
/reports/salary-journal URL rendered a blank frame. The report was never on
the old page and has no view component; the API + generator stay in place for
a proper follow-up. Drops its two now-unused i18n keys.
- Replace opacity-suffixed `border-border/8` section dividers with full-opacity
`border-border` across the extracted settings section components, per the
design system (no opacity-suffixed border tokens on surfaces).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: re-trigger checks (pg-real hit a Docker Hub registry timeout)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: add language preference for customers to support invoice localization
- Introduced language support for invoices, allowing customers to choose between Swedish and English.
- Updated invoice PDF generation to reflect the selected language for titles, labels, and messages.
- Enhanced email templates to generate content in the customer's preferred language.
- Added migration to include a language column in the customers table with a default value of Swedish.
- Updated tests to verify correct language usage in invoice emails and PDFs.
* fix: debounce API requests in InvoicePreviewCard and update F-skatt terminology in email templates
* Fixed user issues
* feat: add personal_number column to customers for individual identification
* feat: add personal_number field to makeCustomer function for enhanced customer identification
* feat: add personal_number column with constraint check for customer identification
* 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
* feat: invoicing & account-security polish bundle
Five independent improvements bundled to ship together:
- BankID/password lockout fix: BankID-only users could enroll MFA and
brick themselves (Supabase requires AAL2 to change password or unenroll
MFA, and AAL2 needs a password sign-in). New app_metadata.has_password
flag tracks this; middleware gates /mfa/enroll behind it, /account/set-
password is the unlock path, SecuritySettings shows a banner, and
/api/account/password is the single write path that flips the flag.
Backfill script for existing users.
- Swish invoice payment method: company_settings.swish + invoice_show_swish
columns, validation in lib/api/schemas.ts (accepts 123XXXXXXX företag or
07XXXXXXXX mobile, strips whitespace/hyphens), rendered on invoice PDFs.
- Send-reminders kill switch: per-company company_settings.send_invoice_
reminders toggle in PdfPrintSettings/Automatisering. Reminder processor
also tightened: positive status allowlist (sent + overdue) so terminal
statuses can never match; skip when customer already responded via
reminder link; race-window re-check before send.
- First-invoice logo prompt: one-shot dialog when creating the first
invoice without a logo (issue #520). Self-limits via head-only count.
- SIE export opening-balance fallback: route IB through getOpeningBalances
so the compute_prior_opening_balances RPC supplies #IB after multi-year
imports where opening_balance_entry_id is intentionally NULL. Previously
#IB silently went to zero and #UB collapsed to current-period movements.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(account-polish): address PR review feedback
- BankID-link path (extensions/general/tic/index.ts): read-merge-write
app_metadata instead of passing { bankid_linked: true } alone.
updateUserById REPLACES app_metadata wholesale, so the previous code
would have wiped has_password for any user who later linked BankID,
causing the set-password banner to (incorrectly) reappear and blocking
the standard MFA enrollment button. The comment is now corrected.
- Middleware (lib/supabase/middleware.ts): thread inner returnTo through
the /mfa/enroll → /account/set-password redirect so the user lands on
their original destination after the full chain completes, not on /.
- safeReturnTo helper (lib/auth/safe-return-to.ts): replace the
starts-with-/-but-not-// guard on mfa/enroll and set-password pages.
The previous guard let /\evil.com and /@evil.com through. The new
helper parses against a synthetic base origin and verifies it matches.
- set-password page (app/(auth)/account/set-password/page.tsx): remove
CLAUDE.md design system violations — bg-gradient-to-b on page bg,
inline shadow-md style on the card, space-y-5, font-medium on the h1,
rounded-xl on the card. Flat surface, hairline border, font-display
h1 per the design tokens.
- Swish dedup (lib/payments/swish.ts): extract normaliseSwish() and
isValidSwish() helpers and use them in lib/api/schemas.ts,
components/settings/BankDetailsForm.tsx, and the invoicing settings
page. Single source of truth for the regex.
- Password route (app/api/account/password/route.ts): emit a structured
success log so the audit pipeline can detect password-set events, not
just failures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expand the tax settings page with F-skatt, VAT registration, fiscal year start month, and salary payment toggles. Refactor SettingsFormWrapper to support onSuccess callbacks so local state only updates after server confirmation. Fix logo upload to use service client for storage RLS bypass. Allow empty email in settings schema. Update CLAUDE.md with comprehensive multi-tenant, auth, and engine documentation. Remove unused langchain skills.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove AI-dependent extensions (ai-chat, ai-categorization, receipt-ocr,
invoice-inbox) and their infrastructure (lib/ai/*, ai-consent, LangChain/
Anthropic/OpenAI deps) to simplify core and reduce bundle size.
Restructure monolithic settings page into dedicated sub-pages (company,
bookkeeping, invoicing, tax, banking, api, account, team, templates) with
shared layout and sidebar navigation.
Add atomic commit_journal_entry RPC so voucher number increment and status
update happen in a single transaction — prevents burned numbers on constraint
failures. Add continuity check report and voucher gap explanation tracking.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>