diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index a6d2fb8b..a30fd8a0 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -5,7 +5,18 @@
"Bash(grep:*)",
"Bash(xargs:*)",
"Bash(ls:*)",
- "Bash(find:*)"
+ "Bash(find:*)",
+ "WebFetch(domain:www.skatteverket.se)",
+ "WebSearch",
+ "mcp__plugin_supabase_supabase__apply_migration",
+ "Bash(cat:*)",
+ "Bash(wc:*)",
+ "Bash(git -C /Users/jakobwennberg/erp-base log --oneline)",
+ "mcp__plugin_supabase_supabase__list_projects",
+ "Bash(python3:*)",
+ "Bash(git -C /Users/jakobwennberg/erp-base status --porcelain)",
+ "Bash(__NEW_LINE_421a23f44da9923d__ echo '=== Checking which index exports are used ===' grep -r @/components/calendar /Users/jakobwennberg/erp-base/app --include=*.tsx --include=*.ts 2)",
+ "Bash(/dev/null __NEW_LINE_421a23f44da9923d__ echo -e '\\\\n=== Checking which calendar deadline components are directly imported ===' grep -rE \"DeadlineList|DeadlineCard|DeadlineForm|DeadlineFilters|PaymentSummaryCard|TaxTodoWidget|UpcomingDeadlinesWidget\" /Users/jakobwennberg/erp-base --include=*.tsx --include=*.ts)"
]
}
}
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 00000000..e443bc74
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,446 @@
+# CLAUDE.md — erp-base
+
+## Project Overview
+
+erp-base is a Swedish-focused accounting SaaS for sole traders (enskild firma) and limited companies (aktiebolag). It implements double-entry bookkeeping compliant with Swedish accounting law (Bokforingslagen), including VAT handling, tax reporting, and 7-year document retention.
+
+**Tech stack**: Next.js 16 (App Router), React 19, TypeScript (strict), Supabase (PostgreSQL + RLS + magic link auth), Tailwind CSS 4 + shadcn/ui, Vercel hosting.
+
+**Integrations**: Enable Banking (PSD2), Anthropic SDK, OpenAI (embeddings), Resend (email), web-push (VAPID).
+
+**Path alias**: `@/*` maps to the project root (tsconfig.json).
+
+**Language**: All code, comments, and commit messages must be in English.
+
+---
+
+## Commands
+
+```bash
+npm run dev # Start development server
+npm run build # Production build
+npm run lint # ESLint
+npm test # Run all Vitest tests
+npx vitest run
# Run tests in a specific directory
+```
+
+---
+
+## Architecture
+
+```
+app/
+ (auth)/ Login, auth callback
+ (onboarding)/ 6-step setup wizard
+ (dashboard)/ Authenticated routes (invoices, customers, transactions,
+ bookkeeping, reports, suppliers, supplier-invoices,
+ receipts, settings, calendar, help, import)
+ (public)/ Public invoice action links (no auth)
+ api/ API routes organized by domain
+
+components/
+ ui/ shadcn/ui primitives (button, card, dialog, table, etc.)
+ [feature]/ Feature-organized components (banking, invoices, suppliers, etc.)
+
+extensions/ First-party extension implementations
+ receipt-ocr/ Receipt image OCR processing
+ ai-categorization/ AI-powered transaction categorization
+ ai-chat/ Claude-based chat assistant
+ ne-bilaga/ NE tax form attachment generation
+ sru-export/ SRU file export
+ push-notifications/ Web push notification system
+ example-logger/ Minimal reference extension (not loaded by default)
+
+lib/
+ bookkeeping/ Core journal entry engine and all entry generators
+ engine.ts Draft/commit workflow, balance validation, voucher numbering
+ invoice-entries.ts Sales invoice journal entries
+ transaction-entries.ts Bank transaction journal entries
+ supplier-invoice-entries.ts Purchase invoice journal entries
+ category-mapping.ts Category-to-BAS-account mapping
+ mapping-engine.ts Rule-based auto-categorization (MCC codes, merchant patterns)
+ vat-entries.ts VAT line generation
+ core/
+ bookkeeping/ Period service, storno reversal, year-end closing
+ documents/ Document archive (upload, versioning, SHA-256 integrity)
+ audit/ Audit trail service
+ tax/ Tax code service
+ banking/ PSD2 integration via Enable Banking
+ reports/ Financial reports (trial-balance, income-statement,
+ balance-sheet, vat-declaration, sie-export,
+ supplier-ledger, supplier-reconciliation)
+ events/ Event bus (bus.ts, types.ts)
+ extensions/ Extension registry, loader, types
+ tax/ Tax calculations, deadlines, Swedish holidays
+ import/ SIE file parser
+ invoice/ VAT rules for invoicing
+ currency/ Riksbanken exchange rates
+ supabase/ Client setup (client.ts = browser, server.ts = server/admin)
+ init.ts Extension loader (idempotent, called by API routes)
+
+types/index.ts Canonical type definitions (70+ types, single source of truth)
+tests/helpers.ts Mock factories and fixture builders
+supabase/migrations/ SQL migration files
+dev_docs/ Extensive project documentation (PRD, architecture, BAS guide, etc.)
+```
+
+### Key Relationships
+
+- **All journal entry creation** routes through `lib/bookkeeping/engine.ts`. The entry generators (`invoice-entries.ts`, `transaction-entries.ts`, `supplier-invoice-entries.ts`) call `createJournalEntry()` from the engine.
+- **API routes** that emit events must call `ensureInitialized()` (from `lib/init.ts`) at module level to load extensions.
+- **Event bus** (`lib/events/bus.ts`) is a module-level singleton. Core services emit, extensions subscribe.
+- **Supabase clients**: browser (`lib/supabase/client.ts`), server with user cookies (`createClient()` from `lib/supabase/server.ts`), and service role (`createServiceClient()`).
+
+---
+
+## Core Bookkeeping Engine
+
+The bookkeeping engine (`lib/bookkeeping/engine.ts`) is the most critical system. All accounting flows route through it.
+
+### Journal Entry Lifecycle
+
+1. **`createDraftEntry(userId, input)`** — Creates entry with `status: 'draft'`, `voucher_number: 0`. Validates balance. Emits `journal_entry.drafted`.
+2. **`commitEntry(userId, entryId)`** — Assigns voucher number via DB RPC (`next_voucher_number`, concurrent-safe). Sets `status: 'posted'`. DB trigger sets `committed_at`. Emits `journal_entry.committed`.
+3. **`createJournalEntry(userId, input)`** — Convenience: draft + commit in one call. This is what all entry generators use.
+4. **`reverseEntry(userId, entryId)`** — Storno reversal: swaps debit/credit, links via `reverses_id`/`reversed_by_id`. Original marked `'reversed'`.
+
+### Entry Generators
+
+| Function | File | Purpose |
+|----------|------|---------|
+| `createInvoiceJournalEntry()` | `invoice-entries.ts` | Debit 1510, Credit 30xx + 26xx VAT |
+| `createInvoicePaymentJournalEntry()` | `invoice-entries.ts` | Debit 1930, Credit 1510 |
+| `createCreditNoteJournalEntry()` | `invoice-entries.ts` | Reverses original invoice entry |
+| `createInvoiceCashEntry()` | `invoice-entries.ts` | Cash method: revenue + VAT at payment |
+| `createTransactionJournalEntry()` | `transaction-entries.ts` | Maps bank transactions via MappingResult |
+| `createSupplierInvoiceRegistrationEntry()` | `supplier-invoice-entries.ts` | Debit expense + 2641, Credit 2440 |
+| `createSupplierInvoicePaymentEntry()` | `supplier-invoice-entries.ts` | Debit 2440, Credit 1930 |
+
+### Key BAS Accounts
+
+| Account | Description |
+|---------|-------------|
+| `1510` | Accounts receivable |
+| `1930` | Business bank account |
+| `2013` | Private withdrawals (enskild firma) |
+| `2440` | Accounts payable |
+| `2611` / `2621` / `2631` | Output VAT 25% / 12% / 6% |
+| `2614` | Output VAT reverse charge |
+| `2641` | Input VAT (deductible) |
+| `2645` | Calculated input VAT (EU reverse charge) |
+| `2893` | Loan from shareholders (aktiebolag) |
+| `3001` / `3002` / `3003` | Revenue by VAT rate (25% / 12% / 6%) |
+| `3305` / `3308` | Export / EU service revenue |
+| `3960` / `7960` | Exchange rate gains / losses |
+
+### VAT Treatments
+
+`standard_25`, `reduced_12`, `reduced_6`, `reverse_charge`, `export`, `exempt`
+
+---
+
+## Accounting Guard Rails
+
+These rules exist for legal compliance and are enforced by database triggers. **Never violate them.**
+
+1. **Committed entries are immutable.** Once `status: 'posted'`, an entry cannot be edited or deleted. Enforced by DB trigger `enforce_journal_entry_immutability`.
+2. **Never delete posted entries.** Use `reverseEntry()` (storno) to cancel. The reversal creates a new entry with swapped debit/credit and bidirectional linking.
+3. **Every entry must balance.** `sum(debits) === sum(credits)`, both must be `> 0`. Checked by `validateBalance()` before insert.
+4. **Voucher numbers are sequential.** Assigned via DB RPC `next_voucher_number` (concurrent-safe). Never set manually.
+5. **Period lock enforcement.** DB trigger `enforce_period_lock` blocks writes to closed/locked fiscal periods. Check period status before creating entries.
+6. **7-year document retention.** DB triggers prevent deletion of documents linked to posted entries. `retention_expires_at` is auto-calculated as `period_end + 7 years`.
+7. **Storno, never edit.** To correct an error: reverse the wrong entry, then create a new correct one. Use `correctEntry()` from `lib/core/bookkeeping/storno-service.ts` for atomic correction.
+8. **Use `Math.round(x * 100) / 100` for all monetary calculations.** Never use `toFixed()` (returns strings, has rounding edge cases).
+9. **Always use engine functions.** Never insert directly into `journal_entries` or `journal_entry_lines` tables. Always go through `lib/bookkeeping/engine.ts`.
+10. **Account numbers are strings.** BAS account numbers like `'1930'` are always strings, never numbers.
+
+---
+
+## Extension Development
+
+Extensions are first-party plugins in the `/extensions/` directory, loaded statically at startup.
+
+### Creating a New Extension
+
+1. Create `extensions//index.ts`
+2. Export an object implementing the `Extension` interface from `lib/extensions/types.ts`
+3. Add a static import to the `FIRST_PARTY_EXTENSIONS` array in `lib/extensions/loader.ts`
+4. Extensions **cannot** use dynamic imports (Next.js bundling constraint)
+
+### Extension Interface
+
+```typescript
+interface Extension {
+ id: string // Unique identifier (e.g. 'receipt-ocr')
+ name: string // Display name
+ version: string // Semver
+
+ // Surfaces (all optional)
+ routes?: RouteDefinition[]
+ apiRoutes?: ApiRouteDefinition[]
+ sidebarItems?: SidebarItem[]
+ eventHandlers?: ExtensionEventHandler[]
+ mappingRuleTypes?: MappingRuleTypeDefinition[]
+ reportTypes?: ReportDefinition[]
+ settingsPanel?: SettingsPanelDefinition
+ taxCodes?: TaxCodeDefinition[]
+ dimensionTypes?: DimensionDefinition[]
+
+ // Lifecycle hooks
+ onInstall?(ctx: ExtensionContext): Promise
+ onUninstall?(ctx: ExtensionContext): Promise
+}
+```
+
+### Minimal Example
+
+See `extensions/example-logger/index.ts`:
+
+```typescript
+import type { Extension } from '@/lib/extensions/types'
+import type { EventPayload } from '@/lib/events/types'
+
+export const myExtension: Extension = {
+ id: 'my-extension',
+ name: 'My Extension',
+ version: '0.1.0',
+ eventHandlers: [
+ {
+ eventType: 'journal_entry.committed',
+ handler: async (payload: EventPayload<'journal_entry.committed'>) => {
+ // React to committed journal entries
+ },
+ },
+ ],
+}
+```
+
+### Available Event Types
+
+All defined in `lib/events/types.ts`:
+
+| Event | Payload |
+|-------|---------|
+| `journal_entry.drafted` | `{ entry, userId }` |
+| `journal_entry.committed` | `{ entry, userId }` |
+| `journal_entry.corrected` | `{ original, storno, corrected, userId }` |
+| `document.uploaded` | `{ document, userId }` |
+| `invoice.created` | `{ invoice, userId }` |
+| `invoice.sent` | `{ invoice, userId }` |
+| `invoice.paid` | `{ invoice, transaction, kursdifferens?, userId }` |
+| `invoice.overdue` | `{ invoice, days, userId }` |
+| `credit_note.created` | `{ creditNote, userId }` |
+| `transaction.synced` | `{ transactions[], userId }` |
+| `transaction.categorized` | `{ transaction, account, taxCode, userId }` |
+| `bank.statement_received` | `{ statement, userId }` |
+| `bank.payment_notification` | `{ notification, userId }` |
+| `period.locked` | `{ period, userId }` |
+| `period.year_closed` | `{ period, userId }` |
+| `customer.created` | `{ customer, userId }` |
+| `customer.pseudonymized` | `{ customerId, userId }` |
+| `receipt.extracted` | `{ receipt, documentId, confidence, userId }` |
+| `receipt.matched` | `{ receipt, transaction, confidence, autoMatched, userId }` |
+| `receipt.confirmed` | `{ receipt, businessTotal, privateTotal, userId }` |
+| `audit.security_event` | `{ event, userId }` |
+
+### Event Bus Behavior
+
+- Handlers run concurrently via `Promise.allSettled` — a failing handler never crashes the emitter
+- Module-level singleton, persists across requests in the same process
+- One-way: core services emit, extensions subscribe
+- Call `eventBus.clear()` in tests to reset state
+
+---
+
+## Testing Guidelines
+
+### Scope
+
+Only test business logic in `lib/`. No component tests, no API route tests, no E2E tests.
+
+### Framework
+
+Vitest 4 with `globals: true` and `environment: 'node'`. Config in `vitest.config.ts`.
+
+### Test Location
+
+Colocated `__tests__/` directories alongside source files in `lib/`.
+
+### Test Helpers (`tests/helpers.ts`)
+
+**Supabase mock**:
+```typescript
+const { supabase, mockResult } = createMockSupabase()
+mockResult({ data: makeTransaction(), error: null })
+// supabase.from('x').select('*').eq('id', '1') resolves to the mocked result
+```
+
+**Fixture factories** (all accept `Partial` overrides):
+- `makeReceipt()` — Receipt with default merchant, amounts, dates
+- `makeTransaction()` — Transaction with default category, amount
+- `makeFiscalPeriod()` — FiscalPeriod with default date range
+- `makeJournalEntry()` — Posted JournalEntry with voucher number
+- `makeJournalEntryLine()` — Line with account number, zero amounts
+- `makeDocumentAttachment()` — Document with hash, storage path
+- `makeTaxCode()` — TaxCode with default output VAT 25%
+
+### Patterns
+
+- Always mock `@/lib/supabase/server` to avoid real DB calls
+- Use `vi.clearAllMocks()` and `eventBus.clear()` in `beforeEach`
+- Test balance validation edge cases (floating point precision, zero amounts)
+- Test error paths (missing fiscal period, unbalanced entries)
+- Verify events are emitted correctly
+
+### Reference Tests
+
+- `lib/bookkeeping/__tests__/engine.test.ts` — Balance validation
+- `lib/core/bookkeeping/__tests__/storno-service.test.ts` — Complex mock queues
+- `lib/core/documents/__tests__/document-service.test.ts` — Storage mocking
+- `lib/events/__tests__/bus.test.ts` — Event bus behavior
+- `lib/extensions/__tests__/registry.test.ts` — Extension registration
+
+---
+
+## Database & Migrations
+
+### Location
+
+`supabase/migrations/` — currently 27 files numbered `20240101000001` through `20240101000027`.
+
+### Naming Convention
+
+`YYYYMMDD00NNNN_descriptive_name.sql` — next migration: `20240101000028_*.sql`
+
+### Migration Rules
+
+1. **Always enable RLS** on new tables: `ALTER TABLE public.tablename ENABLE ROW LEVEL SECURITY;`
+2. **Always create RLS policies** using `auth.uid() = user_id`:
+ ```sql
+ CREATE POLICY "tablename_select" ON public.tablename FOR SELECT USING (auth.uid() = user_id);
+ CREATE POLICY "tablename_insert" ON public.tablename FOR INSERT WITH CHECK (auth.uid() = user_id);
+ CREATE POLICY "tablename_update" ON public.tablename FOR UPDATE USING (auth.uid() = user_id);
+ ```
+3. **Always add `updated_at` trigger**:
+ ```sql
+ CREATE TRIGGER tablename_updated_at BEFORE UPDATE ON public.tablename
+ FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
+ ```
+4. **UUID primary keys**: `id UUID PRIMARY KEY DEFAULT uuid_generate_v4()`
+5. **User ownership**: `user_id UUID REFERENCES auth.users ON DELETE CASCADE NOT NULL`
+6. **Never modify existing migrations** — create new ones instead
+7. **Never modify enforcement triggers** (migration `20240101000017`) — these are legally required
+8. **Never hardcode IDs** in data migrations — use subqueries or variables
+9. **Apply via Supabase MCP tool**: `mcp__plugin_supabase_supabase__apply_migration`
+10. **Test on a branch database** before applying to production (use `create_branch` MCP tool)
+
+### Key Enforcement Triggers (migration 017)
+
+- `enforce_journal_entry_immutability` — Blocks edits/deletes on posted/reversed entries
+- `enforce_journal_entry_line_immutability` — Blocks line modifications on committed entries
+- `enforce_period_lock` — Blocks writes to closed/locked fiscal periods
+- `block_document_deletion` — Prevents deletion of documents linked to committed entries
+- `enforce_retention_journal_entries` — 7-year retention enforcement
+- `set_committed_at` — Auto-sets timestamp on draft-to-posted transition
+- `calculate_retention_expiry` — Auto-sets `retention_expires_at = period_end + 7 years`
+
+---
+
+## Type System
+
+- All shared types live in `types/index.ts` — this is the single source of truth
+- Import via `import type { TypeName } from '@/types'`
+- When adding new domain types, add them to `types/index.ts`
+- Event types are the exception — they live in `lib/events/types.ts` (since they reference domain types)
+
+---
+
+## API Route Patterns
+
+Standard pattern for new API routes:
+
+```typescript
+import { createClient } from '@/lib/supabase/server'
+import { NextResponse } from 'next/server'
+import { ensureInitialized } from '@/lib/init'
+
+ensureInitialized() // Module-level — loads extensions for event emission
+
+export async function POST(request: Request) {
+ const supabase = await createClient()
+ const { data: { user } } = await supabase.auth.getUser()
+
+ if (!user) {
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
+ }
+
+ // Business logic...
+ // Always filter by user_id (defense in depth alongside RLS)
+ // Wrap journal entry creation in try/catch (non-blocking side effect)
+ // Emit events after successful operations
+
+ return NextResponse.json({ data: result })
+}
+```
+
+**Key conventions**:
+- Call `ensureInitialized()` at module level in any route that emits events
+- Dynamic route params use `{ params }: { params: Promise<{ id: string }> }` (Next.js 16)
+- Response shapes: `{ data }` for success, `{ error }` for failures
+- Journal entry creation is non-blocking: catch errors and continue
+
+---
+
+## Skills Usage
+
+- **Always** use the `/frontend-design` skill when creating new UI pages or significant components. This ensures consistent use of shadcn/ui, Tailwind CSS 4, and the existing component library.
+- Use the `langchain` skill when building or modifying AI features (ai-chat, ai-categorization extensions).
+- Use `vercel:deploy` for deployment tasks.
+
+---
+
+## Git Conventions
+
+Use **conventional commits**:
+
+```
+feat: add supplier invoice payment tracking
+fix: correct VAT calculation for reduced 12% rate
+refactor: extract VAT line generation into vat-entries.ts
+test: add balance validation edge cases
+docs: update CLAUDE.md with extension guide
+```
+
+- Atomic commits — one logical change per commit
+- Branch from `main` for new work
+
+---
+
+## Deployment
+
+Hosted on **Vercel** with cron jobs defined in `vercel.json`:
+
+| Cron Job | Schedule |
+|----------|----------|
+| `/api/banking/sync/cron` | Daily 05:00 |
+| `/api/deadlines/status/cron` | Daily 06:00 |
+| `/api/invoices/reminders/cron` | Daily 08:00 |
+| `/api/extensions/push-notifications/cron` | Daily 09:00 |
+| `/api/tax-deadlines/cron` | Monthly, 1st at 00:00 |
+| `/api/documents/verify/cron` | Weekly, Sunday 03:00 |
+
+### Required Environment Variables
+
+```
+NEXT_PUBLIC_SUPABASE_URL # Supabase project URL
+NEXT_PUBLIC_SUPABASE_ANON_KEY # Supabase anonymous key
+SUPABASE_SERVICE_ROLE_KEY # Supabase service role key
+ENABLE_BANKING_APP_ID # Enable Banking app ID
+ENABLE_BANKING_APP_SECRET # Enable Banking app secret
+ENABLE_BANKING_SANDBOX # true for sandbox mode
+ANTHROPIC_API_KEY # Claude API key (ai-chat)
+OPENAI_API_KEY # OpenAI API key (embeddings)
+NEXT_PUBLIC_APP_URL # App base URL
+NEXT_PUBLIC_VAPID_PUBLIC_KEY # Web push public key
+VAPID_PRIVATE_KEY # Web push private key
+```
diff --git a/PRD_Modular_Swedish_ERP_Platform.md b/PRD_Modular_Swedish_ERP_Platform.md
deleted file mode 100644
index b3b6426b..00000000
--- a/PRD_Modular_Swedish_ERP_Platform.md
+++ /dev/null
@@ -1,878 +0,0 @@
-# Product Requirements Document
-## Modular Swedish ERP & Accounting Platform
-
-**Version 2.0 | February 2026 | CONFIDENTIAL**
-
-*A next-generation bokföringssystem for Swedish aktiebolag*
-
----
-
-## Table of Contents
-
-1. [Executive Summary](#1-executive-summary)
-2. [Product Vision & Positioning](#2-product-vision--positioning)
-3. [Target Users & Market](#3-target-users--market)
-4. [Core Platform Architecture](#4-core-platform-architecture)
-5. [Module System Design](#5-module-system-design)
-6. [Core Accounting Engine (Always Active)](#6-core-accounting-engine-always-active)
-7. [Module Catalog: Categories & Modules](#7-module-catalog-categories--modules)
-8. [Industry Packs & Business Type Recommendations](#8-industry-packs--business-type-recommendations)
-9. [User Experience & Onboarding Flow](#9-user-experience--onboarding-flow)
-10. [Technical Architecture](#10-technical-architecture)
-11. [Database Design](#11-database-design)
-12. [Event System](#12-event-system)
-13. [Security & Compliance](#13-security--compliance)
-14. [Integration Strategy](#14-integration-strategy)
-15. [Development Roadmap](#15-development-roadmap)
-16. [Business Model & Pricing](#16-business-model--pricing)
-17. [Success Metrics & KPIs](#17-success-metrics--kpis)
-18. [Risks & Mitigations](#18-risks--mitigations)
-19. [Appendices](#19-appendices)
-
----
-
-## 1. Executive Summary
-
-This document defines the product requirements for a modular Swedish ERP and accounting platform designed to compete directly with Fortnox and Visma. The platform takes a fundamentally different architectural approach: rather than offering a rigid, one-size-fits-all product, it provides a rock-solid core accounting engine with a composable module system that lets every business tailor their experience to their specific industry and needs.
-
-The core insight driving this product is that a restaurant, a hair salon, and a consulting firm all need correct Swedish accounting (BAS-kontoplan, momsredovisning, SIE export), but their day-to-day operational needs are completely different. Today, they all use the same generic Fortnox interface. This platform changes that by letting each business activate industry-specific modules that add relevant functionality, terminology, dashboards, and workflows on top of a shared, audited accounting foundation.
-
-The platform targets Swedish aktiebolag (limited companies) with 5 to 50 employees, starting with the Food & Beverage industry cluster before expanding to Beauty & Wellness, Fitness & Health, and beyond.
-
-> **Key Differentiator:** Every business gets a complete Swedish bokföringssystem out of the box. The module system lets them shape their platform to their industry without custom development, code generation, or AI-driven modifications. Modules are pre-built, tested, and audited by the platform team. The user simply activates what they need.
-
-### 1.1 Document Scope
-
-This PRD covers the full product vision, technical architecture, module system design, core accounting engine specification, initial module catalog, onboarding flow, development roadmap, and business model. It is intended for the founding engineering team and serves as the authoritative reference for building the MVP and subsequent releases.
-
----
-
-## 2. Product Vision & Positioning
-
-### 2.1 Vision Statement
-
-Build the most adaptable accounting platform in Sweden, where every business gets a system that feels like it was built specifically for their industry — powered by a modular architecture that makes this economically viable at scale.
-
-### 2.2 Positioning
-
-The platform sits in a unique position in the Swedish market:
-
-| Competitor | Strength | Weakness | Our Advantage |
-|---|---|---|---|
-| **Fortnox** | Market leader, trusted, integrations | Rigid, same UI for everyone, slow to innovate | Industry-tailored experience from day one |
-| **Visma** | Enterprise-grade, comprehensive | Complex, expensive, overwhelming for SMBs | Simple to start, grows with you via modules |
-| **Bokio** | Simple, modern UI, free tier | Too basic for growing businesses | Professional-grade with modular depth |
-| **Odoo** | Highly modular, open source | Complex setup, requires developer, not Swedish-first | Swedish-native, no developer needed, curated modules |
-
-### 2.3 Core Principles
-
-- **Correctness first:** The accounting engine must be bulletproof. Swedish accounting standards (BAS, K2/K3, BFL, BFN) are non-negotiable. Every module that touches financial data must maintain the integrity of the general ledger.
-- **Composition over configuration:** Users don't configure complex settings. They activate pre-built modules. The platform composes their experience from tested building blocks.
-- **Industry-native experience:** When a restaurant owner uses the platform, it should feel like it was built for restaurants. The terminology, the dashboards, the workflows, the reports — all should speak their language.
-- **Progressive complexity:** Start simple. A sole-owner café might only use core accounting and invoicing. A multi-location restaurant group might activate 15 modules. Both are well-served.
-- **Open data, no lock-in:** SIE4 export is always available. Users own their data. The platform competes on value, not on trapping users.
-
----
-
-## 3. Target Users & Market
-
-### 3.1 Primary Target
-
-Swedish aktiebolag (AB) with 5–50 employees. This segment is large enough to need real accounting but small enough to be underserved by enterprise ERP systems. They typically use Fortnox or Visma today and find these tools either too rigid or too complex.
-
-### 3.2 User Personas
-
-#### Persona 1: The Restaurant Owner
-
-- **Name:** Maria, 38, owns a mid-range restaurant in Göteborg with 12 employees
-- **Current tools:** Fortnox for accounting, Excel for food cost tracking, paper for daily cash reconciliation
-- **Pain points:** Can't see real-time food cost percentage in her accounting system. Spends hours reconciling Z-rapporter manually. Her accountant (redovisningskonsult) has to explain the financial reports because they're too abstract.
-- **What she wants:** Open the app in the morning, see yesterday's omsättning, matkostnadsprocent, and personalkostnad. Import Z-rapport with one click. Have her bokföringsbyrå access the same system.
-
-#### Persona 2: The Redovisningskonsult
-
-- **Name:** Erik, 45, runs a small bokföringsbyrå with 8 clients across different industries
-- **Current tools:** Fortnox for all clients, same interface regardless of industry
-- **Pain points:** Has to manually set up chart of accounts differently for each client. Wastes time explaining generic reports. Wants to standardize his process per industry.
-- **What he wants:** Set up a new restaurant client in 10 minutes with the right modules pre-activated. See all his clients in one view. Access industry-relevant reports without custom configuration.
-
-#### Persona 3: The Growing Business
-
-- **Name:** Ahmed, 32, started a food truck, now expanding to a second location and considering a café
-- **Current tools:** Bokio (outgrowing it), spreadsheets for everything else
-- **Pain points:** Bokio is too basic. Fortnox feels like it's built for accountants, not business owners. Needs to track multiple locations but doesn't want enterprise pricing.
-- **What he wants:** A system that grows with him. Start with food truck modules, add café modules when he expands. One platform, one subscription, one view of his whole business.
-
-### 3.3 Market Size
-
-There are approximately 430,000 active aktiebolag in Sweden. The addressable market of businesses with 5–50 employees in service industries represents roughly 80,000–120,000 companies. The Swedish cloud accounting market is estimated at 8–10 billion SEK annually.
-
----
-
-## 4. Core Platform Architecture
-
-### 4.1 Architecture Overview
-
-The platform follows a three-layer architecture where each layer has clear responsibilities and boundaries:
-
-| Layer | Description | Who Controls It | Examples |
-|---|---|---|---|
-| **Layer 1: Core Engine** | Accounting foundation. Always active. Handles double-entry bookkeeping, BAS-kontoplan, moms, SIE, financial statements. | Platform team only. Never modified by modules. | Huvudbok, verifikationer, momsredovisning, resultaträkning, balansräkning |
-| **Layer 2: Feature Modules** | Self-contained functionality packages. Activated per tenant. Hook into the core via events and APIs. | Platform team builds all modules. Users activate/deactivate. | Fakturering, kassaintegration, matkostnadsanalys, kvittoskanning |
-| **Layer 3: Business Type Config** | Metadata layer. Maps business types to recommended modules. Controls UI terminology and dashboard defaults. | Platform team maintains mappings. Users select their type. | Restaurant pack, Salon pack, Gym pack |
-
-### 4.2 Multi-Tenancy Model
-
-The platform is a single-codebase, multi-tenant SaaS application. All tenants share the same deployment, the same database server (Supabase PostgreSQL), and the same module code. Tenant isolation is achieved through a `tenant_id` column on every database table, enforced at both the application level and through PostgreSQL Row Level Security (RLS) policies — a natural fit since Supabase has first-class RLS support.
-
-Each tenant has a configuration record that tracks which modules are active, which business type they've selected, and any module-specific settings. This configuration drives the entire user experience: which navigation items appear, which dashboard widgets are shown, which pages are accessible, and which API endpoints are available.
-
-### 4.3 Module Lifecycle
-
-Modules go through the following states:
-
-- **Available:** The module exists in the catalog but is not active for this tenant. Its pages, widgets, and routes are hidden.
-- **Activating:** The user has chosen to activate the module. The platform runs the module's `onActivate` hook, which may seed default data and register event subscriptions.
-- **Active:** The module is fully operational. Its navigation items, pages, widgets, API routes, and event hooks are all live.
-- **Deactivating:** The user has chosen to deactivate. The platform runs `onDeactivate`, which hides UI elements and unregisters event hooks. Data is preserved.
-- **Inactive:** Same as Available but retains any data from when it was active. Reactivating restores the module with its previous data intact.
-
-> **Design Decision — Data Preservation:** When a module is deactivated, its data is never deleted. This is critical for accounting integrity. If a user activated kassaintegration for 6 months and then deactivated it, those 6 months of dagskassa records must remain in the database and be accessible for auditing and reporting. Deactivation only hides the UI and stops event processing.
-
----
-
-## 5. Module System Design
-
-### 5.1 Module Contract
-
-Every module is a feature folder in the codebase that exports a standardized definition. This contract is the foundation of the entire system. A module can register the following capabilities:
-
-| Capability | Description | Example |
-|---|---|---|
-| **Database Schema** | New tables required by this module (defined in Supabase migrations) | `mod_kassa_dagskassa` table for daily cash register data |
-| **API Routes** | Next.js API route handlers under `app/api/modules/{moduleId}/` | `GET /api/modules/kassaintegration/dagskassa/:date` |
-| **Supabase Edge Functions** | Server-side logic for external integrations requiring secrets | Tink bank API calls, Stripe webhook processing |
-| **Event Hooks** | Subscriptions to core events or other module events | On `leverantorsfaktura.added`, check if food supplier and update food cost |
-| **Navigation Items** | Sidebar menu entries that appear when module is active | "Dagskassa" and "Z-rapporter" menu items |
-| **Pages** | Full page views accessible via Next.js routing | DagskassaPage showing daily sales breakdown |
-| **Dashboard Widgets** | Cards/charts that appear on the user's dashboard | Today's sales widget showing revenue vs yesterday |
-| **Settings Panel** | Module-specific configuration UI | Select POS system type, configure moms split defaults |
-| **Seed Data** | Default data created when module is activated | Default BAS-konto mappings for food cost categories |
-| **Scheduled Jobs** | Recurring background tasks (via Supabase pg_cron or Edge Functions + cron) | Nightly food cost percentage rollup calculation |
-| **Dependencies** | Other modules that must be active for this one to work | Matkostnadsanalys depends on varuinkop module |
-
-### 5.2 Module Registration Pattern
-
-Modules are statically imported and registered at build time. There is no dynamic plugin loading. This is a deliberate choice for a small team: it keeps the system simple, fully type-safe, and easy to debug. Every module is part of the same codebase, the same test suite, and the same deployment.
-
-The module registry maintains a master list of all available modules. At runtime, it consults the tenant's configuration (stored in the `tenant_modules` table in Supabase) to determine which modules are active and should have their routes, hooks, and UI elements registered for that tenant's requests.
-
-### 5.3 Module Isolation Rules
-
-- **Modules may read from core tables:** Any module can query the general ledger, chart of accounts, invoices, and other core data via Supabase client or server-side queries.
-- **Modules must not write to core tables directly:** Instead, modules use core services (e.g., `verifikation.create()`) to interact with the accounting engine. This ensures all writes go through validation and double-entry enforcement.
-- **Modules own their own tables:** Each module prefixes its tables (e.g., `mod_kassa_`, `mod_food_cost_`) and has full read/write access to them. All module tables have RLS policies scoped to `tenant_id`.
-- **Modules communicate via events:** If module A needs to notify module B of something, it emits an event. Module B subscribes. There are no direct function calls between modules.
-- **Modules may extend core UI:** Modules can add widgets to the dashboard, items to the navigation, and columns to existing list views via extension points defined by the core.
-
-### 5.4 Module Dependency Management
-
-Some modules depend on other modules. For example, matkostnadsanalys (food cost analysis) requires varuinkop (purchasing) to be active because it analyzes purchasing data. When a user tries to activate a module with unmet dependencies, the platform clearly shows what else needs to be activated and offers to activate the dependencies together.
-
-Circular dependencies are not allowed and are enforced at build time through static analysis of the module definitions.
-
----
-
-## 6. Core Accounting Engine (Always Active)
-
-### 6.1 Overview
-
-The core accounting engine is the non-negotiable foundation of the platform. It is always active for every tenant and cannot be deactivated or modified by modules. It implements Swedish accounting standards as defined by BFN (Bokföringsnämnden), BFL (Bokföringslagen), and ÅRL (Årsredovisningslagen) for K2 companies.
-
-### 6.2 Chart of Accounts (BAS-kontoplan)
-
-The platform ships with the standard BAS-kontoplan pre-configured. On tenant creation, the full BAS 2024 chart of accounts is seeded into the tenant's account table. The platform supports all standard BAS account classes:
-
-| Class | Range | Description | Examples |
-|---|---|---|---|
-| 1 | 1000–1999 | Tillgångar (Assets) | 1930 Bankkonto, 1910 Kassa, 1510 Kundfordringar |
-| 2 | 2000–2999 | Eget kapital & skulder | 2440 Leverantörsskulder, 2610 Utgående moms 25% |
-| 3 | 3000–3999 | Intäkter (Revenue) | 3001 Försäljning varor 25%, 3002 Försäljning varor 12% |
-| 4 | 4000–4999 | Varuinköp & direkta kostnader | 4010 Inköp varor, 4011 Inköp livsmedel |
-| 5–6 | 5000–6999 | Övriga externa kostnader | 5010 Lokalhyra, 6110 Kontorsförnödenheter |
-| 7 | 7000–7999 | Personalkostnader | 7010 Löner, 7510 Arbetsgivaravgifter |
-| 8 | 8000–8999 | Finansiella poster & bokslut | 8310 Ränteintäkter, 8999 Årets resultat |
-
-Users can customize account names and add sub-accounts but cannot modify the fundamental structure. Modules can suggest additional accounts during their activation (e.g., the food cost module suggests adding 4011 Inköp livsmedel if not present).
-
-### 6.3 Double-Entry Bookkeeping Engine
-
-Every financial transaction in the system is recorded as a verifikation (journal entry) with one or more debit and credit rows that must balance to zero. The engine enforces the following invariants:
-
-- **Balance requirement:** Sum of all debit amounts must equal sum of all credit amounts for every verifikation. Unbalanced entries are rejected.
-- **Immutability:** Posted verifikationer cannot be modified. Corrections are made by creating new correcting entries. This complies with BFL 5 kap. 5§.
-- **Sequential numbering:** Verifikationer are numbered sequentially within each räkenskapsår (fiscal year) with no gaps. This complies with BFL 5 kap. 6§.
-- **Audit trail:** Every verifikation records who created it, when, and from which source (manual entry, module, import, integration).
-- **Period control:** Entries can only be posted to open periods. Closed periods are locked and require explicit re-opening with audit logging.
-
-### 6.4 Momsredovisning (VAT Reporting)
-
-The platform handles Swedish moms (VAT) at all standard rates:
-
-| Rate | Usage | BAS Account (Output) | BAS Account (Input) |
-|---|---|---|---|
-| 25% | Standard rate (most goods and services) | 2610 Utgående moms 25% | 2640 Ingående moms |
-| 12% | Food, restaurant services, hotel | 2620 Utgående moms 12% | 2640 Ingående moms |
-| 6% | Books, newspapers, culture, transport | 2630 Utgående moms 6% | 2640 Ingående moms |
-| 0% | Healthcare, education, financial services | N/A | N/A |
-
-The system automatically determines the momsredovisningsperiod based on the company's annual turnover: monthly (omsättning > 40M SEK), quarterly (> 1M SEK), or annually. It generates the momsdeklaration (VAT return) data in the format required by Skatteverket.
-
-### 6.5 Financial Statements
-
-The core engine generates the following reports, always available to every tenant:
-
-- **Resultaträkning (Income Statement):** Follows the K2 format with revenue, cost of goods sold, gross profit, operating expenses, operating result, financial items, and net result.
-- **Balansräkning (Balance Sheet):** Assets (tillgångar), equity and liabilities (eget kapital och skulder), following K2 structure.
-- **Huvudbok (General Ledger):** Complete listing of all transactions per account for any selected period.
-- **Verifikationslista (Journal Entry List):** Sequential list of all verifikationer with full details.
-- **Saldobalans (Trial Balance):** All accounts with their debit/credit balances for a selected period.
-- **Momsrapport (VAT Report):** Summary of output and input VAT for the declaration period.
-
-### 6.6 SIE4 Import & Export
-
-SIE (Standard Import Export) version 4 is the standard data exchange format for Swedish accounting. The platform supports full SIE4 import (for migrating from another system) and export (for sharing with accountants or switching systems). The import process validates data integrity, maps accounts to the BAS-kontoplan, and flags any discrepancies for manual review.
-
-### 6.7 Räkenskapsår (Fiscal Year) Management
-
-The core supports standard calendar-year fiscal years (January–December) and brutet räkenskapsår (non-calendar fiscal years). It handles årsbokslut (year-end closing) by transferring the result to retained earnings and opening balances for the new year. The first räkenskapsår may be shorter or longer than 12 months as permitted by ÅRL.
-
----
-
-## 7. Module Catalog: Categories & Modules
-
-### 7.1 Catalog Structure
-
-The module catalog is organized into categories. Each category groups related functionality. Users browse the catalog to discover and activate modules. When a user selects their business type, relevant categories and modules are highlighted with recommendation badges.
-
-### 7.2 Category: Fakturering & Betalning
-
-Modules related to invoicing, payments, and accounts receivable.
-
-| Module | Description | Dependencies | Key Features |
-|---|---|---|---|
-| **Kundfakturering** | Create, send, and manage customer invoices with Swedish compliance (Mervärdeskattelagen) | Core | Invoice creation, PDF generation, email sending, OCR-nummer, payment status tracking, kundreskontra |
-| **Autofakturering** | Recurring invoice automation for subscription-based services | Kundfakturering | Recurring schedules, automatic generation and sending, pause/resume |
-| **ROT/RUT-hantering** | Handle ROT and RUT tax deductions on invoices per Skatteverket rules | Kundfakturering | Automatic calculation of deduction amount, Skatteverket formatting, buyer personnummer handling |
-| **Påminnelser & Inkasso** | Automated payment reminders and debt collection integration | Kundfakturering | Configurable reminder schedules, late fees (dröjsmålsränta), inkasso handoff |
-
-### 7.3 Category: Bank & Likviditet
-
-| Module | Description | Dependencies | Key Features |
-|---|---|---|---|
-| **Bankintegration** | Auto-import bank transactions via Tink or Open Banking APIs | Core | Daily auto-import, multi-bank support, transaction categorization |
-| **Automatisk matchning** | AI-assisted matching of bank transactions to invoices and expenses | Bankintegration | Rule-based matching, learning from corrections, unmatched queue |
-| **Likviditetsprognos** | Cash flow forecasting based on receivables, payables, and recurring costs | Bankintegration, Kundfakturering | 30/60/90-day forecasts, scenario modeling, alert thresholds |
-
-### 7.4 Category: Leverantörer & Inköp
-
-| Module | Description | Dependencies | Key Features |
-|---|---|---|---|
-| **Leverantörsreskontra** | Manage supplier invoices, payment tracking, and accounts payable | Core | Invoice registration, due dates, payment scheduling, OCR import |
-| **Inköpsorder** | Create and track purchase orders to suppliers | Leverantörsreskontra | PO creation, supplier management, delivery tracking, PO-to-invoice matching |
-| **Kvittoskanning** | OCR-based receipt scanning that auto-creates bokföring entries | Core | Photo capture, OCR extraction, auto-kontosättning, manual review queue |
-
-### 7.5 Category: Rapporter & Analys
-
-| Module | Description | Dependencies | Key Features |
-|---|---|---|---|
-| **Budgetmodul** | Set budgets per account/category and track actual vs budget | Core | Annual budget setup, monthly breakdown, variance analysis, alerts |
-| **KPI-dashboard** | Customizable dashboard with business-relevant key metrics | Core | Configurable widgets, period comparison, export to PDF |
-| **Periodjämförelse** | Compare financial performance across months, quarters, or years | Core | Side-by-side comparison, trend visualization, anomaly highlighting |
-
-### 7.6 Category: Personal & Lön
-
-| Module | Description | Dependencies | Key Features |
-|---|---|---|---|
-| **Löneintegration** | Import salary data from external payroll systems (Hogia, Visma Lön, etc.) | Core | File import, auto-bokföring of payroll entries, arbetsgivaravgifter |
-| **Personalkostnadsöversikt** | Track and analyze total staff costs vs revenue | Löneintegration | Cost per employee, ratio to omsättning, trend analysis |
-| **Traktamente & Utlägg** | Employee expense and travel allowance management | Core | Expense submission, approval workflow, Skatteverket traktamente rates |
-| **Semesterskuldberäkning** | Calculate and track vacation pay liability per employee | Löneintegration | Automatic calculation per ÅL, liability tracking, period accruals |
-
-### 7.7 Category: Restaurang & Mat (F&B Cluster)
-
-These modules are recommended for businesses in the Food & Beverage industry cluster. This is the first industry-specific category to be built.
-
-| Module | Description | Dependencies | Key Features |
-|---|---|---|---|
-| **Kassaintegration** | Import Z-rapporter from POS systems and auto-bokför daily sales | Core | CSV/file import, iZettle/Trivec support, automatic moms split (12%/25%), dagskassaavstämning |
-| **Matkostnadsanalys** | Track and analyze food cost as percentage of revenue | Inköpsorder | Daily/weekly/monthly food cost %, target vs actual, trend charts, alerts when over target |
-| **Svinnhantering** | Record and analyze food waste by category | Matkostnadsanalys | Waste logging, cost calculation, waste-to-revenue ratio, category breakdown |
-| **Tipshantering** | Track, allocate, and report tips received by staff | Core | Tip pool management, per-employee allocation, tax reporting, bokföring integration |
-| **Receptkalkyl** | Calculate cost per recipe/menu item based on ingredient prices | Inköpsorder | Recipe builder, cost per portion, margin calculation, price change impact analysis |
-| **Alkohol & Accis** | Handle alcohol excise tax (punktskatt) for breweries and bars | Core | Accis calculation, Tullverket reporting format, inventory tracking for excise goods |
-
-### 7.8 Future Categories (Post-MVP)
-
-The following categories are planned for future development and listed here to inform architectural decisions:
-
-- **Salong & Skönhet:** Bokningsintegration, provisionsberäkning per anställd, produktförsäljning (retail vs tjänst moms split).
-- **Fitness & Hälsa:** Medlemshantering, autogiroförsäljning, drop-in vs abonnemang tracking.
-- **Bygg & Hantverkare:** ROT-avdragshantering, projektbudget vs utfall, ÄTA-hantering, underentreprenörsspårning.
-- **E-handel:** Shopify/WooCommerce-integration, automatbokföring av ordrar, lagervärdering, returhantering, multi-currency.
-- **Konsultbolag:** Projektredovisning, timregistrering, milstolpsfakturering, resekostnader.
-
----
-
-## 8. Industry Packs & Business Type Recommendations
-
-### 8.1 How Industry Packs Work
-
-An industry pack is not a separate product or a pre-configured instance. It is a metadata layer that maps a business type to a set of recommended modules. When a user selects their business type during onboarding (or changes it later in settings), the platform uses this mapping to surface relevant modules in the catalog with recommendation badges.
-
-The user is never restricted to their industry pack's recommendations. They can browse the entire catalog and activate any module. The business type selection simply provides a curated starting point.
-
-### 8.2 F&B Cluster: Business Types and Recommended Modules
-
-| Module | Restaurang | Café | Bageri | Bar/Pub | Bryggeri | Food Truck | Catering |
-|---|---|---|---|---|---|---|---|
-| Kundfakturering | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓✓ |
-| Leverantörsreskontra | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Kassaintegration | ✓✓ | ✓✓ | ✓ | ✓✓ | ✓ | ✓ | — |
-| Matkostnadsanalys | ✓✓ | ✓ | ✓✓ | — | ✓ | ✓ | ✓ |
-| Svinnhantering | ✓✓ | ✓ | ✓✓ | — | — | ✓ | ✓ |
-| Tipshantering | ✓✓ | ✓ | — | ✓✓ | — | — | — |
-| Receptkalkyl | ✓ | ✓ | ✓✓ | — | ✓✓ | ✓ | ✓ |
-| Alkohol & Accis | ✓ | — | — | ✓✓ | ✓✓ | — | ✓? |
-| Inköpsorder | ✓ | ✓ | ✓✓ | ✓ | ✓✓ | ✓ | ✓ |
-| Bankintegration | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Personalkostnadsöversikt | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ |
-| KPI-dashboard | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-
-**Legend:** ✓✓ = Highly recommended (pre-checked during onboarding), ✓ = Recommended (shown prominently), — = Not typically relevant (available but not highlighted).
-
-### 8.3 Onboarding Module Suggestion UX
-
-After the user selects their business type, the platform presents a module suggestion screen organized into three tiers:
-
-- **Included with your plan:** Core accounting modules that are always active (huvudbok, moms, resultaträkning, etc.)
-- **Recommended for your business:** Modules flagged as ✓✓ for their business type, pre-checked. The user can uncheck any they don't want.
-- **Also popular in your industry:** Modules flagged as ✓, shown but not pre-checked.
-
-Below these, a link to "Browse all modules" opens the full catalog. This onboarding step is skippable and all choices are changeable later.
-
----
-
-## 9. User Experience & Onboarding Flow
-
-### 9.1 Onboarding Flow
-
-The onboarding is designed to get the user to a working, personalized accounting platform in under 5 minutes:
-
-1. **Create Account:** Email/password or BankID login via Supabase Auth. Enter company org.nr.
-2. **Company Setup:** Platform pulls company data from Bolagsverket via org.nr (company name, address, F-skatt status, momsregistrering, SNI-kod). User confirms or corrects.
-3. **Import or Start Fresh:** Option to import SIE4 file from existing system (Fortnox, Visma) or start with a clean räkenskapsår. Import includes validation and discrepancy flagging.
-4. **Select Business Type:** Visual grid of business types organized by industry cluster. SNI-kod from Bolagsverket can auto-suggest. User picks one (or skips for generic setup).
-5. **Module Suggestions:** Based on business type, platform suggests recommended modules (as described in section 8.3). User reviews and confirms.
-6. **Connect Bank:** Optional step to connect their bank account via Tink/Open Banking for automatic transaction import.
-7. **Dashboard:** User lands on their personalized dashboard with active module widgets, quick-start guide, and contextual help.
-
-### 9.2 Main Application Layout
-
-The application follows a standard SaaS layout with module-driven navigation:
-
-- **Left sidebar:** Primary navigation. Shows core items (Dashboard, Bokföring, Rapporter) at the top, followed by active module navigation items grouped by category. Inactive modules are not shown.
-- **Top bar:** Company name, räkenskapsår selector, notification bell, user menu, and a search bar that searches across all active modules.
-- **Main content area:** Renders the active page from either core or an active module via Next.js App Router.
-- **Dashboard:** The home page. Shows widgets from active modules arranged in a grid. Users can rearrange widgets but the initial layout is determined by the business type configuration.
-
-### 9.3 Module Catalog UI
-
-Accessible from settings, the module catalog is where users discover and manage modules:
-
-- **Category browsing:** Modules organized by category with counts showing how many are active vs available.
-- **Recommendation badges:** Modules recommended for the user's business type are badged with "Rekommenderas för [business type]."
-- **Module detail page:** Each module has a detail page showing description, screenshots, what it adds (pages, widgets, reports), dependencies, and an activate/deactivate button.
-- **Active modules view:** A filtered view showing only currently active modules with quick deactivation options.
-
-### 9.4 Redovisningskonsult (Accountant) Access
-
-The platform supports a multi-user model where a business owner can invite their bokföringsbyrå (accounting firm) to access their account. The accountant gets a separate role with access to all accounting data and reports, the ability to create and edit verifikationer, perform årsbokslut, and generate SIE exports. The accountant may have access to multiple client tenants and can switch between them from a single login.
-
----
-
-## 10. Technical Architecture
-
-### 10.1 Tech Stack
-
-| Component | Technology | Rationale |
-|---|---|---|
-| **Language** | TypeScript (everywhere) | Team's strongest language. Shared types between frontend and backend. Single language reduces context switching. |
-| **Framework** | Next.js (App Router) | Full-stack React framework. API routes, Server Components, Server Actions, SSR/SSG — all in one. One deploy, one mental model. Eliminates need for separate backend. |
-| **Styling** | Tailwind CSS + shadcn/ui | Utility-first for rapid development. shadcn/ui provides professional, accessible components out of the box. |
-| **Database** | PostgreSQL (via Supabase) | Rock-solid, ACID-compliant, perfect for financial data. Supabase provides managed Postgres with built-in RLS, auth, storage, edge functions, and real-time. |
-| **Backend-as-a-Service** | Supabase | Handles auth, database, storage, edge functions, real-time subscriptions, and cron jobs (pg_cron). Reduces infrastructure work dramatically for a small team. |
-| **ORM / Query** | Supabase JS Client + Drizzle ORM | Supabase client for standard CRUD and RLS-enforced queries. Drizzle for complex queries, migrations, and type-safe schema definitions. |
-| **Authentication** | Supabase Auth | Built-in email/password, magic link, OAuth providers, and potential for BankID via custom provider. Row-level security integrates directly with auth. |
-| **File Storage** | Supabase Storage | Receipt images, invoice PDFs, SIE file uploads. Scoped per tenant with storage policies. |
-| **Edge Functions** | Supabase Edge Functions (Deno) | Server-side logic requiring secrets: bank API calls (Tink), payment webhooks (Stripe), OCR processing, Skatteverket integration. |
-| **Scheduled Jobs** | Supabase pg_cron + Edge Functions | Nightly food cost rollups, bank transaction sync, overdue invoice checks. pg_cron triggers Edge Functions on schedule. |
-| **Hosting** | Vercel (frontend) + Supabase (backend) | Vercel for Next.js with EU region deployment. Supabase for all backend services with EU region (Frankfurt or Stockholm). Both support EU data residency. |
-| **Testing** | Vitest + Playwright | Vitest for unit/integration (fast, TypeScript-native). Playwright for E2E. |
-| **CI/CD** | GitHub Actions | Standard, integrates with Vercel deployments and Supabase migrations. |
-
-### 10.2 Project Structure
-
-The entire application lives in a single Next.js project:
-
-```
-├── app/ ← Next.js App Router
-│ ├── (auth)/ ← Auth pages (login, signup, onboarding)
-│ │ ├── login/page.tsx
-│ │ ├── signup/page.tsx
-│ │ └── onboarding/
-│ │ ├── company/page.tsx
-│ │ ├── business-type/page.tsx
-│ │ └── modules/page.tsx
-│ │
-│ ├── (app)/ ← Authenticated app shell
-│ │ ├── layout.tsx ← Sidebar + topbar (reads active modules)
-│ │ ├── dashboard/page.tsx ← Dynamic dashboard with module widgets
-│ │ │
-│ │ ├── bokforing/ ← Core accounting pages
-│ │ │ ├── huvudbok/page.tsx
-│ │ │ ├── verifikationer/page.tsx
-│ │ │ ├── kontoplan/page.tsx
-│ │ │ └── perioder/page.tsx
-│ │ │
-│ │ ├── rapporter/ ← Core report pages
-│ │ │ ├── resultatrakning/page.tsx
-│ │ │ ├── balansrakning/page.tsx
-│ │ │ ├── momsrapport/page.tsx
-│ │ │ └── saldobalans/page.tsx
-│ │ │
-│ │ ├── moduler/ ← Module catalog
-│ │ │ ├── page.tsx ← Browse all modules
-│ │ │ └── [moduleId]/page.tsx ← Module detail page
-│ │ │
-│ │ ├── installningar/ ← Settings
-│ │ │ ├── foretag/page.tsx
-│ │ │ ├── anvandare/page.tsx
-│ │ │ └── moduler/page.tsx
-│ │ │
-│ │ └── m/ ← Module pages (namespaced)
-│ │ ├── fakturering/
-│ │ │ ├── page.tsx ← Invoice list
-│ │ │ └── ny/page.tsx ← New invoice
-│ │ ├── kassaintegration/
-│ │ │ ├── dagskassa/page.tsx
-│ │ │ └── z-rapporter/page.tsx
-│ │ ├── matkostnadsanalys/
-│ │ │ └── page.tsx
-│ │ └── ... more module pages
-│ │
-│ └── api/ ← API routes
-│ ├── core/ ← Core accounting API
-│ │ ├── verifikationer/route.ts
-│ │ ├── konton/route.ts
-│ │ └── rapporter/route.ts
-│ ├── modules/ ← Module API routes
-│ │ ├── fakturering/route.ts
-│ │ ├── kassaintegration/route.ts
-│ │ └── ... more module routes
-│ └── webhooks/ ← External webhooks
-│ ├── tink/route.ts
-│ └── stripe/route.ts
-│
-├── modules/ ← Module definitions & business logic
-│ ├── _registry.ts ← Master module registry
-│ ├── _types.ts ← Module contract types
-│ │
-│ ├── core-bokforing/ ← Core accounting (always active)
-│ │ ├── module.ts ← Module definition
-│ │ ├── services/
-│ │ │ ├── huvudbok.service.ts
-│ │ │ ├── verifikation.service.ts
-│ │ │ ├── moms.service.ts
-│ │ │ └── sie.service.ts
-│ │ ├── validators/
-│ │ │ └── verifikation.validator.ts
-│ │ └── events.ts ← Core events emitted
-│ │
-│ ├── fakturering/
-│ │ ├── module.ts
-│ │ ├── services/
-│ │ │ ├── faktura.service.ts
-│ │ │ └── paminnelse.service.ts
-│ │ ├── components/ ← Module-specific UI components
-│ │ │ ├── FakturaForm.tsx
-│ │ │ └── FakturaPreview.tsx
-│ │ ├── widgets/
-│ │ │ └── ObetaladaFakturorWidget.tsx
-│ │ └── hooks.ts ← Event subscriptions
-│ │
-│ ├── kassaintegration/
-│ │ ├── module.ts
-│ │ ├── services/
-│ │ │ ├── zrapport.parser.ts
-│ │ │ └── dagskassa.service.ts
-│ │ ├── components/
-│ │ │ └── ZRapportImport.tsx
-│ │ ├── widgets/
-│ │ │ └── DagensForsaljningWidget.tsx
-│ │ └── hooks.ts
-│ │
-│ ├── matkostnadsanalys/
-│ │ ├── module.ts
-│ │ ├── services/
-│ │ │ └── food-cost.service.ts
-│ │ ├── components/
-│ │ │ └── FoodCostChart.tsx
-│ │ ├── widgets/
-│ │ │ └── MatkostnadWidget.tsx
-│ │ └── hooks.ts
-│ │
-│ └── ... more modules
-│
-├── lib/ ← Shared utilities
-│ ├── supabase/
-│ │ ├── client.ts ← Browser Supabase client
-│ │ ├── server.ts ← Server-side Supabase client
-│ │ └── admin.ts ← Service role client (for migrations/admin)
-│ ├── events/
-│ │ ├── emitter.ts ← Typed event emitter
-│ │ └── types.ts ← Event type definitions
-│ ├── tenant/
-│ │ ├── context.ts ← Tenant context provider
-│ │ └── middleware.ts ← Tenant resolution middleware
-│ └── modules/
-│ ├── guard.ts ← Module activation check middleware
-│ └── loader.ts ← Active module loader for UI
-│
-├── components/ ← Shared UI components
-│ ├── ui/ ← shadcn/ui components
-│ ├── layout/
-│ │ ├── Sidebar.tsx ← Module-aware sidebar
-│ │ ├── Topbar.tsx
-│ │ └── DashboardGrid.tsx ← Widget grid renderer
-│ └── shared/
-│ ├── DataTable.tsx
-│ ├── KontoSelector.tsx
-│ └── PeriodPicker.tsx
-│
-├── supabase/ ← Supabase configuration
-│ ├── migrations/ ← Database migrations (Drizzle-generated)
-│ │ ├── 0001_core_tables.sql
-│ │ ├── 0002_bas_kontoplan_seed.sql
-│ │ ├── 0003_mod_fakturering.sql
-│ │ ├── 0004_mod_kassaintegration.sql
-│ │ └── ...
-│ ├── functions/ ← Supabase Edge Functions
-│ │ ├── tink-sync/index.ts
-│ │ ├── ocr-receipt/index.ts
-│ │ └── nightly-rollup/index.ts
-│ └── seed.sql ← Development seed data
-│
-├── types/ ← Global TypeScript types
-│ ├── database.ts ← Generated Supabase types
-│ ├── modules.ts ← Module system types
-│ └── accounting.ts ← Accounting domain types
-│
-├── middleware.ts ← Next.js middleware (auth + tenant resolution)
-├── next.config.ts
-├── tailwind.config.ts
-├── tsconfig.json
-└── package.json
-```
-
-### 10.3 Backend Architecture
-
-The backend uses a hybrid approach leveraging both Next.js and Supabase:
-
-- **Next.js API Routes** handle application logic: module activation/deactivation, complex business operations, report generation, SIE import/export, and any operation that requires orchestrating multiple database queries or service calls.
-- **Next.js Server Actions** handle form mutations: creating verifikationer, sending invoices, updating settings — anywhere a form submits data. This eliminates boilerplate API route code for simple CRUD operations.
-- **Supabase Direct Access** from the client handles simple reads: fetching lists, loading dashboard data, real-time subscriptions for collaborative editing. RLS policies ensure tenant isolation even for direct client queries.
-- **Supabase Edge Functions** handle external integrations: Tink bank API calls, OCR processing, Stripe webhooks — anything requiring secrets that shouldn't be in the Next.js bundle or that benefits from running close to the data.
-
-Request flow for a module operation: incoming request hits Next.js middleware (auth check, tenant resolution) → API route or Server Action checks module activation status → calls module service → service uses Supabase client for database operations → core events are emitted → subscribed module hooks process side effects.
-
-### 10.4 Frontend Architecture
-
-The frontend uses Next.js App Router with Server Components as the default. Module pages are regular Next.js pages under the `/m/` namespace. The app shell (`layout.tsx`) fetches the tenant's active modules and dynamically renders the sidebar navigation and dashboard widgets.
-
-Module UI code is organized within each module's feature folder (`modules/{name}/components/` and `modules/{name}/widgets/`). Module pages in `app/(app)/m/` import from these folders. This keeps the routing in Next.js's domain while the business logic and UI components live with the module definition.
-
-A module guard middleware wraps all `/m/{moduleId}/` routes and `/api/modules/{moduleId}/` routes, checking the tenant's active modules before allowing access. If the module is not active, the user sees a "Module not activated" page with a link to the catalog.
-
----
-
-## 11. Database Design
-
-### 11.1 Multi-Tenancy Strategy
-
-The platform uses a shared-database, shared-schema multi-tenancy model with row-level tenant isolation. Every table includes a `tenant_id` column. Supabase's built-in Row Level Security (RLS) is the primary isolation mechanism:
-
-```sql
--- Example RLS policy (applied to every table)
-CREATE POLICY "Tenant isolation" ON verifikationer
- USING (tenant_id = (SELECT current_setting('app.current_tenant_id')::uuid))
- WITH CHECK (tenant_id = (SELECT current_setting('app.current_tenant_id')::uuid));
-```
-
-The tenant ID is set in the Supabase session context via the JWT claims from Supabase Auth, ensuring that every query — whether from the Next.js server, the client, or an Edge Function — is automatically scoped to the correct tenant.
-
-### 11.2 Core Tables
-
-| Table | Purpose | Key Columns |
-|---|---|---|
-| `tenants` | Company/organization records | id, org_nr, name, address, f_skatt, moms_registered, moms_period, fiscal_year_start, business_type |
-| `users` | User accounts with tenant membership | id (Supabase Auth UID), tenant_id, email, name, role (owner, admin, staff, accountant) |
-| `accounts` | Chart of accounts (BAS-kontoplan) | tenant_id, account_number, name, type, is_active, parent_account |
-| `fiscal_years` | Räkenskapsår definitions | tenant_id, start_date, end_date, status (open, closed), opening_balances_posted |
-| `verifikationer` | Journal entries (the core of everything) | tenant_id, nummer, date, description, fiscal_year_id, created_by, source_module, is_posted |
-| `verifikation_rows` | Individual debit/credit lines | verifikation_id, account_number, debit, credit, moms_code, description |
-| `tenant_modules` | Which modules are active per tenant | tenant_id, module_id, activated_at, deactivated_at, status, config (JSONB) |
-| `business_types` | Reference table of business types | id, name, cluster, icon, sni_codes[], recommended_modules[] |
-
-### 11.3 Module Table Convention
-
-Every module that needs database storage follows the naming convention `mod_{module_short_name}_{table_name}`. For example, the kassaintegration module uses `mod_kassa_dagskassa` and `mod_kassa_z_rapporter`. All module tables include `tenant_id` and have RLS policies identical to core tables.
-
-Module tables are created via Supabase migrations stored in `supabase/migrations/`. The tables exist for all tenants (they're part of the shared schema), but only contain data for tenants that have activated the module. When a module is activated for a tenant, the `onActivate` hook may seed tenant-specific default data.
-
-### 11.4 Configuration Storage
-
-Module-specific configuration is stored as JSONB in the `tenant_modules` table's `config` column. This allows each module to store arbitrary settings (e.g., the kassaintegration module stores the POS system type and default moms split rules) without requiring schema changes. The JSONB schema is validated at the application level using Zod schemas defined in each module's definition.
-
----
-
-## 12. Event System
-
-### 12.1 Purpose
-
-The event system is the primary mechanism for inter-module communication and the way modules react to changes in the core accounting engine. It ensures loose coupling: the core and individual modules never call each other's functions directly. Instead, they emit typed events that any module can subscribe to.
-
-### 12.2 Core Events
-
-| Event | Emitted When | Payload |
-|---|---|---|
-| `verifikation.created` | A new journal entry is posted | tenantId, verifikationId, date, rows[], sourceModule |
-| `verifikation.reversed` | A correction entry reverses a previous one | tenantId, originalId, reversalId |
-| `faktura.created` | A new customer invoice is created | tenantId, fakturaId, customerId, totalAmount, momsAmount |
-| `faktura.sent` | An invoice is sent to the customer | tenantId, fakturaId, sentVia (email/post) |
-| `faktura.paid` | An invoice is marked as paid | tenantId, fakturaId, paymentDate, paymentMethod |
-| `faktura.overdue` | An invoice passes its due date unpaid | tenantId, fakturaId, dueDate, daysPastDue |
-| `leverantorsfaktura.added` | A new supplier invoice is registered | tenantId, fakturaId, supplierId, totalAmount, momsAmount |
-| `leverantorsfaktura.paid` | A supplier invoice is paid | tenantId, fakturaId, paymentDate |
-| `bank_transaction.imported` | A new bank transaction arrives | tenantId, transactionId, amount, date, description, bankAccount |
-| `bank_transaction.matched` | A bank transaction is matched to a record | tenantId, transactionId, matchedType, matchedId |
-| `period.closed` | A month/quarter is closed | tenantId, periodStart, periodEnd |
-| `period.reopened` | A previously closed period is reopened | tenantId, periodStart, periodEnd, reopenedBy |
-| `fiscal_year.closed` | A fiscal year is closed (årsbokslut) | tenantId, fiscalYearId |
-
-### 12.3 Implementation
-
-For the Next.js + Supabase architecture, the event system has two layers:
-
-**In-request events:** A simple typed event emitter (same pattern as before) handles synchronous events within a single API route or Server Action. When a verifikation is created, the emitter fires `verifikation.created` and all subscribed module hooks run within the same request. This covers the majority of use cases.
-
-**Async/cross-request events:** For events that need to trigger background processing (e.g., nightly rollups, or events that should fire even if no user is currently making a request), Supabase provides two mechanisms:
-
-- **Database triggers + pg_notify:** A PostgreSQL trigger fires on INSERT to `verifikationer`, sending a notification that a Supabase Edge Function can pick up.
-- **Supabase Realtime:** For real-time UI updates when another user or background process makes changes (e.g., accountant creates a verifikation, business owner's dashboard updates live).
-
-If a module's event handler fails, the failure is logged but does not roll back the core operation that emitted the event. Module handlers are expected to be idempotent and to handle their own error recovery.
-
----
-
-## 13. Security & Compliance
-
-### 13.1 Data Residency
-
-All data is stored within the EU. Supabase supports EU region deployment (Frankfurt). The Next.js frontend is deployed to Vercel's EU edge. This is a non-negotiable requirement for Swedish financial data. Both services must guarantee EU data residency and GDPR compliance.
-
-### 13.2 Authentication & Authorization
-
-Authentication is handled by Supabase Auth with support for email/password, magic links, and Google OAuth. BankID integration is a future consideration via a custom Supabase Auth provider.
-
-Authorization follows a role-based model:
-
-- **Owner:** Full access including billing and tenant settings.
-- **Admin:** Full access except billing.
-- **Staff:** Access to active modules, no admin functions.
-- **Accountant:** Read access to all financial data, write access to verifikationer and reports, access to SIE export and årsbokslut.
-
-Module-level authorization is enforced by middleware that checks whether the requested module is active for the tenant before processing the request. RLS policies in Supabase provide defense-in-depth at the database level.
-
-### 13.3 Financial Data Integrity
-
-- **Immutable verifikationer:** Once posted, journal entries cannot be modified. This is enforced at the database level with a PostgreSQL trigger that prevents UPDATE on posted verifikationer.
-- **Audit logging:** All state changes to financial data are logged with timestamp, user, and before/after values. Supabase's `auth.uid()` function automatically captures the acting user.
-- **Backup strategy:** Supabase provides automated daily backups with point-in-time recovery (PITR) on Pro plan. Minimum 7-day retention (30-day on Team plan).
-- **Encryption:** Data encrypted at rest (Supabase uses AES-256) and in transit (TLS 1.3). Sensitive fields (personnummer, bank account numbers) are additionally encrypted at the application level before storage.
-
----
-
-## 14. Integration Strategy
-
-### 14.1 Banking
-
-Bank transaction import via Tink (now part of Visa) or similar Open Banking aggregator. Tink supports all major Swedish banks (Swedbank, SEB, Nordea, Handelsbanken, Danske Bank, Länsförsäkringar). Implemented as the Bankintegration module, with the Tink API calls running in a Supabase Edge Function (to keep API secrets secure).
-
-### 14.2 POS Systems
-
-The kassaintegration module supports importing daily sales data from point-of-sale systems. Initial support focuses on file-based import (CSV, Z-rapport format) for maximum compatibility. Future versions will add direct API integrations with major Swedish POS providers: Zettle (iZettle), Trivec, Lightspeed, and Square.
-
-### 14.3 Payroll
-
-The löneintegration module imports salary data from external payroll systems. Initial support via SIE-L (the payroll subset of SIE) and CSV import. Future API integrations with Hogia Lön, Visma Lön, and Fortnox Lön.
-
-### 14.4 Skatteverket
-
-Electronic filing integration with Skatteverket for momsdeklaration and arbetsgivardeklaration. This is a high-value feature that requires certification. Planned for post-MVP when the core is stable.
-
-### 14.5 Third-Party API Strategy
-
-All external integrations follow a consistent adapter pattern within their respective modules. Each integration defines an adapter interface, and specific providers implement that interface. This allows swapping providers (e.g., switching from Tink to another bank aggregator) without modifying the module's business logic. External API calls always run in Supabase Edge Functions to keep secrets out of the Next.js client bundle.
-
----
-
-## 15. Development Roadmap
-
-### 15.1 Phase 1: Foundation (Weeks 1–5)
-
-Build the core infrastructure and accounting engine. No modules beyond the always-active core.
-
-- **Week 1–2:** Next.js project setup with App Router, Supabase project creation (EU region), Supabase Auth integration, multi-tenancy with RLS policies on all tables, basic module registry with one dummy module to validate the pattern, event system implementation, Tailwind + shadcn/ui component library setup.
-- **Week 3–4:** Core accounting engine: BAS-kontoplan seeding on tenant creation, verifikation creation with double-entry enforcement, huvudbok, saldobalans, period management. All core pages built with Server Components.
-- **Week 5:** Financial statements: resultaträkning and balansräkning generation, momsrapport, SIE4 export.
-
-> **Milestone 1:** At the end of Phase 1, a user can sign up, get a working bokföringssystem with BAS-kontoplan, create verifikationer, view huvudbok, generate resultaträkning, balansräkning, momsrapport, and export SIE4. No industry-specific features yet, but the core is rock-solid.
-
-### 15.2 Phase 2: First Modules (Weeks 6–10)
-
-Build the first set of universally useful modules.
-
-- **Week 6–7:** Kundfakturering module: invoice creation, PDF generation (via Supabase Edge Function or server-side), email sending, kundreskontra, payment tracking.
-- **Week 8:** SIE4 import (migration from other systems), leverantörsreskontra module.
-- **Week 9–10:** Bankintegration module (via Tink Edge Function): auto-import, transaction list, basic matching UI. Module catalog UI where users can browse and activate modules.
-
-> **Milestone 2:** At the end of Phase 2, the platform is a functional Fortnox alternative. Users can do daily bokföring, send invoices, track supplier bills, import bank transactions, and migrate from their old system via SIE4. The module system is live.
-
-### 15.3 Phase 3: F&B Cluster (Weeks 11–16)
-
-Build the first industry-specific modules and the business type selection/recommendation system.
-
-- **Week 11–12:** Kassaintegration module (Z-rapport import, dagskassa, auto-bokföring). Business type selection UI in onboarding.
-- **Week 13–14:** Matkostnadsanalys and svinnhantering modules.
-- **Week 15–16:** Tipshantering, receptkalkyl modules. KPI-dashboard module with customizable widgets. Industry pack recommendation engine.
-
-> **Milestone 3:** At the end of Phase 3, a restaurant owner can sign up, select "Restaurang," get recommended modules, activate them, and have a daily workflow that includes importing Z-rapporter, tracking food costs, managing tips, and seeing industry-specific KPIs. This is the differentiation point from Fortnox.
-
-### 15.4 Phase 4: Growth & Polish (Weeks 17–24)
-
-- **Weeks 17–18:** Kvittoskanning module (OCR via Supabase Edge Function), automatisk matchning (AI-assisted bank matching).
-- **Weeks 19–20:** Budgetmodul, periodjämförelse, advanced reporting.
-- **Weeks 21–22:** Accountant access (multi-client view), redovisningskonsult portal.
-- **Weeks 23–24:** Performance optimization, security audit, onboarding polish, preparation for public launch.
-
----
-
-## 16. Business Model & Pricing
-
-### 16.1 Pricing Strategy
-
-The pricing model follows a base-plus-modules approach:
-
-| Tier | Price (SEK/month) | Includes | Target |
-|---|---|---|---|
-| **Starter** | 199 | Core accounting, SIE export, 1 user, up to 3 modules | Solo founders, very small AB |
-| **Business** | 499 | Core accounting, SIE, invoicing, bank integration, 5 users, up to 10 modules | Small businesses, 5–15 employees |
-| **Professional** | 999 | Everything in Business, unlimited modules, unlimited users, accountant access, priority support | Growing businesses, 15–50 employees, businesses with accountant |
-| **Enterprise** | Custom | Custom pricing, SSO, dedicated support, SLA, custom integrations | Larger organizations, bokföringsbyråer managing many clients |
-
-### 16.2 Revenue Expansion
-
-The module system creates natural upsell paths. As users grow and need more functionality, they activate more modules, which may push them to higher tiers. Industry-specific modules provide clear value that justifies the Business or Professional tier. Accountant access is gated to the Professional tier, creating incentive for businesses whose bokföringsbyrå recommends the platform.
-
-### 16.3 Cost Structure
-
-Supabase pricing is usage-based (database size, edge function invocations, auth users, storage). The Pro plan ($25/month per project) covers most needs for early growth. Vercel Pro ($20/month per team member) handles the frontend. Total infrastructure cost at launch is estimated at $50–100/month, scaling with usage.
-
----
-
-## 17. Success Metrics & KPIs
-
-### 17.1 Product Metrics
-
-- **Activation rate:** Percentage of signups that complete onboarding and create at least one verifikation within 7 days. Target: > 40%.
-- **Module adoption:** Average number of active modules per tenant. Target: > 4 within first month.
-- **Daily active usage:** Percentage of paying tenants that log in at least once per business day. Target: > 60%.
-- **Churn rate:** Monthly churn of paying tenants. Target: < 3%.
-- **Net Promoter Score:** Measured quarterly. Target: > 50 (Fortnox averages ~30).
-
-### 17.2 Technical Metrics
-
-- **Page load time:** Largest Contentful Paint < 1.5s (leveraging Next.js Server Components and edge caching).
-- **API response time:** p95 < 200ms for all read operations, < 500ms for writes.
-- **Uptime:** 99.9% availability (< 8.7 hours downtime per year). Critical for accounting software.
-- **Module activation time:** < 2 seconds from click to fully active module with UI visible.
-- **SIE4 import speed:** < 30 seconds for a typical 3-year import with 10,000+ verifikationer.
-
----
-
-## 18. Risks & Mitigations
-
-| Risk | Impact | Likelihood | Mitigation |
-|---|---|---|---|
-| Accounting engine bugs causing incorrect financial data | Critical | Medium | Extensive test suite with known-good BAS scenarios. Double-entry balance check on every write. Automated reconciliation tests. External auditor review before launch. |
-| Module activation/deactivation causing data inconsistency | High | Medium | Modules never delete core data. Activation/deactivation wrapped in transactions. Comprehensive integration tests for module lifecycle. |
-| Supabase service outage affecting all tenants | High | Low | Supabase has 99.9% SLA on Pro. Implement graceful degradation for non-critical features. Daily backups with PITR. Document manual failover procedures. |
-| Tink/bank integration downtime | Medium | Medium | Graceful degradation: manual import always available. Queue failed syncs for retry. Clear user communication of sync status. |
-| Swedish accounting regulation changes (BAS update, moms rate change) | Medium | Low (annual) | Abstract regulatory values into configuration. BAS-kontoplan versioning. Regression tests for regulation-dependent calculations. |
-| Difficulty competing with Fortnox's ecosystem and integrations | High | High | Focus on differentiation (industry-specific experience) rather than matching Fortnox feature-for-feature. Target underserved segments first (restaurants, salons). |
-| Supabase vendor lock-in | Medium | Low | Use Drizzle ORM for schema/migrations (portable). Core business logic in Next.js, not Edge Functions. Supabase is open source — self-hosting is a fallback option. |
-| Performance degradation as data grows | Medium | Medium | Proper indexing (tenant_id + date on all queries). Supabase connection pooling (Supavisor). Read replicas for heavy reporting. Load testing at 10x expected volume. |
-
----
-
-## 19. Appendices
-
-### 19.1 Appendix A: Swedish Accounting Standards Reference
-
-- **BFL (Bokföringslagen 1999:1078):** The Swedish Bookkeeping Act. Defines who must keep books, requirements for verifikationer, arkivering (7 years), and årsbokslut obligations.
-- **BFN (Bokföringsnämnden):** The Swedish Accounting Standards Board. Issues BFNAR (Bokföringsnämndens allmänna råd) including the K2 and K3 frameworks.
-- **ÅRL (Årsredovisningslagen 1995:1554):** The Annual Reports Act. Defines the format and content of annual financial statements.
-- **K2 (BFNAR 2016:10):** Simplified annual report rules for smaller companies. Most AB in our target segment use K2. Defines fixed formats for resultaträkning and balansräkning.
-- **BAS-kontoplanen:** The standard chart of accounts used by virtually all Swedish companies. Maintained by BAS-kontogruppen. Updated annually.
-- **SIE (Standard Import Export):** The standard file format for exchanging accounting data between Swedish accounting systems. Version 4 (SIE4) includes full transaction-level data.
-- **Mervärdeskattelagen (ML):** The Swedish VAT Act. Defines moms rates, reporting periods, and compliance requirements.
-
-### 19.2 Appendix B: Glossary
-
-| Swedish Term | English Translation | Description |
-|---|---|---|
-| Bokföring | Bookkeeping | The recording of financial transactions |
-| Verifikation | Journal entry / voucher | A record of a financial transaction with debit and credit rows |
-| Huvudbok | General ledger | Complete record of all transactions organized by account |
-| Kontoplan | Chart of accounts | The structured list of accounts used for bookkeeping |
-| Räkenskapsår | Fiscal year | The 12-month period for financial reporting |
-| Resultaträkning | Income statement | Report showing revenue, costs, and profit/loss |
-| Balansräkning | Balance sheet | Report showing assets, equity, and liabilities |
-| Momsredovisning | VAT reporting | Periodic reporting of output and input VAT to Skatteverket |
-| Redovisningskonsult | Accounting consultant | External accountant managing a company's books |
-| Bokföringsbyrå | Accounting firm | Firm providing bookkeeping and accounting services |
-| Årsbokslut | Year-end closing | The process of closing a fiscal year and preparing annual reports |
-| Dagskassa | Daily cash register | Daily reconciliation of cash register / POS system sales |
-| Z-rapport | Z-report | End-of-day summary report from a POS system |
-| Kundreskontra | Accounts receivable | Tracking of outstanding customer invoices |
-| Leverantörsreskontra | Accounts payable | Tracking of outstanding supplier invoices |
-| Arbetsgivaravgifter | Employer contributions | Social security contributions paid by the employer |
-| Traktamente | Travel allowance | Per diem allowance for business travel |
-| Omsättning | Turnover / revenue | Total sales revenue for a period |
-| Matkostnadsprocent | Food cost percentage | Food cost as a percentage of food revenue (key F&B metric) |
-| Svinn | Waste / shrinkage | Food or inventory lost to waste, spoilage, or theft |
-
----
-
-*End of Document*
diff --git a/README.md b/README.md
index e215bc4c..dbe6347d 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,31 @@
-This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
+# erp-base
+
+Swedish accounting SaaS for sole traders (enskild firma) and limited companies (aktiebolag). Implements double-entry bookkeeping compliant with Swedish accounting law (Bokforingslagen), including VAT handling, tax reporting, and 7-year document retention.
+
+## Tech Stack
+
+- **Framework**: Next.js 16 (App Router), React 19, TypeScript (strict)
+- **Database**: Supabase (PostgreSQL + RLS + magic link auth)
+- **Styling**: Tailwind CSS 4 + shadcn/ui
+- **Hosting**: Vercel
+- **Integrations**: Enable Banking (PSD2), Anthropic SDK, OpenAI (embeddings), Resend (email), web-push (VAPID)
## Getting Started
-First, run the development server:
-
```bash
+npm install
npm run dev
-# or
-yarn dev
-# or
-pnpm dev
-# or
-bun dev
```
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+## Commands
-You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+```bash
+npm run dev # Start development server
+npm run build # Production build
+npm run lint # ESLint
+npm test # Run all Vitest tests
+```
-This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
+## Documentation
-## Learn More
-
-To learn more about Next.js, take a look at the following resources:
-
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
-
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
-
-## Deploy on Vercel
-
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
-
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
+See `CLAUDE.md` for comprehensive project documentation including architecture, bookkeeping engine, extension development, and database conventions.
diff --git a/app/(dashboard)/customers/page.tsx b/app/(dashboard)/customers/page.tsx
index e463e990..996ec003 100644
--- a/app/(dashboard)/customers/page.tsx
+++ b/app/(dashboard)/customers/page.tsx
@@ -161,7 +161,7 @@ export default function CustomersPage() {
) : (
-
+ setIsDialogOpen(true)} />
)}
diff --git a/app/(dashboard)/invoices/[id]/page.tsx b/app/(dashboard)/invoices/[id]/page.tsx
index 876fdd42..e88673d9 100644
--- a/app/(dashboard)/invoices/[id]/page.tsx
+++ b/app/(dashboard)/invoices/[id]/page.tsx
@@ -147,29 +147,45 @@ export default function InvoiceDetailPage({ params }: { params: Promise<{ id: st
setIsUpdating(true)
- const updates: Partial = { status }
- if (status === 'paid') {
- updates.paid_at = new Date().toISOString()
- updates.paid_amount = invoice.total
- }
+ try {
+ if (status === 'sent') {
+ // Use mark-sent API for proper bookkeeping
+ const response = await fetch(`/api/invoices/${invoice.id}/mark-sent`, {
+ method: 'POST',
+ })
+ if (!response.ok) {
+ const data = await response.json()
+ throw new Error(data.error || 'Kunde inte markera som skickad')
+ }
+ } else if (status === 'paid') {
+ // Use mark-paid API for proper bookkeeping
+ const response = await fetch(`/api/invoices/${invoice.id}/mark-paid`, {
+ method: 'POST',
+ })
+ if (!response.ok) {
+ const data = await response.json()
+ throw new Error(data.error || 'Kunde inte markera som betald')
+ }
+ } else {
+ // Other status changes (cancelled) — direct update is fine
+ const { error } = await supabase
+ .from('invoices')
+ .update({ status })
+ .eq('id', invoice.id)
+ if (error) throw new Error(error.message)
+ }
- const { error } = await supabase
- .from('invoices')
- .update(updates)
- .eq('id', invoice.id)
-
- if (error) {
- toast({
- title: 'Fel',
- description: 'Kunde inte uppdatera status',
- variant: 'destructive',
- })
- } else {
toast({
title: 'Uppdaterad',
description: `Fakturan är nu markerad som ${statusConfig[status].label.toLowerCase()}`,
})
fetchInvoice()
+ } catch (error) {
+ toast({
+ title: 'Fel',
+ description: error instanceof Error ? error.message : 'Kunde inte uppdatera status',
+ variant: 'destructive',
+ })
}
setIsUpdating(false)
diff --git a/app/(dashboard)/reports/page.tsx b/app/(dashboard)/reports/page.tsx
index 019b14ba..76de10b4 100644
--- a/app/(dashboard)/reports/page.tsx
+++ b/app/(dashboard)/reports/page.tsx
@@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button'
import { Label } from '@/components/ui/label'
import { Badge } from '@/components/ui/badge'
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
-import { Download, FileText, FileDown, TrendingUp, Scale, AlertCircle, Receipt, Briefcase } from 'lucide-react'
+import { Download, FileText, FileDown, TrendingUp, Scale, AlertCircle, Receipt, Briefcase, Building2 } from 'lucide-react'
import { NEDeclarationView } from '@/extensions/ne-bilaga/NEDeclarationView'
import { SRUExportView } from '@/extensions/sru-export/SRUExportView'
import type {
@@ -124,6 +124,10 @@ export default function ReportsPage() {
SRU-export
+
+
+ Lev.reskontra
+
@@ -146,6 +150,9 @@ export default function ReportsPage() {
+
+
+
) : (
@@ -898,3 +905,204 @@ function VatRutaRow({
>
)
}
+
+interface SupplierLedgerData {
+ ledger: {
+ entries: {
+ supplier_id: string
+ supplier_name: string
+ current: number
+ days_1_30: number
+ days_31_60: number
+ days_61_90: number
+ days_90_plus: number
+ total_outstanding: number
+ }[]
+ total_outstanding: number
+ total_current: number
+ total_overdue: number
+ unpaid_count: number
+ }
+ reconciliation: {
+ supplier_ledger_total: number
+ account_2440_balance: number
+ difference: number
+ is_reconciled: boolean
+ } | null
+}
+
+function SupplierLedgerView({ periodId }: { periodId: string }) {
+ const [data, setData] = useState(null)
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState(null)
+
+ const fetchData = async () => {
+ setLoading(true)
+ setError(null)
+ try {
+ const res = await fetch(`/api/reports/supplier-ledger?period_id=${periodId}`)
+ const result = await res.json()
+ if (result.error) {
+ setError(result.error)
+ } else {
+ setData(result.data)
+ }
+ } catch {
+ setError('Kunde inte hämta leverantörsreskontra')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ useEffect(() => {
+ if (periodId) fetchData()
+ }, [periodId])
+
+ if (loading) {
+ return (
+
+
+ Laddar leverantörsreskontra...
+
+
+ )
+ }
+
+ if (error) {
+ return (
+
+
+
+ {error}
+
+
+ )
+ }
+
+ if (!data || !data.ledger) {
+ return (
+
+
+ Ingen data tillgänglig.
+
+
+ )
+ }
+
+ const { ledger, reconciliation } = data
+
+ return (
+
+ {settings?.entity_type === 'aktiebolag'
+ ? 'Aktiebolag måste använda faktureringsmetoden enligt BFL.'
+ : 'Kontantmetoden är tillgänglig för enskild firma med omsättning under 3 MSEK.'}
+
- )
-}
-
-function formatSEK(amount: number): string {
- return new Intl.NumberFormat('sv-SE', {
- style: 'currency',
- currency: 'SEK',
- minimumFractionDigits: 0,
- }).format(amount)
-}
-```
-
----
-
-## Phase 7: Deployment
-
-### 7.1 Vercel Setup
-
-```json
-// vercel.json
-{
- "crons": [
- {
- "path": "/api/banking/sync",
- "schedule": "0 6 * * *"
- }
- ]
-}
-```
-
-### 7.2 Environment Variables in Vercel
-
-Set via Vercel dashboard or CLI:
-- `NEXT_PUBLIC_SUPABASE_URL`
-- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
-- `SUPABASE_SERVICE_ROLE_KEY`
-- Banking provider credentials
-
-### 7.3 Deploy Commands
-
-```bash
-# Push database migrations
-supabase db push
-
-# Deploy to Vercel
-vercel --prod
-```
-
----
-
-## MVP Launch Checklist
-
-- [ ] Auth flow working (magic link)
-- [ ] Profile + company settings CRUD
-- [ ] Manual transaction entry (before bank integration)
-- [ ] Transaction categorization (list view first, then swipe)
-- [ ] Tax calculation display
-- [ ] Customer CRUD
-- [ ] Invoice creation with VAT logic
-- [ ] PDF generation
-- [ ] Invoice list with status
-- [ ] Basic dashboard with balance card
-- [ ] Mobile responsive
-- [ ] Error handling + loading states
-- [ ] Legal disclaimer on tax estimates
diff --git a/dev_docs/07-FUTURE-FEATURES.md b/dev_docs/07-FUTURE-FEATURES.md
deleted file mode 100644
index 29dcd218..00000000
--- a/dev_docs/07-FUTURE-FEATURES.md
+++ /dev/null
@@ -1,519 +0,0 @@
-# Future Features & Regulatory Integrations
-
-## Phase 2: SIE File Import (Migration)
-
-### Overview
-
-SIE (Standard Import Export) is the Swedish standard for accounting data exchange. Users migrating from Fortnox, Visma, or other systems can export their data as SIE files.
-
-### SIE File Types
-
-| Type | Content | Use Case |
-|------|---------|----------|
-| SIE1 | Årssaldon | Year-end balances only |
-| SIE2 | Periodsaldon | Monthly/periodic balances |
-| SIE3 | Objektsaldon | Balances with cost centers |
-| SIE4 | Transaktioner | Full transaction history |
-
-**Recommended:** Support SIE4 for complete migration, SIE1/2 for simpler imports.
-
-### Implementation Notes
-
-```typescript
-// lib/import/sie-parser.ts
-
-interface SIETransaction {
- verifikationsnummer: string
- datum: Date
- kontonummer: string
- belopp: number
- text: string
-}
-
-interface SIEImportResult {
- company: {
- name: string
- orgNumber: string
- fiscalYearStart: Date
- }
- accounts: Array<{ number: string; name: string }>
- transactions: SIETransaction[]
- balances: Array<{ account: string; balance: number }>
-}
-
-// SIE files use CP437 encoding and specific format
-// Example line: #VER A 1 20240115 "Faktura 1001"
-```
-
-### Mapping Decisions Needed
-
-Before implementing, determine mapping for:
-- BAS account numbers → system categories
-- Opening balances → how to represent
-- Customer/supplier data (if present in SIE)
-- Historical invoices → create as "imported" status?
-
----
-
-## Phase 2: Benefits & Gifts Module (Förmånshantering)
-
-### Problem
-
-Influencers receive products ("PR-utskick", "gifted collabs") that may be taxable income. Skatteverket actively audits this. Getting it wrong = skattetillägg.
-
-### Decision Tree Logic
-
-```typescript
-// lib/benefits/gift-classifier.ts
-
-interface GiftClassification {
- taxable: boolean
- marketValue: number
- deductibleAsExpense: boolean
- bookingType: 'income' | 'income_and_expense' | 'tax_free'
- reasoning: string
-}
-
-interface GiftInput {
- estimatedValue: number
- hasMotprestation: boolean // Required post/video/mention?
- usedInBusiness: boolean // Used as props/equipment?
- usedPrivately: boolean // Personal use?
- isSimplePromoItem: boolean // Pen, mug, basic merch?
-}
-
-const TAX_FREE_PROMO_THRESHOLD = 450 // SEK, Skatteverket guideline
-
-export function classifyGift(input: GiftInput): GiftClassification {
- // Rule 1: Simple promotional items under threshold = tax free
- if (input.isSimplePromoItem && input.estimatedValue <= TAX_FREE_PROMO_THRESHOLD && !input.hasMotprestation) {
- return {
- taxable: false,
- marketValue: input.estimatedValue,
- deductibleAsExpense: false,
- bookingType: 'tax_free',
- reasoning: 'Enklare reklamgåva under 450 kr utan krav på motprestation'
- }
- }
-
- // Rule 2: Motprestation exists = always taxable
- if (input.hasMotprestation) {
- if (input.usedInBusiness && !input.usedPrivately) {
- return {
- taxable: true,
- marketValue: input.estimatedValue,
- deductibleAsExpense: true,
- bookingType: 'income_and_expense',
- reasoning: 'Skattepliktig förmån (motprestation krävdes). Avdragsgill som rekvisita då den endast används i verksamheten.'
- }
- }
-
- return {
- taxable: true,
- marketValue: input.estimatedValue,
- deductibleAsExpense: false,
- bookingType: 'income',
- reasoning: 'Skattepliktig förmån (motprestation krävdes). Ej avdragsgill då produkten används privat.'
- }
- }
-
- // Rule 3: High value without motprestation but used privately
- if (input.estimatedValue > TAX_FREE_PROMO_THRESHOLD && input.usedPrivately) {
- return {
- taxable: true,
- marketValue: input.estimatedValue,
- deductibleAsExpense: false,
- bookingType: 'income',
- reasoning: 'Värdet överstiger gränsen för skattefria reklamgåvor och produkten används privat.'
- }
- }
-
- // Default: taxable if significant value
- return {
- taxable: input.estimatedValue > TAX_FREE_PROMO_THRESHOLD,
- marketValue: input.estimatedValue,
- deductibleAsExpense: input.usedInBusiness,
- bookingType: input.estimatedValue > TAX_FREE_PROMO_THRESHOLD ? 'income' : 'tax_free',
- reasoning: 'Klassificering baserad på värde och användning'
- }
-}
-```
-
-### UI Flow
-
-1. User taps "Logga gåva/produkt"
-2. Photo capture or manual entry
-3. System queries price APIs (Prisjakt, Google Shopping) for value estimate
-4. Decision tree questions:
- - "Fanns krav på att du skulle posta om denna produkt?" [Ja/Nej]
- - "Använder du produkten i din content-produktion?" [Ja/Nej]
- - "Använder du produkten privat?" [Ja/Nej]
-5. System shows classification + tax impact
-6. Auto-booking to correct accounts
-
----
-
-## Phase 2: NE-bilaga Generation
-
-### SRU File Format
-
-Skatteverket accepts SRU (Standardiserat RäkenskapsUtdrag) files for tax form import.
-
-```typescript
-// lib/tax/sru-generator.ts
-
-interface NEBilaga {
- // R1-series: Income
- R1_nettoomsattning: number // Net revenue
- R2_ovriga_intakter: number // Other income
-
- // R3-series: Costs
- R3_varor: number // Cost of goods
- R4_ovriga_kostnader: number // Other expenses
- R5_personal: number // Personnel costs (usually 0 for sole proprietor)
- R6_avskrivningar: number // Depreciation
-
- // R7-series: Financial
- R7_ranteintakter: number
- R8_rantekostnader: number
-
- // Result
- R9_resultat: number // Profit/loss before adjustments
-
- // Adjustments
- R10_periodiseringsfond_avsatt: number // Max 30% of profit
- R11_periodiseringsfond_aterforing: number
- R12_expansionsfond: number
-
- // Final
- R14_overskott_underskott: number
-}
-
-function generateSRUFile(data: NEBilaga, personnummer: string, year: number): string {
- const lines: string[] = []
-
- // Header
- lines.push('#DATABESKRIVNING_START')
- lines.push('#PRODUKT SIE')
- lines.push('#FORMAT PC8')
- lines.push('#FILTYP NARINGSBILAGA')
- lines.push(`#UPPGIFTSLAMNARE ${personnummer}`)
- lines.push(`#INKOMSTAR ${year}`)
- lines.push('#DATABESKRIVNING_SLUT')
-
- // Data rows (simplified)
- lines.push(`#UPPGIFT 7001 ${data.R1_nettoomsattning}`) // R1
- lines.push(`#UPPGIFT 7002 ${data.R2_ovriga_intakter}`) // R2
- // ... continue for all fields
-
- lines.push('#UPPGIFT_SLUT')
-
- return lines.join('\n')
-}
-```
-
-### BAS Account to NE Mapping
-
-| BAS Account | Description | NE Ruta |
-|-------------|-------------|---------|
-| 3000-3999 | Intäkter | R1 |
-| 3900-3999 | Övriga rörelseintäkter | R2 |
-| 4000-4999 | Varuinköp | R3 |
-| 5000-6999 | Övriga externa kostnader | R4 |
-| 7000-7699 | Personalkostnader | R5 |
-| 7800-7899 | Avskrivningar | R6 |
-| 8300-8399 | Ränteintäkter | R7 |
-| 8400-8499 | Räntekostnader | R8 |
-
-### Tax Optimization Suggestions
-
-Before generating NE-bilaga, system should suggest:
-
-1. **Periodiseringsfond** (max 30% of profit)
- - Defer tax to future years
- - Must be reversed within 6 years
- - Good for income smoothing
-
-2. **Expansionsfond**
- - Tax profit at 22% corporate rate instead of marginal personal rate
- - Good if marginal rate > 22%
- - More complex rules
-
-```typescript
-function suggestTaxOptimization(profit: number, marginalTaxRate: number) {
- const suggestions = []
-
- if (profit > 0) {
- const maxPeriodisering = profit * 0.30
- suggestions.push({
- type: 'periodiseringsfond',
- amount: maxPeriodisering,
- taxSaved: maxPeriodisering * marginalTaxRate,
- description: `Sätt av ${formatSEK(maxPeriodisering)} till periodiseringsfond för att skjuta upp ${formatSEK(maxPeriodisering * marginalTaxRate)} i skatt.`
- })
- }
-
- if (profit > 100000 && marginalTaxRate > 0.30) {
- suggestions.push({
- type: 'expansionsfond',
- description: 'Din marginalskatt är hög. Överväg expansionsfond för att beskattas med 22% istället.'
- })
- }
-
- return suggestions
-}
-```
-
----
-
-## Phase 2b: AB Salary Optimization (3:12-reglerna)
-
-### Overview
-
-For aktiebolag owners, the split between lön (salary) and utdelning (dividend) significantly impacts total tax. The 3:12 rules (Inkomstskattelagen kapitel 57) determine how much dividend can be taxed at the favorable 20% rate vs marginal income tax rates.
-
-### Key Concepts
-
-| Term | Description |
-|------|-------------|
-| Gränsbelopp | Annual limit for dividend taxed at 20% |
-| Löneunderlag | Salary base that increases gränsbelopp |
-| Kvalificerade andelar | Shares where owner is "active" in company |
-| Sparat utdelningsutrymme | Unused gränsbelopp carried forward |
-
-### Gränsbelopp Calculation (Simplified)
-
-```typescript
-// lib/tax/ab-optimization.ts
-
-interface GransbeloppCalculation {
- schablonbelopp: number // 2.75 × inkomstbasbelopp
- lonebaserat: number // 50% of löneunderlag (if meets salary requirement)
- sparat: number // Carried forward from previous years
- totalGransbelopp: number
-}
-
-const INKOMSTBASBELOPP_2024 = 74300
-
-function calculateGransbelopp(
- ownerSalary: number,
- totalCompanySalaries: number,
- sparatUtdelningsutrymme: number
-): GransbeloppCalculation {
- // Schablonbelopp: 2.75 × IBB
- const schablonbelopp = 2.75 * INKOMSTBASBELOPP_2024 // ~204k
-
- // Lönebaserat: requires owner salary ≥ 6 IBB (or 9.6% of total + 6 IBB)
- const minOwnerSalary = Math.min(
- 6 * INKOMSTBASBELOPP_2024,
- 0.096 * totalCompanySalaries + 6 * INKOMSTBASBELOPP_2024
- )
-
- const lonebaserat = ownerSalary >= minOwnerSalary
- ? totalCompanySalaries * 0.50
- : 0
-
- return {
- schablonbelopp,
- lonebaserat,
- sparat: sparatUtdelningsutrymme,
- totalGransbelopp: schablonbelopp + lonebaserat + sparatUtdelningsutrymme
- }
-}
-```
-
-### Optimization Engine
-
-```typescript
-interface OptimizationRecommendation {
- recommendedSalary: number
- recommendedDividend: number
- taxOnSalary: number
- taxOnDividend: number
- totalTax: number
- savingsVsAllSalary: number
- explanation: string
-}
-
-function optimizeSalaryDividendSplit(
- availableProfit: number,
- ownerMarginalTaxRate: number,
- sparatUtdelningsutrymme: number
-): OptimizationRecommendation {
- // Consider:
- // - Minimum salary for lönebaserat gränsbelopp (6 IBB = ~446k)
- // - Arbetsgivaravgifter (31.42%) on salary
- // - 20% tax on dividend within gränsbelopp
- // - Marginal tax on dividend above gränsbelopp
- // - Bolagsskatt (20.6%) already paid on profit
-
- // Return optimal split with explanation
-}
-```
-
-### UI Concept
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ 💡 OPTIMERINGSFÖRSLAG │
-│ │
-│ Baserat på ditt resultat och skattesituation: │
-│ │
-│ Rekommenderad lön: 445 800 kr/år │
-│ Rekommenderad utdelning: 204 325 kr │
-│ │
-│ Beräknad total skatt: ~142 000 kr │
-│ vs allt som lön: ~185 000 kr │
-│ ───────────────────────────────────────────────────────── │
-│ Potentiell besparing: ~43 000 kr │
-│ │
-│ ⚠️ Detta är en uppskattning. Rådgör med revisor. │
-└─────────────────────────────────────────────────────────────┘
-```
-
-### Implementation Requirements
-
-- Track sparat utdelningsutrymme (historical data)
-- Input for owner's other income (affects marginal rate)
-- Annual update of inkomstbasbelopp
-- Strong disclaimer: Not tax advice
-
----
-
-## Phase 3: Skatteverket API Integrations
-
-### Available APIs
-
-Skatteverket offers several APIs that can enhance the product:
-
-#### 1. Skattekonto API
-
-Fetch user's tax account balance and transactions.
-
-**Prerequisite:** User must grant "Läsombud" access in Skatteverket's system.
-
-```typescript
-// Conceptual - actual implementation requires OAuth2 + organizational agreement
-interface SkattekontoBala {
- saldo: number
- senastInbetalning: Date
- kommandeForfall: Array<{
- datum: Date
- belopp: number
- typ: string // 'F-skatt', 'Moms', etc.
- }>
-}
-
-// Use case: "Du har 15 000 kr på skattekontot, men beräknad skatt är 20 000 kr. Sätt in 5 000 kr nu."
-```
-
-#### 2. Momsdeklaration API
-
-Submit VAT declaration directly from app.
-
-**Prerequisites:**
-- Registered as e-tjänstleverantör with Skatteverket
-- User authentication via BankID
-- Signed agreement with Skatteverket
-
-```typescript
-interface MomsdeklarationSubmission {
- period: string // '2024-01' for January
- ruta05: number // Momspliktig försäljning
- ruta39: number // Tjänsteförsäljning EU
- ruta40: number // Export
- ruta21: number // Inköp tjänster EU
- ruta48: number // Utgående moms inköp
- // ... all required rutor
-}
-```
-
-#### 3. Arbetsgivardeklaration API
-
-Not typically needed for sole proprietors without employees, but relevant if they hire.
-
-### Integration Roadmap
-
-| Phase | Integration | User Value |
-|-------|-------------|------------|
-| MVP | None (manual) | - |
-| v1.5 | VIES VAT validation | Automated reverse charge |
-| v2.0 | Skattekonto (read) | Real-time tax position |
-| v2.5 | Momsdeklaration (submit) | One-click VAT filing |
-| v3.0 | NE-bilaga (submit) | Full declaration automation |
-
----
-
-## Phase 2: Reklammärkning Compliance
-
-### Marknadsföringslagen Requirement
-
-Swedish law requires clear ad disclosure. The "Kissie" case established that marking must be:
-- At the very beginning of content
-- Immediately visible
-- Unambiguous ("Reklam" or "Annons", not just "Samarbete")
-
-### Implementation
-
-In Deal-to-Invoice flow, add mandatory checkbox:
-
-```typescript
-interface DealComplianceCheck {
- reklamMarkerad: boolean
- markeringTyp: 'inlagg' | 'video' | 'story' | 'podcast'
- bekraftelse: string // Timestamp of user confirmation
-}
-
-// Before invoice can be marked as complete:
-const complianceText = `Jag intygar att allt publicerat material för detta samarbete har reklammarkerats tydligt i början av varje inlägg/video i enlighet med Marknadsföringslagen (2008:486).`
-```
-
----
-
-## Data Retention & GDPR
-
-### Conflict Resolution
-
-**Bokföringslagen**: 7 years mandatory retention for räkenskapsinformation
-**GDPR**: Right to erasure
-
-Resolution:
-- Accounting records (verifikationer, fakturor, kvitton): 7-year mandatory retention
-- Non-accounting data (support chats, preferences, analytics): Can be deleted on request
-- Technical implementation: Separate data stores with different retention policies
-
-```typescript
-// Database design consideration
-interface UserDataPolicy {
- accountingData: {
- retention: '7_years_from_fiscal_year_end',
- deletable: false,
- legal_basis: 'Bokföringslagen 7 kap. 2 §'
- },
- operationalData: {
- retention: 'until_deletion_request',
- deletable: true,
- legal_basis: 'Consent / Legitimate interest'
- }
-}
-```
-
-### Digital Archive Requirements (July 2024 Law)
-
-Receipt photos must be:
-- Stored in immutable format (PDF/A-3, locked JPEG)
-- Backed up regularly
-- Hosted within EU/EES or adequate country
-- Tamper-evident (hash verification)
-
-```typescript
-interface ReceiptArchive {
- originalFilename: string
- storedAs: string // UUID.pdf
- format: 'PDF/A-3'
- sha256Hash: string
- capturedAt: Date
- linkedTransactionId: string
- storageLocation: 'eu-north-1' // Must be EU
-}
-```
diff --git a/dev_docs/08-BAS-ACCOUNTING-GUIDE.md b/dev_docs/08-BAS-ACCOUNTING-GUIDE.md
deleted file mode 100644
index 03135959..00000000
--- a/dev_docs/08-BAS-ACCOUNTING-GUIDE.md
+++ /dev/null
@@ -1,903 +0,0 @@
-# BAS Accounting Guide for Creator Economy
-
-## Overview
-
-This document provides the accounting logic layer for automatic transaction categorization using the Swedish BAS-kontoplan. It covers MCC code mapping, expense validation rules, and VAT handling for influencer-specific transactions.
-
-## BAS Account Structure
-
-The BAS-kontoplan uses a hierarchical 4-digit system where each position carries semantic meaning:
-
-| Position | Name | Example | Meaning |
-|----------|------|---------|---------|
-| 1 | Kontoklass | **5**410 | Category (5 = External costs) |
-| 2 | Kontogrupp | 5**4**10 | Type (54 = Consumables) |
-| 3 | Huvudkonto | 54**1**0 | Main account for reporting |
-| 4 | Underkonto | 541**0** | Detail level, VAT codes |
-
-This enables validation logic built directly on account number structure.
-
----
-
-## Account Classes Overview
-
-| Class | Swedish | English | Influencer Relevance |
-|-------|---------|---------|---------------------|
-| 1xxx | Tillgångar | Assets | Equipment, bank accounts |
-| 2xxx | Eget kapital & Skulder | Equity & Liabilities | VAT, owner withdrawals |
-| 3xxx | Intäkter | Revenue | Platform income, sponsorships |
-| 4xxx | Direkta kostnader | Direct costs | Merchandise COGS (rare) |
-| 5xxx | Övriga externa kostnader | Other external costs | 90% of expenses land here |
-| 6xxx | Övriga externa kostnader | Other external costs | Services, representation |
-| 7xxx | Personalkostnader | Personnel costs | AB salary (see salary module) |
-| 8xxx | Finansiella poster | Financial items | Interest, currency gains/losses |
-
----
-
-## Critical BAS Accounts for Influencers
-
-### Assets (Class 1)
-
-| Account | Name | Use Case | Notes |
-|---------|------|----------|-------|
-| 1210 | Maskiner och inventarier | Cameras, computers > 29,400 kr | Depreciate over 5 years (20%/year) |
-| 1930 | Företagskonto | Main bank account | Primary reconciliation account |
-
-### Equity & Liabilities (Class 2)
-
-| Account | Name | Use Case | Notes |
-|---------|------|----------|-------|
-| 2010 | Eget kapital | Owner's equity | Rolling balance |
-| 2013 | Eget uttag | Private expenses paid with business card | **Critical for rejected deductions** |
-| 2018 | Egen insättning | Owner deposits / travel allowance credit | Traktamente booking |
-| 2440 | Leverantörsskulder | Accounts payable | If not paying immediately |
-| 2611 | Utgående moms 25% | Output VAT 25% | Swedish domestic sales |
-| 2614 | Utg. moms utländska förvärv | Output VAT on foreign purchases | Reverse charge (credit side) |
-| 2641 | Ingående moms | Input VAT | Deductible VAT on purchases |
-| 2645 | Ing. moms utländska förvärv | Input VAT on foreign purchases | Reverse charge (debit side) |
-
-### Revenue (Class 3)
-
-| Account | Name | Use Case | Notes |
-|---------|------|----------|-------|
-| 3001 | Försäljning 25% | Swedish sponsorships/collaborations | Standard domestic |
-| 3044 | Försäljning tjänst EU | AdSense (Ireland), EU affiliates | VAT-free, requires Periodisk sammanställning |
-| 3045 | Försäljning tjänst Export | Twitch (USA), non-EU platforms | VAT-free (export) |
-| 3900 | Övriga intäkter | Stipends, royalties, misc | |
-
-### Costs (Class 5-6)
-
-| Account | Name | Use Case | Notes |
-|---------|------|----------|-------|
-| 5010 | Lokalhyra | Studio rental | Not for home office (strict rules) |
-| 5410 | Förbrukningsinventarier | Cameras, computers < 29,400 kr | Direct deduction |
-| 5420 | Programvaror | Adobe CC, Epidemic Sound, SaaS | Licenses/subscriptions |
-| 5480 | Arbetskläder | Protective gear, uniforms | **NOT regular clothes** |
-| 5490 | Övriga förbrukningsartiklar | Props, consumable supplies | |
-| 5800 | Resekostnader | Train, flights, car rental | VAT varies (6% domestic travel) |
-| 5820 | Taxikostnader | Taxi, Uber | |
-| 5831 | Kost och logi Sverige | Hotels in Sweden | 12% VAT |
-| 5832 | Kost och logi utlandet | Hotels abroad | No VAT recovery |
-| 5841 | Traktamente, avdragsgillt | Travel allowance | Calculated per Skatteverket rates |
-| 5890 | Övriga resekostnader | Non-deductible travel portion | For mixed-use trips |
-| 5910 | Annonsering | Facebook Ads, Google Ads | Often triggers reverse charge |
-| 5930 | Reklamtrycksaker | Promotional materials | |
-| 6071 | Representation, avdragsgill | Simple refreshments (max 60 kr/person) | Very limited deduction |
-| 6072 | Representation, ej avdragsgill | Meals for representation | VAT still deductible |
-| 6230 | Datakommunikation | Web hosting, domains, internet | Infrastructure |
-| 6500 | Övriga externa tjänster | Photographers, editors (with F-skatt) | Consultant services |
-| 6991 | Övriga avdragsgilla kostnader | Miscellaneous deductible | Use sparingly |
-| 6992 | Övriga ej avdragsgilla | Fines, penalties | No tax effect |
-
----
-
-## MCC Code Mapping
-
-Merchant Category Codes (MCC) are the primary signal for automatic categorization from bank transactions.
-
-### Implementation
-
-```typescript
-// lib/accounting/mcc-mapping.ts
-
-interface MCCMapping {
- mcc: string
- description: string
- riskLevel: 'low' | 'medium' | 'high' | 'very_high'
- primaryAccount: string
- secondaryAccount?: string
- requiresUserInput: boolean
- autoRejectReason?: string
- logic: string
-}
-
-const MCC_MAPPINGS: MCCMapping[] = [
- // ADVERTISING & MARKETING
- {
- mcc: '7311',
- description: 'Advertising Services',
- riskLevel: 'low',
- primaryAccount: '5910',
- secondaryAccount: '5930',
- requiresUserInput: false,
- logic: 'Standard for Facebook/Google Ads. Triggers EU VAT check.'
- },
-
- // ELECTRONICS & EQUIPMENT
- {
- mcc: '5732',
- description: 'Electronics Stores',
- riskLevel: 'medium',
- primaryAccount: '5410',
- secondaryAccount: '1210',
- requiresUserInput: false,
- logic: 'Amount determines routing. >29,400 kr → 1210 (asset).'
- },
- {
- mcc: '5946',
- description: 'Camera & Photo Supply',
- riskLevel: 'medium',
- primaryAccount: '5410',
- secondaryAccount: '1210',
- requiresUserInput: false,
- logic: 'Same as electronics. Check amount threshold.'
- },
-
- // RESTAURANTS & FOOD - HIGH RISK
- {
- mcc: '5812',
- description: 'Eating Places/Restaurants',
- riskLevel: 'high',
- primaryAccount: '6072',
- secondaryAccount: '2013',
- requiresUserInput: true,
- logic: 'Requires user input: Representation or private? Default to private (2013).'
- },
- {
- mcc: '5814',
- description: 'Fast Food',
- riskLevel: 'high',
- primaryAccount: '2013',
- requiresUserInput: false,
- autoRejectReason: 'Fast food is typically private expense',
- logic: 'Default to eget uttag. Rarely valid business expense.'
- },
-
- // CLOTHING - VERY HIGH RISK (Almost always rejected)
- {
- mcc: '5611',
- description: "Men's Clothing",
- riskLevel: 'very_high',
- primaryAccount: '2013',
- secondaryAccount: '5480',
- requiresUserInput: true,
- autoRejectReason: 'Clothes that can be worn privately are not deductible (RÅ81 1:29)',
- logic: 'Default MUST be 2013 (private). Only 5480 if protective/uniform.'
- },
- {
- mcc: '5621',
- description: "Women's Ready-to-Wear",
- riskLevel: 'very_high',
- primaryAccount: '2013',
- secondaryAccount: '5480',
- requiresUserInput: true,
- autoRejectReason: 'Clothes that can be worn privately are not deductible',
- logic: 'Default MUST be 2013 (private).'
- },
- {
- mcc: '5631',
- description: "Women's Accessories",
- riskLevel: 'very_high',
- primaryAccount: '2013',
- requiresUserInput: false,
- autoRejectReason: 'Accessories are private expenses',
- logic: 'Always 2013.'
- },
-
- // COSMETICS - VERY HIGH RISK
- {
- mcc: '5977',
- description: 'Cosmetic Stores',
- riskLevel: 'very_high',
- primaryAccount: '2013',
- secondaryAccount: '5490',
- requiresUserInput: true,
- autoRejectReason: 'Cosmetics are private expenses unless specific props',
- logic: 'Default private (2013). Only 5490 if clearly production props.'
- },
-
- // TRAVEL - MEDIUM RISK
- {
- mcc: '4111',
- description: 'Commuter Transport',
- riskLevel: 'low',
- primaryAccount: '5800',
- requiresUserInput: false,
- logic: 'Train/bus. 6% VAT in Sweden.'
- },
- {
- mcc: '4112',
- description: 'Passenger Railways',
- riskLevel: 'low',
- primaryAccount: '5800',
- requiresUserInput: false,
- logic: 'Train tickets. 6% VAT.'
- },
- {
- mcc: '4121',
- description: 'Taxicabs/Limousines',
- riskLevel: 'medium',
- primaryAccount: '5820',
- secondaryAccount: '2013',
- requiresUserInput: true,
- logic: 'Business trip or private? Ask user.'
- },
- {
- mcc: '4722',
- description: 'Travel Agencies',
- riskLevel: 'medium',
- primaryAccount: '5800',
- secondaryAccount: '2013',
- requiresUserInput: true,
- logic: 'Is the trip business-related? May need to split.'
- },
- {
- mcc: '7011',
- description: 'Hotels/Motels',
- riskLevel: 'medium',
- primaryAccount: '5831',
- secondaryAccount: '5832',
- requiresUserInput: false,
- logic: '5831 for Sweden (12% VAT), 5832 for abroad (no VAT).'
- },
-
- // SOFTWARE & DIGITAL SERVICES - LOW RISK
- {
- mcc: '7372',
- description: 'Computer Programming',
- riskLevel: 'low',
- primaryAccount: '6230',
- secondaryAccount: '5420',
- requiresUserInput: false,
- logic: 'Web hosting, domains, SaaS subscriptions.'
- },
- {
- mcc: '5734',
- description: 'Computer Software Stores',
- riskLevel: 'low',
- primaryAccount: '5420',
- requiresUserInput: false,
- logic: 'Software licenses.'
- },
-
- // ALCOHOL - ALWAYS REJECT
- {
- mcc: '5921',
- description: 'Package Stores (Systembolaget)',
- riskLevel: 'very_high',
- primaryAccount: '2013',
- requiresUserInput: false,
- autoRejectReason: 'Alcohol is not deductible',
- logic: 'Always 2013. No exceptions.'
- },
-
- // GROCERIES - HIGH RISK
- {
- mcc: '5411',
- description: 'Grocery Stores',
- riskLevel: 'high',
- primaryAccount: '2013',
- secondaryAccount: '6072',
- requiresUserInput: true,
- autoRejectReason: 'Food is typically private expense',
- logic: 'Default 2013. Only 6072 if documented representation.'
- },
-
- // STREAMING SERVICES
- {
- mcc: '4899',
- description: 'Cable/Streaming Services',
- riskLevel: 'medium',
- primaryAccount: '5420',
- secondaryAccount: '2013',
- requiresUserInput: true,
- logic: 'Netflix for research? Usually private. Ask user.'
- },
-
- // GYM & FITNESS - ALWAYS REJECT
- {
- mcc: '7941',
- description: 'Sports Clubs/Gyms',
- riskLevel: 'very_high',
- primaryAccount: '2013',
- requiresUserInput: false,
- autoRejectReason: 'Gym memberships are private expenses, even for fitness influencers',
- logic: 'Always 2013. IL 9 kap. 2 §'
- }
-]
-```
-
----
-
-## Keyword-Based Categorization
-
-For generic MCCs (Amazon, PayPal), analyze transaction description text.
-
-```typescript
-// lib/accounting/keyword-rules.ts
-
-interface KeywordRule {
- keywords: string[]
- account: string
- confidence: 'high' | 'medium' | 'low'
- vatTreatment?: 'standard' | 'reverse_charge' | 'none'
-}
-
-const KEYWORD_RULES: KeywordRule[] = [
- // Software & Subscriptions
- {
- keywords: ['adobe', 'creative cloud'],
- account: '5420',
- confidence: 'high',
- vatTreatment: 'reverse_charge' // Adobe Ireland
- },
- {
- keywords: ['epidemic sound'],
- account: '5420',
- confidence: 'high',
- vatTreatment: 'standard' // Swedish company
- },
- {
- keywords: ['canva'],
- account: '5420',
- confidence: 'high',
- vatTreatment: 'reverse_charge'
- },
- {
- keywords: ['spotify', 'spotify ab'],
- account: '2013', // Usually private
- confidence: 'medium'
- },
- {
- keywords: ['spotify for business', 'soundtrack'],
- account: '5420',
- confidence: 'high'
- },
-
- // Web Infrastructure
- {
- keywords: ['one.com', 'loopia', 'godaddy', 'namecheap', 'cloudflare'],
- account: '6230',
- confidence: 'high'
- },
- {
- keywords: ['vercel', 'netlify', 'heroku', 'aws', 'digitalocean'],
- account: '6230',
- confidence: 'high',
- vatTreatment: 'reverse_charge'
- },
-
- // Advertising Platforms
- {
- keywords: ['facebook', 'meta', 'instagram ads', 'fb ads'],
- account: '5910',
- confidence: 'high',
- vatTreatment: 'reverse_charge' // Meta Ireland
- },
- {
- keywords: ['google ads', 'adwords'],
- account: '5910',
- confidence: 'high',
- vatTreatment: 'reverse_charge' // Google Ireland
- },
- {
- keywords: ['tiktok ads', 'tiktok for business'],
- account: '5910',
- confidence: 'high',
- vatTreatment: 'reverse_charge'
- },
-
- // Transport
- {
- keywords: ['uber', 'bolt', 'taxi'],
- account: '5820',
- confidence: 'medium' // Could be private
- },
- {
- keywords: ['sj', 'mtrx', 'sj biljett'],
- account: '5800',
- confidence: 'high'
- },
- {
- keywords: ['sas', 'norwegian', 'ryanair', 'flygbiljett'],
- account: '5800',
- confidence: 'medium' // Could be private trip
- },
-
- // Always Private
- {
- keywords: ['systembolaget'],
- account: '2013',
- confidence: 'high'
- },
- {
- keywords: ['apotek', 'apoteket', 'apotea'],
- account: '2013',
- confidence: 'high'
- },
- {
- keywords: ['ica', 'coop', 'willys', 'hemköp', 'lidl'],
- account: '2013',
- confidence: 'medium' // Usually private groceries
- }
-]
-```
-
----
-
-## Amount-Based Routing (Asset vs Expense)
-
-```typescript
-// lib/accounting/asset-routing.ts
-
-const PRISBASBELOPP_2025 = 58800
-const HALF_PBB = PRISBASBELOPP_2025 / 2 // 29,400 kr
-
-interface AssetDecision {
- shouldCapitalize: boolean
- account: string
- depreciationYears?: number
- depreciationRate?: number
-}
-
-function routeEquipmentPurchase(
- amountExVat: number,
- mccCode: string
-): AssetDecision {
- const isEquipmentMCC = ['5732', '5946', '5045'].includes(mccCode)
-
- if (!isEquipmentMCC) {
- return { shouldCapitalize: false, account: '5410' }
- }
-
- if (amountExVat > HALF_PBB) {
- return {
- shouldCapitalize: true,
- account: '1210',
- depreciationYears: 5,
- depreciationRate: 0.20
- }
- }
-
- return {
- shouldCapitalize: false,
- account: '5410'
- }
-}
-
-// Update HALF_PBB annually - Skatteverket publishes in November
-```
-
----
-
-## Reverse Charge VAT Handling
-
-When purchasing services from foreign (usually EU) companies, Swedish businesses must self-report VAT.
-
-### Detection Logic
-
-```typescript
-// lib/accounting/reverse-charge.ts
-
-interface ReverseChargeResult {
- applies: boolean
- reason: string
- bookings: Array<{
- account: string
- debit?: number
- credit?: number
- description: string
- }>
-}
-
-const EU_DIGITAL_SERVICES_VENDORS = [
- { name: 'meta', country: 'IE', keywords: ['facebook', 'meta', 'instagram'] },
- { name: 'google', country: 'IE', keywords: ['google', 'youtube', 'adwords'] },
- { name: 'adobe', country: 'IE', keywords: ['adobe'] },
- { name: 'microsoft', country: 'IE', keywords: ['microsoft', 'office 365', 'azure'] },
- { name: 'amazon', country: 'LU', keywords: ['aws', 'amazon web services'] },
- { name: 'canva', country: 'AU', keywords: ['canva'] }, // Non-EU, different treatment
-]
-
-function handleForeignPurchase(
- amount: number,
- vendorName: string,
- vendorCountry: string,
- expenseAccount: string
-): ReverseChargeResult {
- const isEU = isEUCountry(vendorCountry)
- const vatRate = 0.25
- const vatAmount = amount * vatRate
-
- if (isEU && vendorCountry !== 'SE') {
- // EU purchase - reverse charge applies
- return {
- applies: true,
- reason: `Omvänd skattskyldighet - inköp från ${vendorCountry}`,
- bookings: [
- { account: expenseAccount, debit: amount, description: 'Kostnad' },
- { account: '2645', debit: vatAmount, description: 'Beräknad ing. moms utl. förvärv' },
- { account: '2614', credit: vatAmount, description: 'Utg. moms utl. förvärv' },
- { account: '1930', credit: amount, description: 'Utbetalning' }
- ]
- }
- }
-
- if (!isEU) {
- // Non-EU purchase - no reverse charge, just expense
- return {
- applies: false,
- reason: 'Import från land utanför EU',
- bookings: [
- { account: expenseAccount, debit: amount, description: 'Kostnad' },
- { account: '1930', credit: amount, description: 'Utbetalning' }
- ]
- }
- }
-
- // Swedish domestic
- return {
- applies: false,
- reason: 'Inrikes inköp',
- bookings: [] // Normal VAT handling
- }
-}
-```
-
-### Momsdeklaration Mapping
-
-| Scenario | Ruta | Description |
-|----------|------|-------------|
-| Domestic purchase 25% VAT | 48 (utgående), deduct in 48 | Normal |
-| EU service purchase (reverse charge) | 21 (purchase amount), 48 (calculated VAT) | Self-report |
-| Non-EU service purchase | No VAT reporting | Just expense |
-
----
-
-## Revenue Account Selection
-
-```typescript
-// lib/accounting/revenue-routing.ts
-
-interface RevenueRouting {
- account: string
- vatRate: number
- momsRuta: number
- requiresPeriodiskSammanstallning: boolean
-}
-
-function routeRevenue(
- customerCountry: string,
- customerType: 'business' | 'consumer',
- hasValidVatNumber: boolean
-): RevenueRouting {
- // Swedish customer
- if (customerCountry === 'SE') {
- return {
- account: '3001', // Försäljning 25%
- vatRate: 25,
- momsRuta: 5,
- requiresPeriodiskSammanstallning: false
- }
- }
-
- // EU business with VAT number
- if (isEUCountry(customerCountry) && customerType === 'business' && hasValidVatNumber) {
- return {
- account: '3044', // Försäljning tjänst EU
- vatRate: 0,
- momsRuta: 39,
- requiresPeriodiskSammanstallning: true // Quarterly report required!
- }
- }
-
- // EU consumer (OSS rules may apply if >10k EUR/year)
- if (isEUCountry(customerCountry) && customerType === 'consumer') {
- return {
- account: '3001', // Or OSS-specific account
- vatRate: 25, // Swedish VAT until OSS threshold
- momsRuta: 5,
- requiresPeriodiskSammanstallning: false
- }
- }
-
- // Non-EU (USA, etc.) - Export
- return {
- account: '3045', // Försäljning tjänst Export
- vatRate: 0,
- momsRuta: 40,
- requiresPeriodiskSammanstallning: false
- }
-}
-```
-
----
-
-## Conservative Bias Principle
-
-The system must be designed with a **conservative bias** - prefer rejecting deductions over accepting questionable ones.
-
-### Rationale
-- Burden of proof lies with taxpayer (IL 9 kap. 2 §)
-- Skattetillägg (tax surcharge) is 40% of avoided tax
-- Better to warn user than cause audit problems
-
-### Implementation
-
-```typescript
-// lib/accounting/risk-assessment.ts
-
-interface RiskAssessment {
- riskLevel: 'low' | 'medium' | 'high' | 'very_high'
- suggestedAccount: string
- requiresConfirmation: boolean
- warningMessage?: string
- legalBasis?: string
-}
-
-function assessTransactionRisk(
- mcc: string,
- amount: number,
- description: string
-): RiskAssessment {
- const mapping = getMCCMapping(mcc)
-
- if (mapping.riskLevel === 'very_high') {
- return {
- riskLevel: 'very_high',
- suggestedAccount: '2013', // Default to private (eget uttag)
- requiresConfirmation: true,
- warningMessage: mapping.autoRejectReason,
- legalBasis: 'IL 9 kap. 2 § - Privata levnadskostnader'
- }
- }
-
- if (mapping.riskLevel === 'high') {
- return {
- riskLevel: 'high',
- suggestedAccount: mapping.primaryAccount,
- requiresConfirmation: true,
- warningMessage: `Denna typ av utgift kräver dokumentation. ${mapping.logic}`
- }
- }
-
- // Low/medium risk - auto-categorize but allow override
- return {
- riskLevel: mapping.riskLevel,
- suggestedAccount: mapping.primaryAccount,
- requiresConfirmation: false
- }
-}
-```
-
----
-
-## Private Use Split
-
-For items with mixed business/private use:
-
-```typescript
-// lib/accounting/split-usage.ts
-
-interface SplitTransaction {
- businessPortion: {
- account: string
- amount: number
- }
- privatePortion: {
- account: string // Always 2013
- amount: number
- }
-}
-
-function splitMixedUse(
- totalAmount: number,
- businessPercentage: number,
- expenseAccount: string
-): SplitTransaction {
- const businessAmount = totalAmount * (businessPercentage / 100)
- const privateAmount = totalAmount - businessAmount
-
- return {
- businessPortion: {
- account: expenseAccount,
- amount: Math.round(businessAmount * 100) / 100
- },
- privatePortion: {
- account: '2013',
- amount: Math.round(privateAmount * 100) / 100
- }
- }
-}
-
-// UI should ask: "Används denna uteslutande i företaget?"
-// If no → prompt for percentage split
-```
-
----
-
-## Travel Allowance (Traktamente)
-
-For business trips, the owner can claim tax-free travel allowance at Skatteverket's rates.
-
-```typescript
-// lib/accounting/traktamente.ts
-
-// 2024 rates - update annually
-const TRAKTAMENTE_RATES = {
- sweden: {
- fullDay: 260, // Hel dag
- halfDay: 130, // Halv dag
- night: 130 // Nattraktamente
- },
- // Foreign rates vary by country - see Skatteverket's list
- foreign: {
- USA: { fullDay: 620, reduced: 434 },
- UK: { fullDay: 550, reduced: 385 },
- Germany: { fullDay: 420, reduced: 294 },
- // ... etc
- }
-}
-
-interface TraktamenteCalculation {
- amount: number
- bookings: Array<{
- account: string
- debit?: number
- credit?: number
- }>
-}
-
-function calculateTraktamente(
- destination: 'sweden' | string,
- fullDays: number,
- halfDays: number,
- nights: number
-): TraktamenteCalculation {
- const rates = destination === 'sweden'
- ? TRAKTAMENTE_RATES.sweden
- : TRAKTAMENTE_RATES.foreign[destination] || TRAKTAMENTE_RATES.sweden
-
- const amount =
- (fullDays * rates.fullDay) +
- (halfDays * (rates.halfDay || rates.fullDay / 2)) +
- (nights * (rates.night || 0))
-
- return {
- amount,
- bookings: [
- { account: '5841', debit: amount }, // Traktamente, avdragsgillt
- { account: '2018', credit: amount } // Egen insättning (skuld till ägare)
- ]
- }
-}
-```
-
----
-
-## Non-Cash Transactions (Barter/Gifts)
-
-Influencers receive products that must be accounted for even without bank transaction.
-
-```typescript
-// lib/accounting/non-cash.ts
-
-interface BarterTransaction {
- productValue: number
- hasMotprestation: boolean // Required post/exposure?
- usedInBusiness: boolean
- bookings: Array<{
- account: string
- debit?: number
- credit?: number
- description: string
- }>
-}
-
-function bookBarterTransaction(
- productValue: number,
- hasMotprestation: boolean,
- usedInBusiness: boolean
-): BarterTransaction['bookings'] {
- if (!hasMotprestation && productValue < 450) {
- // Tax-free promotional gift
- return [] // No booking required
- }
-
- if (hasMotprestation) {
- // Taxable barter - must recognize as income
- const bookings = [
- { account: '3001', credit: productValue, description: 'Förmån/Byteshandel' },
- { account: '1510', debit: productValue, description: 'Fordran (kvittad mot produkt)' }
- ]
-
- if (usedInBusiness) {
- // Can also expense it
- bookings.push(
- { account: '5490', debit: productValue, description: 'Rekvisita' },
- { account: '1510', credit: productValue, description: 'Kvittning fordran' }
- )
- } else {
- // Private use - eget uttag
- bookings.push(
- { account: '2013', debit: productValue, description: 'Eget uttag (förmån)' },
- { account: '1510', credit: productValue, description: 'Kvittning fordran' }
- )
- }
-
- return bookings
- }
-
- // Gift without motprestation but valuable - still taxable
- return [
- { account: '3001', credit: productValue, description: 'Skattepliktig gåva' },
- { account: '2013', debit: productValue, description: 'Eget uttag (gåva)' }
- ]
-}
-```
-
----
-
-## System Configuration
-
-```typescript
-// lib/accounting/config.ts
-
-export const ACCOUNTING_CONFIG = {
- // Update annually
- prisbasbelopp: 58800, // 2025
- halfPrisbasbelopp: 29400,
-
- // VAT rates
- vatRates: {
- standard: 25,
- reduced: 12, // Food, hotels
- low: 6, // Transport, books
- },
-
- // Depreciation defaults
- depreciation: {
- equipment: { years: 5, rate: 0.20 },
- computers: { years: 3, rate: 0.33 },
- vehicles: { years: 5, rate: 0.20 },
- },
-
- // Risk thresholds
- riskSettings: {
- autoRejectVeryHigh: true,
- requireConfirmationHigh: true,
- allowOverrideMedium: true,
- }
-}
-```
-
----
-
-## Integration Points
-
-This guide integrates with:
-
-1. **Transaction categorization UI** (05-UI-SPECIFICATION.md) - Swipe interface uses MCC mapping
-2. **Tax calculator** (06-IMPLEMENTATION-GUIDE.md) - Uses account classifications for tax estimation
-3. **Invoice VAT rules** (04-API-SPECIFICATION.md) - Revenue account selection aligns with momsdeklaration
-4. **Expense warnings** (06-IMPLEMENTATION-GUIDE.md) - Risk levels drive warning display
-
----
-
-## Annual Maintenance
-
-Update each January:
-1. Prisbasbelopp (from Skatteverket, published November)
-2. Traktamente rates (Skatteverket)
-3. Any BAS account changes (BAS-kontogruppen)
-4. Tax rates if changed by Riksdag
diff --git a/dev_docs/ALICE_DATA_02_10.json b/dev_docs/ALICE_DATA_02_10.json
deleted file mode 100644
index 575debc6..00000000
--- a/dev_docs/ALICE_DATA_02_10.json
+++ /dev/null
@@ -1,721 +0,0 @@
-{
- "accounts": [
- {
- "info": {
- "psu_status": "OPEN",
- "uid": "d3a05b17-62d0-47ae-b5f6-bbff3ab0776a",
- "identification_hashes": [
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoiaWJhbiIKXQpd.CMv8KPVyC9Jb2K/o4iLTHs0/Rm6oBpLZ2Dk94dLUUqY=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoiaWJhbiIKXSwKWwoiYWNjb3VudCIsCiJjdXJyZW5jeSIKXQpd.KHox2S2cDHB0qpvDl/UbtAYEOFT0bkKlDBaIbiJbOYs=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.YvAsATX9mYjlf4gudQxRshFYi9Qf4mWLmaS4N6XA+do=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.11au3gbnyahIaOUJ+34GVhawiFxuqno1YFYMozafKcI=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.wrdjfOu/bFCI1mKxgyNYkwyi0CJuuDlEQIk/L7u0BRU=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.3D+Eg8xEbNOBIaId0JvB4AdJbRAq7H4eSIHjHu1h7SY=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.wsxsnRROHXrRPiE0Q2kGZAvwuvKG6ozdZRWVeUiRQtA=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.HDktnbN78H+BytoIzLMomebkcAc6VCMoiKhHjF1cLDw=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.cPNpoeUyy8YheNam7y5Jk2cx3iG+qq6yEo1n/BveClU=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.H1mYrXAPxkI6n0ehgmB5mtBIls9OcjXI2ynisJcGaYw=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKInJlc291cmNlX2lkIgpdCl0=.yuDuYREXfxEWdB8C0YwTXDqW5POBjc/3jlmRVVzVa70=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKIm5hbWUiCl0KXQ==.JiZ4C/jjfO9u/6DSSTS8QUjFIvbP24KNkyChx2B0yW4="
- ],
- "usage": null,
- "credit_limit": {
- "currency": "SEK",
- "amount": "0.00"
- },
- "account_id": {
- "other": {
- "issuer": null,
- "scheme_name": "BBAN",
- "identification": "99602621638218"
- },
- "iban": "SE9795000099602621638218"
- },
- "product": "PLUSGIROKONTO FTG",
- "account_servicer": {
- "clearing_system_member_id": {
- "member_id": "9960",
- "clearing_system_id": "SESBA"
- },
- "bic_fi": "NDEASESS",
- "name": null
- },
- "name": "JÖNSSON,ALICE",
- "currency": "SEK",
- "identification_hash": "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoiaWJhbiIKXSwKWwoiYWNjb3VudCIsCiJjdXJyZW5jeSIKXQpd.KHox2S2cDHB0qpvDl/UbtAYEOFT0bkKlDBaIbiJbOYs=",
- "cash_account_type": "CACC",
- "postal_address": null,
- "details": null,
- "all_account_ids": [
- {
- "issuer": null,
- "scheme_name": "PGNR",
- "identification": "21638218"
- },
- {
- "issuer": null,
- "scheme_name": "BBAN",
- "identification": "99602621638218"
- },
- {
- "issuer": null,
- "scheme_name": "IBAN",
- "identification": "SE9795000099602621638218"
- }
- ]
- },
- "transactions": [
- {
- "entry_reference": "2025-12-30-16.17.03.380410058H1021638218 EK",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "8730.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BARCLAYS BANK PLC",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Andra",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2025-12-30",
- "value_date": "2025-12-30",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "18730.00"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "005 BaByliss\r\nURSPRUNGLIGT BELOPP M M: SEK",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "SEK",
- "exchange_rate": "1.0000000",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "SEK",
- "amount": "8730.00"
- }
- },
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "06200021638218000100000000125-12-2900H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "10000.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BG INSÄTTNING 1",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "BGC LB-betalningar",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2025-12-29",
- "value_date": "2025-12-30",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "10000.00"
- },
- "reference_number": "0051385052",
- "reference_number_schema": null,
- "remittance_information": [
- "0051385052",
- "",
- "5138-5052"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "06400021638218000100000000126-01-0200H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "15625.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BG INSÄTTNING 1",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "BGC LB-betalningar",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-02",
- "value_date": "2026-01-05",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "34355.00"
- },
- "reference_number": "0051385052",
- "reference_number_schema": null,
- "remittance_information": [
- "0051385052",
- "",
- "5138-5052"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "06600021638218000200000000126-01-0700H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "1409.85"
- },
- "creditor": {
- "name": "AVGIFTER NORDEA",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": null,
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Debitering av avgift",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "DBIT",
- "status": "BOOK",
- "booking_date": "2026-01-07",
- "value_date": "2026-01-07",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "32945.15"
- },
- "reference_number": null,
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "AVGIFTER NORDEA"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "2026-01-09-16.25.07.272909064H1021638218 EK",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "7000.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "NORDEA BANK ABP",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Andra",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-12",
- "value_date": "2026-01-12",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "39945.15"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "/ROC/E20304164B207920 INVOICE 003\r\nURSPRUNGLIGT BELOPP M M: SEK",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "SEK",
- "exchange_rate": "1.0000000",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "SEK",
- "amount": "7000.00"
- }
- },
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "07700021638218000400000000126-01-2200H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "2500.00"
- },
- "creditor": {
- "name": "Uttag",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "creditor_account": {
- "iban": null,
- "other": {
- "identification": "1411450057",
- "scheme_name": "BBAN",
- "issuer": null
- }
- },
- "creditor_agent": null,
- "debtor": null,
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Generell O-Typ från Cello-kassa via INL",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "DBIT",
- "status": "BOOK",
- "booking_date": "2026-01-22",
- "value_date": "2026-01-22",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "37445.15"
- },
- "reference_number": null,
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "Anslutningsavgift"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "2026-01-26-16.16.34.120637074H1021638218 EK",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "313.70"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "SPAR NORD BANK A/S",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Andra",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-26",
- "value_date": "2026-01-26",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "37758.85"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "2025DEC58 BRANDHEROES\r\nURSPRUNGLIGT BELOPP M M: EUR",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "EUR",
- "exchange_rate": "10.4567000",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "EUR",
- "amount": "30.00"
- }
- },
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "08100021638218000600000000126-01-2800H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "3750.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BG INSÄTTNING 1",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "BGC LB-betalningar",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-28",
- "value_date": "2026-01-29",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "41508.85"
- },
- "reference_number": "0051385052",
- "reference_number_schema": null,
- "remittance_information": [
- "0051385052",
- "",
- "5138-5052"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "08600021638218000700000000226-02-0400H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "3.70"
- },
- "creditor": {
- "name": "AVGIFTER NORDEA",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": null,
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Debitering av avgift",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "DBIT",
- "status": "BOOK",
- "booking_date": "2026-02-04",
- "value_date": "2026-02-04",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "57130.15"
- },
- "reference_number": null,
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "AVGIFTER NORDEA"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "08600021638218000700000000126-02-0400H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "15625.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BG INSÄTTNING 1",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "BGC LB-betalningar",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-02-04",
- "value_date": "2026-02-05",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "57130.15"
- },
- "reference_number": "0051385052",
- "reference_number_schema": null,
- "remittance_information": [
- "0051385052",
- "",
- "5138-5052"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": null,
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "3956.14"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "UTLANDSBETALNING",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": {
- "iban": null,
- "other": {
- "identification": "5275745",
- "scheme_name": "BBAN",
- "issuer": null
- }
- },
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Ankomm utlandsbet., kredite av kundkonto",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "PDNG",
- "booking_date": null,
- "value_date": "2026-02-10",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "119953.62"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "EUR",
- "exchange_rate": "0E-7",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "EUR",
- "amount": "375.00"
- }
- },
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": null,
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "58867.33"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "UTLANDSBETALNING",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": {
- "iban": null,
- "other": {
- "identification": "5275748",
- "scheme_name": "BBAN",
- "issuer": null
- }
- },
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Ankomm utlandsbet., kredite av kundkonto",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "PDNG",
- "booking_date": null,
- "value_date": "2026-02-10",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "119953.62"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "EUR",
- "exchange_rate": "0E-7",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "EUR",
- "amount": "5580.00"
- }
- },
- "note": null,
- "transaction_id": null
- }
- ],
- "balances": [
- {
- "name": "Available balance",
- "balance_type": "ITAV",
- "balance_amount": {
- "amount": "119953.62",
- "currency": "SEK"
- },
- "last_change_date_time": null,
- "last_committed_transaction": null,
- "reference_date": null
- },
- {
- "name": "Booked balance",
- "balance_type": "ITBD",
- "balance_amount": {
- "amount": "119953.62",
- "currency": "SEK"
- },
- "last_change_date_time": null,
- "last_committed_transaction": null,
- "reference_date": null
- }
- ],
- "raw_data": {
- "transactions": [
- "{\"group_header\":{\"message_identification\":\"0e97ebad347b1692\",\"creation_date_time\":\"2026-02-09T18:58:26.583121261Z\",\"http_code\":200},\"response\":{\"transactions\":[{\"transaction_id\":\"2026-02-09-08.23.18.690071021638218X1SEK TK\",\"currency\":\"SEK\",\"booking_date\":\"2026-02-09\",\"value_date\":\"2026-02-10\",\"type_description\":\"Ankomm utlandsbet., kredite av kundkonto\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"5275745\",\"counterparty_name\":\"UTLANDSBETALNING\",\"original_currency\":\"EUR\",\"original_currency_amount\":\"375.00\",\"currency_rate\":\"0.0000000\",\"balance_after_transaction\":\"119953.62\",\"amount\":\"3956.14\",\"from_account_name\":\"UTLANDSBETALNING\",\"from_account_country\":\"\",\"bank_name\":\"\",\"bank_address\":\"\",\"bank_code\":\"\",\"bank_bic\":\"\",\"transaction_type_code\":\"SE154\"},{\"transaction_id\":\"2026-02-09-08.23.18.826801021638218X1SEK TK\",\"currency\":\"SEK\",\"booking_date\":\"2026-02-09\",\"value_date\":\"2026-02-10\",\"type_description\":\"Ankomm utlandsbet., kredite av kundkonto\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"5275748\",\"counterparty_name\":\"UTLANDSBETALNING\",\"original_currency\":\"EUR\",\"original_currency_amount\":\"5580.00\",\"currency_rate\":\"0.0000000\",\"balance_after_transaction\":\"119953.62\",\"amount\":\"58867.33\",\"from_account_name\":\"UTLANDSBETALNING\",\"from_account_country\":\"\",\"bank_name\":\"\",\"bank_address\":\"\",\"bank_code\":\"\",\"bank_bic\":\"\",\"transaction_type_code\":\"SE154\"},{\"transaction_id\":\"08600021638218000700000000226-02-0400H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-02-04\",\"value_date\":\"2026-02-04\",\"type_description\":\"Debitering av avgift\",\"narrative\":\"AVGIFTER NORDEA\",\"message\":\"\",\"status\":\"billed\",\"counterparty_account\":\"\",\"counterparty_name\":\"AVGIFTER NORDEA\",\"balance_after_transaction\":\"57130.15\",\"amount\":\"-3.70\",\"to_account_name\":\"AVGIFTER NORDEA\",\"to_account_country\":\"\",\"transaction_type_code\":\"SE931\"},{\"transaction_id\":\"08600021638218000700000000126-02-0400H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-02-04\",\"value_date\":\"2026-02-05\",\"type_description\":\"BGC LB-betalningar\",\"narrative\":\"5138-5052\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"0051385052\",\"counterparty_account\":\"\",\"counterparty_name\":\"BG INSÄTTNING 1\",\"balance_after_transaction\":\"57130.15\",\"amount\":\"15625.00\",\"from_account_name\":\"BG INSÄTTNING 1\",\"from_account_country\":\"\",\"transaction_type_code\":\"SE218\"},{\"transaction_id\":\"08100021638218000600000000126-01-2800H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-28\",\"value_date\":\"2026-01-29\",\"type_description\":\"BGC LB-betalningar\",\"narrative\":\"5138-5052\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"0051385052\",\"counterparty_account\":\"\",\"counterparty_name\":\"BG INSÄTTNING 1\",\"balance_after_transaction\":\"41508.85\",\"amount\":\"3750.00\",\"from_account_name\":\"BG INSÄTTNING 1\",\"from_account_country\":\"\",\"transaction_type_code\":\"SE218\"},{\"transaction_id\":\"2026-01-26-16.16.34.120637074H1021638218 EK\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-26\",\"value_date\":\"2026-01-26\",\"type_description\":\"Andra\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"2025DEC58 BRANDHEROES\\r\\nURSPRUNGLIGT BELOPP M M: EUR\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"\",\"counterparty_name\":\"SPAR NORD BANK A/S\",\"payment_date\":\"2026-01-26\",\"original_currency\":\"EUR\",\"original_currency_amount\":\"30.00\",\"currency_rate\":\"10.4567000\",\"balance_after_transaction\":\"37758.85\",\"amount\":\"313.70\",\"from_account_name\":\"SPAR NORD BANK A/S\",\"from_account_country\":\"DK\",\"bank_name\":\"SPAR NORD BANK A/S\",\"bank_address\":\"\",\"bank_code\":\"AALBORG\",\"bank_bic\":\"SPNODK22A\",\"transaction_type_code\":\"SE\"},{\"transaction_id\":\"07700021638218000400000000126-01-2200H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-22\",\"value_date\":\"2026-01-22\",\"type_description\":\"Generell O-Typ från Cello-kassa via INL\",\"narrative\":\"Anslutningsavgift\",\"message\":\"\",\"status\":\"billed\",\"counterparty_account\":\"1411450057\",\"counterparty_name\":\"Uttag\",\"balance_after_transaction\":\"37445.15\",\"amount\":\"-2500.00\",\"to_account_name\":\"Uttag\",\"to_account_country\":\"\",\"transaction_type_code\":\"SE976\"},{\"transaction_id\":\"2026-01-09-16.25.07.272909064H1021638218 EK\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-12\",\"value_date\":\"2026-01-12\",\"type_description\":\"Andra\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"/ROC/E20304164B207920 INVOICE 003\\r\\nURSPRUNGLIGT BELOPP M M: SEK\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"\",\"counterparty_name\":\"NORDEA BANK ABP\",\"payment_date\":\"2026-01-12\",\"original_currency\":\"SEK\",\"original_currency_amount\":\"7000.00\",\"currency_rate\":\"1.0000000\",\"balance_after_transaction\":\"39945.15\",\"amount\":\"7000.00\",\"from_account_name\":\"NORDEA BANK ABP\",\"from_account_country\":\"FI\",\"bank_name\":\"NORDEA BANK ABP\",\"bank_address\":\"\",\"bank_code\":\"HELSINKI\",\"bank_bic\":\"NDEAFIHHS\",\"transaction_type_code\":\"SE\"},{\"transaction_id\":\"06600021638218000200000000126-01-0700H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-07\",\"value_date\":\"2026-01-07\",\"type_description\":\"Debitering av avgift\",\"narrative\":\"AVGIFTER NORDEA\",\"message\":\"\",\"status\":\"billed\",\"counterparty_account\":\"\",\"counterparty_name\":\"AVGIFTER NORDEA\",\"balance_after_transaction\":\"32945.15\",\"amount\":\"-1409.85\",\"to_account_name\":\"AVGIFTER NORDEA\",\"to_account_country\":\"\",\"transaction_type_code\":\"SE931\"},{\"transaction_id\":\"06400021638218000100000000126-01-0200H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-02\",\"value_date\":\"2026-01-05\",\"type_description\":\"BGC LB-betalningar\",\"narrative\":\"5138-5052\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"0051385052\",\"counterparty_account\":\"\",\"counterparty_name\":\"BG INSÄTTNING 1\",\"balance_after_transaction\":\"34355.00\",\"amount\":\"15625.00\",\"from_account_name\":\"BG INSÄTTNING 1\",\"from_account_country\":\"\",\"transaction_type_code\":\"SE218\"},{\"transaction_id\":\"2025-12-30-16.17.03.380410058H1021638218 EK\",\"currency\":\"SEK\",\"booking_date\":\"2025-12-30\",\"value_date\":\"2025-12-30\",\"type_description\":\"Andra\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"005 BaByliss\\r\\nURSPRUNGLIGT BELOPP M M: SEK\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"\",\"counterparty_name\":\"BARCLAYS BANK PLC\",\"payment_date\":\"2025-12-30\",\"original_currency\":\"SEK\",\"original_currency_amount\":\"8730.00\",\"currency_rate\":\"1.0000000\",\"balance_after_transaction\":\"18730.00\",\"amount\":\"8730.00\",\"from_account_name\":\"BARCLAYS BANK PLC\",\"from_account_country\":\"GB\",\"bank_name\":\"BARCLAYS BANK PLC\",\"bank_address\":\"\",\"bank_code\":\"LONDON\",\"bank_bic\":\"BARCGB22V\",\"transaction_type_code\":\"SE\"},{\"transaction_id\":\"06200021638218000100000000125-12-2900H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2025-12-29\",\"value_date\":\"2025-12-30\",\"type_description\":\"BGC LB-betalningar\",\"narrative\":\"5138-5052\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"0051385052\",\"counterparty_account\":\"\",\"counterparty_name\":\"BG INSÄTTNING 1\",\"balance_after_transaction\":\"10000.00\",\"amount\":\"10000.00\",\"from_account_name\":\"BG INSÄTTNING 1\",\"from_account_country\":\"\",\"transaction_type_code\":\"SE218\"}],\"_links\":[{\"rel\":\"self\",\"href\":\"/v4/accounts/SE21638218-SEK/transactions?from_date=2025-02-09&to_date=2026-02-09\"}]}}"
- ],
- "balances": {
-
- },
- "details": {
-
- }
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/dev_docs/ARCHITECTURE.md b/dev_docs/ARCHITECTURE.md
deleted file mode 100644
index 0e8755f1..00000000
--- a/dev_docs/ARCHITECTURE.md
+++ /dev/null
@@ -1,406 +0,0 @@
-Base ERP Architecture: Core + Add-on System (v2)
-The Core
-Every item here is non-negotiable for legal compliance or market viability. Nothing below can be an add-on.
-
-Authentication, Tenancy & Access Control
-Magic link auth via Supabase
-Onboarding wizard (entity type EF/AB, company details, tax registration, fiscal year, bank connection)
-RLS on every table, user_id scoping
-Multi-company support per user
-Delegated access roles: owner, accountant (full read/write), audit:read (read-only, scoped to fiscal year). The audit role is the foundation for Digital Audit 2026 compliance where Skatteverket gets API access to a specific fiscal year.
-
-Document Archive (Compliance Layer)
-The July 2024 Bokföringslagen amendment makes the system the legal archive. This is not a feature, it is a legal obligation.
-Hash-on-upload. Every uploaded file (receipt image, e-invoice XML, PDF) gets a SHA-256 hash computed and stored alongside the blob. The hash is the proof of integrity.
-WORM storage. Uploaded documents are write-once. Any modification (crop, contrast, re-scan) creates a new version. The original remains accessible and linked in the version chain.
-Deletion blocking. The system hard-rejects any attempt to delete a document linked to a committed voucher or a locked period. No admin override.
-Digitization metadata. Every upload logs: user who uploaded, timestamp, source (camera, file upload, e-invoice), and a digitization date field. This justifies destruction of the paper original.
-Linkage integrity. Strict foreign key from journal_entry_lines to document_attachments. No orphaned documents, no undocumented entries.
-
-Seven-Year Retention & Purge Prevention
-System calculates retention expiry: fiscal year end + 7 calendar years.
-All delete operations (company, fiscal year, journal entries, documents) are blocked within the retention window.
-"Delete Company" requires a verified full SIE4 export + linked document archive before proceeding, and only after retention expires.
-GDPR conflict resolution: pseudonymize CRM master data on request, but never touch the ledger. Invoice snapshots with names remain intact as part of the fiscal record.
-
-Chart of Accounts (BAS Kontoplan)
-BAS seeding per entity type (EF/AB), K1 vs full plan
-Account CRUD: add, deactivate, rename. Deactivated accounts preserve historical data but block new postings.
-Account metadata: type (tillgång/skuld/intäkt/kostnad), default tax code, SRU code mapping
-SRU mapping table. Every BAS account maps to an SRU code. This is what makes tax filing work. Without it the system cannot generate Inkomstdeklaration 2 data.
-Annual BAS updates. Migration mechanism for BAS Group changes. Deprecated accounts get frozen (no new postings), not deleted.
-Dimensions. Minimum two dimension types: Kostnadsställe (cost center) and Projekt. Stored on journal entry lines. Required for SIE4 dimension export (#OBJEKT) and expected by any consultancy or construction firm.
-
-Double-Entry Bookkeeping (Immutable Ledger)
-Draft/Commit lifecycle:
-Journal entries start as drafts with temporary IDs (TMP-xxxx). Drafts are freely editable.
-On commit ("Bokför"), the system assigns the next permanent voucher number from the series. At this moment the row becomes immutable.
-DB-level enforcement: committed rows have UPDATE and DELETE restrictions. Application code cannot bypass this.
-Voucher series management:
-Sequential numbering per series per fiscal year. Gaps are impermissible under Bokföringslagen.
-Gap detection: background check that flags any missing numbers in a committed series.
-Concurrent write safety: SELECT ... FOR UPDATE or advisory locks to prevent duplicate number assignment.
-Storno correction logic:
-Posted vouchers are never edited. Corrections follow the three-step flow:
-Step 1: System generates a reversal voucher (storno) that nullifies the original.
-Step 2: System generates the corrected entry with the right data.
-Step 3: All three vouchers (original, reversal, correction) are linked in the behandlingshistorik.
-UI presents a single "Correct" button. The user sees a "Corrected" status tag. The triple-entry logic runs in the background.
-Debit == Credit validation: enforced at DB level via check constraint or trigger. No exceptions.
-Guaranteed delivery: transactional outbox pattern for journal creation from upstream events (invoice created, payment received, etc.). Failed entries go to a dead letter queue with alerting. Silent failure is not acceptable.
-
-Audit Trail (Behandlingshistorik)
-Every mutation to journal entries, accounts, documents, settings, user roles logged with: actor, timestamp, action type, before-state, after-state.
-Committed vouchers log all correction chains (original -> storno -> corrected).
-Attempted deletions of protected data logged as security events.
-The audit log itself is append-only. No updates, no deletes.
-
-Period Management
-Fiscal year definition with support for broken fiscal years (brutet räkenskapsår).
-Multi-fiscal-year support with clean year boundaries.
-Period locking (låsning av period). Locked periods reject all writes to journal entries and documents within that period. Locking is one-way without admin unlock + audit log entry.
-Year-end closing (årsbokslut):
-Zero out result accounts (class 3-8).
-Transfer net result to equity (account 2099).
-Generate closing entries as committed vouchers.
-Calculate and verify that UB of year N == IB of year N+1.
-Block manual editing of IB to prevent breaking continuity.
-Opening balances workflow for new companies or mid-year migrations.
-
-Tax Code Engine
-Decoupled from the chart of accounts. Tax codes tag transaction lines independently.
-Code
-Rate
-Description
-Momsdeklaration Boxes
-MP1
-25%
-Standard output VAT
-05 (basis) + 10 (tax)
-MP2
-12%
-Food/hotel
-06 (basis) + 11 (tax)
-MP3
-6%
-Books/transport/culture
-07 (basis) + 12 (tax)
-MPI
-25/12/6%
-Standard input VAT
-48
-IV
-0%
-Intra-community acquisition
-20 (basis) + 30 (input) + 30 (output)
-EUS
-0%
-EU sale of goods/services
-35/36 + Periodisk sammanställning
-IP
-0%
-Import of goods
-50 (basis) + 60 (output) + 48 (input)
-EXP
-0%
-Export outside EU
-08 (basis)
-OSS
-varies
-One Stop Shop (e-commerce)
-Excluded from boxes 05-49, routed to OSS report
-
-Momsdeklaration generated by summing per tax code, not per account. This survives any account plan customization.
-Validation: calculated tax (basis * rate) must match reported tax within tolerance. Deviations trigger warnings.
-Periodisk sammanställning (EC Sales List) auto-populated from EUS-tagged lines.
-
-Financial Reports
-Resultaträkning (income statement) by BAS class
-Balansräkning (balance sheet) with assets == equity + liabilities validation
-Råbalans (trial balance) with zero-sum verification
-Momsdeklaration (all rutor 05-49) generated from tax code engine
-SRU-based tax data for Inkomstdeklaration 2 (sums per SRU code)
-All reports respect period locks, fiscal year boundaries, and dimension filters (kostnadsställe, projekt)
-
-SIE4
-Export: spec-validated output including #IB, #UB, #RES, #VER, #OBJEKT (dimensions), #KONTO with all used accounts. Explicit character encoding handling (CP437/Latin-1) with Swedish character validation. #ORGNR validated against Luhn algorithm.
-Import: 4-step wizard (upload, parse, map accounts, review & execute). Creates journal entries from imported data. Validates that imported IB matches existing UB if prior year exists.
-Round-trip integrity: export from system, re-import, verify all balances match with zero difference.
-Cross-system validation: export must parse without errors in Visma and Fortnox.
-
-Invoicing
-Create, edit, send, track invoices
-Credit notes with automatic storno reversal entries
-VAT via tax code engine (not hardcoded per account)
-Multi-currency with Riksbanken exchange rates
-Currency gain/loss (kursdifferens). When payment arrives at a different rate than invoiced, system auto-books the difference to 3960/7960.
-PDF generation
-Peppol BIS Billing 3.0. Generate and send e-invoices via Peppol network. This is the mandated B2G standard and increasingly B2B. Validate output against Peppol Schematron. This replaces email delivery for Peppol-capable recipients.
-Public payment/dispute page (token-based, no auth)
-Configurable reminder system (intervals, templates, enable/disable)
-
-Banking
-PSD2 connection via Enable Banking for transaction sync
-OAuth consent flow with 90-day renewal handling
-Transaction sync with deduplication (unique(user_id, external_id))
-Invoice-to-payment matching (amount + date + OCR reference)
-ISO 20022 file handling:
-PAIN.001 generation for outgoing supplier payments. Batch multiple payments per PaymentInformation block. Validate against bank-specific XSD before download.
-CAMT.053 parsing for end-of-day bank statements. Feed into reconciliation engine matching to general ledger.
-CAMT.054 parsing for incoming payment notifications with OCR references. Auto-mark invoices as paid.
-
-Transaction Management
-Transaction list with categorization
-Manual categorization creates journal entries (via draft/commit flow)
-Mapping rules engine: MCC code, merchant name, description pattern, amount threshold
-Extensible rule types (hook for add-ons to register custom rules)
-
-Customers
-Name, org number, VAT number (validated format), address, payment terms, international flag
-Peppol participant ID (for e-invoice routing)
-Linked to invoices
-Subject to GDPR pseudonymization (but not deletion if linked to fiscal records)
-
-Tax Calendar
-Auto-generated Swedish tax deadlines: F-skatt, arbetsgivardeklaration, momsdeklaration (monthly/quarterly), inkomstdeklaration, årsredovisning, bokslut
-Calendar views (month/week/day) + ICS export
-Deadline status tracking (upcoming, due, overdue, filed)
-
-The Extension Architecture
-1. Event Bus
-The core emits events. Extensions subscribe. One-way dependency.
-typescript
-// lib/events/types.ts
-export type CoreEvent =
- // Bookkeeping
- | { type: 'journal_entry.drafted'; payload: DraftJournalEntry }
- | { type: 'journal_entry.committed'; payload: JournalEntry }
- | { type: 'journal_entry.corrected'; payload: { original: JournalEntry; storno: JournalEntry; corrected: JournalEntry } }
- // Documents
- | { type: 'document.uploaded'; payload: Document & { hash: string } }
- // Invoicing
- | { type: 'invoice.created'; payload: Invoice }
- | { type: 'invoice.sent'; payload: Invoice }
- | { type: 'invoice.paid'; payload: Invoice & { transaction: Transaction; kursdifferens?: number } }
- | { type: 'invoice.overdue'; payload: Invoice & { days: number } }
- | { type: 'credit_note.created'; payload: CreditNote }
- // Banking
- | { type: 'transaction.synced'; payload: Transaction[] }
- | { type: 'transaction.categorized'; payload: Transaction & { account: string; taxCode: string } }
- | { type: 'bank.statement_received'; payload: CAMT053Statement }
- | { type: 'bank.payment_notification'; payload: CAMT054Notification }
- // Periods
- | { type: 'period.locked'; payload: { fiscalYear: number; period: number } }
- | { type: 'period.year_closed'; payload: { fiscalYear: number } }
- // Customers
- | { type: 'customer.created'; payload: Customer }
- | { type: 'customer.pseudonymized'; payload: { customerId: string } }
- // Audit
- | { type: 'audit.security_event'; payload: AuditSecurityEvent }
-Implementation: in-process handlers initially. Add webhook dispatch (POST to registered URLs) when external plugin consumers exist.
-2. Extension Registry
-typescript
-// lib/extensions/types.ts
-export interface Extension {
- id: string
- name: string
- version: string
-
- // Surfaces
- routes?: RouteDefinition[]
- apiRoutes?: ApiRouteDefinition[]
- sidebarItems?: SidebarItem[]
- eventHandlers?: EventSubscription[]
- mappingRuleTypes?: MappingRuleType[]
- reportTypes?: ReportDefinition[]
- settingsPanel?: SettingsPanelDef
- taxCodes?: TaxCodeDefinition[] // for add-ons introducing new tax scenarios
- dimensionTypes?: DimensionDefinition[] // for add-ons adding custom dimensions beyond the base two
-
- onInstall?(ctx: ExtensionContext): Promise
- onUninstall?(ctx: ExtensionContext): Promise
-}
-3. Database Extension Pattern
-First-party add-ons: own migration folder, own tables with user_id + RLS.
-Third-party add-ons: use API routes + webhook events + generic extension_data table:
-sql
-create table extension_data (
- id uuid primary key default gen_random_uuid(),
- user_id uuid references auth.users not null,
- extension_id text not null,
- key text not null,
- value jsonb not null,
- created_at timestamptz default now(),
- unique(user_id, extension_id, key)
-);
-```
-
-### Core constraint
-
-The base never imports from `extensions/`. Dependency flows one direction: extensions import from `lib/core/`, `lib/events/`, `lib/extensions/`.
-
-### Type ownership
-
-Extension-specific types live in their extension directory (e.g. `extensions/ne-bilaga/types.ts`). For convenience, `types/index.ts` re-exports them so existing importers continue to work with `import type { NEDeclaration } from '@/types'`. The canonical source is always the extension file.
-
-| Extension | Type file | Types |
-|-----------|-----------|-------|
-| `push-notifications` | `extensions/push-notifications/types.ts` | `PushSubscription`, `NotificationSettings`, `NotificationType`, `NotificationLog` |
-| `receipt-ocr` | `extensions/receipt-ocr/types.ts` | `Receipt`, `ReceiptLineItem`, `ReceiptExtractionResult`, `ExtractedLineItem`, `ReceiptMatchCandidate`, `ReceiptQueueSummary`, `CameraQualityFeedback`, etc. |
-| `ne-bilaga` | `extensions/ne-bilaga/types.ts` | `NEDeclaration`, `NEDeclarationRutor`, `NEAccountMapping`, `SRURecord`, `SRUFile`, `NE_RUTA_LABELS` |
-| `sru-export` | `extensions/sru-export/types.ts` | `SRUExportResult`, `SRUCoverageStats` |
-
-### API route convention
-
-All extension API routes live under `app/api/extensions//`. No extension routes should exist outside this namespace.
-
----
-
-## Add-ons
-
-Each add-on is self-contained. Listed by priority tier.
-
-### Tier 1: High value, build soon after core
-
-**`receipt-ocr`**
-- Subscribes to: `document.uploaded`
-- Does: Claude Vision OCR, extracts merchant/date/line items/totals, fuzzy-matches to bank transactions (±3 days, amount similarity), suggests BAS account + tax code
-- Special rules: Systembolaget -> non-deductible, restaurant -> representation (90 kr/person limit)
-- Registers: custom mapping rule types for OCR-based categorization
-
-**`ai-categorization`**
-- Subscribes to: `transaction.synced`
-- Does: suggests BAS account + tax code for uncategorized transactions
-- No hard dependency on any specific AI provider. Interface-based so the model is swappable.
-
-**`ne-bilaga`**
-- Registers as: `reportType` via extension registry
-- Does: generates NE-bilaga (income tax appendix for enskild firma, fields R1-R11) from journal entries
-- Only relevant for EF entity type. Hidden for AB.
-
-**`sru-export`**
-- Registers as: `reportType`
-- Does: generates SRU files for Skatteverket electronic filing. Reads SRU mappings from core account metadata.
-
-**`push-notifications`**
-- Subscribes to: `invoice.overdue`, `period.locked`, deadline events from tax calendar
-- Does: Web Push via VAPID. Per-user preferences with quiet hours.
-
-**`owner-payroll`**
-- Registers: routes, sidebar item, settings panel
-- Does: single-employee salary for AB owner. Gross salary, tax deduction, employer contributions (arbetsgivaravgifter). Monthly AGI XML generation for Skatteverket. Box 821 absence reporting (VAB, parental leave) with date tracking. Bilförmån and traktamente input fields with Skatteverket standard rates.
-- Subscribes to: tax calendar deadline events for arbetsgivardeklaration due dates
-
-### Tier 2: Market differentiation
-
-**`annual-report`**
-- Registers as: `reportType` + routes
-- Does: K2 taxonomy mapping from BAS accounts. Generates iXBRL for Bolagsverket digital filing. API integration: validate, upload, redirect to BankID signing. Board member signature flow.
-- K3 support as a sub-toggle within this add-on (component depreciation, fair value).
-
-**`ai-chat`**
-- Registers: floating widget component, routes for session management
-- Does: RAG-powered Swedish tax/accounting assistant using LangChain + embeddings. Session history. Rate limited.
-- No event subscriptions. Read-only access to user's bookkeeping data for context.
-
-**`bankid`**
-- Registers: auth provider, signing flow component
-- Does: BankID integration for login and document signing. Secure Start (animated QR code, mandatory since May 2024). Certificate management for merchant certificates.
-- Used by: `annual-report` (Bolagsverket signing), `owner-payroll` (AGI signing), future audit access.
-
-**`deductions`**
-- Registers: routes, sidebar item, report types
-- Does: Schablonavdrag for mileage (korjournal, 25 kr/mil) and home office (2,000-4,000 kr/year). Generates journal entries.
-
-### Tier 3: Vertical enablers
-
-**`inventory-value`**
-- Registers: routes, report type
-- Does: tracks financial value of stock on account 1400. Accepts journal entries from vertical inventory modules (retail, construction, food). Does not do logistics, variants, batches, or expiry tracking. That is the vertical's job.
-
-**`multi-currency-advanced`**
-- Registers: additional tax codes, report types
-- Does: automated unrealized gain/loss calculations at period end. Currency revaluation entries. Beyond the base kursdifferens on invoice payment.
-
-**`oss-reporting`**
-- Registers: report type, tax codes
-- Does: OSS (One Stop Shop) VAT return for e-commerce sellers. Transactions tagged with OSS tax codes excluded from standard momsdeklaration and routed here.
-
-**`saf-t-export`**
-- Registers: report type
-- Does: SAF-T XML generation. Forward-looking compliance for potential 2026 EU mandate. Maps from the core's granular data model (header -> line -> tax detail).
-
----
-
-## Repo Structure
-```
-app/
- (auth)/
- (onboarding)/
- (dashboard)/
- bookkeeping/
- invoices/
- transactions/
- banking/
- customers/
- reports/
- calendar/
- settings/
- extensions/ → marketplace / management
- (public)/
- api/
- journal-entries/
- invoices/
- transactions/
- banking/
- reports/
- customers/
- deadlines/
- documents/ → upload, hash verification, version history
- audit/ → audit log queries, security events
- extensions/ → register, list, config
- webhooks/ → outbound event delivery
-
-lib/
- core/
- bookkeeping/ → draft/commit, storno, voucher series, period locking
- accounts/ → BAS kontoplan, SRU mapping, dimensions
- reports/ → resultaträkning, balansräkning, råbalans, moms
- invoicing/ → create, send, credit, VAT, Peppol, reminders
- banking/ → PSD2, sync, matching, ISO 20022 (PAIN/CAMT)
- transactions/ → categorization, mapping rules
- tax/ → tax code engine, deadlines, fiscal year, year-end closing
- sie/ → import + export with dimension support
- documents/ → hash-on-upload, WORM storage, deletion blocking, versioning
- audit/ → append-only audit log, behandlingshistorik
- retention/ → purge prevention, retention expiry calculation
- events/ → event bus, types, webhook dispatch
- extensions/ → registry, types, loader
-
-extensions/ → first-party add-ons
- receipt-ocr/
- ai-categorization/
- ai-chat/
- ne-bilaga/
- sru-export/
- push-notifications/
- owner-payroll/
- annual-report/
- bankid/
- deductions/
- inventory-value/
- multi-currency-advanced/
- oss-reporting/
- saf-t-export/
-
-components/
- ui/ → Radix primitives, design system
- core/ → base feature components
- extensions/ → shared extension UI patterns
-
-supabase/
- migrations/ → base schema only
-
-types/
-
-
diff --git a/dev_docs/FEEDBACK_02_09.md b/dev_docs/FEEDBACK_02_09.md
deleted file mode 100644
index 0c9ee934..00000000
--- a/dev_docs/FEEDBACK_02_09.md
+++ /dev/null
@@ -1,357 +0,0 @@
-# Förtydligad feedback med tolkningar
-
-## 1. Onboarding-flöde
-
-**Influencer Business → Influencer Assistant**
-- "Influencer Business" står troligen som appnamn/rubrik i onboarding-flödet
-- Ska ersättas med "Influencer Assistant" överallt där det förekommer
-- Förmodligen i header, sidtitel och eventuellt metadata
-
-**Localhost redirect problem vid auth genom mail**
-- Magic link-autentisering redirectar till `localhost:3000` istället för produktions-URL
-- Environment variable för NEXT_PUBLIC_SITE_URL är förmodligen inte satt korrekt i Supabase
-
-**Ta bort alla detaljer kring EF/AB**
-- Nuvarande onboarding har förklarande text typ "Enklare bokföring, lägre egenavgifter" vid bolagsformsval
-- Ska bli en ren dropdown med endast "Enskild firma", "Aktiebolag", "Inget bolag ännu (frilans)"
-- Ingen pedagogisk text, bara valet
-
-**Lägg till "Inget bolag ännu (frilans)"**
-- Tredje alternativ för creators som tar sina första samarbeten men inte formaliserat verksamheten än
-- Låter dem använda appen för att spåra inkomster innan de registrerar bolag
-- Förmodligen med begränsad funktionalitet (ingen bokföring, bara spårning)
-
-**Verksamhetsnamn lägg till (Eller ditt namn vid EF)**
-- Labeln "Verksamhetsnamn" ska ha suffix-text "(Eller ditt namn vid EF)"
-- Placeholder bör vara "Alices Influencer-verksamhet" eller "Alice Andersson"
-- Gör det tydligt att EF-användare kan använda personnamn
-
-**Org nummer förklara att det är ens personnummer vid EF**
-- Placeholder-text: "ÅÅMMDD-XXXX (ditt personnummer vid EF)"
-- Eller hjälptext under fältet: "Vid enskild firma är orgnummer samma som ditt personnummer"
-- Görs obligatoriskt för EF/AB (ta bort "frivilligt")
-
-**Ta bort frivilligt för EF**
-- Orgnummer är obligatoriskt för både EF och AB
-- Required-validering ska gälla
-
-**Ändra till brun färg där det är grönt**
-- Primärfärg i appen är troligen grön idag
-- Ska bytas till brun enligt brand guidelines
-- Gäller knappar, accenter, aktiva tillstånd
-
-**Bankkonto ta bort? Eller direkt till Enable Banking?**
-- Nuvarande flöde: manuellt IBAN-fält i onboarding
-- Ska ersättas med Enable Banking-integration direkt
-- Dvs. istället för textfält → knapp "Koppla bankkonto" som öppnar Enable Banking
-- Hoppar över manuell input helt? Eller?
-
-**Fixa knapp så att den går direkt vid klick på bank och inte två steg**
-- Nuvarande: Klicka på en bank , sedan ändå behöva scrolla ner och klicka "autentisera till X" knapp.
-
----
-
-## 2. Dashboard (första sidan)
-
-**"Godmorgon Alice, idag ska du göra X" eller "Allt är som det ska"**
-- Personaliserad hero-sektion högst upp på dashboarden
-- "Godmorgon Alice, idag ska du: Skicka faktura till H&M (förfaller om 3 dagar), Betala moms (deadline 12 feb)"
-- Om inga pending items: "Godmorgon Alice, allt är som det ska"
-- Hämtar från kommande kalenderhändelser + fakturor nära förfall + obetalda fakturor
-
-**Pengarna under**
-- "Pengarna under" = summan pengar som finns under/kvar efter att preliminärskatt dragits av
-- Visar nettoresultat efter beräknad skatt
-- Dashboard ska visa: Bruttoinkomst, Beräknad skatt, Kvar att ta ut
-- "Kvar att ta ut: 45 000 kr" typ
-
-**Undersök skatteberäkning?**
-
-**Intäkter / Kostnader också 0, undersök**
-- Dashboard visar 0 kr för både intäkter och kostnader, undersök detta om det stämmer
-
-**Ny kampanj → Nytt samarbete**
-- CTA-knapp eller sektionshuvud säger "Ny kampanj"
-- Ska vara "Nytt samarbete" eller "+ Skapa samarbete"
-- Matchar creators mentala modell bättre
-
-**Spåra leverabler svårt ord**
-- "Leverabler" är projektledarjargong, inte creator-språk
-- Ska vara "Spåra innehåll" eller "Håll koll på publiceringar"
-- Mindre formellt, mer intuitivt
-
-**Ta bort logga körning från första sidan**
-- Det finns en sektion/knapp för mileage tracking på dashboarden
-- Ska tas bort helt (inte relevant för målgruppen)
-- Creators kör sällan tjänsteresor, prioritera inte detta
-
-**Skita i personlig kortkoppling, arbeta endast med företagskort**
-- Endast företagskort via Enable Banking
-- Kategorisera alla transaktioner från företagskonto
-- Enklare modell, färre edge cases
-
-**Ta bort sammanfattning månadsvis kalendervy**
-- Kalendervyn har förmodligen en rad per månad som aggregerar events
-- Tar onödigt utrymme och är inte så användbar
-- Visa bara enskilda events i kronologisk ordning
-
-**Kalender större och mer tilltalande**
-- Nuvarande kalender är förmodligen en liten widget eller sidomodul
-- Ska ta mer plats (förmodligen halva skärmbredden eller större)
-- Kanske full-width på mobil
-- Mer visuellt prominent, då det är core feature
-
-**Ta bort "Håll koll på betalningar och deadlines"**
-- Beskrivande text under kalendersektion
-- Är överflödig/upprepande
-- Ta bort, låt kalendern tala för sig själv
-
----
-
-## 3. Samarbeten (f.d. kampanjer)
-
-**Kampanjer → Samarbete**
-- Överallt där "Kampanj" används som term
-
-**Flytta upp så att det är "+ Skapa samarbete" och "Importera avtal" där uppe istället**
-- Nuvarande: CTA-knappar längre ner på sidan eller i subnavigation
-- Ska vara: Primary actions i toppen av sidan (header-nivå)
-
-**Start och slutdatum för samarbete ändras när man ändrar publiceringsdatum**
-- Bugg: När användaren ändrar publiceringsdatum, ändras även start/slutdatum automatiskt
-- Ska inte hända - olika fält, oberoende av varandra
-- Eller: Ta bort start/slutdatum helt (se nästa punkt)
-
-**Start och slutdatum irrelevant**
-- Start/slutdatum är inte viktiga för creators
-- Relevant är: Publiceringsdatum (när contentet går live) och Utkastdeadline (när drafts ska skickas)
-- Ta bort Start/Slutdatum-fält helt, ersätt med:
- - "Publiceringsdatum" (datum)
- - "Utkastdeadline" (datum, optional)
-
-**Att det ska stå varumärke / direktkund men inte lägga in som kund**
-- Fält för "Varumärke" (t.ex. "H&M") - fritextfält
-- Fält för "Byrå" (t.ex. "Swim Communication") - dropdown/autocomplete som skapar Customer-post
-- Endast byrå ska finnas i Customers-tabellen
-- Varumärke är metadata på samarbetet, inte en relation
-
-**Endast byrå ska läggas in som kund**
-- Customer-tabellen innehåller bara byråer (de som faktiskt betalar)
-- Varumärken är bara en textsträng på samarbetet
-- Fakturan går till byrån, inte varumärket
-
-**Slutkund är ibland varumärke, ibland byrå**
-- "Slutkund" = den entitet som ska synas på fakturan och i kommunikation
-- Om direktkund (inget mellanled): slutkund = varumärke
-- Om via byrå: slutkund = byrå
-- Automatisk logik: Om byrå finns → byrå är slutkund. Annars → varumärke är slutkund
-
-**"Skapa ny kund" knapp inte helt intuitiv i ladda upp avtal flödet**
-
-**Byt ut leverabler (svårt ord), extraheras kan också beskrivas lättare**
-- "Leverabler" → "Innehåll" eller "Publiceringar"
-- "Extraheras" → "Hittades i avtalet" eller "AI fyllde i automatiskt"
-- Enklare språk, mindre jargong
-
-**Exklusivitet inte extraherat korrekt (competing brands i x veckor)**
-- AI-extrahering hittar inte exklusivitetsklausuler korrekt
-- Exempel: "No competing brands for 4 weeks" ska extraheras till "4 veckor"
-- Förbättra prompt eller lägg till specifik parsing för exklusivitet
-
-**Lägg till funktion att man kan lägga in exklusivitet själv**
-- Om AI missar exklusivitet, ska användaren kunna lägga till manuellt (även där det står "ingen exklusivitet hittades")
-- Fält: "Exklusivitet (valfritt)" med dropdown för antal veckor och fritextfält för competing brands
-- Eller: Edit-knapp vid extraherad exklusivitet
-
-**Textinnehåll sammanfatta på briefing med AI**
--"Klistra in mailetråd"
-- Användaren klistrar in hela mejlkonversationen eller annan text.
-- AI extraherar och sammanfattar till strukturerad briefing
-
-**Från kampanj till faktura: populera automatiskt**
-- När användaren skapar faktura från ett samarbete
-- Auto-populera: Kund (byrå), Belopp (från samarbetsavtalet), Beskrivning (samarbetsnamn), Förfallodatum (publiceringsdatum + 30 dagar)
-- Knapp i samarbetsdetaljer: "Skapa faktura" som öppnar fakturaformulär med förifyllda fält
-
-**Fixa UI kundsida**
-- Kundsidan (kund-detaljer) har dålig layout/design
-- Behöver omarbetas: bättre typografi, spacing, färgschema enligt brand
-- Förmodligen legacy-design som inte uppdaterats efter rebrand
-
----
-
-## 4. Transaktioner & Kategorisering
-
-**Automatiskt fetcha banktransaktioner**
-- Enable Banking är redan integrerat men transaktioner hämtas inte automatiskt
-- Implementera: Cron job eller webhook som hämtar transaktioner dagligen
-- Supabase Edge Function + scheduled trigger för att synka transactions
-
-**Kategorisera logiken lägger av efter 3/6 transaktioner**
-- AI-kategorisering fungerar för de första transaktionerna
-- Efter 3-6 transaktioner slutar den kategorisera (returnerar null eller default-kategori)
-- Förmodligen: Rate limit, token limit, eller bugg i loop-logiken
-- Fix: Batch-processa i chunks, kolla error handling
-
-**Undersök balans/resultat??**
-- Rapporterad balans/resultat matchar inte faktiskt banksaldo eller förväntad vinst (kanske)
-- Förmodligen: Kategoriseringsbuggen ovan gör att många transaktioner blir okategoriserade
-- Eller: Dubbelbokföring, felaktig summering
-- Fix: Debugga query som beräknar balans, verifiera mot banksaldo
-
-**Gör om swipe funktionen till att man swipear till rätt kostnadskonto istället**
-- De mest troliga kostnadskonton visas på skärmen, alternativ för fler om det inte stämmer.
-
-**Lägga till fler alternativ för varje kostnad (ex bankkostnad är inte med)**
-- Nuvarande kategorilista är ofullständig
-- "Bankkostnad" saknas (avgifter från banken)
-- Lägg till: Bankkostnad, Kortavgifter, Valutaväxling, eventuellt fler
-- Förmodligen hårdkodad enum, utöka listan
-
-**Faktura ska mappas till transaktioner**
-- När en faktura betalas, ska den kopplas till motsvarande banktransaktion
-- Auto-matching baserat på: Belopp (±1%), Datum (±7 dagar), Kund-referens
-- UI: Ikon som visar "Kopplad till faktura #123" på transaktionen
-- Underlättar reconciliation
-- Detta kan vara en del av kategoriserings swipe funktionen.
-
----
-
-## 5. Kalender & Deadlines
-
-**Lägg in så att prel skatte inbetalningsdatum ligger i kalendern**
-- Preliminärskatt ska visas som återkommande events i kalendern
-- Månatlig (om stor omsättning), kvartalsvis (standard), eller årlig (låg omsättning)
-- Automatisk beräkning baserat på ackumulerad vinst
-- Event: "Preliminärskatt 12 500 kr" med datum och länk till betalning
-
-**Månadsvis/kvartal/år**
-- Intervall för prelskatt beror på förväntad omsättning:
- - Månad: >1M kr/år
- - Kvartal: 100k-1M kr/år (default)
- - År: <100k kr/år
-- Automatisk detektering baserat på faktiska intäkter
-- Eller: Användarinställning om de vet sin skatteklass
-
----
-
-## 6. Intäktstyper
-
-**Lägg till "Podcast" som sätt att man får betalt**
-- Nuvarande intäktstyper: Instagram, TikTok, YouTube, Sponsrad post, etc.
-- Lägg till: "Podcast" (brandintegration i podcast-episoder)
-- Ska vara eget val i dropdown "Typ av samarbete" eller "Plattform"
-- Samma hantering som andra samarbetstyper: fakturering, kategorisering, momsklassificering
-
-ISSUES:
-## Error Type
-Runtime SyntaxError
-
-## Error Message
-Unexpected token '<'
-
-Next.js version: 16.1.5 (Turbopack)
-
-
-Fixa så att det är tre cards istället: EF, AB, Frilans (coming soon)
-
-Blir inte automatiskt redirectad till nästa steg efter bank connect:
-
- POST /api/banking/connect 200 in 988ms (compile: 37ms, render: 951ms)
- GET /api/banking/callback?state=acdf00c6-82a1-4068-ac07-7510ee41667d&code=061d67b7-81d7-4996-8bb5-9cd731651108 307 in 2.0s (compile: 35ms, render: 2.0s)
- GET /onboarding 200 in 167ms (compile: 5ms, proxy.ts: 127ms, render: 35ms)
- GET /onboarding 200 in 315ms (compile: 5ms, proxy.ts: 276ms, render: 33ms)
-
-Dessa är på fel ställe och är inkorrekta:
-
-Välkommen till din översikt!
-Steg 1 av 5
-
-Stäng guide
-Här ser du hela din ekonomiska situation på ett ställe. Låt oss gå igenom de viktigaste delarna.
-
-Fixa namn / bolagsnamn efter God kväll på main page.
-
-Trippla lägg till samarbetsknappar på https://marguerite-nonhieratical-becki.ngrok-free.dev/campaigns
-
-Får ## Error Type
-Runtime SyntaxError
-
-## Error Message
-Unexpected token '<'
-
-Next.js version: 16.1.5 (Turbopack)
- när jag försöker ta bort exklusivitetsmärke från AI extraheringen.
-
-
-Och detta när jag förösker lägga till exklusivitet manuellt:
-## Error Type
-Runtime TypeError
-
-## Error Message
-Cannot read properties of undefined (reading 'length')
-
-
- at Step5Exclusivity (components/contracts/ContractImportWizard.tsx:1169:50)
- at renderStepContent (components/contracts/ContractImportWizard.tsx:324:16)
- at ContractImportWizard (components/contracts/ContractImportWizard.tsx:403:10)
- at CampaignImportPage (app/(dashboard)/campaigns/import/page.tsx:37:7)
-
-## Code Frame
- 1167 |
- 1168 |
-> 1169 | {extraction.exclusivity.excludedBrands.length > 0 && (
- | ^
- 1170 |
- 1171 |
- 1172 |
-
-Next.js version: 16.1.5 (Turbopack)
-
-"Kunde inte kategorisera. Tryck "Hoppa över" för att gå vidare." när jag förösker välja bankkostnader / kortkostnader
-
- POST /api/transactions/d100f6a5-5512-464f-a500-1f63f561e72b/categorize 200 in 1440ms (compile: 474ms, render: 966ms)
-Failed to update transaction: {
- code: '23514',
- details: null,
- hint: null,
- message: 'new row for relation "transactions" violates check constraint "transactions_category_check"'
-}
- POST /api/transactions/5d926784-7acb-483c-8859-e34ff29bdd49/categorize 500 in 1045ms (compile: 10ms, render: 1035ms)
-Failed to update transaction: {
- code: '23514',
- details: null,
- hint: null,
- message: 'new row for relation "transactions" violates check constraint "transactions_category_check"'
-}
- POST /api/transactions/5d926784-7acb-483c-8859-e34ff29bdd49/categorize 500 in 799ms (compile: 6ms, render: 793ms)
- POST /api/transactions/c81e8863-0085-465a-a96b-f3647f28551f/categorize 200 in 1055ms (compile: 6ms, render: 1049ms)
- POST /api/transactions/7001bd21-c4e0-46a2-b069-fbb6dc16cd43/categorize 200 in 848ms (compile: 7ms, render: 842ms)
- POST /api/transactions/f7dc202a-0938-4614-99cc-254c43e63144/categorize 200 in 902ms (compile: 6ms, render: 896ms)
- POST /api/transactions/batch-match-invoices 200 in 425ms (compile: 3ms, render: 422ms)
- POST /api/transactions/suggest-categories 200 in 291ms (compile: 1823µs, render: 289ms)
- POST /api/transactions/2ebaeaa7-b452-437c-94d3-3716d45085d4/categorize 200 in 836ms (compile: 3ms, render: 833ms)
- POST /api/transactions/9bc5e6bb-0dec-4ce0-8732-e6540f44e229/categorize 200 in 860ms (compile: 6ms, render: 853ms)
- POST /api/transactions/batch-match-invoices 200 in 124ms (compile: 5ms, render: 119ms)
- POST /api/transactions/suggest-categories 200 in 235ms (compile: 2ms, render: 233ms)
-Failed to update transaction: {
- code: '23514',
- details: null,
- hint: null,
- message: 'new row for relation "transactions" violates check constraint "transactions_category_check"'
-}
- POST /api/transactions/5d926784-7acb-483c-8859-e34ff29bdd49/categorize 500 in 920ms (compile: 6ms, render: 914ms)
-
-Fixa transaktionslogiken allmänt. Ta bort privatvalet helt.
-
-Undersök om alla intäkter ska vara 3900 övriga rörelseintäkter
-
-Gör en TODO (tex "två passerade deadlines" är direkt under God kväll)
-
-Fixa så titel på samarbete syns.
-
-Värde -> Arvode
-
-Se över bankuppgifter i faktura. Och fakturanr, IBAN, EU momsnmr.
-
-Ta bort skatte "ditt att spendera"
\ No newline at end of file
diff --git a/dev_docs/FULL_BAS.md b/dev_docs/FULL_BAS.md
deleted file mode 100644
index 1359a1b6..00000000
--- a/dev_docs/FULL_BAS.md
+++ /dev/null
@@ -1,2192 +0,0 @@
-KONTOPLAN BAS 2026
-v 1.0
-För ändringar jämfört med 2025 hänvisas till webbsidan där du under Jämför kontoplaner
-hittar en excelfil i vilken skillnaderna presenteras.
-# = Konton som inte ska användas när K2 tillämpas.
-Huvudkonton Underkonton
-10
-IMMATERIELLA
-ANLÄGGNINGSTILLGÅNGAR
-1010# Utvecklingsutgifter 1011#
-Balanserade utgifter för forskning och
-utveckling
-1012# Balanserade utgifter för programvaror
-Ackumulerade nedskrivningar på
-1018#
-balanserade utgifter
-Ackumulerade avskrivningar på
-1019#
-balanserade utgifter
-1020 Koncessioner m.m. 1028
-1029
-Ackumulerade nedskrivningar på
-koncessioner m.m.
-Ackumulerade avskrivningar på
-koncessioner m.m.
-1030 Patent 1038 Ackumulerade nedskrivningar på patent
-1039 Ackumulerade avskrivningar på patent
-1040 Licenser 1048
-Ackumulerade nedskrivningar på
-licenser
-1049 Ackumulerade avskrivningar på licenser
-1050 Varumärken 1058
-1059
-Ackumulerade nedskrivningar på
-varumärken
-Ackumulerade avskrivningar på
-varumärken
-1060 Hyresrätter och liknande 1068
-1069
-Ackumulerade nedskrivningar på
-hyresrätter och liknande
-Ackumulerade avskrivningar på
-hyresrätter och liknande
-1070 Goodwill 1078
-Ackumulerade nedskrivningar på
-goodwill
-1079 Ackumulerade avskrivningar på goodwill
-1080
-Pågående projekt och förskott
-för immateriella anläggningstillgångar 1081
-1088
-Pågående projekt för immateriella
-anläggningstillgångar
-Förskott för immateriella
-anläggningstillgångar
-1090
-Övriga immateriella
-anläggningstillgångar 1092 Tomträtter
-1098
-1099
-Ackumulerade nedskrivningar på övriga
-immateriella anläggningstillgångar
-Ackumulerade avskrivningar på övriga
-immateriella anläggningstillgångar
-11 BYGGNADER OCH MARK
-1110 Byggnader 1111 Byggnader på egen mark
-1112 Byggnader på annans mark
-Ackumulerade nedskrivningar på
-1118
-byggnader
-Ackumulerade avskrivningar på
-1119
-byggnader
-1120
-Förbättringsutgifter på annans
-fastighet 1129
-Ackumulerade avskrivningar på
-förbättringsutgifter på annans fastighet
-1130 Mark
-1140 Tomter och obebyggda markområden
-1150 Markanläggningar 1158
-1159
-Ackumulerade nedskrivningar på
-markanläggningar
-Ackumulerade avskrivningar på
-markanläggningar
-1180
-Pågående nyanläggningar och
-förskott för byggnader och mark 1181 1188 Pågående ny-, till- och ombyggnad
-Förskott för byggnader och mark
-12 MASKINER RESPEKTIVE INVENTARIER
-1210
-Maskiner och andra tekniska
-anläggningar 1211
-Maskiner och andra tekniska
-anläggningar i övrigt
-Byggnads- och markinventarier (för
-1212
-produktion)
-1214 Datorer (för produktion)
-1216 Arbetsfordon
-1217 Finansiellt leasade maskiner
-Ackumulerade nedskrivningar på
-maskiner och andra tekniska
-1218
-anläggningar
-Ackumulerade avskrivningar på
-maskiner och andra tekniska
-1219
-anläggningar
-1220 Inventarier, verktyg och installationer 1221
-Inventarier, verktyg och installationer i
-övrigt
-Byggnads- och markinventarier (ej för
-1222
-produktion)
-1224 Datorer (ej för produktion)
-Bilar och transportmedel (ej för
-1226
-produktion)
-1227 Finansiellt leasade inventarier
-Ackumulerade nedskrivningar på
-1228
-inventarier, verktyg och installationer
-Ackumulerade avskrivningar på
-1229
-inventarier, verktyg och installationer
-1230
-(Fritt konto för Maskiner och andra
-tekniska anläggningar)
-1240
-(Fritt konto för Maskiner och andra
-tekniska anläggningar)
-1250
-(Fritt konto för Inventarier, verktyg
-och installationer)
-1260
-(Fritt konto för Inventarier, verktyg
-och installationer)
-1280
-Pågående nyanläggningar och förskott
-för maskiner respektive inventarier 1281
-1288
-Pågående nyanläggningar, maskiner
-respektive inventarier
-Förskott för maskiner respektive
-inventarier
-1290
-Övriga materiella
-anläggningstillgångar 1291 Konst och liknande tillgångar
-Djur som klassificeras som
-1292
-anläggningstillgång
-1298
-1299
-Ackumulerade nedskrivningar på övriga
-materiella anläggningstillgångar
-Ackumulerade avskrivningar på övriga
-materiella anläggningstillgångar
-13
-FINANSIELLA
-ANLÄGGNINGSTILLGÅNGAR
-1310 Andelar i koncernföretag 1311
-1312
-1313
-1314
-1316 1317
-1318
-Aktier i noterade svenska
-koncernföretag
-Aktier i onoterade svenska
-koncernföretag
-Aktier i noterade utländska
-koncernföretag
-Aktier i onoterade utländska
-koncernföretag
-Andra andelar i svenska koncernföretag
-Andra andelar i utländska
-koncernförertag
-Ackumulerade nedskrivningar av
-andelar i koncernföretag
-1320
-1330
-1340
-1350
-Långfristiga fordringar hos
-koncernföretag 1321
-Långfristiga fordringar hos
-moderföretag
-1322 Långfristiga fordringar hos dotterföretag
-Långfristiga fordringar hos andra
-1323
-koncernföretag
-Ackumulerade nedskrivningar av
-långfristiga fordringar hos
-1328
-koncernföretag
-Andelar i intresseföretag och
-gemensamt styrda företag samt övriga
-företag som det finns ett ägarintresse i 1331 1332
-1333 1334
-1336
-1337
-Andelar i intresseföretag
-Ackumulerade nedskrivningar av
-andelar i intresseföretag
-Andelar i gemensamt styrda företag
-Ackumulerade nedskrivningar av
-andelar i gemensamt styrda företag
-Andelar i övriga företag som det finns
-ett ägarintresse i
-Ackumulerade nedskrivningar av
-andelar i övriga företag som det finns
-ett ägarintresse i
-Långfristiga fordringar hos
-intresseföretag och gemensamt styrda
-företag samt övriga företag som det
-finns ett ägarintresse i 1341
-1342
-1343
-1344
-1346
-1347
-Långfristiga fordringar hos
-intresseföretag
-Ackumulerade nedskrivningar av
-långfristiga fordringar hos
-intresseföretag
-Långfristiga fordringar hos gemensamt
-styrda företag
-Ackumulerade nedskrivningar av
-långfristiga fordringar hos gemensamt
-styrda företag
-Långfristiga fordringar hos övriga
-företag som det finns ett ägarintresse i
-Ackumulerade nedskrivningar av
-långfristiga fordringar hos övriga företag
-som det finns ett ägarintresse i
-Andra långfristiga
-värdepappersinnehav 1351 Andelar i noterade företag
-1352 Andra andelar
-1353 Andelar i bostadsrättsföreningar
-1354 Obligationer
-1356 Andelar i ekonomiska föreningar
-1357 Andelar i handelsbolag
-1358
-Ackumulerade nedskrivningar av andra
-långfristiga värdepappersinnehav
-1360
-Lån till delägare eller närstående,
-långfristig del 1369
-Ackumulerade nedskrivningar av lån till
-delägare eller närstående, långfristig del
-1370# Uppskjuten skattefordran
-1380 Andra långfristiga fordringar 1381 Långfristiga reversfordringar
-1382 Långfristiga fordringar hos anställda
-1383 Lämnade depositioner, långfristiga
-1384 Derivat
-1385 Kapitalförsäkring
-1387 Långfristiga kontraktsfordringar
-1388 Långfristiga kundfordringar
-Ackumulerade nedskrivningar av andra
-1389
-långfristiga fordringar
-14
-LAGER, PRODUKTER I ARBETE OCH
-PÅGÅENDE ARBETEN
-1410 Lager av råvaror 1419 Förändring av lager av råvaror
-1420
-Lager av tillsatsmaterial och
-förnödenheter 1429
-Förändring av lager av tillsatsmaterial
-och förnödenheter
-1440 Produkter i arbete 1449 Förändring av produkter i arbete
-1450 Lager av färdiga varor 1459 Förändring av lager av färdiga varor
-1460 Lager av handelsvaror 1465 Lager av varor VMB
-1466 Nedskrivning av varor VMB
-1467 1469 Lager av varor VMB förenklad
-Förändring av lager av handelsvaror
-1470 Pågående arbeten 1471 Pågående arbeten, nedlagda kostnader
-1478 Pågående arbeten, fakturering
-1479 Förändring av pågående arbeten
-1480 Förskott för varor och tjänster 1481 Remburser
-1489 Övriga förskott till leverantörer
-1490 Övriga lagertillgångar 1491 Lager av värdepapper
-1492 Lager av fastigheter
-Djur som klassificeras som
-1493
-omsättningstillgång
-15 KUNDFORDRINGAR
-1510 Kundfordringar 1511 Kundfordringar
-1512 Belånade kundfordringar (factoring)
-1513 Kundfordringar – delad faktura
-1516 Tvistiga kundfordringar
-1518# Ej reskontraförda kundfordringar
-1519 Nedskrivning av kundfordringar
-1520 Växelfordringar 1525 Osäkra växelfordringar
-1529 Nedskrivning av växelfordringar
-1530 Kontraktsfordringar 1531 Kontraktsfordringar
-1532 Belånade kontraktsfordringar
-1536 Tvistiga kontraktsfordringar
-1539 Nedskrivning av kontraktsfordringar
-1550 Konsignationsfordringar
-1560 Kundfordringar hos koncernföretag 1561 Kundfordringar hos moderföretag
-1562 Kundfordringar hos dotterföretag
-Kundfordringar hos andra
-1563
-koncernföretag
-Ej reskontraförda kundfordringar hos
-1568
-koncernföretag
-Nedskrivning av kundfordringar hos
-1569
-koncernföretag
-1570
-Kundfordringar hos intresseföretag,
-gemensamt styrda företag och övriga
-företag som det finns ett ägarintresse i 1571 1572
-1573
-Kundfordringar hos intresseföretag
-Kundfordringar hos gemensamt styrda
-företag
-Kundfordringar hos övriga företag som
-det finns ett ägarintresse i
-16 ÖVRIGA KORTFRISTIGA FORDRINGAR
-1610 Kortfristiga fordringar hos anställda 1611 Reseförskott
-1612 Kassaförskott
-1613 Övriga förskott
-1614 Tillfälliga lån till anställda
-1619 Övriga fordringar hos anställda
-1620 Upparbetad men ej fakturerad intäkt
-1630
-Avräkning för skatter och avgifter
-(skattekonto)
-1640 Skattefordringar
-1650 Momsfordran
-1660
-Kortfristiga fordringar hos
-koncernföretag 1661 Kortfristiga fordringar hos moderföretag
-1662 Kortfristiga fordringar hos dotterföretag
-Kortfristiga fordringar hos andra
-1663
-koncernföretag
-1670
-Kortfristiga fordringar hos
-intresseföretag, gemensamt styrda
-företag och övriga företag som det finns
-ett ägarintresse i 1671
-1672
-Kortfristiga fordringar hos
-intresseföretag
-Kortfristiga fordringar hos gemensamt
-styrda företag
-1673
-Kortfristiga fordringar hos övriga företag
-som det finns ett ägarintresse i
-1680 Andra kortfristiga fordringar 1681 Utlägg för kunder
-1682 Kortfristiga lånefordringar
-1683 Derivat
-1684 Kortfristiga fordringar hos leverantörer
-Kortfristiga fordringar hos delägare eller
-1685
-närstående
-1686 Fordringar för kontokort och kuponger
-1687 Kortfristig del av långfristiga fordringar
-1688 Fordran arbetsmarknadsförsäkringar
-1689 Övriga kortfristiga fordringar
-1690
-Fordringar för tecknat men ej
-inbetalt aktiekapital
-17
-FÖRUTBETALDA KOSTNADER OCH
-UPPLUPNA INTÄKTER
-1710 Förutbetalda hyreskostnader
-1720 Förutbetalda leasingavgifter
-1730 Förutbetalda försäkringspremier
-1740 Förutbetalda räntekostnader
-1750 Upplupna hyresintäkter
-1760 Upplupna ränteintäkter
-1770 Tillgångar av kostnadsnatur
-1780 Upplupna avtalsintäkter
-1790
-Övriga förutbetalda kostnader
-och upplupna intäkter
-18 KORTFRISTIGA PLACERINGAR
-1810 Andelar i börsnoterade företag
-1820 Obligationer
-1830 Konvertibla skuldebrev
-1860 Andelar i koncernföretag, kortfristigt
-1880 Andra kortfristiga placeringar 1886 Derivat
-1889 Andelar i övriga företag
-1890
-Nedskrivning av kortfristiga
-placeringar
-19 KASSA OCH BANK
-1910 Kassa 1911 Huvudkassa
-1912 Kassa 2
-1913 Kassa 3
-1920 PlusGiro
-1930 Företagskonto
-1940 Övriga bankkonton
-1950 Bankcertifikat
-1960 Koncernkonto moderföretag
-1970 Särskilda bankkonton 1972 Upphovsmannakonto
-1973 Skogskonto
-1974 Spärrade bankmedel
-1979 Övriga särskilda bankkonton
-1980 Valutakonton
-1990 Redovisningsmedel
-20 EGET KAPITAL
-2010 Eget kapital 2011 Egna varuuttag
-2013 Övriga egna uttag
-2017 Årets kapitaltillskott
-2018 Övriga egna insättningar
-2019 Årets resultat, delägare 1
-2020 Eget kapital 2021 Egna varuuttag
-2023 Övriga egna uttag
-2027 Årets kapitaltillskott
-2028 Övriga egna insättningar
-2029 Årets resultat, delägare 2
-2030 Eget kapital 2031 Egna varuuttag
-2033 Övriga egna uttag
-2037 Årets kapitaltillskott
-2038 Övriga egna insättningar
-2039 Årets resultat, delägare 3
-2040 Eget kapital 2041 Egna varuuttag
-2043 Övriga egna uttag
-2047 Årets kapitaltillskott
-2048 Övriga egna insättningar
-2049 Årets resultat, delägare 4
-2050 Avsättning till expansionsfond
-2060
-Eget kapital i ideella föreningar,
-stiftelser och registrerade trossamfund 2061 Kapital/stiftelsekapital/grundkapital
-2064 Ackumulerat realisationsresultat
-2065 Fond för verkligt värde
-2066 Värdesäkringsfond
-2067 Balanserat överskott eller underskott
-Överskott eller underskott från
-2068
-föregående år
-2069 Årets resultat
-2070 Ändamålsbestämda medel 2071 Ändamål 1
-2072 Ändamål 2
-2080 Bundet eget kapital 2081 Aktiekapital
-2082 Ej registrerat aktiekapital
-2083 Medlemsinsatser
-2084 Förlagsinsatser
-2085 Uppskrivningsfond
-2086 Reservfond
-2087 Bunden överkursfond
-2087 Insatsemission
-2088 Fond för yttre underhåll
-2089 Fond för utvecklingsutgifter
-2090 Fritt eget kapital 2091 Balanserad vinst eller förlust
-2092# Mottagna/lämnade koncernbidrag
-2093 Erhållna aktieägartillskott
-2094 Egna aktier
-2095 Fusionsresultat
-2096# Fond för verkligt värde
-2097 Fri överkursfond
-2098 Vinst eller förlust från föregående år
-2099 Årets resultat
-21 OBESKATTADE RESERVER
-2110 Periodiseringsfonder
-2120 Periodiseringsfond 2020 2120 Periodiseringsfond 2020
-2121 Periodiseringsfond 2021
-2122 Periodiseringsfond 2022
-2123 Periodiseringsfond 2023
-2124 Periodiseringsfond 2024
-2125 Periodiseringsfond 2025
-2126 Periodiseringsfond 2026
-2127 Periodiseringsfond 2027
-2129 Periodiseringsfond 2019
-2130 Periodiseringsfond 2020 – nr 2 2130 Periodiseringsfond 2020 – nr 2
-2131 Periodiseringsfond 2021 – nr 2
-2132 Periodiseringsfond 2022 – nr 2
-2133 Periodiseringsfond 2023 – nr 2
-2134 Periodiseringsfond 2024 – nr 2
-2135 Periodiseringsfond 2025 - nr 2
-2136 Periodiseringsfond 2026 – nr 2
-2137 Periodiseringsfond 2027 - nr 2
-2139 Periodiseringsfond 2019 – nr 2
-2150 Ackumulerade överavskrivningar 2151
-2152
-2153
-Ackumulerade överavskrivningar på
-immateriella anläggningstillgångar
-Ackumulerade överavskrivningar på
-byggnader och markanläggningar
-Ackumulerade överavskrivningar på
-maskiner respektive inventarier
-2160 Ersättningsfond 2161
-2162
-2164
-Ersättningsfond maskiner och
-inventarier
-Ersättningsfond byggnader och
-markanläggningar
-Ersättningsfond för djurlager i jordbruk
-och renskötsel
-2190 Övriga obeskattade reserver 2196 Lagerreserv
-2199 Övriga obeskattade reserver
-22 AVSÄTTNINGAR
-2210
-Avsättningar för pensioner enligt
-tryggandelagen
-2220 Avsättningar för garantier
-2230
-Övriga avsättningar för pensioner och
-liknande förpliktelser
-2240# Avsättningar för uppskjutna skatter
-2250 Övriga avsättningar för skatter 2252 Avsättningar för tvistiga skatter
-Avsättningar särskild löneskatt,
-2253
-deklarationspost
-2290 Övriga avsättningar
-23 LÅNGFRISTIGA SKULDER
-2310 Obligations- och förlagslån
-2320 Konvertibla lån och liknande 2321 Konvertibla lån
-2322 Lån förenade med optionsrätt
-2323 Vinstandelslån
-2324 Kapitalandelslån
-2330 Kontokredit
-2340 Byggnadskreditiv
-2350
-Andra långfristiga skulder till
-kreditinstitut 2351 Fastighetslån, långfristig del
-Långfristiga lån i utländsk valuta från
-kreditinstitut
-2355
-2359 Övriga långfristiga lån från kreditinstitut
-2360
-Långfristiga skulder till
-koncernföretag 2361 Långfristiga skulder till moderföretag
-2362 Långfristiga skulder till dotterföretag
-Långfristiga skulder till andra
-2363
-koncernföretag
-2370
-Långfristiga skulder till intresseföretag,
-gemensamt styrda företag och övriga
-företag som det finns ett ägarintresse i 2371 2372
-2373
-Långfristiga skulder till intresseföretag
-Långfristiga skulder till gemensamt
-styrda företag
-Långfristiga skulder till övriga företag
-som det finns ett ägarintresse i
-2390 Övriga långfristiga skulder 2391 Avbetalningskontrakt, långfristig del
-2392 Villkorliga långfristiga skulder
-Lån från närstående personer, långfristig
-2393
-del
-2394 Långfristiga leverantörskrediter
-2395 2396 Derivat
-Andra långfristiga lån i utländsk valuta
-2397 Mottagna depositioner, långfristiga
-2399 Övriga långfristiga skulder
-24
-KORTFRISTIGA SKULDER TILL
-KREDITINSTITUT, KUNDER OCH
-LEVERANTÖRER
-2410
-Andra kortfristiga låneskulder till
-kreditinstitut 2411 Kortfristiga lån från kreditinstitut
-2412 Byggnadskreditiv, kortfristig del
-Kortfristig del av långfristiga skulder till
-2417
-kreditinstitut
-Övriga kortfristiga skulder till
-2419
-kreditinstitut
-2420 Förskott från kunder 2421 Ej inlösta presentkort
-2429 Övriga förskott från kunder
-2430 Pågående arbeten 2431 Pågående arbeten, fakturering
-2438 Pågående arbeten, nedlagda kostnader
-Beräknad förändring av pågående
-2439
-arbeten
-2440 Leverantörsskulder 2441 Leverantörsskulder
-2443 Konsignationsskulder
-2445 Tvistiga leverantörsskulder
-2448# Ej reskontraförda leverantörsskulder
-2450 Fakturerad men ej upparbetad intäkt
-2460 Leverantörsskulder till koncernföretag 2461 Leverantörsskulder till moderföretag
-2462 Leverantörsskulder till dotterföretag
-Leverantörsskulder till andra
-2463
-koncernföretag
-2470
-Leverantörsskulder till intresseföretag,
-gemensamt styrda företag och övriga
-företag som det finns ett ägarintresse i 2471 2472
-2473
-Leverantörsskulder till intresseföretag
-Leverantörsskulder till gemensamt
-styrda företag
-Leverantörsskulder till övriga företag
-som det finns ett ägarintresse i
-2480 Kontokredit, kortfristig
-2490
-Övriga kortfristiga skulder till
-kreditinstitut, kunder och leverantörer 2491 Avräkning spelarrangörer
-2492 Växelskulder
-2499 Andra övriga kortfristiga skulder
-25 SKATTESKULDER
-2510 Skatteskulder 2512 Beräknad inkomstskatt
-26 MOMS OCH PUNKTSKATTER
-2610 Utgående moms, 25 % 2620 Utgående moms, 12 % 2630 Utgående moms, 6 % 2640 Ingående moms Beräknad
-2513
-fastighetsskatt/fastighetsavgift
-Beräknad särskild löneskatt på
-2514
-pensionskostnader
-2515 Beräknad avkastningsskatt
-2517 Beräknad utländsk skatt
-2518 Betald F-skatt
-2611
-2612 2613 2614
-2615 2616 2618 Utgående moms på försäljning inom
-Sverige, 25 %
-Utgående moms på egna uttag, 25 %
-Utgående moms för uthyrning, 25 %
-Utgående moms omvänd
-betalskyldighet, 25 %
-Utgående moms import av varor, 25 %
-Utgående moms VMB 25 %
-Vilande utgående moms, 25 %
-2621
-2622 2623 2624
-2625 2626 2628 Utgående moms på försäljning inom
-Sverige, 12 %
-Utgående moms på egna uttag, 12 %
-Utgående moms för uthyrning, 12 %
-Utgående moms omvänd
-betalningsskyldighet 12 %
-Utgående moms import av varor, 12 %
-Utgående moms VMB 12 %
-Vilande utgående moms, 12 %
-2631
-2632 2633 2634
-2635 2636 2638 Utgående moms på försäljning inom
-Sverige, 6 %
-Utgående moms på egna uttag, 6 %
-Utgående moms för uthyrning, 6 %
-Utgående moms omvänd
-betalningsskyldighet, 6 %
-Utgående moms import av varor, 6 %
-Utgående moms VMB 6 %
-Vilande utgående moms, 6 %
-2641 Debiterad ingående moms
-Debiterad ingående moms i anslutning
-2642
-till frivillig betalningsskyldighet
-Beräknad ingående moms på förvärv
-2645
-från utlandet
-2646 Ingående moms på uthyrning
-Ingående moms omvänd
-betalningsskyldighet varor och tjänster i
-2647
-Sverige
-2648 Vilande ingående moms
-2649 Ingående moms, blandad verksamhet
-2650 Redovisningskonto för moms
-2660 Punktskatter
-2670
-Utgående moms på försäljning inom
-EU, OSS
-27
-PERSONALENS SKATTER, AVGIFTER OCH
-LÖNEAVDRAG
-2710 Personalskatt
-2730
-Lagstadgade sociala avgifter och
-särskild löneskatt 2731 Avräkning lagstadgade sociala avgifter
-2732 Avräkning särskild löneskatt
-2740 Avtalade sociala avgifter
-2750 Utmätning i lön m.m.
-2760 Semestermedel 2761 Avräkning semesterlöner
-2762 Semesterlönekassa
-2790 Övriga löneavdrag 2791 Personalens intressekonto
-2792 Lönsparande
-2793 försäkringspremier
-2794 Fackföreningsavgifter
-2795 Mätnings- och granskningsarvoden
-2799 Övriga löneavdrag
-28 ÖVRIGA KORTFRISTIGA SKULDER
-2810
-Avräkning för factoring och belånade
-kontraktsfordringar 2811 Avräkning för factoring
-Avräkning för belånade
-2812
-kontraktsfordringar
-2820 Kortfristiga skulder till anställda 2821 Löneskulder
-2822 Reseräkningar
-2823 Tantiem, gratifikationer
-2829 Övriga kortfristiga skulder till anställda
-2830 Avräkning för annans räkning
-2840 Kortfristiga låneskulder 2841 Kortfristig del av långfristiga skulder
-2849 Övriga kortfristiga låneskulder
-2850
-Avräkning för skatter och avgifter
-(skattekonto) 2852
-Anståndsbelopp för moms,
-arbetsgivaravgifter och personalskatt
-2860 Kortfristiga skulder till koncernföretag 2861 Kortfristiga skulder till moderföretag
-2862 Kortfristiga skulder till dotterföretag
-Kortfristiga skulder till andra
-2863
-koncernföretag
-2870
-Kortfristiga skulder till intresseföretag,
-gemensamt styrda företag och övriga
-företag som det finns ett ägarintresse i 2871 Kortfristiga skulder till intresseföretag
-2872
-2873
-Kortfristiga skulder till gemensamt
-styrda företag
-Kortfristiga skulder till övriga företag
-som det finns ett ägarintresse i
-2880 Skuld erhållna bidrag
-2890 Övriga kortfristiga skulder 2891 Skulder under indrivning
-2892 Inre reparationsfond/underhållsfond
-Skulder till närstående personer,
-2893
-kortfristig del
-2895 Derivat (kortfristiga skulder)
-2897 Mottagna depositioner, kortfristiga
-2898 Outtagen vinstutdelning
-2899 Övriga kortfristiga skulder
-29
-UPPLUPNA KOSTNADER OCH
-FÖRUTBETALDA INTÄKTER
-2910 Upplupna löner 2911 Löneskulder
-2912 Ackordsöverskott
-2919 Övriga upplupna löner
-2920 Upplupna semesterlöner
-2930 Upplupna pensionskostnader 2931 Upplupna pensionsutbetalningar
-2940
-Upplupna lagstadgade sociala och
-andra avgifter 2941
-Beräknade upplupna lagstadgade sociala
-avgifter
-2942 Beräknad upplupen särskild löneskatt
-2943
-2944
-Beräknad upplupen särskild löneskatt på
-pensionskostnader, deklarationspost
-Beräknad upplupen avkastningsskatt på
-pensionskostnader
-2950 Upplupna avtalade sociala avgifter 2951
-2959
-Upplupna avtalade
-arbetsmarknadsförsäkringar
-Upplupna avtalade
-pensionsförsäkringsavgifter,
-deklarationspost
-2960 Upplupna räntekostnader
-2970 Förutbetalda intäkter 2971 Förutbetalda hyresintäkter
-2972 Förutbetalda medlemsavgifter
-2979 Övriga förutbetalda intäkter
-2980 Upplupna avtalskostnader
-2990
-Övriga upplupna kostnader och
-förutbetalda intäkter 2991 Beräknat arvode för bokslut
-2992 Beräknat arvode för revision
-2993 Ospecificerad skuld till leverantörer
-2995 Ej ankomna leverantörsfakturor
-Övriga upplupna kostnader och
-2998
-förutbetalda intäkter
-2999 OBS-konto
-30 HUVUDINTÄKTER
-3000 Försäljning inom Sverige 3001 Försäljning inom Sverige, 25 % moms
-3002 3003 Försäljning inom Sverige, 12 % moms
-Försäljning inom Sverige, 6 % moms
-3004 Försäljning inom Sverige, momsfri
-3100 Försäljning av varor utanför Sverige 3105 Försäljning varor till land utanför EU
-Försäljning varor till annat EU-land,
-3106
-momspliktig
-Försäljning varor till annat EU-land,
-3108
-momsfri
-3200 Försäljning VMB och omvänd moms 3211 Försäljning positiv VMB 25 %
-3212 Försäljning negativ VMB 25 %
-Försäljning inom byggsektorn, omvänd
-3231
-betalningsskyldighet moms
-3300 Försäljning av tjänster utanför Sverige 3305 Försäljning tjänster till land utanför EU
-3308 Försäljning tjänster till annat EU-land
-3400 Försäljning, egna uttag 3401 Egna uttag momspliktiga, 25 %
-3402 3403 Egna uttag momspliktiga, 12 %
-Egna uttag momspliktiga, 6 %
-3404 Egna uttag, momsfria
-35 FAKTURERADE KOSTNADER
-3500 Fakturerade kostnader (gruppkonto)
-3510 Fakturerat emballage 3511 Fakturerat emballage
-3518 Returnerat emballage
-3520 Fakturerade frakter 3521 Fakturerade frakter, EU-land
-3522 Fakturerade frakter, export
-3530
-Fakturerade tull- och
-speditionskostnader m.m.
-3540 Faktureringsavgifter 3541 Faktureringsavgifter, EU-land
-3542 Faktureringsavgifter, export
-3550 Fakturerade resekostnader
-3560
-Fakturerade kostnader till
-koncernföretag 3561 Fakturerade kostnader till moderföretag
-3562 Fakturerade kostnader till dotterföretag
-Fakturerade kostnader till andra
-3563
-koncernföretag
-3570
-Fakturerade kostnader till
-intresseföretag, gemensamt styrda
-företag och övriga företag som det finns
-ett ägarintresse i
-3590 Övriga fakturerade kostnader
-36 RÖRELSENS SIDOINTÄKTER
-3600 Rörelsens sidointäkter (gruppkonto)
-3610 Försäljning av material 3611 Försäljning av råmaterial
-3612 Försäljning av skrot
-3613 Försäljning av förbrukningsmaterial
-3619 Försäljning av övrigt material
-3620 Tillfällig uthyrning av personal
-3630 Tillfällig uthyrning av transportmedel
-3670 Intäkter från värdepapper 3671 Försäljning av värdepapper
-3672 Utdelning från värdepapper
-3679 Övriga intäkter från värdepapper
-3680 Management fees
-3690 Övriga sidointäkter
-37 INTÄKTSKORRIGERINGAR
-3700 Intäktskorrigeringar (gruppkonto)
-3710 Ofördelade intäktsreduktioner
-3730 Lämnade rabatter 3731 Lämnade kassarabatter
-3732 Lämnade mängdrabatter
-3740 Öres- och kronutjämning
-3750 Punktskatter 3751 Intäktsförda punktskatter (kreditkonto)
-3752 Skuldförda punktskatter (debetkonto)
-3790 Övriga intäktskorrigeringar
-38 AKTIVERAT ARBETE FÖR EGEN RÄKNING
-3800
-Aktiverat arbete för egen räkning
-(gruppkonto)
-3840 Aktiverat arbete (material)
-3850 Aktiverat arbete (omkostnader)
-3870 Aktiverat arbete (personal)
-39 ÖVRIGA RÖRELSEINTÄKTER
-3900 Övriga rörelseintäkter (gruppkonto)
-3910 Hyres- och arrendeintäkter 3911 Hyresintäkter
-3912 Arrendeintäkter
-3913 Frivilligt momspliktiga hyresintäkter
-3914 Övriga momspliktiga hyresintäkter
-3920
-Provisionsintäkter, licensintäkter och
-royalties 3921 Provisionsintäkter
-3922 Licensintäkter och royalties
-3925 Franchiseintäkter
-3940#
-Orealiserade negativa/positiva
-värdeförändringar på
-säkringsinstrument
-3950
-Återvunna, tidigare avskrivna
-kundfordringar
-3960
-Valutakursvinster på fordringar och
-skulder av rörelsekaraktär
-3970
-Vinst vid avyttring av immateriella och
-materiella anläggningstillgångar 3971
-3972
-3973
-Vinst vid avyttring av immateriella
-anläggningstillgångar
-Vinst vid avyttring av byggnader och
-mark
-Vinst vid avyttring av maskiner och
-inventarier
-3980 Erhållna offentliga bidrag 3981 Erhållna EU-bidrag
-3985 Erhållna statliga bidrag
-3987 Erhållna kommunala bidrag
-3988 Erhållna offentliga bidrag för personal
-3989 Övriga erhållna offentliga bidrag
-3990
-Övriga ersättningar, bidrag och
-intäkter 3991 Konfliktersättning
-3992 Erhållna skadestånd
-3993 Erhållna donationer och gåvor
-3994 Försäkringsersättningar
-Erhållet ackord på skulder av
-3995
-rörelsekaraktär
-3996 Erhållna reklambidrag
-3997 Sjuklöneersättning
-Återbäring av överskott från
-3998
-försäkringsföretag
-3999 Övriga rörelseintäkter
-40 INKÖP AV HANDELSVAROR
-4000 Inköp av handelsvaror (gruppkonto)
-4010 Inköp av handelsvaror i Sverige
-4060
-Inköp av handelsvaror i Sverige,
-omvänd betalningsskyldighet 4065
-4066
-4067
-Inköp av handelsvaror i Sverige, omvänd
-betalningsskyldighet, 25 % moms
-Inköp av handelsvaror i Sverige, omvänd
-betalningsskyldighet, 12 % moms
-Inköp av handelsvaror i Sverige, omvänd
-betalningsskyldighet, 6 % moms
-4070
-Inköp av handelsvaror från annat
-EU-land 4075
-4076
-4077
-4078
-Inköp av handelsvaror från annat EU-
-land, 25 % moms
-Inköp av handelsvaror från annat EU-
-land, 12 % moms
-Inköp av handelsvaror från annat EU-
-land, 6 % moms
-Inköp av handelsvaror från annat EU-
-land, momsfri
-4080 Import av handelsvaror 4085 Import av handelsvaror, 25 % moms
-4086 4087 Import av handelsvaror, 12 % moms
-Import av handelsvaror, 6 % moms
-4090 Erhållna rabatter (Handelsvaror) 4091 Erhållna kassarabatter (Handelsvaror)
-Erhållna mängdrabatter (inkl. bonus)
-4092
-(Handelsvaror)
-Övriga reduktioner av inköpspriser
-4099
-(Handelsvaror)
-42 SÅLDA HANDELSVAROR VMB
-4200 Sålda handelsvaror VMB (gruppkonto)
-4210 Sålda handelsvaror VMB 4211 Sålda handelsvaror positiv VMB 25 %
-4212 Sålda handelsvaror negativ VMB 25 %
-43
-INKÖP AV RÅVAROR OCH MATERIAL I
-SVERIGE (RÅVAROR OCH
-FÖRNÖDENHETER)
-4300
-Inköp av råvaror och material i Sverige
-(gruppkonto)
-4310 Inköp av råvaror och material i Sverige
-44
-INKÖP AV RÅVAROR OCH MATERIAL,
-TJÄNSTER M.M. I SVERIGE, OMVÄND
-BETALNINGSSKYLDIGHET (RÅVAROR
-OCH FÖRNÖDENHETER)
-4400
-Inköp av råvaror och material, tjänster
-m.m. i Sverige, omvänd
-betalningsskyldighet (gruppkonto)
-4410
-Inköp av råvaror och material i
-Sverige, omvänd betalningsskyldighet 4415
-4416
-Inköp av råvaror och material i Sverige,
-omvänd betalningsskyldighet, 25 %
-moms
-Inköp av råvaror och material i Sverige,
-omvänd betalningsskyldighet, 12 %
-moms
-4417
-Inköp av råvaror och material i Sverige,
-omvänd betalningsskyldighet, 6 % moms
-4420
-Inköp av tjänster i Sverige, omvänd
-betalningsskyldighet 4425
-4426
-4427
-Inköp av tjänster i Sverige, omvänd
-betalningsskyldighet, 25 % moms
-Inköp av tjänster i Sverige, omvänd
-betalningsskyldighet, 12 % moms
-Inköp av tjänster i Sverige, omvänd
-betalningsskyldighet, 6 % moms
-45
-INKÖP AV RÅVAROR OCH MATERIAL,
-TJÄNSTER M.M. FRÅN UTLANDET
-(RÅVAROR OCH FÖRNÖDENHETER)
-4500
-Inköp av råvaror och material, tjänster
-m.m. från utlandet (gruppkonto)
-4510
-Inköp av råvaror och material från
-annat EU-land 4515
-4516
-4517
-4518
-4530 Inköp av tjänster m.m. från utlandet 4531
-4532
-4533
-4535
-4536
-4537
-4538
-4540 Import av råvaror och material 4545
-4546
-4547
-46
-INKÖP AV TJÄNSTER,
-UNDERENTREPRENADER OCH
-LEGOARBETEN I SVERIGE (RÅVAROR
-OCH FÖRNÖDENHETER)
-4600
-Inköp av tjänster, underentreprenader
-och legoarbeten i Sverige (gruppkonto)
-4610
-Inköp av tjänster och
-underentreprenader
-4670 Inköp av legoarbeten
-47
-REDUKTION AV INKÖPSPRISER
-(RÅVAROR OCH FÖRNÖDENHETER)
-4700
-Reduktion av inköpspriser
-(gruppkonto)
-Inköp av råvaror och material från annat
-EU-land, 25 %
-Inköp av råvaror och material från annat
-EU-land, 12 %
-Inköp av råvaror och material från annat
-EU-land, 6 %
-Inköp av råvaror och material från annat
-EU-land, momsfri
-Inköp av tjänster från ett land utanför
-EU, 25 % moms
-Inköp av tjänster från ett land utanför
-EU, 12 % moms
-Inköp av tjänster från ett land utanför
-EU, 6 % moms
-Inköp av tjänster från annat EU-land, 25
-%
-Inköp av tjänster från annat EU-land, 12
-%
-Inköp av tjänster från annat EU-land, 6
-%
-Inköp av tjänster från annat EU-land,
-momsfri
-Import av råvaror och material, 25 %
-moms
-moms
-moms
-Import av råvaror och material, 12 %
-Import av råvaror och material, 6 %
-4730
-Erhållna rabatter (Råvaror och
-förnödenheter) 4731
-4732
-4739
-48
-ANDRA PRODUKTIONSKOSTNADER
-(RÅVAROR OCH FÖRNÖDENHETER)
-4800
-Andra produktionskostnader
-(gruppkonto)
-4810
-Kostnader för energi (Råvaror och
-förnödenheter)
-4820
-Kostnader för drivmedel (Råvaror och
-förnödenheter)
-4830
-Kostnader för resor (Råvaror och
-förnödenheter)
-4840
-Kostnader för hyra av utrustning
-(Råvaror och förnödenheter)
-4890
-Övriga produktionskostnader (Råvaror
-och förnödenheter)
-49
-FÖRÄNDRING AV LAGER, PRODUKTER I
-ARBETE OCH PÅGÅENDE ARBETEN
-4900 Förändring av lager (gruppkonto)
-4910 Förändring av lager av råvaror
-4920
-Förändring av lager av tillsatsmaterial
-och förnödenheter
-4940 Förändring av produkter i arbete 4944
-4945
-4947
-4950 Förändring av lager av färdiga varor
-4960 Förändring av lager av handelsvaror
-4970
-Förändring av pågående arbeten,
-nedlagda kostnader 4974
-4975
-4977
-4980
-Förändring av lager av värdepapper
-(Handelsvaror) 4981
-4987
-4988
-Erhållna kassarabatter (Råvaror och
-förnödenheter)
-Erhållna mängdrabatter (inkl. bonus)
-(Råvaror och förnödenheter)
-Övriga reduktioner av inköpspriser
-(Råvaror och förnödenheter)
-Förändring av produkter i arbete,
-material och utlägg
-Förändring av produkter i arbete,
-omkostnader
-Förändring av produkter i arbete,
-personalkostnader
-Förändring av pågående arbeten,
-material och utlägg
-Förändring av pågående arbeten,
-omkostnader
-Förändring av pågående arbeten,
-personalkostnader
-Sålda värdepappers anskaffningsvärde
-(Handelsvaror)
-Nedskrivning av värdepapper
-(Handelsvaror)
-Återföring av nedskrivning av
-värdepapper (Handelsvaror)
-50 LOKALKOSTNADER
-5000 Lokalkostnader (gruppkonto)
-5010 Lokalhyra 5011 Hyra för kontorslokaler
-5012 Hyra för garage
-5013 Hyra för lagerlokaler
-5019 Övriga kostnader för lokalhyra
-5020 El
-5030 Värme
-5040 Vatten och avlopp
-5050 Lokaltillbehör
-5060 Städning och renhållning 5061 Städning
-5062 Sophämtning
-5064 Snöröjning
-5065 Trädgårdsskötsel
-Övriga kostnader för städning och
-5069
-underhåll
-5070 Reparation och underhåll av lokaler
-5090 Övriga lokalkostnader
-51 FASTIGHETSKOSTNADER
-5100 Fastighetskostnader (gruppkonto)
-5110 Tomträttsavgäld/arrende
-5120 El
-5130 Värme 5131 Uppvärmning
-5132 Sotning
-5139 Övriga kostnader för värme
-5140 Vatten och avlopp
-5160 Städning och renhållning 5161 Städning
-5162 Sophämtning
-5164 Snöröjning
-5165 Trädgårdsskötsel
-Övriga kostnader för städning och
-5169
-renhållning
-5170 Reparation och underhåll av fastighet
-5190 Övriga fastighetskostnader 5191 Fastighetsskatt/fastighetsavgift
-5192 Fastighetsförsäkringspremier
-5193 Fastighetsskötsel och förvaltning
-5198 Övriga fastighetskostnader
-52 HYRA AV ANLÄGGNINGSTILLGÅNGAR
-5200
-Hyra av anläggningstillgångar
-(gruppkonto)
-5210
-Hyra av maskiner och andra tekniska
-anläggningar, ej datorer och fordon
-5220
-Hyra av inventarier och verktyg, ej
-datorer och fordon
-5250 Hyra av datorer
-5290
-Hyra av övriga anläggningstillgångar, ej
-datorer och fordon
-53
-ENERGIKOSTNADER FÖR DRIFT (EJ
-RÅVAROR OCH FÖRNÖDENHETER)
-5300
-Energikostnader för drift (gruppkonto)
-(ej råvaror och förnödenheter)
-5310
-El för drift (ej råvaror och
-förnödenheter)
-5320
-Gas för drift (ej råvaror och
-förnödenheter)
-5330
-Eldningsolja för drift (ej råvaror och
-förnödenheter)
-5340
-Stenkol och koks för drift (ej råvaror och
-förnödenheter)
-5350
-Torv, träkol, ved, m.m. för drift (ej
-råvaror och förnödenheter)
-5360
-Bensin, fotogen och motorbrännolja för
-drift (ej råvaror och förnödenheter)
-5370
-Fjärrvärme, kyla och ånga för drift (ej
-råvaror och förnödenheter)
-5380
-Vatten för drift (ej råvaror och
-förnödenheter)
-5390
-Övriga energikostnader för drift (ej
-råvaror och förnödenheter)
-54
-FÖRBRUKNINGSINVENTARIER OCH
-FÖRBRUKNINGSMATERIAL
-5400
-Förbrukningsinventarier och
-förbrukningsmaterial (gruppkonto)
-5410 Förbrukningsinventarier 5411
-5412
-Förbrukningsinv med en livslängd på
-mer än ett år
-Förbrukningsinv med en livslängd om
-högst ett år
-5420 Programvaror
-5430 Transportinventarier
-5440 Förbrukningsemballage
-5460 Förbrukningsmaterial
-5480 Arbetskläder och skyddsmaterial
-55 REPARATION OCH UNDERHÅLL
-5500 Reparation och underhåll (gruppkonto)
-5510
-Reparation och underhåll av maskiner
-och andra tekniska anläggningar
-5520
-Reparation och underhåll av inventarier,
-verktyg och datorer m.m.
-5530
-Reparation och underhåll byggnads- och
-markinventarier
-5550
-Reparation och underhåll av
-förbrukningsinventarier
-5580 Underhåll och tvätt av arbetskläder
-5590
-Övriga kostnader för reparation och
-underhåll
-56 KOSTNADER FÖR TRANSPORTMEDEL
-5600
-Kostnader för transportmedel
-(gruppkonto)
-5610 Personbils- och mc-kostnader, m.m. 5611 Drivmedel för personbilar, mc, m.m.
-Försäkring och skatt för personbilar, mc,
-5612
-m.m.
-Reparation och underhåll av
-5613
-5615 personbilar, mc, m.m.
-Leasing av personbilar, mc, m.m.
-5616 Trängselskatt personbilar
-Övriga kostnader för personbilar och
-5619
-mc, m.m.
-5620 Lastbils- och busskostnader, m.m. 5621 Drivmedel lastbilar och bussar
-5622 Försäkring och skatt lastbilar och bussar
-Reparation och underhåll lastbilar och
-5623
-bussar
-5625 Leasing lastbilar och bussar
-5626 Trängselskatt lastbilar och bussar
-5629 Övriga lastbils- och busskostnader
-5630 Truckkostnader 5631 Drivmedel truckar
-5632 Försäkring och skatt truckar
-5633 Reparation och underhåll truckar
-5635 Leasing truckar
-5639 Övriga kostnader för truckar
-5640 Kostnader för arbetsmaskiner 5641 Drivmedel arbetsmaskiner
-5642 Försäkring och skatt arbetsmaskiner
-Reparation och underhåll
-5643
-arbetsmaskiner
-5645 Leasing arbetsmaskiner
-5646 Trängselskatt arbetsmaskiner
-5649 Övriga kostnader för arbetsmaskiner
-5650 Traktorkostnader 5651 Drivmedel traktorer
-5652 Försäkring och skatt traktorer
-5653 Reparation och underhåll traktorer
-5655 Leasing traktorer
-5656 Trängselskatt traktorer
-5659 Övriga kostnader för traktorer
-5670 Kostnader för fartyg och luftfartyg 5671 Drivmedel fartyg och luftfartyg
-5672 Försäkring och skatt fartyg och luftfartyg
-Reparation och underhåll fartyg och
-5673
-luftfartyg
-5675 Leasing fartyg och luftfartyg
-Övriga kostnader för fartyg och
-5679
-luftfartyg
-5680 Kostnader för rälsfordon 5681 Drivmedel rälsfordon
-5682 Försäkring och skatt rälsfordon
-5683 Reparation och underhåll rälsfordon
-5685 Leasing rälsfordon
-5689 Övriga kostnader för rälsfordon
-5690 Kostnader för övriga transportmedel 5691 Drivmedel övriga transportmedel
-Försäkring och skatt övriga
-5692
-transportmedel
-Reparation och underhåll övriga
-5693
-transportmedel
-5695 Leasing övriga transportmedel
-5696 Trängselskatt övriga transportmedel
-Övriga kostnader för övriga
-5699
-transportmedel
-57 FRAKTER OCH TRANSPORTER
-5700 Frakter och transporter (gruppkonto)
-5710
-Frakter och försäkringar vid
-varudistribution 5711 Fraktkostnader
-5712 Försäkringar vid frakter
-5720 Tull- och speditionskostnader m.m. 5721 Tullkostnader
-5722 Speditionskostnader
-Övriga tull- och speditionskostnader
-5729
-m.m.
-5730 Arbetstransporter
-5790
-Övriga kostnader för frakter och
-transporter
-58 RESEKOSTNADER
-5800 Resekostnader (gruppkonto)
-5810 Biljetter
-5820 Hyrbilskostnader
-5830 Kost och logi 5831 Kost och logi i Sverige
-5832 Kost och logi i utlandet
-5890 Övriga resekostnader
-59 REKLAM OCH PR
-5900 Reklam och PR (gruppkonto)
-5910 Annonsering
-5920 Utomhus- och trafikreklam
-5930 Reklamtrycksaker och direktreklam
-5940 Utställningar och mässor
-5950 Butiksreklam och återförsäljarreklam
-5960
-Varuprover, reklamgåvor,
-presentreklam och tävlingar
-5970 Film-, radio-, TV- och Internetreklam
-5980 Sponsring 5981 Avdragsgill sponsring
-5982 Ej avdragsgill sponsring
-5990 Övriga kostnader för reklam och PR
-60 ÖVRIGA FÖRSÄLJNINGSKOSTNADER
-6000
-Övriga försäljningskostnader
-(gruppkonto)
-6010 Kataloger, prislistor m.m.
-6020 Egna facktidskrifter
-6030 Speciella orderkostnader
-6040 Kontokortsavgifter
-6050 Försäljningsprovisioner 6055 Franchisekostnader
-6059 Övriga försäljningsprovisionskostnader
-6060 Kreditförsäljningskostnader 6061 Kreditupplysning
-6062 Inkasso och KFM-avgifter
-6063 Kreditförsäkringspremier
-6064 Factoringavgifter
-6069 Övriga kreditförsäljningskostnader
-6070 Representation 6071 Representation, avdragsgill
-6072 Representation, ej avdragsgill
-6080 Bankgarantier
-6090 Övriga försäljningskostnader
-61 KONTORSMATERIAL OCH TRYCKSAKER
-6100
-Kontorsmateriel och trycksaker
-(gruppkonto)
-6110 Kontorsmateriel
-6150 Trycksaker
-62 TELE, DATA OCH POST
-6200 Tele, data och post (gruppkonto)
-6210 Telekommunikation 6211 Fast telefoni
-6212 Mobiltelefon
-Övriga kostnader för
-6219
-telekommunikation
-6230 Datakommunikation
-6250 Porto
-6290 Övriga tele-, data- och postkostnader
-63
-FÖRETAGSFÖRSÄKRINGAR OCH ÖVRIGA
-RISKKOSTNADER
-6300
-Företagsförsäkringar och övriga
-riskkostnader (gruppkonto)
-6310 Företagsförsäkringar
-6320 Självrisker vid skada
-6330 Förluster i pågående arbeten
-6340 Lämnade skadestånd 6341 Lämnade skadestånd, avdragsgilla
-6342 Lämnade skadestånd, ej avdragsgilla
-6350 Förluster på kundfordringar 6351
-Konstaterade förluster på
-kundfordringar
-6352 Befarade förluster på kundfordringar
-6360 Garantikostnader 6361 Förändring av garantiavsättning
-6362 Faktiska garantikostnader
-6370 Kostnader för bevakning och larm
-6380
-Förluster på övriga kortfristiga
-fordringar
-6390 Övriga riskkostnader 6391 Övriga riskkostnader, avdragsgilla
-6392 Övriga riskkostnader, ej avdragsgilla
-64 FÖRVALTNINGSKOSTNADER
-6400 Förvaltningskostnader (gruppkonto)
-6420 Ersättningar till revisor 6421 Revision
-6422 Revisonsverksamhet utöver revision
-6423 Skatterådgivning – revisor
-6424 Övriga tjänster – revisor
-6430 Management fees
-6440 Årsredovisning och delårsrapporter
-6450
-Bolagsstämma/års- eller
-föreningsstämma
-6490 Övriga förvaltningskostnader
-65 ÖVRIGA EXTERNA TJÄNSTER
-6500 Övriga externa tjänster (gruppkonto)
-6510 Mätningskostnader
-6520 Ritnings- och kopieringskostnader
-6530 Redovisningstjänster
-6540 IT-tjänster
-6550 Konsultarvoden 6551 Arkitekttjänster
-6552 Teknisk provning och analys
-6553 Tekniska konsulttjänster
-Finansiell- och övrig ekonomisk
-6554
-rådgivning
-Skatterådgivning inkl. insolvens- och
-6555
-konkursförv.
-Köpta tjänster avseende forskning och
-6556
-utveckling
-6559 Övriga konsultarvoden
-6560
-Serviceavgifter till
-branschorganisationer
-6570 Bankkostnader
-6580 Advokat- och rättegångskostnader
-6590 Övriga externa tjänster
-67
-SÄRSKILT FÖR IDEELLA FÖRENINGAR
-OCH STIFTELSER
-6700
-Särskilt för ideella föreningar och
-stiftelser (gruppkonto)
-6710 Lämnade bidrag
-68 INHYRD PERSONAL
-6800 Inhyrd personal (gruppkonto)
-6810 Inhyrd produktionspersonal
-6820 Inhyrd lagerpersonal
-6830 Inhyrd transportpersonal
-6840 Inhyrd kontors- och ekonomipersonal
-6850 Inhyrd IT-personal
-6860
-Inhyrd marknads- och
-försäljningspersonal
-6870 Inhyrd restaurang- och butikspersonal
-6880 Inhyrda företagsledare
-6890 Övrig inhyrd personal
-69 ÖVRIGA EXTERNA KOSTNADER
-6900 Övriga externa kostnader (gruppkonto)
-6910 Licensavgifter och royalties
-6920 Kostnader för egna patent
-6930 Kostnader för varumärken m.m.
-6940
-Kontroll-, provnings- och
-stämpelavgifter
-6950 Tillsynsavgifter myndigheter
-6970 Tidningar, facklitteratur, m.m.
-6980 Föreningsavgifter 6981 Föreningsavgifter, avdragsgilla
-6982 Föreningsavgifter, ej avdragsgilla
-6990 Övriga externa kostnader 6991 Övriga externa kostnader, avdragsgilla
-Övriga externa kostnader, ej
-6992
-avdragsgilla
-6993 Lämnade bidrag och gåvor
-6996 Betald utländsk inkomstskatt
-6997 Obetald utländsk inkomstskatt
-6998 Utländsk moms
-6999 Ingående moms, blandad verksamhet
-70 LÖNER TILL KOLLEKTIVANSTÄLLDA
-7000 Löner till kollektivanställda (gruppkonto)
-7010 Löner till kollektivanställda 7011 Löner till kollektivanställda
-7012 Vinstandelar till kollektivanställda
-7013 Lön växa-stöd kollektivanställda 10,21 %
-7017 Avgångsvederlag till kollektivanställda
-7018 Bruttolöneavdrag, kollektivanställda
-Upplupna löner och vinstandelar till
-7019
-kollektivanställda
-7030
-Löner till kollektivanställda
-(utlandsanställda) 7031
-7032
-7037
-7038
-7039
-Löner till kollektivanställda
-(utlandsanställda)
-Vinstandelar till kollektivanställda
-(utlandsanställda)
-Avgångsvederlag till kollektivanställda
-(utlandsanställda)
-Bruttolöneavdrag, kollektivanställda
-(utlandsanställda)
-Upplupna löner och vinstandelar till
-kollektivanställda (utlandsanställda)
-7080
-Löner till kollektivanställda för ej
-arbetad tid 7081 Sjuklöner till kollektivanställda
-7082 Semesterlöner till kollektivanställda
-7083 Föräldraersättning till kollektivanställda
-Övriga löner till kollektivanställda för ej
-7089
-arbetad tid
-7090 Förändring av semesterlöneskuld
-72
-LÖNER TILL TJÄNSTEMÄN OCH
-FÖRETAGSLEDARE
-7200
-Löner till tjänstemän och företagsledare
-(gruppkonto)
-7210 Löner till tjänstemän 7211 Löner till tjänstemän
-7212 Vinstandelar till tjänstemän
-7213 Lön växa-stöd tjänstemän 10,21 %
-7217 Avgångsvederlag till tjänstemän
-7218 Bruttolöneavdrag, tjänstemän
-Upplupna löner och vinstandelar till
-7219
-tjänstemän
-7220 Löner till företagsledare 7221 Löner till företagsledare
-7222 Tantiem till företagsledare
-7227 Avgångsvederlag till företagsledare
-7228 Bruttolöneavdrag, företagsledare
-Upplupna löner och tantiem till
-7229
-företagsledare
-7230
-Löner till tjänstemän och ftgsledare
-(utlandsanställda) 7231
-7232
-7237
-7238
-7239
-Löner till tjänstemän och ftgsledare
-(utlandsanställda)
-Vinstandelar till tjänstemän och
-ftgsledare (utlandsanställda)
-Avgångsvederlag till tjänstemän och
-ftgsledare (utlandsanställda)
-Bruttolöneavdrag, tjänstemän och
-ftgsledare (utlandsanställda)
-Upplupna löner och vinstandelar till
-tjänstemän och ftgsledare
-(utlandsanställda)
-7240 Styrelsearvoden
-7280
-Löner till tjänstemän och företagsledare
-för ej arbetad tid 7281 Sjuklöner till tjänstemän
-7282 Sjuklöner till företagsledare
-7283 Föräldraersättning till tjänstemän
-7284 Föräldraersättning till företagsledare
-7285 Semesterlöner till tjänstemän
-7286 Semesterlöner till företagsledare
-Övriga löner till tjänstemän för ej
-7288
-arbetad tid
-Övriga löner till företagsledare för ej
-7289
-arbetad tid
-7290 Förändring av semesterlöneskuld 7291
-7292
-Förändring av semesterlöneskuld till
-tjänstemän
-Förändring av semesterlöneskuld till
-företagsledare
-73
-KOSTNADSERSÄTTNINGAR OCH
-FÖRMÅNER
-7300
-Kostnadsersättningar och förmåner
-(gruppkonto)
-7310 Kontanta extraersättningar 7311 Ersättningar för sammanträden m.m.
-Ersättningar för förslagsverksamhet och
-7312
-uppfinningar
-Ersättningar för/bidrag till
-7313
-bostadskostnader
-Ersättningar för/bidrag till
-7314
-måltidskostnader
-Ersättningar för/bidrag till resor till och
-7315
-från arbetsplatsen
-7316 Ersättningar för/bidrag till arbetskläder
-Ersättningar för/bidrag till
-7317
-arbetsmaterial och arbetsverktyg
-7318 Felräkningspengar
-7319 Övriga kontanta extraersättningar
-7320 Traktamenten vid tjänsteresa 7321 Skattefria traktamenten, Sverige
-7322 Skattepliktiga traktamenten, Sverige
-7323 Skattefria traktamenten, utlandet
-7324 Skattepliktiga traktamenten, utlandet
-7330 Bilersättningar 7331 Skattefria bilersättningar
-7332 Skattepliktiga bilersättningar
-7333 Ersättning för trängselskatt, skattefri
-7350 Ersättningar för föreskrivna arbetskläder
-7370 Representationsersättningar
-7380 Kostnader för förmåner till anställda 7381 Kostnader för fri bostad
-Kostnader för fria eller subventionerade
-7382
-måltider
-Kostnader för fria resor till och från
-7383
-arbetsplatsen
-Kostnader för fria eller subventionerade
-7384
-arbetskläder
-7385 Kostnader för fri bil
-7386 Subventionerad ränta
-7387 Kostnader för lånedatorer
-Anställdas ersättning för erhållna
-7388
-förmåner
-7389 Övriga kostnader för förmåner
-7390
-Övriga kostnadsersättningar och
-förmåner 7391 Kostnad för trängselskatteförmån
-Kostnad för förmån av hushållsnära
-7392
-tjänster
-74 PENSIONSKOSTNADER
-7400 Pensionskostnader (gruppkonto)
-7410 Pensionsförsäkringspremier 7411
-7412
-Premier för kollektiva
-pensionsförsäkringar
-Premier för individuella
-pensionsförsäkringar
-7420 Förändring av pensionsskuld
-7430 Avdrag för räntedel i pensionskostnad
-7440 Förändring av pensionsstiftelsekapital 7441
-Överföring av medel till
-pensionsstiftelse
-7448 Gottgörelse från pensionsstiftelse
-7460 Pensionsutbetalningar 7461
-7462
-7463
-Pensionsutbetalningar till f.d.
-kollektivanställda
-Pensionsutbetalningar till f.d.
-tjänstemän
-Pensionsutbetalningar till f.d.
-företagsledare
-7470
-Förvaltnings- och
-kreditförsäkringsavgifter
-7490 Övriga pensionskostnader
-75
-SOCIALA OCH ANDRA AVGIFTER ENLIGT
-LAG OCH AVTAL
-7500
-Sociala och andra avgifter enligt lag och
-avtal (gruppkonto)
-7510 Arbetsgivaravgifter 31,42 % 7511
-Arbetsgivaravgifter för löner och
-ersättningar
-7512 Arbetsgivaravgifter för förmånsvärden
-Arbetsgivaravgifter på skattepliktiga
-7515
-kostnadsersättningar
-7516 Arbetsgivaravgifter på arvoden
-7518
-7519
-Arbetsgivaravgifter på bruttolöneavdrag
-m.m.
-Arbetsgivaravgifter för semester- och
-löneskulder
-7530 Särskild löneskatt 7531
-7532
-Särskild löneskatt för vissa
-försäkringsersättningar m.m.
-Särskild löneskatt pensionskostnader,
-deklarationspost
-7533 Särskild löneskatt för pensionskostnader
-7550 Avkastningsskatt på pensionsmedel 7551
-7552
-7553
-7554
-Avkastningsskatt 15 %
-försäkringsföretag m.fl. samt avsatt till
-pensioner
-Avkastningsskatt 15 % utländska
-pensionsförsäkringar
-Avkastningsskatt 30 % utländska
-försäkringsföretag m.fl.
-Avkastningsskatt 30 % utländska
-kapitalförsäkringar
-7570 Premier för arbetsmarknadsförsäkringar 7571 Arbetsmarknadsförsäkringar
-Arbetsmarknadsförsäkringar
-pensionsförsäkringspremier,
-7572
-deklarationspost
-7580 Gruppförsäkringspremier 7581 Grupplivförsäkringspremier
-7582 Gruppsjukförsäkringspremier
-7583 Gruppolycksfallsförsäkringspremier
-7589 Övriga gruppförsäkringspremier
-7590
-Övriga sociala och andra avgifter enligt
-lag och avtal
-76 ÖVRIGA PERSONALKOSTNADER
-7600 Övriga personalkostnader (gruppkonto)
-7610 Utbildning
-7620 Sjuk- och hälsovård 7621 Sjuk- och hälsovård, avdragsgill
-7622 Sjuk- och hälsovård, ej avdragsgill
-7623 Sjukvårdsförsäkring, ej avdragsgill
-7630 Personalrepresentation 7631 Personalrepresentation, avdragsgill
-7632 Personalrepresentation, ej avdragsgill
-7650 Sjuklöneförsäkring
-7670 Förändring av personalstiftelsekapital 7671 Avsättning till personalstiftelse
-7678 Gottgörelse från personalstiftelse
-7690 Övriga personalkostnader 7691 Personalrekrytering
-7692 Begravningshjälp
-7693 Fritidsverksamhet
-7699 Övriga personalkostnader
-77
-NEDSKRIVNINGAR OCH ÅTERFÖRING AV
-NEDSKRIVNINGAR
-7710
-Nedskrivningar av immateriella
-anläggningstillgångar
-7720 Nedskrivningar av byggnader och mark
-7730
-Nedskrivningar av maskiner respektive
-inventarier 7731
-7732
-7733
-Nedskrivningar av maskiner och andra
-tekniska anläggningar
-Nedskrivningar av inventarier, verktyg
-och installationer
-Nedskrivningar av övriga materiella
-anläggningstillgångar
-7740
-Nedskrivningar av vissa
-omsättningstillgångar
-7760
-Återföring av nedskrivningar av
-immateriella anläggningstillgångar
-7770
-Återföring av nedskrivningar av
-byggnader och mark
-7780
-Återföring av nedskrivningar av
-maskiner respektive inventarier 7781
-7782
-7783
-Återföring av nedskrivningar av
-maskiner och andra tekniska
-anläggningar
-Återföring av nedskrivningar av
-inventarier, verktyg och installationer
-Återföring av nedskrivningar av övriga
-materiella anläggningstillgångar
-7790
-Återföring av nedskrivningar av vissa
-omsättningstillgångar
-78 AVSKRIVNINGAR ENLIGT PLAN
-7810
-Avskrivningar på immateriella
-anläggningstillgångar 7811 Avskrivningar på balanserade utgifter
-7812 Avskrivningar på koncessioner m.m.
-7813 Avskrivningar på patent
-7814 Avskrivningar på licenser
-7815 Avskrivningar på varumärken
-7816 Avskrivningar på hyresrätter
-7817 Avskrivningar på goodwill
-Avskrivningar på övriga immateriella
-7819
-anläggningstillgångar
-7820
-Avskrivningar på byggnader och
-markanläggningar 7821 Avskrivningar på byggnader
-7824 Avskrivningar på markanläggningar
-7829 Avskrivningar på övriga byggnader
-7830
-Avskrivningar på maskiner respektive
-inventarier 7831
-7832
-Avskrivningar på maskiner och andra
-tekniska anläggningar
-Avskrivningar på inventarier, verktyg
-och installationer
-7836 Avskrivningar på leasade tillgångar
-Avskrivningar på övriga materiella
-7839
-anläggningstillgångar
-7840
-Avskrivningar på förbättringsutgifter på
-annans fastighet
-79 ÖVRIGA RÖRELSEKOSTNADER
-7940#
-Orealiserade positiva/negativa
-värdeförändringar på
-säkringsinstrument
-7960
-Valutakursförluster på fordringar och
-skulder av rörelsekaraktär
-7970
-Förlust vid avyttring av immateriella och
-materiella anläggningstillgångar 7971
-7972
-7973
-Förlust vid avyttring av immateriella
-anläggningstillgångar
-Förlust vid avyttring av byggnader och
-mark
-Förlust vid avyttring av maskiner och
-inventarier
-7990 Övriga rörelsekostnader
-80
-RESULTAT FRÅN ANDELAR I
-KONCERNFÖRETAG
-8010 Utdelning på andelar i koncernföretag 8012 Utdelning på andelar i dotterföretag
-8016 Emissionsinsats, koncernföretag
-8020
-Resultat vid försäljning av andelar i
-koncernföretag
-8030
-Resultatandelar från handelsbolag
-(dotterföretag)
-8070
-Nedskrivningar av andelar i och
-långfristiga fordringar hos
-koncernföretag 8072
-8076
-8077
-Nedskrivningar av andelar i
-dotterföretag
-Nedskrivningar av långfristiga fordringar
-hos moderföretag
-Nedskrivningar av långfristiga fordringar
-hos dotterföretag
-8080
-Återföringar av nedskrivningar av
-andelar i och långfristiga fordringar hos
-koncernföretag 8082
-8086
-8087
-Återföringar av nedskrivningar av
-andelar i dotterföretag
-Återföringar av nedskrivningar av
-långfristiga fordringar hos moderföretag
-Återföringar av nedskrivningar av
-långfristiga fordringar hos dotterföretag
-81
-8110
-8120
-8130
-8170
-RESULTAT FRÅN ANDELAR I
-INTRESSEFÖRETAG OCH GEMENSAMT
-STYRDA FÖRETAG SAMT ÖVRIGA
-FÖRETAG SOM DET FINNS ETT
-ÄGARINTRESSE I
-Utdelningar på andelar i intresseföretag
-och gemensamt styrda företag samt
-övriga företag som det finns ett
-ägarintresse i 8111 Utdelningar på andelar i intresseföretag
-Utdelningar på andelar i gemensamt
-8112
-styrda företag
-Utdelningar på andelar i övriga företag
-8113
-som det finns ett ägarintresse i
-8116 Emissionsinsats, intresseföretag
-Emissionsinsats, gemensamt styrda
-8117
-företag
-Emissionsinsats, övriga företag som det
-8118
-finns ett ägarintresse i
-Resultat vid försäljning av andelar i
-intresseföretag och gemensamt styrda
-företag samt övriga företag som det
-finns ett ägarintresse i 8121
-8122
-8123
-Resultat vid försäljning av andelar i
-intresseföretag
-Resultat vid försäljning av andelar i
-gemensamt styrda företag
-Resultat vid försäljning av andelar i
-övriga företag som det finns ett
-ägarintresse i
-Resultatandelar från handelsbolag
-(intresseföretag och gemensamt styrda
-företag samt övriga företag som det
-finns ett ägarintresse i) 8131
-8132
-8133
-Resultatandelar från handelsbolag
-(intresseföretag)
-Resultatandelar från handelsbolag
-(gemensamt styrda företag)
-Resultatandelar från handelsbolag
-(övriga företag som det finns ett
-ägarintresse i)
-Nedskrivningar av andelar i och
-långfristiga fordringar hos
-intresseföretag och gemensamt styrda
-företag samt övriga företag som det
-finns ett ägarintresse i 8171
-8172
-8173
-Nedskrivningar av andelar i
-intresseföretag
-Nedskrivningar av långfristiga fordringar
-hos intresseföretag
-Nedskrivningar av andelar i gemensamt
-styrda företag
-8174
-8176
-8177
-Nedskrivningar av långfristiga fordringar
-hos gemensamt styrda företag
-Nedskrivningar av andelar i övriga
-företag som det finns ett ägarintresse i
-Nedskrivningar av långfristiga fordringar
-hos övriga företag som det finns ett
-ägarintresse i
-8180
-Återföringar av nedskrivningar av
-andelar i och långfristiga fordringar hos
-intresseföretag och gemensamt styrda
-företag samt övriga företag som det
-finns ett ägarintresse i 8181
-8182
-8183
-8184
-8186
-8187
-Återföringar av nedskrivningar av
-andelar i intresseföretag
-Återföringar av nedskrivningar av
-långfristiga fordringar hos
-intresseföretag
-Återföringar av nedskrivningar av
-andelar i gemensamt styrda företag
-Återföringar av nedskrivningar av
-långfristiga fordringar hos gemensamt
-styrda företag
-Återföringar av nedskrivningar av
-andelar i övriga företag som det finns
-ett ägarintresse i
-Återföringar av nedskrivningar av
-långfristiga fordringar hos övriga företag
-som det finns ett ägarintresse i
-82
-RESULTAT FRÅN ÖVRIGA VÄRDEPAPPER
-OCH LÅNGFRISTIGA FORDRINGAR
-(ANLÄGGNINGSTILLGÅNGAR)
-8210 Utdelningar på andelar i andra företag 8212 Utdelningar, andra företag
-8216 Insatsemissioner, andra företag
-8220
-Resultat vid försäljning av värdepapper i
-och långfristiga fordringar hos andra
-företag 8221
-8222
-8223
-Resultat vid försäljning av andelar i
-andra företag
-Resultat vid försäljning av långfristiga
-fordringar hos andra företag
-Resultat vid försäljning av derivat
-(långfristiga värdepappersinnehav)
-8230
-Valutakursdifferenser på långfristiga
-fordringar 8231
-Valutakursvinster på långfristiga
-fordringar
-8236
-Valutakursförluster på långfristiga
-fordringar
-8240
-Resultatandelar från handelsbolag
-(andra företag)
-8250
-Ränteintäkter från långfristiga
-fordringar hos och värdepapper i andra
-företag 8251
-Ränteintäkter från långfristiga
-fordringar
-8252 Ränteintäkter från övriga värdepapper
-Skattefria ränteintäkter, långfristiga
-8254
-tillgångar
-8255 Avkastningsskatt kapitalplacering
-8260
-Ränteintäkter från långfristiga
-fordringar hos koncernföretag 8261
-8262
-8263
-Ränteintäkter från långfristiga
-fordringar hos moderföretag
-Ränteintäkter från långfristiga
-fordringar hos dotterföretag
-Ränteintäkter från långfristiga
-fordringar hos andra koncernföretag
-8270
-Nedskrivningar av innehav av andelar i
-och långfristiga fordringar hos andra
-företag 8271
-8272
-8273
-Nedskrivningar av andelar i andra
-företag
-Nedskrivningar av långfristiga fordringar
-hos andra företag
-Nedskrivningar av övriga värdepapper
-hos andra företag
-8280
-Återföringar av nedskrivningar av
-andelar i och långfristiga fordringar hos
-andra företag 8281
-8282
-8283
-Återföringar av nedskrivningar av
-andelar i andra företag
-Återföringar av nedskrivningar av
-långfristiga fordringar hos andra företag
-Återföringar av nedskrivningar av övriga
-värdepapper i andra företag
-8290#
-Värdering till verkligt värde,
-anläggningstillgångar 8291#
-8295#
-Orealiserade värdeförändringar på
-anläggningstillgångar
-Orealiserade värdeförändringar på
-derivatinstrument
-83
-ÖVRIGA RÄNTEINTÄKTER OCH
-LIKNANDE RESULTATPOSTER
-8310 Ränteintäkter från omsättningstillgångar 8311 Ränteintäkter från bank
-Ränteintäkter från kortfristiga
-8312
-placeringar
-8313 Ränteintäkter från kortfristiga fordringar
-8314 Skattefria ränteintäkter
-8317
-8319
-Ränteintäkter för dold
-räntekompensation
-Övriga ränteintäkter från
-omsättningstillgångar
-8320#
-Värdering till verkligt värde,
-omsättningstillgångar 8321#
-8325#
-Orealiserade värdeförändringar på
-omsättningstillgångar
-Orealiserade värdeförändringar på
-derivatinstrument (oms.-tillg.)
-8330
-Valutakursdifferenser på kortfristiga
-fordringar och placeringar 8331
-8336
-Valutakursvinster på kortfristiga
-fordringar och placeringar
-Valutakursförluster på kortfristiga
-fordringar och placeringar
-8340 Utdelningar på kortfristiga placeringar
-8350
-Resultat vid försäljning av kortfristiga
-placeringar
-8360
-Övriga ränteintäkter från
-koncernföretag 8361 Övriga ränteintäkter från moderföretag
-8362 Övriga ränteintäkter från dotterföretag
-Övriga ränteintäkter från andra
-8363
-koncernföretag
-8370
-Nedskrivningar av kortfristiga
-placeringar
-8380
-Återföringar av nedskrivningar av
-kortfristiga placeringar
-8390 Övriga finansiella intäkter
-84
-RÄNTEKOSTNADER OCH LIKNANDE
-RESULTATPOSTER
-8400 Räntekostnader (gruppkonto)
-8410 Räntekostnader för långfristiga skulder 8411
-Räntekostnader för obligations-, förlags-
-och konvertibla lån
-8412 Räntedel i årets pensionskostnad
-8413 Räntekostnader för kontokredit
-Räntekostnader för andra skulder till
-8415
-kreditinstitut
-Räntekostnader för dold
-8417
-räntekompensation m.m.
-8418 Avdragspost för räntesubventioner
-Övriga räntekostnader för långfristiga
-8419
-skulder
-8420 Räntekostnader för kortfristiga skulder 8421 Räntekostnader till kreditinstitut
-8422 Dröjsmålsräntor för leverantörsskulder
-8423 Räntekostnader för skatter och avgifter
-8424 Räntekostnader byggnadskreditiv
-Övriga räntekostnader för kortfristiga
-8429
-skulder
-8430 Valutakursdifferenser på skulder 8431 Valutakursvinster på skulder
-8436 Valutakursförluster på skulder
-8440 Erhållna räntebidrag
-8450#
-Orealiserade värdeförändringar på
-skulder 8451#
-8455#
-Orealiserade värdeförändringar på
-skulder
-Orealiserade värdeförändringar på
-säkringsinstrument
-8460 Räntekostnader till koncernföretag 8461 Räntekostnader till moderföretag
-8462 Räntekostnader till dotterföretag
-Räntekostnader till andra
-8463
-koncernföretag
-8480# Aktiverade ränteutgifter
-8490 Övriga skuldrelaterade poster 8491
-Erhållet ackord på skulder till
-kreditinstitut m.m.
-88 BOKSLUTSDISPOSITIONER
-8810 Förändring av periodiseringsfond 8811 Avsättning till periodiseringsfond
-8819 Återföring från periodiseringsfond
-8820 Mottagna koncernbidrag
-8830 Lämnade koncernbidrag
-8840 Lämnade gottgörelser
-8850 Förändring av överavskrivningar 8851
-8852
-8853
-Förändring av överavskrivningar,
-immateriella anläggningstillgångar
-Förändring av överavskrivningar,
-byggnader och markanläggningar
-Förändring av överavskrivningar,
-maskiner respektive inventarier
-8860 Förändring av ersättningsfond 8861
-Avsättning till ersättningsfond för
-inventarier
-Avsättning till ersättningsfond för
-8862
-byggnader och markanläggningar
-Avsättning till ersättningsfond för
-8864
-djurlager i jordbruk och renskötsel
-Ianspråktagande av ersättningsfond för
-8865
-avskrivningar
-Ianspråktagande av ersättningsfond för
-8866
-annat än avskrivningar
-8869 Återföring från ersättningsfond
-8890 Övriga bokslutsdispositioner 8892
-Nedskrivningar av
-konsolideringskaraktär av
-anläggningstillgångar
-8896 Förändring av lagerreserv
-8899 Övriga bokslutsdispositioner
-89 SKATTER OCH ÅRETS RESULTAT
-8910 Skatt som belastar årets resultat
-8920 Skatt på grund av ändrad beskattning
-8930 Restituerad skatt
-8940# Uppskjuten skatt
-8980 Övriga skatter
-8990 Resultat 8999 Årets resultat
\ No newline at end of file
diff --git a/dev_docs/K1_BAS.md b/dev_docs/K1_BAS.md
deleted file mode 100644
index 9b58fe61..00000000
--- a/dev_docs/K1_BAS.md
+++ /dev/null
@@ -1,469 +0,0 @@
-1/9
-BAS Förenklat årsbokslut (K1) – Kontoplan 2018
-Inga ändring eller tillägg har gjorts
-jämfört med 2017.
-1 Tillgångar
-10 Immateriella anläggningstillgångar
-BAS-konton Rad Underkonton Rad
-1000 Immateriella
-anläggningstillgångar
-B1 1009 Årets avskrivningar på
-immateriella
-B1
-anläggningstillgångar
-11 Byggnader och mark
-BAS-konton Rad Underkonton Rad
-1110 Byggnader B2 1119 Ackumulerade avskrivningar på
-byggnader
-B2
-1130 Mark B3
-1150 Markanläggningar B2 1159 Ackumulerade avskrivningar på
-markanläggningar
-B2
-1180 Pågående nyanläggningar och
-förskott för byggnader och
-B3
-mark
-12 Maskiner och inventarier
-BAS-konton Underkonton
-Rad Rad
-1220 Maskiner och inventarier B4 1221 Årets nyanskaffning av
-maskiner och inventarier
-B4
-1222 Årets ersättning för maskiner
-och inventarier
-B4
-1229 Årets avskrivningar på maskiner
-och inventarier
-B4
-1230 Byggnads- och markinventarier B4 1231 Årets nyanskaffning av
-byggnads- och markinventarier
-B4
-1232 Årets ersättning för byggnads-
-och markinventarier
-B4
-1239 Årets avskrivningar på
-byggnads- och markinventarier
-B4
-1240 Bilar och andra transportmedel B4 1241 Årets nyanskaffning av bilar och
-andra transportmedel
-B4
-1242 Årets ersättning för bilar och
-andra transportmedel
-B4
-1249 Årets avskrivningar på bilar och
-andra transportmedel
-B4
-13 Övriga anläggningstillgångar
-BAS-konton Underkonton
-Rad Rad
-1300 Andelar B5
-14 Lager
-BAS-konton
-Underkonton
-Rad Rad
-Kontoplan_K1_2018_ver1
-2/9
-1400 Lager B6
-15 Kundfordringar
-BAS-konton
-Underkonton
-Rad Rad
-1500 Kundfordringar B7
-16 Övriga fordringar
-BAS-konton Underkonton
-Rad Rad
-1600 Övriga fordringar B8
-1650 Momsfordran B8
-17 Förskott till leverantörer
-BAS-konton Underkonton
-Rad
-1700 Förskott till leverantörer B8
-19 Kassa och bank
-BAS-konton
-Underkonton
-Rad
-1910 Kassa B9
-1920 PlusGiro B9
-1930 Företagskonto/checkkonto/affär
-skonto
-B9
-1940 Övriga bankkonton B9
-1970 Särskilda bankkonton B9
-2 EGET KAPITAL OCH SKULDER
-20 Eget kapital
-BAS-konton Underkonton
-Rad Rad
-2010 Eget kapital, delägare 1 B10 2011 Egna varuuttag B10
-2012 Avräkning för skatter och
-avgifter (skattekonto)
-B10
-2013 Övriga egna uttag B10
-2014 Uttag förmåner B10
-2017 Egna insättningar B10
-2019 Årets resultat, delägare 1 B10
-2020 Eget kapital, delägare 2 B10 Se delägre 1
-2030 Eget kapital, delägare 3 B10 Se delägre 1
-2040 Eget kapital, delägare 4 B10 Se delägre 1
-2050 Avsättning till expansionsfond U2
-2060 Ersättningsfond U3
-2070 Insatsemissioner,
-avbetalningsplan på skog,
-skogskonto,
-U4
-2080 Periodiseringsfonder upphovsmannakonto
-U1 2083 Periodiseringsfond vid 2012 års
-taxering
-U1
-Kontoplan_K1_2018_ver1
-3/9
-2084 Periodiseringsfond vid 2013 års
-taxering
-U1
-2085 Periodiseringsfond 2013 U1
-2086 Periodiseringsfond 2014 U1
-2087 Periodiseringsfond 2015 U1
-2088 Periodiseringsfond 2016 U1
-2089 Periodiseringsfond 2017 U1
-2090 Utjämningskonto upplysningar
-1-4
-23 Låneskulder
-BAS-konton Underkonton
-Rad Rad
-2330 Checkräkningskredit B13
-2350 Skulder till kreditinstitut B13
-2390 Övriga låneskulder B13
-24 Skulder till leverantörer
-BAS-konton
-Underkonton
-Rad Rad
-2440 Leverantörsskulder B15
-26 Moms och särskilda punktskatter
-BAS-konton Underkonton
-Rad Rad
-2610 Utgående moms, 25 % B14 2611 Utgående moms på försäljning
-inom Sverige, 25 %
-B14
-2612 Utgående moms på egna uttag,
-25 %
-B14
-2613 Utgående moms för uthyrning,
-25 %
-B14
-2614 Utgående moms omvänd
-skattskyldighet, 25 %
-B14
-2615 Utgående moms import av
-varor, 25 %
-B14
-2618 Vilande utgående moms, 25 % B14
-2620 Utgående moms, 12 % B14 2621 Utgående moms på försäljning
-inom Sverige, 12 %
-B14
-2622 Utgående moms på egna uttag,
-12 %
-B14
-2623 Utgående moms för uthyrning,
-12 %
-B14
-2624 Utgående moms omvänd
-skattskyldighet, 12 %
-B14
-2625 Utgående moms import av
-varor, 12 %
-B14
-2628 Vilande utgående moms, 12 % B14
-2630 Utgående moms, 6 % B14 2631 Utgående moms på försäljning
-inom Sverige, 6 %
-B14
-2632 Utgående moms på egna uttag,
-6 %
-B14
-Kontoplan_K1_2018_ver1
-4/9
-2633 Utgående moms för uthyrning,
-6 %
-B14
-2634 Utgående moms omvänd
-skattskyldighet, 6 %
-B14
-2635 Utgående moms import av
-varor, 6 %
-B14
-2638 Vilande utgående moms, 6 % B14
-2640 Ingående moms B14 2641 Debiterad ingående moms B14
-2642 Debiterad ingående moms i
-anslutning till frivillig
-B14
-2645 Beräknad ingående moms på
-skattskyldighet
-förvärv från utlandet
-B14
-2646 Ingående moms på uthyrning B14
-2648 Vilande ingående moms B14
-2649 Ingående moms, blandad
-verksamhet
-B14
-2650 Redovisningskonto för moms B14 B14
-2660 Särskilda punktskatter B14 B14
-27 Personalens skatter, avgifter och löneavdrag
-BAS-konton Underkonton
-Rad Rad
-2710 Personalskatt B14
-2730 Lagstadgade/avtalade sociala
-avgifter och särskild löneskatt
-B14
-29 Övriga skulder
-BAS-konton Underkonton
-Rad Rad
-2900 Övriga skulder B16
-3 RÖRELSENS INKOMSTER/INTÄKTER
-30-34 Huvudintäkter
-BAS-konton
-Underkonton
-Rad Rad
-3000 Försäljning och utfört arbete
-samt övriga momspliktiga
-R1
-3100 intäkter
-Momsfria intäkter R2
-3200 Bil- och bostadsförmån m.m. R3
-35 Fakturerade kostnader
-BAS-konton
-Underkonton
-Rad Rad
-3500 Fakturerade kostnader R1
-37 Intäktskorrigeringar
-BAS-konton
-Underkonton
-Rad Rad
-3700 Lämnade rabatter, bonus etc. R1/R2
-Kontoplan_K1_2018_ver1
-5/9
-39 Övriga rörelseintäkter
-BAS-konton
-Underkonton
-Rad Rad
-3900 Övriga rörelseintäkter R1/R2
-3970 Vinst vid avyttring av
-immateriella och materiella
-R2
-3980 anläggningstillgångar
-Erhållna bidrag R2
-4 UTGIFTER/KOSTNADER FÖR VAROR, MATERIAL OCH VISSA
-KÖPTA TJÄNSTER
-40-45 Inköp av varor och material
-BAS-konton
-Underkonton
-Rad Rad
-4000 Varor R5
-46 Legoarbeten, underentreprenader
-BAS-konton Underkonton
-Rad Rad
-4600 Legoarbeten och
-underentreprenader
-R5
-47 Reduktion av inköpspriser
-BAS-konton Underkonton
-Rad Rad
-4700 Erhållna rabatter, bonus etc. R6
-49 Förändring av lager
-BAS-konton
-Underkonton
-Rad Rad
-4900 Förändring av lager R5
-5-6 ÖVRIGA EXTERNA RÖRELSEUTGIFTER/KOSTNADER
-50 Lokalkostnader
-BAS-konton
-Underkonton
-Rad Rad
-5000 Lokalkostnader R6
-51 Fastighetskostnader
-BAS-konton
-Underkonton
-Rad Rad
-5100 Fastighetskostnader R6
-52 Hyra av anläggningstillgångar
-BAS-konton Underkonton
-Rad Rad
-5200 Hyra av anläggningstillgångar R6
-54 Förbrukningsinventarier och förbrukningsmaterial
-Kontoplan_K1_2018_ver1
-6/9
-BAS-konton Underkonton
-Rad Rad
-5400 Förbrukningsinventarier och
-förbrukningsmaterial
-R6
-55 Reparation och underhåll
-BAS-konton
-Underkonton
-Rad Rad
-5500 Reparation och underhåll R6
-56 Kostnader för transportmedel
-BAS-konton
-Underkonton
-Rad Rad
-5600 Kostnader för transportmedel R6
-5610 Personbilskostnader R6 5611 Drivmedel för personbilar R6
-5612 Försäkring och skatt för
-R6
-5613 Reparation och underhåll av
-personbilar
-personbilar
-R6
-5615 Leasing av personbilar R6
-5618 Schablonmässig milkostnad
-privat personbil
-R6
-5619 Övriga personbilskostnader R6
-5620 Lastbilskostnader R6
-57 Frakter och transporter
-BAS-konton
-Underkonton
-Rad Rad
-5700 Frakter och transporter R6
-58 Resekostnader
-BAS-konton
-Underkonton
-Rad Rad
-5800 Resekostnader R6
-59 Reklam och PR
-BAS-konton
-Underkonton
-Rad Rad
-5900 Reklam och PR R6
-60 Övriga försäljningskostnader
-BAS-konton Underkonton
-Rad Rad
-6000 Övriga försäljningskostnader
-R6
-R6 R6
-6070 Representation R6 R6 6071 Representation, avdragsgill
-6072 Representation, ej avdragsgill R6
-+
-NE
-sid.
-2
-Kontoplan_K1_2018_ver1
-7/9
-61 Kontorsmateriel och trycksaker
-BAS-konton Underkonton
-Rad Rad
-6100 Kontorsmateriel och trycksaker R6
-62 Tele och post
-BAS-konton Underkonton
-Rad Rad
-6200 Tele och post R6
-63 Företagsförsäkringar och övriga riskkostnader
-BAS-konton Underkonton
-Rad Rad
-6300 Företagsförsäkringar och
-övriga riskkostnader
-R6
-6310 Företagsförsäkringar R6
-65 Övriga externa tjänster
-BAS-konton Underkonton
-Rad Rad
-6500 Övriga externa tjänster R6
-68 Inhyrd personal
-BAS-konton Underkonton
-Rad Rad
-6800 Inhyrd personal R6
-69 Övriga kostnader
-BAS-konton
-Underkonton
-Rad Rad
-6900 Övriga kostnader R6
-6980 Föreningsavgifter R6
-7 UTGIFTER/KOSTNADER FÖR PERSONAL, AVSKRIVNINGAR
-70 Löner till anställda
-BAS-konton Underkonton
-Rad Rad
-7000 Löner till anställda R7
-73 Kostnadsersättningar och förmåner
-BAS-konton Underkonton
-Rad Rad
-7300 Kostnadsersättningar och
-förmåner
-R7
-74 Pensionskostnader
-BAS-konton Underkonton
-Rad Rad
-7400 Pensionskostnader R7
-Kontoplan_K1_2018_ver1
-8/9
-75 Sociala och andra avgifter enligt lag och avtal
-BAS-konton Underkonton
-Rad Rad
-7500 Sociala och andra avgifter
-enligt lag och avtal
-R7
-76 Övriga personalkostnader
-BAS-konton Underkonton
-Rad Rad
-7600 Övriga personalkostnader R7 7631 Personalrepresentation,
-avdragsgill
-R7
-7632 Personalrepresentation, ej
-avdragsgill
-R7
-+
-NE
-sid.
-2
-77 Nedskrivningar och återföring av nedskrivningar
-BAS-konton Underkonton
-Rad Rad
-7700 Nedskrivningar R9
-alt.
-R10
-78 Avskrivningar
-BAS-konton
-Underkonton
-Rad Rad
-7810 Avskrivningar på immateriella
-anläggningstillgångar
-R10
-7820 Avskrivningar på byggnader
-och markanläggningar
-R9
-7830 Avskrivningar på maskiner och
-inventarier
-R10
-79 Övriga rörelsekostnader
-BAS-konton Underkonton
-Rad Rad
-7970 Förlust vid avyttring av
-immateriella och materiella
-anläggningstillgångar
-R6
-7980 Ersättningsfonder R9/
-10
-8 FINANSIELLA OCH ANDRA INKOMSTER/INTÄKTER OCH
-UTGIFTER/ KOSTNADER
-83 Övriga ränteintäkter och liknande resultatposter
-BAS-konton Underkonton
-Rad Rad
-Kontoplan_K1_2018_ver1
-9/9
-8310 Ränteintäkter och utdelningar R4 8314 Skattefria ränteintäkter R4
-+
-NE
-sid.
-2
-8330 Valutakursdifferenser på
-fordringar och placeringar
-R4
-84 Räntekostnader och liknande
-BAS-konton Underkonton
-Rad Rad
-8410 Räntekostnader för skulder R8
-8430 Valutakursdifferenser på
-skulder R8
-88 Bokslutsdispositioner
-89 Årets resultat
-BAS-konton Underkonton
-Rad Rad
-8990 Resultat R11 R11 8999 Årets resultat R11
-Kontoplan_K1_2018_ver1
\ No newline at end of file
diff --git a/dev_docs/NYA_FEATURES.md b/dev_docs/NYA_FEATURES.md
deleted file mode 100644
index 8e1c95a4..00000000
--- a/dev_docs/NYA_FEATURES.md
+++ /dev/null
@@ -1,41 +0,0 @@
-. Media Kit-generator
-Standardverktyg i creator-ekonomin 2025, men inget svenskt verktyg erbjuder det. Kreatörer bygger idag media kits manuellt i Canva.
-Implementation: Dra in analytics från Instagram, TikTok, YouTube via API. Generera professionell PDF med demografi, engagemangsgrad, tidigare samarbeten. Inkludera prisförslag baserat på följarantal och engagemang. Automatisk uppdatering kvartalsvis.
-Svårighetsgrad: Medel. API-integrationer finns redan delvis i din app.
-3. Avtalsmallar och e-signering
-Creator-specifika avtal saknas helt på den svenska marknaden. Verktyg som CreatorIQ, RosterGrid och HoneyBook erbjuder detta internationellt. Svenska kreatörer använder inga avtal alls eller kopierar generiska mallar.
-Implementation: Mallbibliotek anpassat för svenska influencersamarbeten: leveranser, betalningsvillkor, contenträttigheter, exklusivitet, bytesaffärer. Integrera e-signering (BankID om möjligt). Lagra i kampanjhanteringssystemet.
-Svårighetsgrad: Medel. Juridisk granskning krävs men templaten är straightforward.
-4. Automatiserade betalningspåminnelser och inkasso-workflow
-Ingen kreatör vill jaga betalningar. Det är det näst vanligaste klagomålet efter sena betalningar överhuvudtaget.
-Implementation: Automatiska påminnelser vid 15, 30 och 45 dagar. Eskaleringsflöde. Professionell inkassokommunikation. Eventuellt kopplad till fakturafinaliseringen ovan.
-Svårighetsgrad: Låg. Primärt e-post/SMS-automation.
-5. Multi-currency rate cards och prisriktlinjer
-Kreatörer, särskilt nya, underprissätter sig systematiskt. Internationella plattformar erbjuder pricing benchmarks.
-Implementation: Föreslå priser baserat på följarantal, engagemang, plattform, nisch. Svenska branschriktlinjer. Visa vad liknande kreatörer tar betalt. Integrera med faktureringsflödet.
-Svårighetsgrad: Låg-medel. Datainsamling är huvudutmaningen.
-
-Features att FÖRBÄTTRA
-1. AI-assistent: Scenariospecifik, inte generisk
-Din kunskapsbas med 30+ scenarion är en stark grund. Men assistenten behöver bli proaktiv, inte reaktiv.
-Förbättring: "Du har 3 obetalda fakturor äldre än 30 dagar." "Din barter-deal med X saknar värdering, jag behöver marknadsvärdet." "Du har inte deklarerat periodisk sammanställning för Q3." Assistenten ska agera som en digital revisor som håller koll, inte som en FAQ.
-2. Bokföring: "Creator Mode" som default
-BAS-kontoplanen är korrekt men onödig för 90% av målgruppen. De behöver inte se konto 2641.
-Förbättring: Förenklad vy med creator-kategorier: "Plattformsintäkter", "Samarbeten", "Barter", "Resor", "Utrustning". Full BAS i bakgrunden för SIE-export. Automatisk kategorisering via AI. En-klicks-avstämning för vanliga transaktioner.
-3. Bankintegration: Automatisk matchning
-PSD2-synk och swipe-kategorisering finns. Saknas: automatisk matchning av banktransaktioner mot fakturor. Flagga transaktioner som kan vara oredovisade intäkter. Kassaflödesprognos baserad på betalningshistorik.
-4. Gåvo-/produktspårning: Fullständig skattehantering
-Nuvarande feature finns men behöver utökas: automatisk beräkning av marknadsvärde för skatt, spåra om produkt behålls/returneras/ges bort/används som arbetsredskap, generera dokumentation mot Skatteverket, varning när en produkt blir en skattepliktig händelse. Skatteverket granskar influencersektorn aktivt. Det här är compliance-kritiskt.
-5. Kampanjhantering: Content-workflow
-Lägg till content approval-flöden, varumärkesportal där kunder kan granska leveranser, automatisk spårning av publiceringsschema, prestandamätning per kampanj (räckvidd, engagemang, konverteringar).
-
-Features att ÖVERVÄGA (lägre prioritet)
-Affiliate-integration: Många kreatörer tjänar via Adtraction, Awin, Amazon Associates. Auto-import av provisionsdata och skatterapportering. Relevant men inte brådskande.
-Kvittomatchning: OCR finns. Lägg till automatisk matchning av kvitto mot banktransaktion. Minskar dubbelinmatning.
-Team-access: Kreatörer som skalar anställer assistenter. Begränsade roller (bokförare, assistent, revisor) med auditlogg.
-
-Features att IFRÅGASÄTTA
-Fullständigt bokföringsmodulen
-De flesta kreatörer behöver inte fullständig BAS-bokföring och kommer ändå outsourca till revisor. Överväg att göra "Exportera till revisor"-paket till huvudflödet och behålla förenklat läge som default. Den avancerade vyn blir opt-in, inte standard.
-Kalender som fristående feature
-Deadlines är viktiga men kan duplicera verktyg kreatören redan använder. Om användningen är låg, integrera med Google Calendar istället och ta bort egen kalendervy. Deadlines och påminnelser kan leva i appen utan att vara en separat sektion.
\ No newline at end of file
diff --git a/dev_docs/README.md b/dev_docs/README.md
deleted file mode 100644
index 542e57bd..00000000
--- a/dev_docs/README.md
+++ /dev/null
@@ -1,186 +0,0 @@
-# Influencer Business-in-a-Box MVP
-
-## Quick Context for AI Builders
-
-Financial management SaaS for Swedish influencers/content creators. Supports both enskild firma (sole proprietor) and aktiebolag (limited company). Core problem: tax anxiety and admin overload. Core solution: automated compliance and simplified invoicing.
-
-## Tech Stack
-
-- **Framework**: Next.js 14 (App Router) + TypeScript
-- **UI**: Tailwind CSS + shadcn/ui + Framer Motion
-- **Database**: Supabase (PostgreSQL with RLS)
-- **Auth**: Supabase Auth (magic link)
-- **Hosting**: Vercel
-- **PDF**: @react-pdf/renderer
-- **Banking**: Enable Banking (PSD2 AISP)
-- **Currency**: Riksbanken API for exchange rates
-
-## Documentation Index
-
-| Doc | Purpose |
-|-----|---------|
-| [01-PRD.md](./docs/01-PRD.md) | Product requirements, user stories, success metrics |
-| [02-ARCHITECTURE.md](./docs/02-ARCHITECTURE.md) | Technical architecture, PSD2 strategy, security |
-| [03-DATABASE-SCHEMA.md](./docs/03-DATABASE-SCHEMA.md) | Full Supabase schema with RLS policies |
-| [04-API-SPECIFICATION.md](./docs/04-API-SPECIFICATION.md) | All API endpoints, VAT rules, momsdeklaration rutor |
-| [05-UI-SPECIFICATION.md](./docs/05-UI-SPECIFICATION.md) | Wireframes, component specs, design system |
-| [06-IMPLEMENTATION-GUIDE.md](./docs/06-IMPLEMENTATION-GUIDE.md) | Step-by-step build guide with code examples |
-| [07-FUTURE-FEATURES.md](./docs/07-FUTURE-FEATURES.md) | Phase 2+ features: benefits tracking, NE-bilaga, Skatteverket APIs |
-| [08-BAS-ACCOUNTING-GUIDE.md](./docs/08-BAS-ACCOUNTING-GUIDE.md) | BAS account mapping, MCC codes, auto-categorization rules |
-
-## MVP Feature Scope
-
-### Included in MVP
-
-1. **Entity Support**: Both enskild firma and aktiebolag with appropriate tax logic
-2. **Bank Integration**: Enable Banking (PSD2) with multiple account support
-3. **Tax Dashboard**: "Disponibelt saldo" with F-skatt comparison warning
-4. **Transaction Categorization**: Swipe UI with schablonavdrag suggestions
-5. **Multi-currency Invoicing**: SEK, EUR, USD with Riksbanken auto-conversion
-6. **VAT Automation**: Swedish (25%), EU reverse charge (0%), Export (0%)
-7. **Credit Notes**: Kreditfaktura support for invoice corrections
-8. **Expense Warnings**: Alert on non-deductible lifestyle costs
-9. **Configurable Settings**: Momsperiod (monthly/quarterly), custom invoice numbering
-
-### Deferred to Later
-
-- Receipt photo capture and matching
-- Benefits/gifts tracking (förmånshantering)
-- NE-bilaga / Årsredovisning auto-generation
-- Automated payment reminders
-- Quotes/proforma invoices
-- English UI
-
-## Entity Type Tax Differences
-
-| Aspect | Enskild Firma | Aktiebolag |
-|--------|---------------|------------|
-| Profit tax | Egenavgifter (28.97%) + kommunalskatt (~32%) | Bolagsskatt (20.6%) |
-| Owner payment | Eget uttag | Lön + utdelning |
-| Annual filing | NE-bilaga | Årsredovisning + INK2 |
-
-## Key Swedish Tax & Legal Concepts
-
-| Term | English | Rate/Rule |
-|------|---------|-----------|
-| Enskild firma | Sole proprietorship | Personal liability, NE-bilaga |
-| Aktiebolag (AB) | Limited company | 20.6% bolagsskatt, årsredovisning |
-| Egenavgifter | Self-employment contributions | 28.97% (enskild firma only) |
-| Arbetsgivaravgifter | Employer contributions | 31.42% (AB paying salary) |
-| Bolagsskatt | Corporate tax | 20.6% on AB profit |
-| Kommunalskatt | Municipal income tax | ~30-35% varies |
-| F-skatt | Business tax registration | Required for invoicing |
-| Debiterad preliminärskatt | Preliminary tax set | Monthly F-skatt payment amount |
-| Moms | VAT | 25% standard, threshold 80k SEK |
-| Momsperiod | VAT reporting period | Monthly or quarterly |
-| Räkenskapsår | Fiscal year | Calendar or brutet (broken) |
-| Brutet räkenskapsår | Non-calendar fiscal year | e.g., July 1 - June 30 |
-| Omvänd skattskyldighet | Reverse charge | EU B2B: buyer reports VAT |
-| Kreditfaktura | Credit note | Corrects/cancels issued invoice |
-| Schablonavdrag | Standard deduction | Fixed amounts (hemmakontor 2000 kr/år) |
-| AGI-deklaration | Employer declaration | Monthly report for AB salaries |
-| SIE-fil | Standard Import Export | Accounting data exchange format |
-
-## Entity Type Tax Differences
-
-| Aspect | Enskild Firma | Aktiebolag |
-|--------|---------------|------------|
-| Profit tax | Egenavgifter (28.97%) + kommunalskatt (~32%) | Bolagsskatt (20.6%) |
-| Owner payment | Eget uttag | Lön + utdelning |
-| Salary costs | N/A | Arbetsgivaravgifter (31.42%) |
-| Annual filing | NE-bilaga | Årsredovisning + INK2 |
-| Periodiseringsfond | Max 30% | Max 25% |
-
-**MVP Note:** For AB, system tracks salary payments and calculates arbetsgivaravgifter. Lön/utdelning optimization (3:12-reglerna) deferred to future phase.
-
-## MVP Technical Notes
-
-| Aspect | Implementation |
-|--------|----------------|
-| Banking | Enable Banking (PSD2 AISP) |
-| Email | Supabase built-in |
-| Payment on invoices | Bank transfer only (future: third-party) |
-| Partial payments | Not supported (paid/unpaid binary) |
-| Fiscal year | Calendar + brutet räkenskapsår |
-| Multi-user | Single user per account |
-| UI Language | Swedish only |
-| Data import | SIE file (future feature) |
-
-## Momsdeklaration Ruta Quick Reference
-
-| Ruta | When Used |
-|------|-----------|
-| 05 | Swedish domestic sales with 25% VAT |
-| 39 | EU B2B services (reverse charge) |
-| 40 | Export to non-EU |
-| 21 | Service purchases from EU (input) |
-| 48 | Self-assessed output VAT on foreign purchases |
-
-## Critical Implementation Notes
-
-1. **All tax figures are estimates** - display disclaimer prominently
-2. **VIES validation required** for EU reverse charge - without it, charge 25% VAT
-3. **Non-custodial design** - app NEVER holds user funds
-4. **Multi-currency**: Store original + SEK converted amounts, use Riksbanken rate on invoice date
-5. **Invoice numbers**: Allow custom starting number (user may have history elsewhere)
-6. **Credit notes**: Must reference original invoice, use negative amounts
-7. **Expense warnings** - clothing, cosmetics, gym are NOT deductible per Kammarrätten rulings
-8. **7-year retention** - Bokföringslagen requires, GDPR does not override for accounting records
-9. **RLS on all tables** - users must only access own data
-10. **Swedish UI only** for MVP
-
-## Schablonavdrag Defaults
-
-| Type | Amount | Notes |
-|------|--------|-------|
-| Hemmakontor | 2 000 kr/år | If dedicated room |
-| Bilkostnader | 18.50 kr/mil | Business travel |
-| Telefon | Actual or % split | Based on business use |
-
-## Quick Start for Builder AI
-
-1. Read docs in order: PRD → Architecture → Schema → API → UI → Implementation → Future
-2. Start with auth + middleware (including onboarding redirect logic)
-3. Build onboarding wizard (6 steps, all required except preliminary tax)
-4. Implement Enable Banking integration in onboarding step 6
-5. Build dashboard with tax calculations (adapt for entity type)
-6. Add invoice creation with multi-currency + VIES validation
-7. Implement credit note flow
-8. Polish UI (Swedish language)
-
-## File Structure
-
-```
-/
-├── app/
-│ ├── (auth)/login/page.tsx
-│ ├── (onboarding)/onboarding/ # Wizard steps 1-6
-│ ├── (dashboard)/
-│ │ ├── page.tsx # Dashboard
-│ │ ├── transactions/page.tsx
-│ │ ├── invoices/
-│ │ │ ├── page.tsx
-│ │ │ ├── new/page.tsx
-│ │ │ └── [id]/credit/page.tsx # Credit notes
-│ │ ├── customers/page.tsx
-│ │ └── settings/page.tsx
-│ └── api/...
-├── components/
-│ ├── ui/ # shadcn components
-│ ├── onboarding/ # Wizard components
-│ ├── dashboard/
-│ ├── transactions/
-│ └── invoices/
-├── lib/
-│ ├── supabase/
-│ ├── banking/enable-banking.ts
-│ ├── currency/riksbanken.ts
-│ ├── tax/
-│ │ ├── calculator.ts
-│ │ ├── expense-warnings.ts
-│ │ ├── schablonavdrag.ts
-│ │ └── fskatt-warning.ts
-│ └── invoice/vat-rules.ts
-├── types/index.ts
-└── supabase/migrations/
-```
\ No newline at end of file
diff --git a/dev_docs/archive/alice_bank_data.json b/dev_docs/archive/alice_bank_data.json
deleted file mode 100644
index 34e88f6a..00000000
--- a/dev_docs/archive/alice_bank_data.json
+++ /dev/null
@@ -1,506 +0,0 @@
-{
- "accounts": [
- {
- "info": {
- "psu_status": "OPEN",
- "uid": "36a097d1-60bc-4a2d-836a-0f3c2a234196",
- "identification_hashes": [
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoiaWJhbiIKXQpd.CMv8KPVyC9Jb2K/o4iLTHs0/Rm6oBpLZ2Dk94dLUUqY=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoiaWJhbiIKXSwKWwoiYWNjb3VudCIsCiJjdXJyZW5jeSIKXQpd.KHox2S2cDHB0qpvDl/UbtAYEOFT0bkKlDBaIbiJbOYs=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.YvAsATX9mYjlf4gudQxRshFYi9Qf4mWLmaS4N6XA+do=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.11au3gbnyahIaOUJ+34GVhawiFxuqno1YFYMozafKcI=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.wrdjfOu/bFCI1mKxgyNYkwyi0CJuuDlEQIk/L7u0BRU=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.3D+Eg8xEbNOBIaId0JvB4AdJbRAq7H4eSIHjHu1h7SY=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.wsxsnRROHXrRPiE0Q2kGZAvwuvKG6ozdZRWVeUiRQtA=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.HDktnbN78H+BytoIzLMomebkcAc6VCMoiKhHjF1cLDw=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.cPNpoeUyy8YheNam7y5Jk2cx3iG+qq6yEo1n/BveClU=",
- "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoib3RoZXIiLAoic2NoZW1lX25hbWUiCl0sClsKImFjY291bnQiLAoiYWNjb3VudF9pZCIsCiJvdGhlciIsCiJpZGVudGlmaWNhdGlvbiIKXQpd.H1mYrXAPxkI6n0ehgmB5mtBIls9OcjXI2ynisJcGaYw=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKInJlc291cmNlX2lkIgpdCl0=.yuDuYREXfxEWdB8C0YwTXDqW5POBjc/3jlmRVVzVa70=",
- "WwpbCiJhc3BzcF9uYW1lIgpdLApbCiJhc3BzcF9jb3VudHJ5IgpdLApbCiJhY2NvdW50IiwKIm5hbWUiCl0KXQ==.JiZ4C/jjfO9u/6DSSTS8QUjFIvbP24KNkyChx2B0yW4="
- ],
- "usage": null,
- "credit_limit": {
- "currency": "SEK",
- "amount": "0.00"
- },
- "account_id": {
- "other": {
- "issuer": null,
- "scheme_name": "BBAN",
- "identification": "99602621638218"
- },
- "iban": "SE9795000099602621638218"
- },
- "product": "PLUSGIROKONTO FTG",
- "account_servicer": {
- "clearing_system_member_id": {
- "member_id": "9960",
- "clearing_system_id": "SESBA"
- },
- "bic_fi": "NDEASESS",
- "name": null
- },
- "name": "JÖNSSON,ALICE",
- "currency": "SEK",
- "identification_hash": "WwpbCiJhY2NvdW50IiwKImFjY291bnRfaWQiLAoiaWJhbiIKXSwKWwoiYWNjb3VudCIsCiJjdXJyZW5jeSIKXQpd.KHox2S2cDHB0qpvDl/UbtAYEOFT0bkKlDBaIbiJbOYs=",
- "cash_account_type": "CACC",
- "postal_address": null,
- "details": null,
- "all_account_ids": [
- {
- "issuer": null,
- "scheme_name": "PGNR",
- "identification": "21638218"
- },
- {
- "issuer": null,
- "scheme_name": "BBAN",
- "identification": "99602621638218"
- },
- {
- "issuer": null,
- "scheme_name": "IBAN",
- "identification": "SE9795000099602621638218"
- }
- ]
- },
- "transactions": [
- {
- "entry_reference": "2025-12-30-16.17.03.380410058H1021638218 EK",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "8730.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BARCLAYS BANK PLC",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Andra",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2025-12-30",
- "value_date": "2025-12-30",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "18730.00"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "005 BaByliss\r\nURSPRUNGLIGT BELOPP M M: SEK",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "SEK",
- "exchange_rate": "1.0000000",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "SEK",
- "amount": "8730.00"
- }
- },
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "06200021638218000100000000125-12-2900H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "10000.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BG INSÄTTNING 1",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "BGC LB-betalningar",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2025-12-29",
- "value_date": "2025-12-30",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "10000.00"
- },
- "reference_number": "0051385052",
- "reference_number_schema": null,
- "remittance_information": [
- "0051385052",
- "",
- "5138-5052"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "06400021638218000100000000126-01-0200H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "15625.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BG INSÄTTNING 1",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "BGC LB-betalningar",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-02",
- "value_date": "2026-01-05",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "34355.00"
- },
- "reference_number": "0051385052",
- "reference_number_schema": null,
- "remittance_information": [
- "0051385052",
- "",
- "5138-5052"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "06600021638218000200000000126-01-0700H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "1409.85"
- },
- "creditor": {
- "name": "AVGIFTER NORDEA",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": null,
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Debitering av avgift",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "DBIT",
- "status": "BOOK",
- "booking_date": "2026-01-07",
- "value_date": "2026-01-07",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "32945.15"
- },
- "reference_number": null,
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "AVGIFTER NORDEA"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "2026-01-09-16.25.07.272909064H1021638218 EK",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "7000.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "NORDEA BANK ABP",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Andra",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-12",
- "value_date": "2026-01-12",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "39945.15"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "/ROC/E20304164B207920 INVOICE 003\r\nURSPRUNGLIGT BELOPP M M: SEK",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "SEK",
- "exchange_rate": "1.0000000",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "SEK",
- "amount": "7000.00"
- }
- },
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "07700021638218000400000000126-01-2200H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "2500.00"
- },
- "creditor": {
- "name": "Uttag",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "creditor_account": {
- "iban": null,
- "other": {
- "identification": "1411450057",
- "scheme_name": "BBAN",
- "issuer": null
- }
- },
- "creditor_agent": null,
- "debtor": null,
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Generell O-Typ från Cello-kassa via INL",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "DBIT",
- "status": "BOOK",
- "booking_date": "2026-01-22",
- "value_date": "2026-01-22",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "37445.15"
- },
- "reference_number": null,
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "Anslutningsavgift"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "2026-01-26-16.16.34.120637074H1021638218 EK",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "313.70"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "SPAR NORD BANK A/S",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "Andra",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-26",
- "value_date": "2026-01-26",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "37758.85"
- },
- "reference_number": "",
- "reference_number_schema": null,
- "remittance_information": [
- "",
- "2025DEC58 BRANDHEROES\r\nURSPRUNGLIGT BELOPP M M: EUR",
- "UTLANDSBETALNING"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": {
- "unit_currency": "EUR",
- "exchange_rate": "10.4567000",
- "rate_type": null,
- "contract_identification": null,
- "instructed_amount": {
- "currency": "EUR",
- "amount": "30.00"
- }
- },
- "note": null,
- "transaction_id": null
- },
- {
- "entry_reference": "08100021638218000600000000126-01-2800H1 TR",
- "merchant_category_code": null,
- "transaction_amount": {
- "currency": "SEK",
- "amount": "3750.00"
- },
- "creditor": null,
- "creditor_account": null,
- "creditor_agent": null,
- "debtor": {
- "name": "BG INSÄTTNING 1",
- "postal_address": null,
- "organisation_id": null,
- "private_id": null,
- "contact_details": null
- },
- "debtor_account": null,
- "debtor_agent": null,
- "bank_transaction_code": {
- "description": "BGC LB-betalningar",
- "code": null,
- "sub_code": null
- },
- "credit_debit_indicator": "CRDT",
- "status": "BOOK",
- "booking_date": "2026-01-28",
- "value_date": "2026-01-29",
- "transaction_date": null,
- "balance_after_transaction": {
- "currency": "XXX",
- "amount": "41508.85"
- },
- "reference_number": "0051385052",
- "reference_number_schema": null,
- "remittance_information": [
- "0051385052",
- "",
- "5138-5052"
- ],
- "debtor_account_additional_identification": null,
- "creditor_account_additional_identification": null,
- "exchange_rate": null,
- "note": null,
- "transaction_id": null
- }
- ],
- "balances": [
- {
- "name": "Available balance",
- "balance_type": "ITAV",
- "balance_amount": {
- "amount": "41508.85",
- "currency": "SEK"
- },
- "last_change_date_time": null,
- "last_committed_transaction": null,
- "reference_date": null
- },
- {
- "name": "Booked balance",
- "balance_type": "ITBD",
- "balance_amount": {
- "amount": "41508.85",
- "currency": "SEK"
- },
- "last_change_date_time": null,
- "last_committed_transaction": null,
- "reference_date": null
- }
- ],
- "raw_data": {
- "transactions": [
- "{\"group_header\":{\"message_identification\":\"35146ffa2df21681\",\"creation_date_time\":\"2026-01-29T21:12:00.246234221Z\",\"http_code\":200},\"response\":{\"transactions\":[{\"transaction_id\":\"08100021638218000600000000126-01-2800H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-28\",\"value_date\":\"2026-01-29\",\"type_description\":\"BGC LB-betalningar\",\"narrative\":\"5138-5052\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"0051385052\",\"counterparty_account\":\"\",\"counterparty_name\":\"BG INSÄTTNING 1\",\"balance_after_transaction\":\"41508.85\",\"amount\":\"3750.00\",\"from_account_name\":\"BG INSÄTTNING 1\",\"from_account_country\":\"\",\"transaction_type_code\":\"SE218\"},{\"transaction_id\":\"2026-01-26-16.16.34.120637074H1021638218 EK\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-26\",\"value_date\":\"2026-01-26\",\"type_description\":\"Andra\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"2025DEC58 BRANDHEROES\\r\\nURSPRUNGLIGT BELOPP M M: EUR\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"\",\"counterparty_name\":\"SPAR NORD BANK A/S\",\"payment_date\":\"2026-01-26\",\"original_currency\":\"EUR\",\"original_currency_amount\":\"30.00\",\"currency_rate\":\"10.4567000\",\"balance_after_transaction\":\"37758.85\",\"amount\":\"313.70\",\"from_account_name\":\"SPAR NORD BANK A/S\",\"from_account_country\":\"DK\",\"bank_name\":\"SPAR NORD BANK A/S\",\"bank_address\":\"\",\"bank_code\":\"AALBORG\",\"bank_bic\":\"SPNODK22A\",\"transaction_type_code\":\"SE\"},{\"transaction_id\":\"07700021638218000400000000126-01-2200H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-22\",\"value_date\":\"2026-01-22\",\"type_description\":\"Generell O-Typ från Cello-kassa via INL\",\"narrative\":\"Anslutningsavgift\",\"message\":\"\",\"status\":\"billed\",\"counterparty_account\":\"1411450057\",\"counterparty_name\":\"Uttag\",\"balance_after_transaction\":\"37445.15\",\"amount\":\"-2500.00\",\"to_account_name\":\"Uttag\",\"to_account_country\":\"\",\"transaction_type_code\":\"SE976\"},{\"transaction_id\":\"2026-01-09-16.25.07.272909064H1021638218 EK\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-12\",\"value_date\":\"2026-01-12\",\"type_description\":\"Andra\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"/ROC/E20304164B207920 INVOICE 003\\r\\nURSPRUNGLIGT BELOPP M M: SEK\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"\",\"counterparty_name\":\"NORDEA BANK ABP\",\"payment_date\":\"2026-01-12\",\"original_currency\":\"SEK\",\"original_currency_amount\":\"7000.00\",\"currency_rate\":\"1.0000000\",\"balance_after_transaction\":\"39945.15\",\"amount\":\"7000.00\",\"from_account_name\":\"NORDEA BANK ABP\",\"from_account_country\":\"FI\",\"bank_name\":\"NORDEA BANK ABP\",\"bank_address\":\"\",\"bank_code\":\"HELSINKI\",\"bank_bic\":\"NDEAFIHHS\",\"transaction_type_code\":\"SE\"},{\"transaction_id\":\"06600021638218000200000000126-01-0700H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-07\",\"value_date\":\"2026-01-07\",\"type_description\":\"Debitering av avgift\",\"narrative\":\"AVGIFTER NORDEA\",\"message\":\"\",\"status\":\"billed\",\"counterparty_account\":\"\",\"counterparty_name\":\"AVGIFTER NORDEA\",\"balance_after_transaction\":\"32945.15\",\"amount\":\"-1409.85\",\"to_account_name\":\"AVGIFTER NORDEA\",\"to_account_country\":\"\",\"transaction_type_code\":\"SE931\"},{\"transaction_id\":\"06400021638218000100000000126-01-0200H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2026-01-02\",\"value_date\":\"2026-01-05\",\"type_description\":\"BGC LB-betalningar\",\"narrative\":\"5138-5052\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"0051385052\",\"counterparty_account\":\"\",\"counterparty_name\":\"BG INSÄTTNING 1\",\"balance_after_transaction\":\"34355.00\",\"amount\":\"15625.00\",\"from_account_name\":\"BG INSÄTTNING 1\",\"from_account_country\":\"\",\"transaction_type_code\":\"SE218\"},{\"transaction_id\":\"2025-12-30-16.17.03.380410058H1021638218 EK\",\"currency\":\"SEK\",\"booking_date\":\"2025-12-30\",\"value_date\":\"2025-12-30\",\"type_description\":\"Andra\",\"narrative\":\"UTLANDSBETALNING\",\"message\":\"005 BaByliss\\r\\nURSPRUNGLIGT BELOPP M M: SEK\",\"status\":\"billed\",\"reference\":\"\",\"counterparty_account\":\"\",\"counterparty_name\":\"BARCLAYS BANK PLC\",\"payment_date\":\"2025-12-30\",\"original_currency\":\"SEK\",\"original_currency_amount\":\"8730.00\",\"currency_rate\":\"1.0000000\",\"balance_after_transaction\":\"18730.00\",\"amount\":\"8730.00\",\"from_account_name\":\"BARCLAYS BANK PLC\",\"from_account_country\":\"GB\",\"bank_name\":\"BARCLAYS BANK PLC\",\"bank_address\":\"\",\"bank_code\":\"LONDON\",\"bank_bic\":\"BARCGB22V\",\"transaction_type_code\":\"SE\"},{\"transaction_id\":\"06200021638218000100000000125-12-2900H1 TR\",\"currency\":\"SEK\",\"booking_date\":\"2025-12-29\",\"value_date\":\"2025-12-30\",\"type_description\":\"BGC LB-betalningar\",\"narrative\":\"5138-5052\",\"message\":\"\",\"status\":\"billed\",\"reference\":\"0051385052\",\"counterparty_account\":\"\",\"counterparty_name\":\"BG INSÄTTNING 1\",\"balance_after_transaction\":\"10000.00\",\"amount\":\"10000.00\",\"from_account_name\":\"BG INSÄTTNING 1\",\"from_account_country\":\"\",\"transaction_type_code\":\"SE218\"}],\"_links\":[{\"rel\":\"self\",\"href\":\"/v4/accounts/SE21638218-SEK/transactions?from_date=2025-01-29&to_date=2026-01-29\"}]}}"
- ],
- "balances": {
-
- },
- "details": {
-
- }
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/dev_docs/base_architecture/AI_CATEGORIZATION_EXTENSION.md b/dev_docs/base_architecture/AI_CATEGORIZATION_EXTENSION.md
deleted file mode 100644
index a7b0bdf6..00000000
--- a/dev_docs/base_architecture/AI_CATEGORIZATION_EXTENSION.md
+++ /dev/null
@@ -1,381 +0,0 @@
-# AI Categorization Extension — Implementation Summary
-
-This document describes the ai-categorization extension: the second first-party extension built on the Part 3 event bus and extension registry. It uses Claude Haiku to suggest BAS account categorizations for bank transactions, following the same canonical pattern established by receipt-ocr.
-
----
-
-## Problem
-
-Transaction categorization is the most frequent daily task. Every downstream report (momsdeklaration, income statement, balance sheet, NE-bilaga, SRU export) depends on transactions being mapped to the correct BAS accounts.
-
-Before this extension, suggestions came only from:
-
-- **Mapping rules** — user-defined merchant/description patterns (confidence 0.8)
-- **Pattern matching** — built-in regex heuristics from `expense-warnings.ts` (confidence 0.6)
-- **User history** — most frequently used categories (confidence 0.1–0.5)
-
-These sources cover common recurring transactions but fail on novel descriptions, edge cases, and new users with no history.
-
-## Solution
-
-An `ai-categorization` extension that:
-
-1. Listens to `transaction.synced` events and auto-generates AI-powered category suggestions for uncategorized transactions
-2. Stores suggestions in `extension_data` (pre-computed, ready when the user opens the transaction list)
-3. Exposes an on-demand API for manual "AI suggest" triggers
-4. Merges AI suggestions into the existing suggestion pipeline alongside rule/pattern/history sources
-
-**Key constraint:** Suggestions only, never auto-commit. The extension stores suggestions in `extension_data` but never creates journal entries. The user confirms via the existing categorization UI, preserving audit trail integrity.
-
----
-
-## Files Changed
-
-### New files
-
-| File | Purpose |
-|------|---------|
-| `extensions/ai-categorization/categorizer.ts` | AI provider interface + Anthropic implementation |
-| `extensions/ai-categorization/index.ts` | Extension: settings, event handler, public API, extension object |
-| `app/api/extensions/ai-categorization/settings/route.ts` | GET/PATCH API for per-user extension settings |
-| `app/api/extensions/ai-categorization/suggestions/route.ts` | GET (pre-computed) / POST (on-demand) suggestions API |
-
-### Modified files
-
-| File | Change |
-|------|--------|
-| `lib/extensions/loader.ts` | Imported and registered `aiCategorizationExtension` |
-| `lib/transactions/category-suggestions.ts` | Added `'ai'` to `SuggestedCategory.source` union; added `mergeAiSuggestions()` |
-| `app/api/transactions/suggest-categories/route.ts` | Reads pre-computed AI suggestions from `extension_data` and merges into results |
-
----
-
-## Provider Abstraction
-
-The architecture doc requires "no hard dependency on any specific AI provider". The categorizer implements this via a `CategorizationProvider` interface.
-
-### `CategorizationProvider` interface
-
-```typescript
-interface CategorizationProvider {
- categorize(
- transactions: TransactionForCategorization[],
- context: CategorizationContext
- ): Promise
-}
-```
-
-### `TransactionForCategorization`
-
-Minimal transaction data sent to the AI:
-
-```typescript
-interface TransactionForCategorization {
- id: string
- description: string
- amount: number // negative = expense, positive = income
- date: string
- merchant_name: string | null
- mcc_code: number | null
- currency: string
-}
-```
-
-### `CategorizationContext`
-
-Contextual data that improves accuracy:
-
-```typescript
-interface CategorizationContext {
- entityType: EntityType // 'enskild_firma' | 'aktiebolag'
- recentHistory: { description: string; category: string }[] // last 50 categorized
-}
-```
-
-### `CategorizationSuggestion`
-
-The result per transaction:
-
-```typescript
-interface CategorizationSuggestion {
- transactionId: string
- category: TransactionCategory
- basAccount: string // BAS account number (e.g. '5420')
- taxCode: string | null // 'MPI', 'MP1', or null
- confidence: number // 0.0–1.0
- reasoning: string // Swedish-language explanation
- isPrivate: boolean // true = likely private expense
-}
-```
-
-### `AnthropicCategorizationProvider`
-
-The default implementation using `@anthropic-ai/sdk` (already a project dependency):
-
-- Model: `claude-haiku-4-5-20251001` (same as receipt-analyzer, chosen for cost efficiency)
-- Batch size: max 20 transactions per API call (cross-transaction pattern recognition)
-- Retry logic: 3 attempts with exponential backoff, no retry on JSON parse errors
-- Response validation: filters to valid transaction IDs and valid `TransactionCategory` values
-
-The system prompt includes:
-
-1. Full `TransactionCategory` → BAS account mapping table
-2. Entity type (EF uses 2013 for private, AB uses 2893)
-3. Swedish non-deductible expense rules (kläder, gym, kosmetika, etc. with legal references)
-4. VAT treatment rules (bank fees exempt, standard 25% otherwise)
-5. User's recent categorization history (up to 30 entries) for learning patterns
-
----
-
-## Extension: `extensions/ai-categorization/index.ts`
-
-### Settings
-
-```typescript
-interface AiCategorizationSettings {
- autoSuggestEnabled: boolean // default: true
- confidenceThreshold: number // default: 0.7
- providerModel: string // default: 'claude-haiku-4-5-20251001'
-}
-```
-
-Stored as an `extension_data` row with `extension_id='ai-categorization'`, `key='settings'`, `value=`.
-
-- `getSettings(userId)` reads from DB and merges with defaults (forward-compatible)
-- `saveSettings(userId, partial)` merges partial update with current, upserts on `(user_id, extension_id, key)`
-
-### Event Handler: `transaction.synced`
-
-When new transactions arrive from banking sync:
-
-1. **Gate:** Is `autoSuggestEnabled` in user's settings? — if not, return
-2. **Gate:** Filter to uncategorized transactions only (`is_business === null`) — if none, return
-3. Fetch entity type from `company_settings`
-4. Fetch user's last 50 categorized transactions (for learning patterns)
-5. Call `provider.categorize(batch, context)`
-6. Filter suggestions to those above `confidenceThreshold`
-7. Store each qualified suggestion to `extension_data` as `key: "suggestion:{transactionId}"`
-8. Log summary with `[ai-categorization]` prefix
-
-### Public API: `categorizeTransactions(userId, transactionIds)`
-
-Exported function for on-demand categorization (used by the suggestions POST endpoint):
-
-1. Fetch transactions by IDs
-2. Build context (entity type + history)
-3. Call provider
-4. Store all suggestions (no threshold filtering — user explicitly requested)
-5. Return suggestions
-
-### Extension Object
-
-```typescript
-export const aiCategorizationExtension: Extension = {
- id: 'ai-categorization',
- name: 'AI Kategorisering',
- version: '1.0.0',
- eventHandlers: [
- { eventType: 'transaction.synced', handler: handleTransactionSynced },
- ],
- settingsPanel: {
- label: 'AI Kategorisering',
- path: '/settings/extensions/ai-categorization',
- },
- async onInstall(ctx) { await saveSettings(ctx.userId, DEFAULT_SETTINGS) },
-}
-```
-
----
-
-## Suggestion Storage
-
-Suggestions are stored as individual rows in `extension_data`:
-
-| Column | Value |
-|--------|-------|
-| `user_id` | The user who owns the transaction |
-| `extension_id` | `'ai-categorization'` |
-| `key` | `'suggestion:{transactionId}'` |
-| `value` | The full `CategorizationSuggestion` object as JSONB |
-
-This per-transaction key scheme allows:
-
-- Fast lookup by transaction ID (used by the suggest-categories route)
-- Batch lookup via `IN` clause on keys
-- Natural overwrite on re-categorization (upsert on unique constraint)
-
----
-
-## Suggestions API: `app/api/extensions/ai-categorization/suggestions/route.ts`
-
-### `GET ?transaction_ids=id1,id2,...`
-
-Reads pre-computed suggestions from `extension_data`. Returns only what's already stored — no AI call.
-
-Response: `{ suggestions: { [txId]: CategorizationSuggestion } }`
-
-### `POST { transaction_ids: [...] }`
-
-Triggers on-demand AI categorization via `categorizeTransactions()`. Stores results and returns them.
-
-Response: `{ suggestions: { [txId]: CategorizationSuggestion } }`
-
-Both endpoints limit to 50 transaction IDs per request.
-
----
-
-## Settings API: `app/api/extensions/ai-categorization/settings/route.ts`
-
-Mirrors the receipt-ocr settings route exactly:
-
-- **GET** — Returns the current user's merged settings (DB value + defaults)
-- **PATCH** — Accepts a partial settings object, validates keys against allowlist (`autoSuggestEnabled`, `confidenceThreshold`, `providerModel`), saves via `saveSettings()`
-
----
-
-## Integration with Existing Suggestion Pipeline
-
-### `lib/transactions/category-suggestions.ts`
-
-Two changes:
-
-1. **Source type extended:** `SuggestedCategory.source` union widened from `'mapping_rule' | 'pattern' | 'history'` to `'mapping_rule' | 'pattern' | 'history' | 'ai'`
-
-2. **New merge function:**
-
-```typescript
-function mergeAiSuggestions(
- existing: SuggestedCategory[],
- aiSuggestions: { category: string; basAccount: string; confidence: number; reasoning: string }[]
-): SuggestedCategory[]
-```
-
-Inserts AI suggestions into the list, deduplicating by category (skips categories already present from higher-priority sources). Returns top 5 sorted by confidence.
-
-### `app/api/transactions/suggest-categories/route.ts`
-
-After computing rule/pattern/history suggestions for each transaction, the route now:
-
-1. Fetches pre-computed AI suggestions from `extension_data` for all requested transaction IDs (single batch query)
-2. For each transaction with an AI suggestion, calls `mergeAiSuggestions()` to blend it in
-3. Returns the merged result
-
-This means AI suggestions appear alongside existing sources with no latency — they were pre-computed during bank sync.
-
----
-
-## Suggestion Priority
-
-The existing pipeline already sorts by confidence. With AI added, the effective priority becomes:
-
-| Source | Typical Confidence | When |
-|--------|--------------------|------|
-| Mapping rules | 0.8 | User-defined patterns match |
-| AI | 0.7–0.95 | Pre-computed from sync |
-| Pattern matching | 0.6 | Built-in regex matches |
-| User history | 0.1–0.5 | Most frequently used categories |
-
-AI suggestions naturally slot between mapping rules and pattern matching. For novel transactions where no mapping rule or pattern exists, AI becomes the top suggestion.
-
----
-
-## Event Flow
-
-```
-Bank Sync
- |
-POST /banking/sync
- |
-emit transaction.synced
- |
- +---> receipt-ocr extension (auto-match receipts)
- |
- +---> ai-categorization extension
- |
- Gate: autoSuggestEnabled?
- Gate: has uncategorized transactions?
- |
- Fetch entity type + history
- Call AnthropicCategorizationProvider.categorize()
- Filter by confidenceThreshold
- Store to extension_data (suggestion:{txId})
- |
- [suggestions pre-computed and waiting]
-
-
-User opens transaction list
- |
-POST /api/transactions/suggest-categories
- |
- +---> getSuggestedCategories() [mapping rules + patterns + history]
- +---> Read extension_data [pre-computed AI suggestions]
- +---> mergeAiSuggestions()
- |
- v
-Response: merged suggestions with source labels
- |
-User sees: "AI: Programvara (5420) — confidence 0.9"
-
-
-User clicks "AI suggest" button (on-demand)
- |
-POST /api/extensions/ai-categorization/suggestions
- |
- +---> categorizeTransactions()
- | Call AI provider
- | Store results
- |
- v
-Response: fresh AI suggestions
-```
-
----
-
-## Existing Code Reused
-
-| Import | From | Used in |
-|--------|------|---------|
-| `Anthropic` | `@anthropic-ai/sdk` | `AnthropicCategorizationProvider` |
-| `getSettings()`/`saveSettings()` pattern | `extensions/receipt-ocr/index.ts` | Settings management (same pattern) |
-| `getSuggestedCategories()` | `lib/transactions/category-suggestions.ts` | Existing pipeline (unchanged) |
-| `createClient()` | `lib/supabase/server.ts` | DB access throughout |
-
-No existing service logic was duplicated. The extension adds a new AI-powered source to the existing suggestion pipeline.
-
----
-
-## Architectural Patterns Followed
-
-1. **Suggestions only, never auto-commit.** AI writes to `extension_data`, never to `journal_entries`. The user confirms via existing categorization UI.
-2. **Provider abstraction from day one.** `CategorizationProvider` interface means the AI model is swappable without changing extension logic.
-3. **Cost-efficient model.** Claude Haiku (same as receipt-analyzer) keeps per-sync costs low.
-4. **Batch processing.** One AI call per sync handles up to 20 transactions. Cross-transaction context (e.g., "all ICA transactions = groceries") improves accuracy.
-5. **Pre-computed suggestions.** AI runs on sync, results are stored. No user-facing latency when opening the transaction list.
-6. **Graceful degradation.** If the AI call fails, the handler catches and logs. Existing rule/pattern/history suggestions still work. No user-facing error.
-7. **Gate-guarded.** Every handler checks user settings before doing work.
-8. **One-way dependency.** Base never imports from `extensions/`. Only `loader.ts` imports the extension object.
-9. **`[ai-categorization]` prefix.** Console logging convention for grep-ability.
-
----
-
-## No New Migrations
-
-No database schema changes were needed. The existing `extension_data` table (created in Part 3, migration `20240101000020_extension_data.sql`) handles all storage:
-
-- Settings: `key='settings'`
-- Per-transaction suggestions: `key='suggestion:{transactionId}'`
-
-The unique constraint `(user_id, extension_id, key)` ensures upsert semantics.
-
----
-
-## Verification
-
-- `npx tsc --noEmit` — zero TypeScript errors
-- `npx vitest run` — all 78 existing tests pass (11 test files)
-- Manual: trigger bank sync → check console for `[ai-categorization]` logs
-- Manual: open transactions page → uncategorized transactions show AI suggestions (source: `'ai'`) alongside existing pattern/history suggestions
-- Manual: disable `autoSuggestEnabled` in settings → sync does not trigger AI
-- Manual: `POST /api/extensions/ai-categorization/suggestions` with transaction IDs → returns on-demand suggestions
-- Manual: `GET /api/extensions/ai-categorization/settings` → returns default settings
-- Manual: `PATCH /api/extensions/ai-categorization/settings` → updates settings
diff --git a/dev_docs/base_architecture/NE-BILAGA-EXTENSION.md b/dev_docs/base_architecture/NE-BILAGA-EXTENSION.md
deleted file mode 100644
index 96b8c5a7..00000000
--- a/dev_docs/base_architecture/NE-BILAGA-EXTENSION.md
+++ /dev/null
@@ -1,260 +0,0 @@
-# NE-bilaga Extension
-
-## Overview
-
-The NE-bilaga extension generates the NE appendix (Näringsverksamhet) for income tax reporting of enskild firma (sole proprietorship) to Skatteverket. It maps BAS account balances to NE declaration rutor R1-R11 and optionally produces downloadable SRU files.
-
-Only relevant for **enskild firma** (`entity_type = 'enskild_firma'`). The tab is hidden for AB users.
-
-Previously embedded as core code in `lib/reports/ne-declaration.ts` and `app/api/reports/ne-declaration/route.ts`, the logic was extracted into a proper extension following the same pattern as `extensions/sru-export/`.
-
-## Architecture
-
-```
-extensions/ne-bilaga/
-├── index.ts Extension definition (registered in loader)
-├── ne-engine.ts Account-to-ruta mapping and balance calculation
-├── types.ts NE-specific type definitions (canonical source)
-└── NEDeclarationView.tsx UI component for the NE-bilaga reports tab
-
-app/api/extensions/ne-bilaga/
-└── route.ts GET /api/extensions/ne-bilaga (json + sru)
-```
-
-### Relationship to SRU Export
-
-The NE-bilaga extension and the SRU Export extension serve different purposes but share SRU file generation utilities:
-
-```
-NE-bilaga path (EF only):
- ne-engine.ts (hard-coded R1-R11 account mappings) → lib/reports/sru-generator.ts
-
-SRU Export path (EF + AB):
- sru-engine.ts (reads sru_code from DB) → sru-generator.ts (any form type)
-```
-
-The NE-bilaga engine uses hard-coded account ranges to map balances to NE rutor. The SRU Export engine reads `sru_code` from `chart_of_accounts` for a more generic approach. Both use the shared `sruFileToString()` and `generateSRUFile()` from `lib/reports/sru-generator.ts`.
-
-### Dead code removed
-
-The backward-compatibility shim `lib/reports/ne-declaration.ts` (which re-exported from the extension) has been deleted. It had zero importers after the API route `app/api/reports/ne-declaration/route.ts` was removed earlier. All consumers now import directly from the extension or from `@/types`.
-
-## NE Declaration Rutor
-
-### Revenue (R1-R4)
-
-| Ruta | Account Range | Description |
-|---|---|---|
-| R1 | 3000-3499 (excl 3100) | Forsaljning med moms (25%) |
-| R2 | 3100, 3900, 3970-3980 | Momsfria intakter |
-| R3 | 3200-3299 | Bil/bostadsforman |
-| R4 | 8310-8330 | Ranteintakter |
-
-### Expenses (R5-R10)
-
-| Ruta | Account Range | Description |
-|---|---|---|
-| R5 | 4000-4990 | Varuinkop |
-| R6 | 5000-6990, 7970 | Ovriga kostnader |
-| R7 | 7000-7699 | Lonekostnader |
-| R8 | 8400-8499 | Rantekostnader |
-| R9 | 7820 | Avskrivningar fastighet |
-| R10 | 7700-7899 (excl 7820) | Avskrivningar ovrigt |
-
-### Result
-
-| Ruta | Calculation | Description |
-|---|---|---|
-| R11 | (R1+R2+R3+R4) - (R5+R6+R7+R8+R9+R10) | Arets resultat |
-
-### Gift handling
-
-- Gifts **with** consideration: R1 (VAT-liable exchange transaction)
-- Gifts **without** consideration: R2 via account 3900
-- Deductible gifts: R6 via account 5460
-
-## API Reference
-
-### GET /api/extensions/ne-bilaga
-
-Generate NE declaration for a fiscal period.
-
-**Query parameters:**
-
-| Parameter | Required | Description |
-|---|---|---|
-| `period_id` | Yes | Fiscal period UUID |
-| `format` | No | `json` (default) or `sru` |
-
-**Response (format=json):**
-```json
-{
- "data": {
- "fiscalYear": {
- "id": "uuid",
- "name": "2025",
- "start": "2025-01-01",
- "end": "2025-12-31",
- "isClosed": false
- },
- "rutor": {
- "R1": 150000,
- "R2": 0,
- "R3": 0,
- "R4": 500,
- "R5": 45000,
- "R6": 30000,
- "R7": 0,
- "R8": 1200,
- "R9": 0,
- "R10": 5000,
- "R11": 69300
- },
- "breakdown": {
- "R1": {
- "accounts": [
- { "accountNumber": "3001", "accountName": "Forsaljning tjanster 25%", "amount": 150000 }
- ],
- "total": 150000
- }
- },
- "companyInfo": {
- "companyName": "Mitt Foretag",
- "orgNumber": "801234-5678"
- },
- "warnings": ["Rakenskapsaret ar inte stangt. Siffrorna kan andras."]
- }
-}
-```
-
-**Response (format=sru):** Downloads a `.sru` file with `Content-Disposition: attachment`.
-
-**Error responses:**
-
-| Status | Condition |
-|---|---|
-| 400 | Missing `period_id` parameter |
-| 401 | Not authenticated |
-| 500 | Entity type is not `enskild_firma`, period not found, or database error |
-
-## Engine Details
-
-### Balance calculation
-
-1. Fetch all **posted** journal entries for the given fiscal period
-2. Sum `debit_amount - credit_amount` per account number
-3. Match each account to an NE ruta using `NE_ACCOUNT_MAPPINGS`
-4. For revenue accounts (credit-normal): negate the balance so positive = income
-5. For expense accounts (debit-normal): use as-is
-6. Round each ruta to whole kronor
-7. Calculate R11 as total revenue minus total expenses
-
-### Entity type guard
-
-The engine throws if `company_settings.entity_type !== 'enskild_firma'`. This prevents accidental NE generation for AB entities.
-
-### Warnings
-
-The engine emits warnings when:
-- The fiscal period is not closed (balances may change)
-- No revenue or expenses were found (empty period)
-
-## UI Integration
-
-### NEDeclarationView component
-
-The NE-bilaga UI lives in `extensions/ne-bilaga/NEDeclarationView.tsx` and is imported by the reports page:
-
-```typescript
-import { NEDeclarationView } from '@/extensions/ne-bilaga/NEDeclarationView'
-```
-
-### Reports Page
-
-The **NE-bilaga** tab in `/reports` is conditionally rendered based on `entity_type`:
-
-- **Visible** when `entity_type === 'enskild_firma'`
-- **Hidden** for all other entity types (e.g. `aktiebolag`)
-
-The entity type is fetched from `GET /api/settings` on page load. The tab shows:
-
-1. **Info card** with "Hamta NE-bilaga" and "Ladda ner SRU-fil" buttons
-2. **Warnings card** (orange) if the period is open or no data was found
-3. **Company info card** with company name, org number, and fiscal year badge
-4. **Revenue table** (R1-R4) with expandable account-level detail
-5. **Expenses table** (R5-R10) with expandable account-level detail
-6. **Result card** (R11) showing net result with green/red color coding
-
-Each ruta row is clickable to expand and show contributing accounts with individual amounts.
-
-## Extension Registration
-
-The extension is registered in `lib/extensions/loader.ts`:
-
-```typescript
-import { neBilagaExtension } from '@/extensions/ne-bilaga'
-
-const FIRST_PARTY_EXTENSIONS: Extension[] = [
- receiptOcrExtension,
- aiCategorizationExtension,
- pushNotificationsExtension,
- sruExportExtension,
- neBilagaExtension, // ← added
-]
-```
-
-The extension declares a single report type (`ne-bilaga`) for discovery via `extensionRegistry.getByCapability('reportTypes')`. It has no event handlers, no settings panel, and no sidebar items.
-
-## Type Definitions
-
-Canonical source: `extensions/ne-bilaga/types.ts` (re-exported from `types/index.ts` for convenience):
-
-- **`NEDeclaration`** — Top-level response shape with fiscal year, rutor, breakdown, company info, warnings
-- **`NEDeclarationRutor`** — Record of R1-R11 number values
-- **`NEAccountMapping`** — Mapping config: ruta, account ranges (with exclusions), isExpense flag
-- **`NE_RUTA_LABELS`** — Display labels for each ruta
-- **`SRURecord`** — Single SRU field code + value pair
-- **`SRUFile`** — Collection of SRU records with generation timestamp
-
-## Files Changed
-
-### Created
-
-| File | Purpose |
-|---|---|
-| `extensions/ne-bilaga/index.ts` | Extension definition with report type registration |
-| `extensions/ne-bilaga/ne-engine.ts` | Account mapping + balance calculation (moved from `lib/reports/`) |
-| `extensions/ne-bilaga/types.ts` | Canonical type definitions (`NEDeclaration`, `NEDeclarationRutor`, etc.) |
-| `extensions/ne-bilaga/NEDeclarationView.tsx` | UI component (extracted from reports page) |
-| `app/api/extensions/ne-bilaga/route.ts` | API endpoint with json/sru format support |
-
-### Modified
-
-| File | Change |
-|---|---|
-| `lib/extensions/loader.ts` | Added `neBilagaExtension` to `FIRST_PARTY_EXTENSIONS` |
-| `app/(dashboard)/reports/page.tsx` | Imports `NEDeclarationView` from extension instead of inlining it |
-| `types/index.ts` | NE types replaced with re-exports from `extensions/ne-bilaga/types.ts` |
-
-### Deleted
-
-| File | Reason |
-|---|---|
-| `app/api/reports/ne-declaration/route.ts` | Replaced by `app/api/extensions/ne-bilaga/route.ts` |
-| `lib/reports/ne-declaration.ts` | Dead backward-compat shim with zero importers |
-
-### Reused (not modified)
-
-| File | What was reused |
-|---|---|
-| `lib/reports/sru-generator.ts` | `generateSRUFile()`, `sruFileToString()`, `getSRUFilename()` |
-
-## Verification
-
-- `npx tsc --noEmit` — zero errors
-- `GET /api/extensions/ne-bilaga?period_id=X&format=json` returns NE declaration data
-- `GET /api/extensions/ne-bilaga?period_id=X&format=sru` downloads `.sru` file
-- NE-bilaga tab visible for EF users, hidden for AB users
-- Reports page renders identically to before for EF users
-- Extension appears in `extensionRegistry.getAll()` and `extensionRegistry.getByCapability('reportTypes')`
-- `next build` succeeds with zero errors
diff --git a/dev_docs/base_architecture/PART1_IMPLEMENTATION.md b/dev_docs/base_architecture/PART1_IMPLEMENTATION.md
deleted file mode 100644
index 7b7abad2..00000000
--- a/dev_docs/base_architecture/PART1_IMPLEMENTATION.md
+++ /dev/null
@@ -1,169 +0,0 @@
-# Part 1: Database Foundation & Compliance Core — Implementation Record
-
-## What was implemented
-
-8 Supabase migrations, TypeScript type updates, 4 new service files, and modifications to 3 existing files. No UI changes.
-
----
-
-## Migrations
-
-### Migration 11: ALTER Existing Tables
-`supabase/migrations/20240101000011_alter_existing_tables.sql`
-
-- `chart_of_accounts` — added `sru_code text` for Skatteverket SRU mapping
-- `journal_entries` — added `committed_at timestamptz`, `reversed_by_id uuid FK→self`, `reverses_id uuid FK→self`, `correction_of_id uuid FK→self`
-- `journal_entries` — expanded `source_type` CHECK to include `storno`, `correction`, `import`, `system`
-- `journal_entry_lines` — added `tax_code text`, `cost_center text`, `project text`
-- `fiscal_periods` — added `locked_at timestamptz`, `retention_expires_at date`
-
-### Migration 12: Tax Code Engine
-`supabase/migrations/20240101000012_tax_codes.sql`
-
-New table `tax_codes` with columns: `id`, `user_id`, `code`, `description`, `rate`, `moms_basis_boxes text[]`, `moms_tax_boxes text[]`, `moms_input_boxes text[]`, flags (`is_output_vat`, `is_reverse_charge`, `is_eu`, `is_export`, `is_oss`, `is_system`).
-
-RLS: select own + system (user_id IS NULL), insert/update/delete own only.
-
-Seeded 12 system tax codes: MP1 (25%), MP2 (12%), MP3 (6%), MPI, MPI12, MPI6, IV (intra-EU), EUS (EU sale), IP (import), EXP (export), OSS, NONE.
-
-New function `seed_tax_codes_for_user(p_user_id)` copies system codes to user scope.
-
-### Migration 13: Document Archive
-`supabase/migrations/20240101000013_document_archive.sql`
-
-New table `document_attachments` with: storage fields (`storage_path`, `file_name`, `file_size_bytes`, `mime_type`), integrity (`sha256_hash NOT NULL`), version chain (`version`, `original_id FK→self`, `superseded_by_id FK→self`, `is_current_version`), digitization metadata (`uploaded_by`, `upload_source`, `digitization_date`), linkage (`journal_entry_id FK ON DELETE RESTRICT`, `journal_entry_line_id FK ON DELETE RESTRICT`).
-
-No DELETE RLS policy — deletion handled by trigger in migration 17.
-
-### Migration 14: Audit Log
-`supabase/migrations/20240101000014_audit_log.sql`
-
-New table `audit_log`: `user_id uuid NOT NULL` (no FK cascade — survives user deletion), `action text` with CHECK constraint, `table_name`, `record_id`, `actor_id`, `old_state jsonb`, `new_state jsonb`, `description`. No `updated_at` — append-only.
-
-BEFORE UPDATE and BEFORE DELETE triggers raise exception to enforce immutability.
-
-### Migration 15: Dimensions
-`supabase/migrations/20240101000015_dimensions.sql`
-
-Two new tables:
-- `cost_centers` (`user_id`, `code`, `name`, `is_active`) with UNIQUE(user_id, code)
-- `projects` (`user_id`, `code`, `name`, `is_active`, `start_date`, `end_date`) with UNIQUE(user_id, code)
-
-Both with standard RLS and updated_at triggers.
-
-### Migration 16: Voucher Sequence Hardening
-`supabase/migrations/20240101000016_voucher_sequences.sql`
-
-New table `voucher_sequences` (`user_id`, `fiscal_period_id`, `voucher_series`, `last_number`) for tracking sequence state.
-
-Replaced `next_voucher_number()` with concurrent-safe version using `INSERT ON CONFLICT DO UPDATE RETURNING` (row-level lock instead of MAX+1).
-
-New DEFERRABLE constraint trigger `check_balance_on_post` validates debit==credit when an entry transitions from draft to posted.
-
-New function `detect_voucher_gaps(p_user_id, p_fiscal_period_id, p_series)` returns gap ranges for compliance reporting.
-
-### Migration 17: Enforcement Triggers
-`supabase/migrations/20240101000017_enforcement_triggers.sql`
-
-8 trigger functions:
-
-1. **`enforce_journal_entry_immutability()`** — allows draft→draft, draft→posted, posted→reversed. Blocks all other updates/deletes on committed entries.
-2. **`enforce_journal_entry_line_immutability()`** — blocks modifications to lines of posted/reversed entries.
-3. **`enforce_period_lock()`** — rejects journal_entries writes when `is_closed=true` OR `locked_at IS NOT NULL`.
-4. **`enforce_period_lock_documents()`** — blocks document attachment to entries in locked periods.
-5. **`block_document_deletion()`** — blocks deletion if linked to committed entry or within retention window. Logs blocked attempts to audit_log.
-6. **`enforce_retention_journal_entries()`** — blocks journal entry deletion within 7-year retention window.
-7. **`set_committed_at()`** — auto-sets `committed_at = now()` on draft→posted transition.
-8. **`calculate_retention_expiry()`** — auto-sets `retention_expires_at = period_end + 7 years`. Backfills existing rows.
-
-### Migration 18: Audit Logging Triggers
-`supabase/migrations/20240101000018_audit_triggers.sql`
-
-SECURITY DEFINER function `write_audit_log()` that detects action type from TG_OP and state transitions (draft→posted = COMMIT, posted→reversed = REVERSE, locked_at set = LOCK_PERIOD, is_closed set = CLOSE_PERIOD). Captures old_state/new_state as JSONB.
-
-AFTER triggers on: `journal_entries`, `journal_entry_lines`, `chart_of_accounts`, `document_attachments`, `fiscal_periods`, `company_settings`, `tax_codes`.
-
----
-
-## TypeScript Changes
-
-### Modified types in `types/index.ts`
-
-| Type | Change |
-|------|--------|
-| `JournalEntrySourceType` | Added `'storno' \| 'correction' \| 'import' \| 'system'` |
-| `JournalEntry` | Added `committed_at`, `reversed_by_id`, `reverses_id`, `correction_of_id` |
-| `JournalEntryLine` | Added `tax_code`, `cost_center`, `project` |
-| `CreateJournalEntryLineInput` | Added optional `tax_code`, `cost_center`, `project` |
-| `FiscalPeriod` | Added `locked_at`, `retention_expires_at` |
-| `BASAccount` | Added `sru_code` |
-
-### New types added to `types/index.ts`
-
-- `TaxCode` interface, `TaxCodeId` union type
-- `DocumentAttachment` interface, `DocumentUploadSource` type, `CreateDocumentAttachmentInput`
-- `AuditLogEntry` interface, `AuditAction` union type
-- `CostCenter` interface
-- `Project` interface
-- `VoucherGap` interface
-
----
-
-## New Service Files
-
-### `lib/core/audit/audit-service.ts`
-Read-only service (audit log is written by DB triggers):
-- `getAuditLog(userId, filters)` — paginated query with action/table/date filters
-- `getEntityHistory(userId, tableName, recordId)` — full mutation history of one record
-- `getCorrectionChain(userId, journalEntryId)` — traces original→storno→corrected via linked IDs
-
-### `lib/core/documents/document-service.ts`
-- `uploadDocument(userId, file, metadata)` — computes SHA-256 via Web Crypto, uploads to Supabase Storage, creates record
-- `createNewVersion(userId, originalId, file)` — creates new version, marks old as superseded (WORM)
-- `linkToJournalEntry(userId, documentId, journalEntryId)` — links document to entry
-- `verifyIntegrity(userId, documentId)` — re-downloads, re-hashes, compares to stored hash
-
-### `lib/core/tax/tax-code-service.ts`
-- `getTaxCodes(userId)` — returns user codes + system codes
-- `getTaxCodeByCode(userId, code)` — single lookup, user code takes precedence
-- `calculateMomsFromTaxCodes(userId, periodStart, periodEnd)` — sums journal lines by tax_code, maps to moms boxes via tax_codes table
-- `seedTaxCodes(userId)` — calls `seed_tax_codes_for_user` RPC
-
-### `lib/core/bookkeeping/storno-service.ts`
-- `correctEntry(userId, originalEntryId, correctedLines)` — 3-step correction:
- 1. Creates storno entry with swapped debits/credits, `source_type='storno'`, `reverses_id` set
- 2. Creates corrected entry with new data, `source_type='correction'`, `correction_of_id` set
- 3. Marks original as reversed with `reversed_by_id` set
- 4. Returns `{ reversal, corrected }`
-
----
-
-## Modified Existing Files
-
-### `lib/bookkeeping/engine.ts`
-
-- New `buildLineInserts()` helper that includes `tax_code`, `cost_center`, `project` in all line inserts
-- New `createDraftEntry(userId, input)` — inserts as draft with `voucher_number=0`, no commit
-- New `commitEntry(userId, entryId)` — assigns voucher number via `next_voucher_number` RPC, transitions to posted (DB triggers handle `committed_at` and balance validation)
-- Existing `createJournalEntry()` kept as convenience wrapper (create + immediate commit)
-- `reverseEntry()` rewritten: now sets `reverses_id` on the reversal entry, sets `reversed_by_id` on the original, uses `source_type='storno'`, preserves dimensions on reversed lines
-
-### `lib/reports/vat-declaration.ts`
-
-- Added `TaxCode` import
-- New `calculateVatDeclarationFromTaxCodes(userId, periodType, year, period)` — generates momsdeklaration by querying journal_entry_lines grouped by `tax_code`, then mapping via `tax_codes` table to moms boxes
-- Legacy `calculateVatDeclaration()` preserved for backward compatibility (invoice/transaction/receipt approach)
-
-### `lib/reports/sie-export.ts`
-
-- Now fetches `cost_centers` and `projects` tables
-- Outputs `#DIM 1 "Kostnadsställe"` and `#DIM 6 "Projekt"` dimension definitions
-- Outputs `#OBJEKT` records for each cost center and project
-- Outputs `#SRU` records from `chart_of_accounts.sru_code` after each `#KONTO`
-- `#TRANS` lines now include dimension object lists: `{1 "CC01" 6 "P01"}` when cost_center/project are set
-
----
-
-## Verification
-
-- `npx tsc --noEmit` passes with zero errors
diff --git a/dev_docs/base_architecture/PART2_IMPLEMENTATION.md b/dev_docs/base_architecture/PART2_IMPLEMENTATION.md
deleted file mode 100644
index e73bec43..00000000
--- a/dev_docs/base_architecture/PART2_IMPLEMENTATION.md
+++ /dev/null
@@ -1,198 +0,0 @@
-# Part 2: Period Management & Year-End Closing
-
-## Overview
-
-Part 2 implements **year-end closing (årsbokslut)** — the process that legally closes a fiscal year per Bokföringslagen. This includes period locking, closing entry generation, opening balance propagation, and the API surface to drive the workflow.
-
-**Depends on Part 1:** immutable ledger, audit trail, tax codes, document archive, period lock enforcement, retention protection.
-
----
-
-## What Was Built
-
-### Migration 19: Period Closing Metadata
-
-**File:** `supabase/migrations/20240101000019_period_closing.sql`
-
-Three new columns on `fiscal_periods`:
-
-| Column | Type | Purpose |
-|--------|------|---------|
-| `closing_entry_id` | `uuid FK → journal_entries` | Links to the year-end closing journal entry |
-| `opening_balance_entry_id` | `uuid FK → journal_entries` | Links to the opening balance entry in this period |
-| `previous_period_id` | `uuid FK → fiscal_periods` | Chain link to the prior period for validation |
-
-One new trigger:
-
-- **`enforce_opening_balance_immutability`** — Once `opening_balance_entry_id` or `closing_entry_id` are set, they cannot be changed. This prevents tampering with the closing chain after the fact.
-
----
-
-### TypeScript Types
-
-**File:** `types/index.ts`
-
-Extended `FiscalPeriod` with the three new nullable fields.
-
-New interfaces:
-
-| Interface | Purpose |
-|-----------|---------|
-| `YearEndValidation` | Result of readiness check: `ready`, `errors[]`, `warnings[]`, `draftCount`, `voucherGaps[]`, `trialBalanceBalanced` |
-| `YearEndPreview` | Preview of closing: `netResult`, `closingAccount` (2099/2010), `closingLines[]`, `resultAccountSummary[]` |
-| `YearEndResult` | Result of execution: `closingEntry`, `nextPeriod`, `openingBalanceEntry` |
-| `PeriodStatus` | Status summary: lock/close/draft/opening state |
-
----
-
-### Period Service
-
-**File:** `lib/core/bookkeeping/period-service.ts`
-
-| Function | What it does |
-|----------|-------------|
-| `lockPeriod(userId, fiscalPeriodId)` | Sets `locked_at = now()`. Validates period exists, belongs to user, isn't already locked/closed. After locking, the `enforce_period_lock` trigger (from Part 1) blocks new journal entries. |
-| `closePeriod(userId, fiscalPeriodId)` | Sets `is_closed = true, closed_at = now()`. Requires: already locked AND `closing_entry_id` is set. This is the final, permanent state. |
-| `createNextPeriod(userId, currentPeriodId)` | Creates the next fiscal year. Computes dates from the current period's length to handle **brutet räkenskapsår** (broken fiscal years, e.g. Jul–Jun). Sets `previous_period_id` for chain validation. Auto-generates name like "FY 2025" or "FY 2025/2026". |
-| `getPeriodStatus(userId, fiscalPeriodId)` | Returns a summary: `is_locked`, `is_closed`, `has_closing_entry`, `has_opening_balances`, `draft_count`, `next_period_exists`. |
-
----
-
-### Year-End Service
-
-**File:** `lib/core/bookkeeping/year-end-service.ts`
-
-This is the core new logic.
-
-#### `validateYearEndReadiness(userId, fiscalPeriodId)` → `YearEndValidation`
-
-Checks preconditions before allowing year-end closing:
-
-- **Blocking errors** (prevent closing):
- - Period already closed
- - Closing entry already exists
- - Draft journal entries exist (must be posted or deleted)
- - Trial balance is not balanced
-- **Warnings** (informational):
- - Voucher number gaps detected (via `detect_voucher_gaps()` SQL function)
- - No posted entries in the period
-
-#### `previewYearEndClosing(userId, fiscalPeriodId)` → `YearEndPreview`
-
-Generates a preview without persisting anything:
-
-1. Looks up `entity_type` from `company_settings` → determines closing account:
- - **Aktiebolag (AB):** account `2099` (Årets resultat)
- - **Enskild firma (EF):** account `2010` (Eget kapital)
-2. Runs income statement to get `net_result`
-3. Gets trial balance, filters to class 3–8 accounts
-4. For each account with a non-zero balance: creates a line that zeros it
-5. Adds a final balancing line to the closing account (2099/2010)
-6. Returns the preview with all lines and a summary of result accounts
-
-#### `executeYearEndClosing(userId, fiscalPeriodId)` → `YearEndResult`
-
-Full orchestration (the main entry point):
-
-```
-1. validateYearEndReadiness() → abort if errors
-2. previewYearEndClosing() → get closing lines
-3. createJournalEntry() → create closing entry (source_type: 'year_end')
-4. UPDATE fiscal_periods → set closing_entry_id
-5. lockPeriod() → lock the period
-6. closePeriod() → permanently close
-7. createNextPeriod() → create next fiscal year
-8. generateOpeningBalances() → carry forward class 1-2 balances
-9. Return { closingEntry, nextPeriod, openingBalanceEntry }
-```
-
-#### `generateOpeningBalances(userId, closedPeriodId, nextPeriodId)` → `JournalEntry`
-
-Creates opening balance entries in the new period:
-
-1. Gets trial balance of the closed period (after closing entry)
-2. Filters to balance sheet accounts (class 1–2) with non-zero closing balance
-3. Creates a journal entry with `source_type: 'opening_balance'`:
- - Debit accounts get debit opening, credit accounts get credit opening
-4. Verifies the entry is balanced (total debit = total credit)
-5. Sets `opening_balance_entry_id` and `opening_balances_set = true` on the next period
-
-**Key invariant:** UB (utgående balans) of year N == IB (ingående balans) of year N+1.
-
----
-
-### API Routes
-
-All follow the existing pattern: authenticate via Supabase, delegate to service, return JSON.
-
-| Method | Path | Handler |
-|--------|------|---------|
-| `POST` | `/api/bookkeeping/fiscal-periods/[id]/lock` | `lockPeriod()` |
-| `GET` | `/api/bookkeeping/fiscal-periods/[id]/year-end` | `validateYearEndReadiness()` + `previewYearEndClosing()` |
-| `POST` | `/api/bookkeeping/fiscal-periods/[id]/year-end` | `executeYearEndClosing()` |
-| `POST` | `/api/bookkeeping/fiscal-periods/[id]/close` | `closePeriod()` |
-
----
-
-## Reused Components
-
-| Component | From | Used by |
-|-----------|------|---------|
-| `generateTrialBalance()` | `lib/reports/trial-balance.ts` | Balance aggregation for closing + opening entries |
-| `generateIncomeStatement()` | `lib/reports/income-statement.ts` | Net result calculation |
-| `createJournalEntry()` | `lib/bookkeeping/engine.ts` | Creating closing + opening entries (auto-posts) |
-| `validateBalance()` | `lib/bookkeeping/engine.ts` | Pre-flight balance check |
-| `detect_voucher_gaps()` | Migration 16 SQL function | Gap validation during readiness check |
-| `enforce_period_lock` trigger | Migration 17 | Blocks writes after locking |
-| `enforce_journal_entry_immutability` trigger | Migration 17 | Protects closing/opening entries after posting |
-
----
-
-## Period Lifecycle Diagram
-
-```
- ┌─────────┐
- │ OPEN │ ← Journal entries can be posted
- └────┬────┘
- │ lockPeriod()
- ▼
- ┌─────────┐
- │ LOCKED │ ← No new entries (enforce_period_lock trigger)
- └────┬────┘
- │ closePeriod() (requires closing_entry_id)
- ▼
- ┌─────────┐
- │ CLOSED │ ← Permanent, immutable
- └─────────┘
-```
-
-The `executeYearEndClosing()` function drives the full flow from OPEN → CLOSED in one call, including creating the closing entry, locking, closing, creating the next period, and generating opening balances.
-
----
-
-## Verification Checklist
-
-- [x] `npx tsc --noEmit` — zero TypeScript errors
-- [ ] Migration 19 applies cleanly (`\d fiscal_periods` shows new columns)
-- [ ] `GET /api/bookkeeping/fiscal-periods/[id]/year-end` returns preview with net result
-- [ ] `POST /api/bookkeeping/fiscal-periods/[id]/year-end` creates closing entry, locks, closes, creates next period, generates opening balances
-- [ ] Closing entry zeros all class 3–8 accounts
-- [ ] Opening balance entry in next period matches UB of closed period (class 1–2 only)
-- [ ] Closed period rejects new journal entries (period lock trigger)
-- [ ] Period with draft entries → validation fails with blocking error
-- [ ] Period already closed → validation fails
-- [ ] EF entity type → closing goes to 2010 (not 2099)
-
----
-
-## Files Changed/Created
-
-| File | Action |
-|------|--------|
-| `supabase/migrations/20240101000019_period_closing.sql` | **Created** — 3 ALTER columns + 1 trigger |
-| `types/index.ts` | **Modified** — extended FiscalPeriod, added 4 new interfaces |
-| `lib/core/bookkeeping/period-service.ts` | **Created** — lockPeriod, closePeriod, createNextPeriod, getPeriodStatus |
-| `lib/core/bookkeeping/year-end-service.ts` | **Created** — validateYearEndReadiness, previewYearEndClosing, executeYearEndClosing, generateOpeningBalances |
-| `app/api/bookkeeping/fiscal-periods/[id]/lock/route.ts` | **Created** — POST lock endpoint |
-| `app/api/bookkeeping/fiscal-periods/[id]/year-end/route.ts` | **Created** — GET preview + POST execute |
-| `app/api/bookkeeping/fiscal-periods/[id]/close/route.ts` | **Created** — POST close endpoint |
diff --git a/dev_docs/base_architecture/PART3_IMPLEMENTATION.md b/dev_docs/base_architecture/PART3_IMPLEMENTATION.md
deleted file mode 100644
index 03d4ba42..00000000
--- a/dev_docs/base_architecture/PART3_IMPLEMENTATION.md
+++ /dev/null
@@ -1,235 +0,0 @@
-Part 3: Event Bus & Extension Registry — Implementation
-
-## What Was Built
-
-An in-process event bus, extension registry with static discovery, database tables for extension data and event observability, and event emission retrofitted into all existing service and API route code paths. Backend only, no UI.
-
-This is the foundation for all Tier 1 add-ons (receipt-ocr, ai-categorization, push-notifications, ne-bilaga, etc.). Without it, every add-on would need to be hardwired into core services.
-
----
-
-## New Files
-
-### Event Bus — `lib/events/`
-
-**`lib/events/types.ts`**
-
-Defines the `CoreEvent` discriminated union covering 18 event types across six domains:
-
-| Domain | Events |
-|--------|--------|
-| Bookkeeping | `journal_entry.drafted`, `journal_entry.committed`, `journal_entry.corrected` |
-| Documents | `document.uploaded` |
-| Invoicing | `invoice.created`, `invoice.sent`, `invoice.paid`, `invoice.overdue`, `credit_note.created` |
-| Banking | `transaction.synced`, `transaction.categorized`, `bank.statement_received`, `bank.payment_notification` |
-| Periods | `period.locked`, `period.year_closed` |
-| Customers | `customer.created`, `customer.pseudonymized` |
-| Audit | `audit.security_event` |
-
-Helper types for consuming events:
-
-- `CoreEventType` — string literal union of all event type names
-- `EventPayload` — extracts the payload type for a given event type
-- `EventHandler` — handler function signature for a specific event type
-- `EventSubscription` — event type + handler pair
-
-**`lib/events/bus.ts`**
-
-The event bus singleton. Key design:
-
-- `eventBus.on(eventType, handler)` — subscribe, returns unsubscribe function
-- `eventBus.emit(event)` — runs all handlers via `Promise.allSettled` (a failing handler never crashes the emitter)
-- `eventBus.clear()` — remove all handlers (for testing)
-- Handlers run concurrently, errors logged to console
-- Module-level singleton (persists across requests in same Node.js process)
-
-**`lib/events/index.ts`** — Barrel export.
-
-### Extension Registry — `lib/extensions/`
-
-**`lib/extensions/types.ts`**
-
-The `Extension` interface — the contract for all add-ons:
-
-```typescript
-interface Extension {
- id: string
- name: string
- version: string
-
- // Surfaces
- routes?: RouteDefinition[]
- apiRoutes?: ApiRouteDefinition[]
- sidebarItems?: SidebarItem[]
- eventHandlers?: ExtensionEventHandler[]
- mappingRuleTypes?: MappingRuleTypeDefinition[]
- reportTypes?: ReportDefinition[]
- settingsPanel?: SettingsPanelDefinition
- taxCodes?: TaxCodeDefinition[]
- dimensionTypes?: DimensionDefinition[]
-
- // Lifecycle
- onInstall?(ctx: ExtensionContext): Promise
- onUninstall?(ctx: ExtensionContext): Promise
-}
-```
-
-Supporting types: `RouteDefinition`, `ApiRouteDefinition`, `SidebarItem`, `ReportDefinition`, `SettingsPanelDefinition`, `TaxCodeDefinition`, `DimensionDefinition`, `MappingRuleTypeDefinition`, `ExtensionEventHandler`, `ExtensionContext`.
-
-**`lib/extensions/registry.ts`**
-
-The `extensionRegistry` singleton:
-
-- `register(extension)` — stores extension, wires event handlers to the bus
-- `unregister(extensionId)` — unhooks handlers, removes extension
-- `getAll()` — all registered extensions
-- `get(id)` — specific extension by ID
-- `getByCapability(key)` — extensions that have a specific surface (e.g. all extensions with `reportTypes`)
-- `clear()` — remove all (for testing)
-
-**`lib/extensions/loader.ts`**
-
-Static extension discovery. Next.js bundling requires explicit imports, not dynamic filesystem scanning. Contains an empty `FIRST_PARTY_EXTENSIONS` array — extensions are added here as they are built. `loadExtensions()` has an idempotency guard.
-
-**`lib/extensions/index.ts`** — Barrel export.
-
-### Initialization — `lib/init.ts`
-
-`ensureInitialized()` — calls `loadExtensions()` once. Called from API routes that emit events (at module scope, not per-request).
-
-### Example Extension — `extensions/example-logger/index.ts`
-
-Minimal reference implementation that logs `journal_entry.committed` and `document.uploaded` events to console. Not wired into the loader by default — exists as a template for building real extensions.
-
----
-
-## Migration
-
-**`supabase/migrations/20240101000020_extension_data.sql`**
-
-Two tables:
-
-**`extension_data`** — generic key-value store for extensions:
-- Columns: `id`, `user_id`, `extension_id`, `key`, `value` (jsonb), `created_at`, `updated_at`
-- `UNIQUE(user_id, extension_id, key)`
-- RLS: select, insert, update, delete own rows
-- Auto-update `updated_at` trigger
-
-**`event_log`** — append-only event observability:
-- Columns: `id`, `user_id`, `event_type`, `payload` (jsonb), `created_at`
-- RLS: select + insert only (no update, no delete — append-only)
-- Indexes on `(user_id, event_type)` and `created_at`
-
----
-
-## Type Additions — `types/index.ts`
-
-Placeholder types for event payloads not yet fully built:
-
-| Type | Purpose |
-|------|---------|
-| `CreditNote` | Extends `Invoice` with required `credited_invoice_id` |
-| `CAMT053Statement` | Bank statement (CAMT parsing not yet implemented) |
-| `CAMT054Notification` | Payment notification (CAMT parsing not yet implemented) |
-| `AuditSecurityEvent` | Security event payload for audit events |
-| `ExtensionDataRecord` | Row type for the `extension_data` table |
-
----
-
-## Retrofitted Event Emissions
-
-The pattern is identical everywhere: import `eventBus`, call `await eventBus.emit(...)` after the successful operation. No control flow changes, no return type changes. All events include a `userId` field for RLS-scoped observability.
-
-### Phase A — Service Layer
-
-| File | Function | Event |
-|------|----------|-------|
-| `lib/bookkeeping/engine.ts` | `createDraftEntry()` | `journal_entry.drafted` |
-| `lib/bookkeeping/engine.ts` | `commitEntry()` | `journal_entry.committed` |
-| `lib/bookkeeping/engine.ts` | `createJournalEntry()` | `journal_entry.committed` |
-| `lib/bookkeeping/engine.ts` | `reverseEntry()` | `journal_entry.committed` |
-| `lib/core/bookkeeping/storno-service.ts` | `correctEntry()` | `journal_entry.corrected` |
-| `lib/core/documents/document-service.ts` | `uploadDocument()` | `document.uploaded` |
-| `lib/core/bookkeeping/period-service.ts` | `lockPeriod()` | `period.locked` |
-| `lib/core/bookkeeping/year-end-service.ts` | `executeYearEndClosing()` | `period.year_closed` |
-
-### Phase B — API Routes
-
-| File | Event |
-|------|-------|
-| `app/api/invoices/route.ts` (POST) | `invoice.created` |
-| `app/api/invoices/route.ts` (createCreditNote) | `credit_note.created` |
-| `app/api/invoices/[id]/send/route.ts` | `invoice.sent` |
-| `app/api/customers/route.ts` (POST) | `customer.created` |
-| `app/api/transactions/[id]/categorize/route.ts` | `transaction.categorized` |
-| `app/api/banking/sync/route.ts` | `transaction.synced` |
-
-API routes also call `ensureInitialized()` at module scope to ensure extensions are loaded before events are emitted.
-
-### Deferred (Phase C)
-
-These events are defined in the type system but not yet emitted because the underlying infrastructure doesn't exist:
-
-| Event | Reason |
-|-------|--------|
-| `invoice.paid` | Payment matching with kursdifferens not fully wired |
-| `invoice.overdue` | Needs cron-based detection |
-| `bank.statement_received` | CAMT053 parsing not implemented |
-| `bank.payment_notification` | CAMT054 parsing not implemented |
-| `customer.pseudonymized` | GDPR flow not implemented |
-| `audit.security_event` | Already logged at DB level; app-level TBD |
-
----
-
-## Design Decisions
-
-1. **In-process bus** — architecture specifies "in-process handlers initially, add webhook dispatch when external plugin consumers exist." No message queue, no outbox pattern at the event bus level.
-
-2. **`Promise.allSettled`** — a failing handler never crashes the emitting service. Errors are logged to console. The emitter's control flow is never affected.
-
-3. **Module-level singletons** — `eventBus` and `extensionRegistry` persist across requests in the same Node.js process. They are not per-request or per-user.
-
-4. **Static extension imports** — Next.js bundling requires explicit imports in `loader.ts`, not dynamic `fs.readdirSync`. Extensions are added to the `FIRST_PARTY_EXTENSIONS` array as they are built.
-
-5. **One-way dependency** — `lib/events/` depends on nothing except `types/`. Core services import from `lib/events/`. Extensions import from `lib/core/`, `lib/events/`, and `lib/extensions/`. The base never imports from `extensions/`.
-
-6. **`ensureInitialized()` at module scope** — API routes call this at the top of the file (not inside request handlers). This means extensions are loaded once when the module is first imported by Next.js, not on every request.
-
-7. **Every event payload includes `userId`** — enables RLS-scoped event logging and per-user extension behavior without needing to pass auth context through the bus.
-
----
-
-## How to Build an Extension
-
-1. Create a directory under `extensions/your-extension/`
-2. Export an object satisfying the `Extension` interface
-3. Import it in `lib/extensions/loader.ts` and add to `FIRST_PARTY_EXTENSIONS`
-
-Example (see `extensions/example-logger/index.ts`):
-
-```typescript
-import type { Extension } from '@/lib/extensions/types'
-import type { EventPayload } from '@/lib/events/types'
-
-export const myExtension: Extension = {
- id: 'my-extension',
- name: 'My Extension',
- version: '0.1.0',
- eventHandlers: [
- {
- eventType: 'journal_entry.committed',
- handler: async (payload: EventPayload<'journal_entry.committed'>) => {
- // Your logic here
- },
- },
- ],
-}
-```
-
----
-
-## Verification
-
-- `npx tsc --noEmit` — zero errors
-- All existing API routes unchanged in behavior — event emission is additive, never blocking
-- Extension system is fully wired but dormant (empty extension list) until extensions are added to the loader
diff --git a/dev_docs/base_architecture/PART4_YEAR_END_UI.md b/dev_docs/base_architecture/PART4_YEAR_END_UI.md
deleted file mode 100644
index d67dfa66..00000000
--- a/dev_docs/base_architecture/PART4_YEAR_END_UI.md
+++ /dev/null
@@ -1,251 +0,0 @@
-# Part 4: Year-End Closing UI (Årsbokslut)
-
-## Overview
-
-Part 4 implements the **user interface for year-end closing** — a 4-step wizard that guides the user through validating, previewing, and executing the annual closing per Bokföringslagen. This is a pure frontend implementation; all backend services, API routes, and database migrations were completed in Part 2.
-
-**Depends on Part 2:** period-service, year-end-service, fiscal period API routes (`GET`/`POST` at `/api/bookkeeping/fiscal-periods/[id]/year-end`).
-
----
-
-## What Was Built
-
-### Year-End Wizard Page
-
-**File:** `app/(dashboard)/bookkeeping/year-end/page.tsx`
-
-A single `'use client'` page containing a 4-step wizard at route `/bookkeeping/year-end`. The wizard maps directly to the existing API surface:
-
-| Step | Label | API Call | Purpose |
-|------|-------|----------|---------|
-| 0 | Välj period | `GET /api/bookkeeping/fiscal-periods` | Select which fiscal period to close |
-| 1 | Validering | `GET /api/bookkeeping/fiscal-periods/[id]/year-end` | Check readiness (errors + warnings) |
-| 2 | Förhandsgranskning | *(uses data from step 1)* | Review closing entry before committing |
-| 3 | Genomför | `POST /api/bookkeeping/fiscal-periods/[id]/year-end` | Execute with confirmation dialog |
-
-#### Step 0: Period Selection
-
-- Fetches all fiscal periods on mount
-- Pre-selects the first open (non-closed) period
-- Displays each period as a selectable card with:
- - Period name and date range (`period_start – period_end`)
- - Status badge: **Öppen** (default), **Låst** (outline), **Stängd** (secondary, disabled)
-- Closed periods are visually dimmed and not selectable
-
-#### Step 1: Validation
-
-- Calls `GET /api/bookkeeping/fiscal-periods/[id]/year-end` which returns `{ validation, preview }` from parallel `validateYearEndReadiness()` + `previewYearEndClosing()`
-- Displays a ready/not-ready banner:
- - Green `CheckCircle2` + "Perioden är redo för årsbokslut" when `validation.ready === true`
- - Red `AlertCircle` + "Perioden kan inte stängas ännu" when `validation.ready === false`
-- **Blocking errors** (red): draft entries, unbalanced trial balance, already closed, closing entry exists
-- **Warnings** (amber): voucher number gaps, no posted entries
-- Detail cards showing draft count and trial balance status
-- Voucher gap badges when gaps exist
-- "Validera igen" button to re-run checks after fixing issues
-- "Nästa" button gated on `validation.ready === true`
-
-#### Step 2: Preview
-
-Three cards displaying the preview data:
-
-1. **Net result highlight** — Large centered number with color coding (green for profit, red for loss), closing account label (e.g. "2099 — Årets resultat")
-2. **Result account summary** — Table of class 3–8 accounts being zeroed (account number, name, amount)
-3. **Closing journal lines** — Expandable/collapsible table showing the full closing entry (account, description, debit, credit) with a totals row
-
-#### Step 3: Execute
-
-Pre-execution state:
-- Summary of actions: closing entry creation, period lock + close, next period + opening balances
-- Irreversibility warning banner (amber) referencing Bokföringslagen
-- "Genomför årsbokslut" button (destructive variant) opens a confirmation dialog
-
-Confirmation dialog (`Dialog` component):
-- Repeats period name and net result
-- "Avbryt" and "Stäng perioden" (destructive) buttons
-
-Post-execution success state:
-- `SuccessAnimation` overlay with celebration variant
-- Summary card showing: closing entry link, closed period badge, new period name, opening balances status
-- "Tillbaka till bokföring" navigation
-
----
-
-### Bookkeeping Page Link
-
-**File:** `app/(dashboard)/bookkeeping/page.tsx`
-
-Added a header action button linking to the year-end wizard:
-
-```tsx
-
-```
-
-The header was restructured from a plain `
` to a `flex items-center justify-between` layout to accommodate the button alongside the existing title and description.
-
----
-
-## User Flow Diagram
-
-```
-/bookkeeping
- │
- │ Click "Årsbokslut" button
- ▼
-┌─────────────────────────────────────────────────────┐
-│ Step 0: Välj period │
-│ ┌───────────────────────────────────┐ │
-│ │ FY 2024 (2024-01-01 – 2024-12-31) │ [Öppen] │
-│ └───────────────────────────────────┘ │
-│ ┌───────────────────────────────────┐ │
-│ │ FY 2023 (2023-01-01 – 2023-12-31) │ [Stängd] │
-│ └───────────────────────────────────┘ │
-│ [Nästa →] │
-└────────────────────────┬────────────────────────────┘
- │
- GET /api/bookkeeping/fiscal-periods/[id]/year-end
- │
- ▼
-┌─────────────────────────────────────────────────────┐
-│ Step 1: Validering │
-│ ✅ Perioden är redo för årsbokslut │
-│ ─ or ─ │
-│ ❌ 3 draft entries must be posted │
-│ ⚠️ Voucher gaps: 5–7 │
-│ │
-│ [← Tillbaka] [Validera igen] [Nästa →] │
-└────────────────────────┬────────────────────────────┘
- │
- ▼
-┌─────────────────────────────────────────────────────┐
-│ Step 2: Förhandsgranskning │
-│ │
-│ Årets resultat: 150 000,00 kr │
-│ Bokförs på 2099 — Årets resultat │
-│ │
-│ ┌─ Resultatkonton som nollställs ────────────────┐ │
-│ │ 3001 Tjänsteintäkter -500 000,00 │ │
-│ │ 5010 Lokalhyra 200 000,00 │ │
-│ │ 6570 Bankavgifter 150 000,00 │ │
-│ └────────────────────────────────────────────────┘ │
-│ │
-│ [← Tillbaka] [Nästa →] │
-└────────────────────────┬────────────────────────────┘
- │
- ▼
-┌─────────────────────────────────────────────────────┐
-│ Step 3: Genomför │
-│ │
-│ ⚠️ Denna åtgärd kan inte ångras │
-│ │
-│ [← Tillbaka] [Genomför årsbokslut] │
-│ │ │
-│ ┌─────────▼──────────┐ │
-│ │ Bekräfta årsbokslut │ │
-│ │ Stäng FY 2024? │ │
-│ │ │ │
-│ │ [Avbryt] [Stäng] │ │
-│ └─────────┬──────────┘ │
-│ │ │
-│ POST /api/.../year-end │
-│ │ │
-│ ▼ │
-│ ✅ Årsbokslutet är genomfört │
-│ • Bokslutsverifikation [Visa] │
-│ • Period stängd [Stängd] │
-│ • Nytt räkenskapsår FY 2025 │
-│ • Ingående balanser [Skapade] │
-│ │
-│ [← Tillbaka till bokföring] │
-└─────────────────────────────────────────────────────┘
-```
-
----
-
-## State Management
-
-All state is local to the page component via `useState`:
-
-| State | Type | Purpose |
-|-------|------|---------|
-| `step` | `number` (0–3) | Current wizard step |
-| `periods` | `FiscalPeriod[]` | All fiscal periods from API |
-| `selectedPeriodId` | `string` | Currently selected period |
-| `validation` | `YearEndValidation \| null` | Validation result from API |
-| `preview` | `YearEndPreview \| null` | Preview result from API |
-| `result` | `YearEndResult \| null` | Execution result from API |
-| `loading` | `boolean` | Loading state for validation fetch |
-| `loadingPeriods` | `boolean` | Loading state for periods fetch |
-| `executing` | `boolean` | Loading state for POST execution |
-| `error` | `string \| null` | Error message banner |
-| `showConfirmDialog` | `boolean` | Confirmation dialog visibility |
-| `showLinesDetail` | `boolean` | Expandable closing lines table |
-| `showSuccess` | `boolean` | Success animation overlay |
-
----
-
-## Reused Components
-
-| Component | From | Used for |
-|-----------|------|----------|
-| `Card`, `CardContent`, `CardHeader`, `CardTitle` | `components/ui/card.tsx` | All step containers |
-| `Button` | `components/ui/button.tsx` | Navigation, actions, links |
-| `Badge` | `components/ui/badge.tsx` | Period status, voucher gaps, success indicators |
-| `Table`, `TableBody`, `TableCell`, `TableHead`, `TableHeader`, `TableRow` | `components/ui/table.tsx` | Result accounts + closing lines |
-| `Dialog`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogDescription`, `DialogFooter` | `components/ui/dialog.tsx` | Execution confirmation |
-| `Skeleton` | `components/ui/skeleton.tsx` | Loading states |
-| `SuccessAnimation` | `components/ui/success-animation.tsx` | Post-execution celebration overlay |
-| `useToast` | `components/ui/use-toast.tsx` | Error notifications |
-| `formatAmount()` | Inline helper (same pattern as `reports/page.tsx`) | Swedish locale number formatting |
-
-Lucide icons used: `CheckCircle2`, `AlertCircle`, `AlertTriangle`, `ArrowLeft`, `ArrowRight`, `Loader2`, `Lock`, `BookOpen`, `ChevronDown`, `ChevronUp`.
-
----
-
-## API Endpoints Used
-
-No new API routes were created. The wizard consumes existing endpoints from Part 2:
-
-| Method | Path | Response | Used in step |
-|--------|------|----------|--------------|
-| `GET` | `/api/bookkeeping/fiscal-periods` | `{ data: FiscalPeriod[] }` | 0 (period list) |
-| `GET` | `/api/bookkeeping/fiscal-periods/[id]/year-end` | `{ data: { validation: YearEndValidation, preview: YearEndPreview } }` | 1 + 2 (validation + preview) |
-| `POST` | `/api/bookkeeping/fiscal-periods/[id]/year-end` | `{ data: YearEndResult }` | 3 (execution) |
-
----
-
-## Files Changed/Created
-
-| File | Action |
-|------|--------|
-| `app/(dashboard)/bookkeeping/year-end/page.tsx` | **Created** — 4-step year-end closing wizard (700 lines) |
-| `app/(dashboard)/bookkeeping/page.tsx` | **Modified** — Added "Årsbokslut" link button in header, restructured header layout |
-
-**No new API routes.** No backend changes. No new dependencies. No database migrations.
-
----
-
-## Verification Checklist
-
-- [x] `npx tsc --noEmit` — zero TypeScript errors
-- [x] `npm run build` — builds clean, `/bookkeeping/year-end` route registered
-- [x] `npx vitest run` — all 78 existing tests pass
-- [ ] Navigate to `/bookkeeping` → "Årsbokslut" button visible in header
-- [ ] Click "Årsbokslut" → wizard loads at step 0 with period selector
-- [ ] Closed periods appear dimmed and cannot be selected
-- [ ] Select open period → "Nästa" → validation step loads with skeleton, then shows results
-- [ ] Period with draft entries → red error "X draft journal entries must be posted or deleted"
-- [ ] Period with unbalanced trial balance → red error "Trial balance is not balanced"
-- [ ] Period with voucher gaps → amber warning with gap badges
-- [ ] Fully valid period → green "Perioden är redo för årsbokslut", "Nästa" enabled
-- [ ] Preview step → net result displayed with correct color, result accounts table, expandable closing lines
-- [ ] EF entity type → closing account shows "2010 — Eget kapital"
-- [ ] AB entity type → closing account shows "2099 — Årets resultat"
-- [ ] Execute step → irreversibility warning shown, "Genomför årsbokslut" opens confirmation dialog
-- [ ] Confirmation dialog → "Stäng perioden" triggers POST, success animation + summary displayed
-- [ ] Success state → shows new period name, closing entry link, opening balances badge
diff --git a/dev_docs/base_architecture/PUSH-NOTIFICATIONS-EXTENSION.md b/dev_docs/base_architecture/PUSH-NOTIFICATIONS-EXTENSION.md
deleted file mode 100644
index 35750205..00000000
--- a/dev_docs/base_architecture/PUSH-NOTIFICATIONS-EXTENSION.md
+++ /dev/null
@@ -1,312 +0,0 @@
-# Push Notifications Extension
-
-## Overview
-
-The `push-notifications` extension converts system events into instant push notifications delivered via the Web Push API. It is the third first-party extension, following `receipt-ocr` and `ai-categorization`.
-
-The extension operates in two modes:
-
-1. **Event-driven** — Instant notifications triggered by the event bus (`period.locked`, `receipt.matched`, etc.)
-2. **Cron-based** — Scheduled checks for time-dependent conditions (upcoming tax deadlines, overdue invoices)
-
-Both modes share a single send pipeline that handles settings checks, quiet hours, duplicate prevention, delivery, logging, and subscription cleanup.
-
----
-
-## Architecture
-
-```
- Event Bus
- |
- +---------+---------+
- | |
- period.locked receipt.matched
- invoice.sent receipt.extracted
- period.year_closed
- | |
- v v
- +-----------------------------+
- | Event Handlers (index.ts) |
- | gate: check setting |
- | build: payload-builders |
- +-------------+---------------+
- |
- v
- +-----------------------------+ +---------------------------+
- | sendNotificationToUser() | <---- | Cron Scheduler |
- | (notification-sender.ts) | | (notification-scheduler) |
- | | | tax deadlines, invoices |
- | 1. push_enabled? | +---------------------------+
- | 2. quiet hours? |
- | 3. duplicate? |
- | 4. get subscriptions |
- | 5. web-push send |
- | 6. log to notification_log |
- | 7. disable 410 subs |
- +-----------------------------+
-```
-
-### File Structure
-
-```
-extensions/push-notifications/
- index.ts # Extension object, settings, 5 event handlers
- notification-sender.ts # Unified send pipeline, VAPID config, helpers
- payload-builders.ts # All notification payload constructors
- notification-scheduler.ts # Cron-based tax deadline & invoice scheduling
-
-app/api/extensions/push-notifications/
- settings/route.ts # GET/PATCH settings API
- cron/route.ts # Daily cron (imports from extension)
- subscribe/route.ts # Subscription management (imports VAPID from extension)
-```
-
----
-
-## Event Subscriptions
-
-| Event | Handler | Default Enabled | Notification Content |
-|-------|---------|-----------------|---------------------|
-| `period.locked` | `handlePeriodLocked` | Yes | "{period.name} har lasts" |
-| `period.year_closed` | `handleYearClosed` | Yes | "Arsbokslut klart for {period.name}" |
-| `invoice.sent` | `handleInvoiceSent` | No | "Faktura {number} skickad" |
-| `receipt.extracted` | `handleReceiptExtracted` | Yes | "Kvitto analyserat: {merchant}" |
-| `receipt.matched` | `handleReceiptMatched` | Yes | "Kvitto matchat mot transaktion" |
-
-Each event handler follows the **gate pattern**:
-1. Extract `userId` from event payload
-2. Load extension settings from `extension_data`
-3. Check if the specific notification type is enabled
-4. Build the payload via `payload-builders.ts`
-5. Call `sendNotificationToUser()` from the sender module
-
----
-
-## Cron Scheduling
-
-The cron endpoint (`GET /api/extensions/push-notifications/cron`) runs daily at 09:00 via Vercel Cron and handles two time-dependent notification types:
-
-### Tax Deadlines
-Queries the `deadlines` table for uncompleted tax deadlines due in 7 days, 1 day, or today. Checks the user-level `tax_deadlines_enabled` setting in `notification_settings` before sending.
-
-### Invoice Reminders
-Queries the `invoices` table for sent/overdue invoices due in 3 days, today, or overdue by 3/7 days. Checks the user-level `invoice_reminders_enabled` setting before sending.
-
-Both call `sendNotificationToUser()` which handles the full pipeline (quiet hours, duplicate check, send, log).
-
----
-
-## Settings
-
-### Extension Settings (event-driven toggles)
-
-Stored in the `extension_data` table under `extension_id = 'push-notifications'`, `key = 'settings'`.
-
-```typescript
-interface PushNotificationSettings {
- periodLockedEnabled: boolean // default: true
- periodYearClosedEnabled: boolean // default: true
- invoiceSentEnabled: boolean // default: false
- receiptExtractedEnabled: boolean // default: true
- receiptMatchedEnabled: boolean // default: true
-}
-```
-
-### First-Party Settings (existing tables)
-
-The `notification_settings` table controls transport-level and category-level preferences:
-
-| Column | Type | Purpose |
-|--------|------|---------|
-| `push_enabled` | boolean | Master push toggle |
-| `tax_deadlines_enabled` | boolean | Cron: tax deadline notifications |
-| `invoice_reminders_enabled` | boolean | Cron: invoice due/overdue |
-| `quiet_start` | text | Quiet hours start (e.g., "21:00") |
-| `quiet_end` | text | Quiet hours end (e.g., "08:00") |
-
-Both layers are checked before sending. Extension settings gate event-driven notifications; `notification_settings` gates the transport and cron-based categories.
-
----
-
-## API
-
-### GET /api/extensions/push-notifications/settings
-
-Returns the current user's event-driven notification toggles.
-
-**Response 200:**
-```json
-{
- "data": {
- "periodLockedEnabled": true,
- "periodYearClosedEnabled": true,
- "invoiceSentEnabled": false,
- "receiptExtractedEnabled": true,
- "receiptMatchedEnabled": true
- }
-}
-```
-
-**Response 401:** `{ "error": "Unauthorized" }`
-
-### PATCH /api/extensions/push-notifications/settings
-
-Updates one or more event-driven notification toggles. Only the provided keys are updated; others remain unchanged.
-
-**Request:**
-```json
-{
- "receiptExtractedEnabled": false,
- "invoiceSentEnabled": true
-}
-```
-
-**Response 200:**
-```json
-{
- "data": {
- "periodLockedEnabled": true,
- "periodYearClosedEnabled": true,
- "invoiceSentEnabled": true,
- "receiptExtractedEnabled": false,
- "receiptMatchedEnabled": true
- }
-}
-```
-
-**Response 400:** `{ "error": "No valid settings provided" }`
-
-**Response 401:** `{ "error": "Unauthorized" }`
-
-**Allowed keys:** `periodLockedEnabled`, `periodYearClosedEnabled`, `invoiceSentEnabled`, `receiptExtractedEnabled`, `receiptMatchedEnabled`
-
----
-
-## Notification Types
-
-The `NotificationType` union is defined in `extensions/push-notifications/types.ts` (re-exported from `types/index.ts` for convenience):
-
-| Type | Source | Description |
-|------|--------|-------------|
-| `tax_deadline` | Cron | Upcoming tax deadline |
-| `invoice_due` | Cron | Invoice approaching due date |
-| `invoice_overdue` | Cron | Invoice past due date |
-| `period_locked` | Event | Fiscal period was locked |
-| `period_year_closed` | Event | Year-end closing completed |
-| `receipt_extracted` | Event | Receipt OCR completed |
-| `receipt_matched` | Event | Receipt matched to transaction |
-| `invoice_sent` | Event | Invoice was sent |
-
-These are stored as text in `notification_log.notification_type` (no migration needed).
-
----
-
-## Database Tables Used
-
-No new tables or migrations were required. The extension uses existing tables:
-
-| Table | Usage |
-|-------|-------|
-| `push_subscriptions` | User's active Web Push subscriptions |
-| `notification_settings` | Transport-level and category-level preferences |
-| `notification_log` | Sent notification history (duplicate prevention) |
-| `extension_data` | Event-driven toggle settings |
-| `deadlines` | Tax deadline queries (cron) |
-| `invoices` | Invoice due/overdue queries (cron) |
-
----
-
-## Send Pipeline
-
-`sendNotificationToUser(supabase, userId, payload, notificationType, referenceId, daysBefore?)` executes the following steps:
-
-1. **Settings check** — Load `notification_settings` for the user. If `push_enabled` is false, skip.
-2. **Quiet hours** — Convert current time to Sweden timezone (`Europe/Stockholm`). If within the user's quiet hours window, skip.
-3. **Duplicate check** — Query `notification_log` for a matching `(user_id, notification_type, reference_id, days_before)` tuple. If found, skip.
-4. **Get subscriptions** — Fetch all active push subscriptions from `push_subscriptions`. If none, skip.
-5. **Send** — Deliver via the `web-push` library to all subscriptions using `Promise.allSettled`.
-6. **Log** — Insert a record into `notification_log` with `delivery_status: 'sent'`.
-7. **Cleanup** — Any subscription returning HTTP 410 (Gone) is marked `is_active: false`.
-
-Returns `{ sent: boolean, reason?: string }` where reason can be: `push_disabled`, `quiet_hours`, `duplicate`, `no_subscriptions`, `send_failed`, or `error`.
-
----
-
-## Registration
-
-The extension is registered in `lib/extensions/loader.ts` alongside the other first-party extensions:
-
-```typescript
-const FIRST_PARTY_EXTENSIONS: Extension[] = [
- receiptOcrExtension,
- aiCategorizationExtension,
- pushNotificationsExtension,
-]
-```
-
-When `loadExtensions()` is called, the registry wires up all 5 event handlers to the event bus.
-
----
-
-## Refactoring Notes
-
-### Phase 1: Logic extraction (original)
-
-The following files were deleted. All logic was moved into the extension:
-
-| Deleted File | Logic Moved To |
-|-------------|----------------|
-| `lib/push/web-push.ts` | `extensions/push-notifications/notification-sender.ts` (VAPID config, send functions, types) + `extensions/push-notifications/payload-builders.ts` (payload constructors) |
-| `lib/push/notification-scheduler.ts` | `extensions/push-notifications/notification-scheduler.ts` (cron scheduling) + `extensions/push-notifications/notification-sender.ts` (quiet hours, duplicate check, logging, subscription management) |
-
-### Phase 2: Route relocation
-
-The API routes were moved from `app/api/push/` into the extension namespace to enforce the architecture rule that the core never depends on extension code:
-
-| Old Path | New Path |
-|----------|----------|
-| `app/api/push/cron/route.ts` | `app/api/extensions/push-notifications/cron/route.ts` |
-| `app/api/push/subscribe/route.ts` | `app/api/extensions/push-notifications/subscribe/route.ts` |
-
-Updated consumers:
-- `components/push/PushPrompt.tsx` — fetch URLs updated to `/api/extensions/push-notifications/subscribe`
-- `components/settings/NotificationSettings.tsx` — fetch URLs updated to `/api/extensions/push-notifications/subscribe`
-- `vercel.json` — cron path updated to `/api/extensions/push-notifications/cron`
-
-### Phase 3: Type extraction
-
-Push notification types (`PushSubscription`, `NotificationSettings`, `NotificationType`, `NotificationLog`) were moved from `types/index.ts` to `extensions/push-notifications/types.ts`. Re-exports in `types/index.ts` preserve backward compatibility.
-
----
-
-## Environment Variables
-
-The extension requires the following environment variables (unchanged from before):
-
-| Variable | Purpose |
-|----------|---------|
-| `NEXT_PUBLIC_VAPID_PUBLIC_KEY` | VAPID public key for client-side subscription |
-| `VAPID_PRIVATE_KEY` | VAPID private key for server-side sending |
-| `VAPID_SUBJECT` | VAPID subject (defaults to `mailto:support@erp-base.se`) |
-| `CRON_SECRET` | Secret for authenticating cron requests |
-| `NEXT_PUBLIC_SUPABASE_URL` | Supabase project URL (used by cron service client) |
-| `SUPABASE_SERVICE_ROLE_KEY` | Supabase service role key (used by cron service client) |
-
----
-
-## Testing
-
-### Automated
-- `npx tsc --noEmit` — Zero TypeScript errors
-- `npx vitest run` — All 78 existing tests pass
-
-### Manual Verification
-
-1. **Period locked** — Lock a period via the UI. If the user has an active push subscription and `periodLockedEnabled` is true, they receive a push notification.
-2. **Receipt extracted** — Upload a receipt image. After OCR completes, the `receipt.extracted` event fires and triggers a push notification.
-3. **Receipt matched** — When a receipt is auto-matched to a transaction, the `receipt.matched` event triggers a push notification.
-4. **Invoice sent** — Send an invoice. If `invoiceSentEnabled` is true (default: false), a push notification is sent.
-5. **Year closed** — Complete a year-end closing. The `period.year_closed` event triggers a push notification.
-6. **Settings API** — `GET /api/extensions/push-notifications/settings` returns default settings. `PATCH` with `{ "receiptExtractedEnabled": false }` disables that specific notification type.
-7. **Cron** — `GET /api/extensions/push-notifications/cron` (with Bearer token) runs the tax deadline and invoice reminder checks using the extension's scheduler module.
-8. **Disable toggle** — Set `receiptExtractedEnabled: false` via PATCH, then upload a receipt. No push notification should be sent for the extraction event.
diff --git a/dev_docs/base_architecture/RECEIPT_OCR_EXTENSION.md b/dev_docs/base_architecture/RECEIPT_OCR_EXTENSION.md
deleted file mode 100644
index d6af3edb..00000000
--- a/dev_docs/base_architecture/RECEIPT_OCR_EXTENSION.md
+++ /dev/null
@@ -1,260 +0,0 @@
-# Receipt-OCR Extension — Implementation Summary
-
-This document describes the receipt-ocr extension: the first real extension built on the Part 3 event bus and extension registry infrastructure. It bridges the document archive to the receipt pipeline via events and establishes the canonical pattern for all future extensions.
-
----
-
-## Problem
-
-Receipt-OCR functionality existed as built-in code (`lib/receipts/`, `app/api/receipts/`), but was disconnected from the event system:
-
-- Uploading a document via the archive did not trigger OCR
-- New bank transactions did not auto-match to receipts
-- No domain events were emitted when receipts were extracted, matched, or confirmed
-
-The event bus and extension registry (Part 3) were built but had zero real extensions using them.
-
-## Solution
-
-A `receipt-ocr` extension that:
-
-1. Listens to `document.uploaded` events and auto-triggers OCR on images
-2. Listens to `transaction.synced` events and auto-matches receipts to new transactions
-3. Emits its own domain events (`receipt.extracted`, `receipt.matched`, `receipt.confirmed`) so downstream extensions can react
-
-**Principle followed:** Services = reusable logic in `lib/`. Extensions = event-driven glue. API routes = HTTP interface.
-
----
-
-## Files Changed
-
-### New files
-
-| File | Purpose |
-|------|---------|
-| `extensions/receipt-ocr/index.ts` | The extension: settings, event handlers, extension object |
-| `app/api/extensions/receipt-ocr/settings/route.ts` | GET/PATCH API for per-user extension settings |
-
-### Modified files
-
-| File | Change |
-|------|--------|
-| `lib/events/types.ts` | Added `Receipt` import and 3 new events to `CoreEvent` union |
-| `lib/extensions/loader.ts` | Imported and registered `receiptOcrExtension` |
-| `app/api/receipts/upload/route.ts` | Emits `receipt.extracted` after successful OCR |
-| `app/api/receipts/[id]/match/route.ts` | Emits `receipt.matched` after manual match; upgraded selects to fetch full objects |
-| `app/api/receipts/[id]/confirm/route.ts` | Emits `receipt.confirmed` with computed business/private totals |
-
----
-
-## New Events
-
-Three events were added to `lib/events/types.ts`:
-
-### `receipt.extracted`
-
-Fires when OCR extraction completes on a receipt image, whether via the direct upload path or the document archive path.
-
-```typescript
-{ type: 'receipt.extracted'; payload: {
- receipt: Receipt;
- documentId: string | null; // null when from direct upload path
- confidence: number;
- userId: string;
-}}
-```
-
-### `receipt.matched`
-
-Fires when a receipt is linked to a bank transaction, whether by user manual action or extension auto-match.
-
-```typescript
-{ type: 'receipt.matched'; payload: {
- receipt: Receipt;
- transaction: Transaction;
- confidence: number;
- autoMatched: boolean; // true = extension, false = user manual
- userId: string;
-}}
-```
-
-### `receipt.confirmed`
-
-Fires when a user confirms line item classifications (business vs private).
-
-```typescript
-{ type: 'receipt.confirmed'; payload: {
- receipt: Receipt;
- businessTotal: number;
- privateTotal: number;
- userId: string;
-}}
-```
-
----
-
-## Event Retrofitting
-
-Existing API routes were retrofitted to emit events after their success paths. Each route received:
-
-- `import { eventBus } from '@/lib/events/bus'`
-- `import { ensureInitialized } from '@/lib/init'`
-- `ensureInitialized()` at module scope
-- `await eventBus.emit(...)` after the successful operation, before the response
-
-### `app/api/receipts/upload/route.ts`
-
-Emits `receipt.extracted` after the complete receipt (with line items) is fetched, with `documentId: null` since this is the direct upload path.
-
-### `app/api/receipts/[id]/match/route.ts`
-
-The PATCH handler's ownership verification queries were upgraded from `select('id')` to `select('*, line_items:receipt_line_items(*)')` and `select('*')` respectively, so the full receipt and transaction objects are available for the event payload. Emits `receipt.matched` with `autoMatched: false`.
-
-### `app/api/receipts/[id]/confirm/route.ts`
-
-Computes `businessTotal` and `privateTotal` by iterating over the updated receipt's line items. Emits `receipt.confirmed` with these totals.
-
----
-
-## Extension: `extensions/receipt-ocr/index.ts`
-
-### Settings
-
-```typescript
-interface ReceiptOcrSettings {
- autoOcrEnabled: boolean // default: true
- autoMatchEnabled: boolean // default: true
- autoMatchThreshold: number // default: 0.8
- ocrConfidenceThreshold: number // default: 0.6
-}
-```
-
-Stored as an `extension_data` row with `extension_id='receipt-ocr'`, `key='settings'`, `value=`.
-
-- `getSettings(userId)` reads from DB and merges with defaults (forward-compatible when new settings are added)
-- `saveSettings(userId, partial)` merges partial update with current settings, then upserts on the unique constraint `(user_id, extension_id, key)`
-
-### Event Handler: `document.uploaded`
-
-When an image is uploaded via the document archive:
-
-1. **Gate:** Is `document.mime_type` an image? (`image/jpeg|png|webp|gif`) — if not, return
-2. **Gate:** Is `autoOcrEnabled` in user's settings? — if not, return
-3. Downloads image from `documents` storage bucket
-4. Converts to base64, calls `analyzeReceipt()` from `lib/receipts/receipt-analyzer.ts`
-5. **Gate:** Is `extraction.confidence >= ocrConfidenceThreshold`? — if not, return
-6. Calls `processLineItems()` from `lib/receipts/receipt-categorizer.ts`
-7. Creates receipt record (status: `extracted`) + line items in DB
-8. Emits `receipt.extracted` with `documentId: document.id`
-
-### Event Handler: `transaction.synced`
-
-When new transactions arrive from banking sync:
-
-1. **Gate:** Is `autoMatchEnabled`? — if not, return
-2. Filters to expense transactions only (amount < 0)
-3. Fetches unmatched receipts (`status IN ('extracted','confirmed')`, `matched_transaction_id IS NULL`)
-4. Calls `autoMatchReceipts()` from `lib/receipts/receipt-matcher.ts` with `settings.autoMatchThreshold`
-5. For each match: updates receipt + transaction bidirectional link, emits `receipt.matched` with `autoMatched: true`
-
-### Extension Object
-
-```typescript
-export const receiptOcrExtension: Extension = {
- id: 'receipt-ocr',
- name: 'Receipt OCR',
- version: '1.0.0',
- eventHandlers: [
- { eventType: 'document.uploaded', handler: handleDocumentUploaded },
- { eventType: 'transaction.synced', handler: handleTransactionSynced },
- ],
- mappingRuleTypes: [
- { id: 'receipt-ocr-merchant', name: 'OCR Merchant Match', ... },
- { id: 'receipt-ocr-category', name: 'OCR Category Suggestion', ... },
- ],
- settingsPanel: { label: 'Receipt OCR', path: '/settings/extensions/receipt-ocr' },
- async onInstall(ctx) { await saveSettings(ctx.userId, DEFAULT_SETTINGS) },
-}
-```
-
----
-
-## Settings API: `app/api/extensions/receipt-ocr/settings/route.ts`
-
-Establishes the convention `app/api/extensions/{id}/settings/route.ts` for all extensions.
-
-- **GET** — Returns the current user's merged settings (DB value + defaults)
-- **PATCH** — Accepts a partial settings object, validates keys against an allowlist, saves via `saveSettings()`
-
----
-
-## Existing Code Reused
-
-| Import | From | Used in |
-|--------|------|---------|
-| `analyzeReceipt()` | `lib/receipts/receipt-analyzer.ts` | `handleDocumentUploaded` |
-| `processLineItems()` | `lib/receipts/receipt-categorizer.ts` | `handleDocumentUploaded` |
-| `autoMatchReceipts()` | `lib/receipts/receipt-matcher.ts` | `handleTransactionSynced` |
-| `eventBus` | `lib/events/bus.ts` | Both handlers + retrofit |
-| `createClient()` | `lib/supabase/server.ts` | Settings + DB ops |
-
-No service logic was duplicated. The extension only acts as event-driven glue between existing services.
-
----
-
-## Event Flow
-
-```
-Document Archive Upload Direct Receipt Upload Bank Sync
- | | |
- uploadDocument() POST /receipts/upload POST /banking/sync
- | | |
- emit document.uploaded analyzeReceipt() inline emit transaction.synced
- | | |
- v v v
- +-----------------+ emit receipt.extracted +---------------------+
- | receipt-ocr | | receipt-ocr |
- | extension | | extension |
- | | | |
- | Gate: image? | | Gate: enabled? |
- | Gate: enabled? | | Fetch unmatched |
- | Download image | | autoMatchReceipts() |
- | analyzeReceipt()| | Link matches |
- | Create receipt | | emit receipt.matched|
- | emit receipt. | +---------------------+
- | extracted |
- +-----------------+
-
- User confirms receipt --> POST /receipts/[id]/confirm
- |
- emit receipt.confirmed
- |
- v
- [Future extensions]
- push-notifications
- ne-bilaga, etc.
-```
-
----
-
-## Architectural Patterns Established
-
-1. **Extensions never duplicate service logic.** They call existing functions from `lib/`.
-2. **Extensions are gate-guarded.** Every handler checks user settings before doing work.
-3. **Extensions emit domain events.** Downstream extensions react without coupling.
-4. **Events fire from both paths.** Whether a receipt enters via archive (event-driven) or direct upload (API), the same `receipt.extracted` event fires.
-5. **Settings use `extension_data` with `key='settings'`.** Helpers merge with defaults for forward-compatible schema evolution.
-6. **`onInstall` seeds defaults.** Idempotent via upsert.
-7. **Handlers never crash the emitter.** `Promise.allSettled` in the bus handles this.
-8. **Console logging with `[extension-id]` prefix.** Convention for grep-ability.
-9. **One-way dependency.** Base never imports from `extensions/`. Only `loader.ts` imports extension objects.
-
----
-
-## Verification
-
-- `npx tsc --noEmit` passes with zero errors
-- Manual: upload image via document archive -> receipt auto-created with OCR extraction
-- Manual: sync bank transactions -> unmatched receipts auto-matched
-- Manual: direct receipt upload still works unchanged, now also emits `receipt.extracted`
-- Manual: confirm receipt -> emits `receipt.confirmed`
diff --git a/dev_docs/base_architecture/SRU-EXPORT-EXTENSION.md b/dev_docs/base_architecture/SRU-EXPORT-EXTENSION.md
deleted file mode 100644
index 7f127bcf..00000000
--- a/dev_docs/base_architecture/SRU-EXPORT-EXTENSION.md
+++ /dev/null
@@ -1,257 +0,0 @@
-# SRU Export Extension
-
-## Overview
-
-The SRU Export extension generates SRU (Standardiserat Räkenskapsutdrag) files for electronic tax filing with Skatteverket. It reads `sru_code` from `chart_of_accounts`, aggregates balances by SRU code, and produces downloadable `.sru` files.
-
-Supports both:
-- **NE** (Enskild firma) — field codes 7310-7350
-- **INK2** (Aktiebolag) — field codes 7200-7499
-
-The form type is determined automatically from the user's `entity_type` in `company_settings`.
-
-## Architecture
-
-```
-extensions/sru-export/
-├── index.ts Extension definition (registered in loader)
-├── sru-engine.ts Balance aggregation by SRU code
-├── sru-generator.ts Generic SRU file generation
-├── types.ts SRU-specific type definitions (canonical source)
-└── SRUExportView.tsx UI component for the SRU-export reports tab
-
-app/api/extensions/sru-export/
-├── route.ts GET /api/extensions/sru-export (export endpoint)
-└── coverage/
- └── route.ts GET /api/extensions/sru-export/coverage (stats)
-```
-
-### Relationship to NE-bilaga extension
-
-The NE-bilaga extension (`extensions/ne-bilaga/`) handles the NE-specific declaration path with hard-coded R1-R11 account mappings, served via `/api/extensions/ne-bilaga`. See `dev_docs/base_architecture/NE-BILAGA-EXTENSION.md`.
-
-The generic SRU export is an alternative path that works from raw `account → sru_code` mappings stored in `chart_of_accounts`, rather than hard-coded NE ruta mappings. The generic generator reuses `sruFileToString()` and `validateSRUFile()` from the shared module.
-
-```
-NE-bilaga path (EF only):
- extensions/ne-bilaga/ne-engine.ts → lib/reports/sru-generator.ts (NE field codes)
-
-Generic path (NE + INK2):
- extensions/sru-export/sru-engine.ts (reads sru_code from DB) → sru-generator.ts (any form type)
-```
-
-## Database Changes
-
-### Migration: `20240101000021_sru_codes.sql`
-
-Applied as three remote migrations:
-1. `add_sru_code_column` — `ALTER TABLE chart_of_accounts ADD COLUMN sru_code text`
-2. `sru_codes_backfill` — Updates existing accounts with SRU codes based on account number ranges
-3. `sru_codes_seed_function` — Updates `seed_chart_of_accounts()` to include `sru_code` for new users
-
-The backfill only updates accounts where `sru_code IS NULL`, preserving any manual assignments.
-
-### SRU Code Mappings
-
-#### NE form (EF) — Revenue & Expense accounts
-
-| Account Range | SRU Code | NE Ruta | Description |
-|---|---|---|---|
-| 3000-3499 (excl 3100) | 7310 | R1 | Försäljning med moms |
-| 3100, 3900, 3970-3980 | 7311 | R2 | Momsfria intäkter |
-| 3200-3299 | 7312 | R3 | Bil/bostadsförmån |
-| 8310-8330 | 7313 | R4 | Ränteintäkter |
-| 4000-4990 | 7320 | R5 | Varuinköp |
-| 5000-6990, 7970 | 7321 | R6 | Övriga kostnader |
-| 7000-7699 | 7322 | R7 | Lönekostnader |
-| 8400-8499 | 7323 | R8 | Räntekostnader |
-| 7820 | 7324 | R9 | Avskrivningar fastighet |
-| 7700-7899 (excl 7820) | 7325 | R10 | Avskrivningar övrigt |
-
-#### INK2 form (AB) — Balance Sheet accounts
-
-| Account Range | SRU Code | Description |
-|---|---|---|
-| 1000-1099 | 7201 | Immateriella anläggningstillgångar |
-| 1100-1299 | 7202 | Materiella anläggningstillgångar |
-| 1300-1399 | 7203 | Finansiella anläggningstillgångar |
-| 1400-1499 | 7210 | Varulager |
-| 1500-1599 | 7211 | Kundfordringar |
-| 1600-1999 | 7212 | Övriga omsättningstillgångar |
-| 2081 | 7220 | Aktiekapital |
-| 2085-2098 | 7221 | Övrigt eget kapital |
-| 2099 | 7222 | Årets resultat |
-| 2100-2499 | 7230 | Skulder |
-| 2500-2999 | 7231 | Övriga skulder |
-
-#### INK2 form (AB) — Income Statement accounts
-
-| Account Range | SRU Code | Description |
-|---|---|---|
-| 3000-3999 | 7310 | Nettoomsättning |
-| 4000-4999 | 7320 | Varuinköp |
-| 5000-6999 | 7330 | Övriga externa kostnader |
-| 7000-7699 | 7340 | Personalkostnader |
-| 7700-7899 | 7350 | Avskrivningar |
-| 7900-7999 | 7360 | Övriga rörelsekostnader |
-| 8000-8499 | 7370 | Finansiella poster |
-| 8500-8999 | 7380 | Extraordinära poster |
-
-## API Reference
-
-### GET /api/extensions/sru-export
-
-Generate SRU export for a fiscal period.
-
-**Query parameters:**
-| Parameter | Required | Description |
-|---|---|---|
-| `period_id` | Yes | Fiscal period UUID |
-| `format` | No | `json` (default) or `sru` |
-
-**Response (format=json):**
-```json
-{
- "data": {
- "formType": "NE",
- "entityType": "enskild_firma",
- "companyName": "Mitt Företag AB",
- "orgNumber": "556123-4567",
- "fiscalYear": {
- "id": "uuid",
- "name": "2025",
- "start": "2025-01-01",
- "end": "2025-12-31"
- },
- "balances": [
- {
- "sruCode": "7310",
- "description": "Försäljning med moms",
- "amount": 150000,
- "accounts": [
- { "accountNumber": "3001", "accountName": "Försäljning tjänster 25%", "amount": 150000 }
- ]
- }
- ],
- "warnings": ["Räkenskapsåret är inte stängt. Siffrorna kan ändras."]
- }
-}
-```
-
-**Response (format=sru):** Downloads a `.sru` file with `Content-Disposition: attachment`.
-
-### GET /api/extensions/sru-export/coverage
-
-Returns SRU code coverage statistics for the authenticated user's chart of accounts.
-
-**Response:**
-```json
-{
- "data": {
- "totalAccounts": 30,
- "accountsWithSRU": 28,
- "accountsWithoutSRU": 2,
- "coveragePercent": 93,
- "missingAccounts": [
- { "accountNumber": "1220", "accountName": "Inventarier" }
- ]
- }
-}
-```
-
-## SRU File Format
-
-The generated `.sru` file follows the Skatteverket standard:
-
-```
-#PRODUKT KONTROLLUPPGIFTER
-#SESSION 1
-#PROGRAMNAMN ERPBase
-#PROGRAMVERSION 1.0
-#SKAPAT 20260219
-#BLANKETT NE
-#IDENTITET 5561234567
-#UPPGIFT 7000 20250101-20251231
-#UPPGIFT 7310 150000
-#UPPGIFT 7320 -45000
-#UPPGIFT 7321 -30000
-#BLANKETTSLUT
-```
-
-Each `#UPPGIFT` line contains an SRU field code and the rounded (whole kronor) amount. Zero-amount entries are omitted.
-
-## UI Integration
-
-### SRUExportView component
-
-The SRU export UI lives in `extensions/sru-export/SRUExportView.tsx` and is imported by the reports page:
-
-```typescript
-import { SRUExportView } from '@/extensions/sru-export/SRUExportView'
-```
-
-### Reports Page
-
-The **SRU-export** tab in `/reports` shows:
-
-1. **Info card** with "Förhandsgranska" and "Ladda ner SRU-fil" buttons
-2. **Coverage warning** if accounts lack SRU codes (fetched from `/coverage` endpoint)
-3. **Company info card** showing entity type badge (NE/INK2) and fiscal year
-4. **SRU balances table** with expandable rows showing per-account detail
-
-### Chart of Accounts
-
-A new **SRU** column is added to the accounts table in the Kontoplan view. The column is inline-editable: click a cell to type a new SRU code, press Enter to save, Escape to cancel. Updates go directly to `chart_of_accounts.sru_code` via the Supabase client.
-
-## Extension Registration
-
-The extension is registered in `lib/extensions/loader.ts`:
-
-```typescript
-import { sruExportExtension } from '@/extensions/sru-export'
-
-const FIRST_PARTY_EXTENSIONS: Extension[] = [
- receiptOcrExtension,
- aiCategorizationExtension,
- pushNotificationsExtension,
- sruExportExtension, // ← added
-]
-```
-
-The extension has no event handlers, no settings panel, and no sidebar items. It only declares a report type for discovery purposes.
-
-## Type Definitions
-
-Canonical source: `extensions/sru-export/types.ts` (re-exported from `types/index.ts` for convenience):
-
-- **`SRUExportResult`** — Response shape for the JSON format export endpoint
-- **`SRUCoverageStats`** — Response shape for the coverage endpoint
-
-## Files Changed
-
-### Created
-| File | Purpose |
-|---|---|
-| `supabase/migrations/20240101000021_sru_codes.sql` | Add column, backfill SRU codes, update seed function |
-| `extensions/sru-export/index.ts` | Extension definition |
-| `extensions/sru-export/sru-engine.ts` | Balance aggregation by SRU code |
-| `extensions/sru-export/sru-generator.ts` | Generic SRU file generation |
-| `extensions/sru-export/types.ts` | Canonical type definitions (`SRUExportResult`, `SRUCoverageStats`) |
-| `extensions/sru-export/SRUExportView.tsx` | UI component (extracted from reports page) |
-| `app/api/extensions/sru-export/route.ts` | Export API endpoint |
-| `app/api/extensions/sru-export/coverage/route.ts` | Coverage stats endpoint |
-
-### Modified
-| File | Change |
-|---|---|
-| `lib/extensions/loader.ts` | Added `sruExportExtension` to `FIRST_PARTY_EXTENSIONS` |
-| `app/(dashboard)/reports/page.tsx` | Imports `SRUExportView` from extension instead of inlining it |
-| `types/index.ts` | SRU types replaced with re-exports from `extensions/sru-export/types.ts` |
-| `components/bookkeeping/ChartOfAccounts.tsx` | Added inline-editable SRU code column |
-
-### Reused (not modified)
-| File | What was reused |
-|---|---|
-| `lib/reports/sru-generator.ts` | `sruFileToString()`, `validateSRUFile()` |
-| `extensions/ne-bilaga/ne-engine.ts` | Balance calculation pattern |
-| `lib/reports/sie-export.ts` | `calculateBalances()` pattern |
diff --git a/dev_docs/influencer_ai_info/00-ai-snabbreferens.md b/dev_docs/influencer_ai_info/00-ai-snabbreferens.md
deleted file mode 100644
index 291bad5a..00000000
--- a/dev_docs/influencer_ai_info/00-ai-snabbreferens.md
+++ /dev/null
@@ -1,234 +0,0 @@
-# AI-Agent Snabbreferens
-
-## Dokumentöversikt
-
-| Fil | Innehåll | Användning |
-|-----|----------|------------|
-| 01-karnregler.md | Grundläggande regler, tröskelvärden, bolagsformer | Faktafrågor om regler |
-| 02-scenariobibliotek.md | 30 vanliga situationer med lösningar | "Vad gör jag om..." frågor |
-| 03-plattformskatalog.md | Plattformsspecifik info (VAT, moms, utbetalningar) | Plattformsfrågor |
-| 04-berakningsexempel.md | Konkreta sifferexempel | "Hur beräknar jag..." frågor |
-| 05-beslutstrаd.md | Visuella beslutsflöden | Hjälp med val |
-| 06-felsokningsguide.md | Problemlösning | "Det stämmer inte..." frågor |
-| 07-kalender-deadlines.md | Alla deadlines och påminnelser | Tidsfrågor |
-| 08-varningsflaggor.md | Automatiska kontroller och varningar | Proaktiva varningar |
-
----
-
-## Trigger-ord → Dokument
-
-### Produkter och barter
-- "fick produkt", "pressutskick", "gratis", "barter" → Scenario 001-004
-- "marknadsvärde", "värdering" → Beräkningsexempel 1.2
-
-### Plattformar
-- "YouTube", "AdSense", "Google" → Plattformskatalog (YouTube)
-- "Twitch", "subs", "bits" → Plattformskatalog (Twitch)
-- "Instagram", "Meta", "Reels bonus" → Plattformskatalog (Instagram)
-- "TikTok", "Creator Fund" → Plattformskatalog (TikTok)
-- "Patreon" → Plattformskatalog (Patreon)
-- "affiliate", "Adtraction" → Plattformskatalog (Affiliate)
-
-### Moms
-- "moms", "VAT", "faktura" → Kärnregler sektion 3, Beslutsträd 2.1
-- "periodisk sammanställning" → Kärnregler 3.3, Kalender
-- "Reverse Charge", "EU" → Scenario 007-010, Beslutsträd 2.1
-- "OSS", "privatperson EU" → Kärnregler 3.4, Scenario 018-019
-
-### Bolagsform
-- "EF", "enskild firma" → Kärnregler 4.1, Beslutsträd 3.1
-- "AB", "aktiebolag" → Kärnregler 4.2, Beslutsträd 3.1
-- "byta bolagsform", "starta AB" → Scenario 028, Beslutsträd 3.2
-- "utdelning", "3:12" → Scenario 027, Beräkningsexempel 3.1
-
-### Avdrag
-- "avdrag", "dra av" → Kärnregler 5, Beslutsträd 4.1
-- "kläder", "smink" → Kärnregler 5.2, Scenario 016-017
-- "resa", "arbetsresa" → Scenario 005-006, Beslutsträd 1.2
-- "hemmakontor", "arbetsrum" → Kärnregler 5.3, Beräkningsexempel 5.2
-
-### Social trygghet
-- "SGI", "sjukpenning" → Kärnregler 7, Scenario 023
-- "föräldraledighet", "VAB", "barn" → Beräkningsexempel 3.3, Varningsflaggor 3.3
-- "pension" → Kärnregler 7.2
-
-### Juridik
-- "reklam", "markering", "MFL" → Kärnregler 6, Scenario 024
-- "upphovsrätt", "musik", "licens" → Scenario 025, Varningsflaggor 5.2
-
-### Dubbel struktur
-- "EF och AB", "båda bolag" → Kärnregler 8, Scenario 029-030
-- "internfaktura" → Scenario 030, Varningsflaggor 4.1-4.2
-
-### Deadlines
-- "deadline", "när ska", "förfaller" → Kalender
-- "momsdeklaration" → Kalender (kvartalsvis/månadsvis)
-- "inkomstdeklaration" → Kalender (maj/juli)
-
-### Problem
-- "stämmer inte", "fel", "problem" → Felsökningsguide
-- "Skatteverket", "granskning" → Felsökningsguide 8
-
----
-
-## Kritiska tröskelvärden (snabbåtkomst)
-
-| Belopp | Betydelse |
-|--------|-----------|
-| 1 800 kr | Skattefri tävlingsvinst |
-| 2 000 kr | Schablonavdrag arbetsrum EF |
-| 5 000 kr | Skattefritt friskvårdsbidrag AB |
-| 25 000 kr | Aktiekapital AB |
-| 80 000 kr | Momsbefrielse omsättning |
-| 99 680 kr | OSS-tröskel EU-privatpersoner |
-| 204 325 kr | Schablonbelopp 3:12 (2024) |
-| 615 300 kr | Brytpunkt statlig skatt |
-| 681 600 kr | Lönekrav för lönebaserat 3:12-utrymme |
-
----
-
-## Vanliga plattformars momshantering (snabbåtkomst)
-
-| Plattform | Moms | Ruta | Period. samnst. |
-|-----------|------|------|-----------------|
-| YouTube | Reverse Charge | 39 | Ja |
-| Twitch | Export | 40 | Nej |
-| Instagram | Reverse Charge | 39 | Ja |
-| TikTok | Reverse Charge | 39 | Ja |
-| Patreon | Export | 40 | Nej |
-| Spotify | Svensk 25% | 05-08 | Nej |
-| Adtraction | Svensk 25% | 05-08 | Nej |
-
----
-
-## Standardsvar-mallar
-
-### Vid fråga om skatteplikt
-
-```
-[Inkomsttyp] är [skattepliktig/ej skattepliktig].
-
-Värdering: [Marknadsvärde inkl. moms / Nominellt belopp]
-
-Bokföring:
-- Debet [konto]: [belopp]
-- Kredit [konto]: [belopp]
-
-[Eventuella villkor eller undantag]
-```
-
-### Vid fråga om momshantering
-
-```
-Kund: [Kundtyp och land]
-Momsregel: [Svensk 25% / Reverse Charge / Export]
-
-Faktura:
-- Belopp exkl. moms: [X] kr
-- Moms: [Y] kr / 0 kr
-- Text på faktura: [Om tillämpligt]
-
-Redovisning:
-- Momsdeklaration ruta: [X]
-- Periodisk sammanställning: [Ja/Nej]
-```
-
-### Vid fråga om avdragsrätt
-
-```
-[Kostnadstyp] är [avdragsgill/ej avdragsgill].
-
-Villkor för avdrag:
-- [Villkor 1]
-- [Villkor 2]
-
-[Om delvis avdragsgill: Beräkning av andel]
-
-Dokumentationskrav:
-- [Krav]
-```
-
-### Vid varning
-
-```
-VARNING: [Typ av varning]
-
-Problem: [Beskrivning]
-
-Konsekvens om ej åtgärdat:
-- [Konsekvens 1]
-- [Konsekvens 2]
-
-Åtgärd:
-1. [Steg 1]
-2. [Steg 2]
-
-Deadline: [Om tillämpligt]
-```
-
----
-
-## Konteringsguide (vanliga poster)
-
-### Intäkter
-
-| Typ | Debet | Kredit |
-|-----|-------|--------|
-| Svensk försäljning | 1510 Kundfordringar | 3010 Intäkter + 2610 Utg. moms |
-| EU-försäljning (B2B) | 1510 Kundfordringar | 3011 Försäljning EU |
-| Export (utanför EU) | 1510 Kundfordringar | 3012 Försäljning export |
-| Kontant plattformsintäkt | 1940 Bank | 3011/3012 beroende på plattform |
-| Barter-produkt | 4010 Inköp + 2640 Ing. moms | 3010 Intäkter |
-
-### Kostnader
-
-| Typ | Debet | Kredit |
-|-----|-------|--------|
-| Inköp med moms | [Kostnadskonto] + 2640 Ing. moms | 1940 Bank / 2440 Lev.skuld |
-| Inventarier | 1220 Inventarier + 2640 Ing. moms | 1940 Bank |
-| Prenumerationer | 6540 IT-tjänster + 2640 Ing. moms | 1940 Bank |
-
-### Eget uttag (EF)
-
-| Typ | Debet | Kredit |
-|-----|-------|--------|
-| Privat uttag | 2013 Eget uttag | 1940 Bank |
-| Barter till privat bruk | 2013 Eget uttag | 4010 Inköp + 2640 Ing. moms |
-
-### Valutakursdifferenser
-
-| Typ | Debet | Kredit |
-|-----|-------|--------|
-| Kursvinst | 1940 Bank | 1510 Kundfordringar + 3960 Kursvinst |
-| Kursförlust | 1940 Bank + 7960 Kursförlust | 1510 Kundfordringar |
-
----
-
-## Eskaleringsmatris
-
-| Situation | Åtgärd |
-|-----------|--------|
-| Enkel faktafråga | Svara direkt från dokumentation |
-| Komplex beräkning | Använd beräkningsexempel som mall |
-| Osäkerhet om regler | Hänvisa till Skatteverket.se |
-| Juridisk tvist | Rekommendera jurist |
-| Skatteverket-kontakt | Rekommendera redovisningskonsult |
-| Allvarlig varning | Flagga tydligt, föreslå åtgärd |
-| Utanför scope | Tydliggör begränsning, hänvisa vidare |
-
----
-
-## Begränsningar att kommunicera
-
-AI-agenten kan INTE:
-- Ge juridisk rådgivning (endast information)
-- Garantera skattekonsekvenser
-- Ersätta revisor/redovisningskonsult
-- Lämna in deklarationer
-- Kontakta myndigheter
-
-AI-agenten SKA:
-- Ge saklig information baserad på dokumentation
-- Flagga risker och varningar
-- Rekommendera professionell hjälp vid behov
-- Hänvisa till officiella källor
diff --git a/dev_docs/influencer_ai_info/01-karnregler.md b/dev_docs/influencer_ai_info/01-karnregler.md
deleted file mode 100644
index 962d0ef7..00000000
--- a/dev_docs/influencer_ai_info/01-karnregler.md
+++ /dev/null
@@ -1,219 +0,0 @@
-# Kärnregler: Influencer Ekonomi
-
-## 1. Verksamhetsklassificering
-
-### Tre kumulativa krav för näringsverksamhet
-
-| Krav | Definition | Influencer-exempel |
-|------|------------|-------------------|
-| Vinstsyfte | Objektiv förväntan på överskott över tid | Affärsplan visar skalbar intäktsmodell |
-| Varaktighet | Regelbunden aktivitet, längre period | Daglig/veckovis publicering, löpande samarbeten |
-| Självständighet | Egen utrustning, flera kunder, eget risktagande | Egen kamera, 5+ varumärkessamarbeten/år |
-
-### Klassificeringslogik
-
-```
-ALLA tre krav uppfyllda → Näringsverksamhet (F-skatt, NE/AB)
-EJ alla krav men inkomst finns → Hobbyverksamhet (T2-blankett)
-Tillfälliga uppdrag utan F-skatt → Tjänsteinkomst (A-skatt dras av uppdragsgivare)
-```
-
-### Hobbyverksamhet
-
-- Beskattas som inkomst av tjänst
-- Egenavgifter: 25-29%
-- Underskott: Sparas max 5 år, kvittas endast mot framtida hobbyöverskott
-- Moms: Registreringsplikt om omsättning > 80 000 kr
-
----
-
-## 2. Skattepliktiga inkomster
-
-**Grundprincip:** Allt som erhålls på grund av verksamheten är skattepliktigt oavsett form.
-
-### Inkomsttabell
-
-| Typ | Skattepliktigt | Värdering | Undantag |
-|-----|----------------|-----------|----------|
-| Kontant ersättning | Ja | Nominellt belopp | - |
-| Produkter (avtalat samarbete) | Ja | Marknadsvärde inkl. moms | - |
-| Pressutskick (oombett) | Villkorat | Marknadsvärde inkl. moms | Returnerad/kasserad utan användning |
-| Sponsrad resa | Delvis/helt | Resans faktiska värde | Arbete >30h/vecka, försumbart nöjesinslag |
-| Medföljande på resa | Ja | Medföljarens resekostnad | - |
-| Donations/Bits/Stars/Subs | Ja | Mottaget belopp | - |
-| Affiliate-provision | Ja | Utbetalt belopp | - |
-| Rabattkod eget bruk | Ja | Marknadspris minus betalt pris | - |
-| Tävlingsvinster | Villkorat | Vinstens värde | ≤1 800 kr eller minnesföremål |
-| Virtuella items (skins etc.) | Ja vid försäljning | Försäljningspris | - |
-
----
-
-## 3. Momsregler
-
-### Tröskelvärden
-
-| Gräns | Belopp | Konsekvens |
-|-------|--------|------------|
-| Momsbefrielse | 80 000 kr omsättning | Under: Valfri registrering. Över: Obligatorisk. |
-| OSS-tröskel | 99 680 kr (10 000 EUR) | Försäljning till EU-privatpersoner |
-
-### Momshantering per kundtyp
-
-| Kund | Plats | Moms på faktura | Redovisning |
-|------|-------|-----------------|-------------|
-| Svenskt företag | Sverige | 25% | Ruta 05-08 |
-| EU-företag | Annat EU-land | 0% (Reverse Charge) | Ruta 39 + Periodisk sammanställning |
-| Företag utanför EU | Tredjeland | 0% (Export) | Ruta 40 |
-| Privatperson EU | Annat EU-land | Mottagarlandets moms* | OSS-deklaration |
-| Privatperson utanför EU | Tredjeland | 0% | Ruta 40 |
-
-*Under 99 680 kr/år: Valfritt svensk moms 25%
-
-### Periodisk sammanställning
-
-- **När:** Kvartalsvis vid försäljning till EU-företag
-- **Innehåll:** Köparens VAT-nummer, totalvärde per kund
-- **Deadline:** 20:e i månaden efter kvartalets slut
-- **Förseningsavgift:** 1 250 kr
-- **Kritiskt:** Belopp måste matcha Ruta 39 i momsdeklaration
-
----
-
-## 4. Bolagsformer
-
-### Jämförelse
-
-| Aspekt | Enskild Firma | Aktiebolag |
-|--------|---------------|------------|
-| Kapitalinsats | 0 kr | 25 000 kr |
-| Ansvar | Personligt, obegränsat | Begränsat till aktiekapital |
-| Beskattning | Inkomstskatt + egenavgifter på överskott | Bolagsskatt 20,6% + skatt på lön/utdelning |
-| Utdelning 20% skatt | Ej tillgängligt | Ja, upp till gränsbelopp (3:12) |
-| Friskvårdsbidrag | Ej avdragsgillt | Skattefritt ≤5 000 kr |
-| SGI-grund | Nettoöverskott | Uttagen lön |
-| Administration | NE-bilaga | Årsredovisning |
-| Rekommenderad vinst | <500 000 kr | >500 000 kr |
-
-### Brytpunkter 2024/2025
-
-| Gräns | Belopp |
-|-------|--------|
-| Statlig inkomstskatt | 615 300 kr |
-| Aktiekapital AB | 25 000 kr |
-
----
-
-## 5. Avdragsregler
-
-### Avdragsgilla kostnader
-
-| Kategori | Exempel | Villkor |
-|----------|---------|---------|
-| Teknik | Kamera, dator, mikrofon, ljus, drönare | Yrkesmässig användning |
-| Mjukvara | Redigeringsprogram, molntjänster | Verksamhetsrelaterad |
-| Agentarvode | Provision till manager/agentur | Direkt kopplad till intäkt |
-| Extern lokal | Studiohyra | Exklusiv verksamhetsanvändning |
-| Resor | Arbetsresor med dokumenterat syfte | Ej hem-arbete |
-
-### Ej avdragsgilla kostnader
-
-| Kategori | Motivering |
-|----------|------------|
-| Kläder (normala) | Användbart privat |
-| Smink, hudvård | Privat levnadskostnad |
-| Skönhetsingrepp | Privat levnadskostnad |
-| Accessoarer (väskor, smycken) | Användbart privat |
-| Träning, gym | Privat (undantag: friskvård i AB) |
-
-### Arbetsrum i bostad
-
-| Typ | Krav | Avdrag |
-|-----|------|--------|
-| Faktiskt avdrag | Separat rum, ej bostad, exklusiv användning | Faktisk kostnad |
-| Schablon (EF) | >800 h arbete i bostad/år | 2 000 kr/år |
-
----
-
-## 6. Marknadsföringslagen
-
-### Krav på reklammarkering
-
-| Element | Krav |
-|---------|------|
-| Placering | Början av inlägg/video |
-| Text | "REKLAM" eller "ANNONS" |
-| Synlighet | Framträdande färg, storlek |
-| Video | Muntligt och/eller textgrafik |
-| Sändarangivelse | Vem som betalar ska framgå |
-
-### Överträdelser
-
-- Influencern har eget medverkansansvar
-- Förbud vid vite
-- Marknadsstörningsavgift
-- Skadestånd
-
-### Upphovsrätt
-
-- Licens krävs för musik/material i kommersiella sammanhang
-- Referensfall: ABBA-fallet, 200 000 kr ersättning
-
----
-
-## 7. Social trygghet
-
-### SGI (Sjukpenninggrundande inkomst)
-
-| Bolagsform | SGI baseras på |
-|------------|----------------|
-| Enskild Firma | Skattemässigt överskott |
-| Aktiebolag | Uttagen lön (ej utdelning) |
-| Dubbel struktur | Summan av båda |
-
-**Uppbyggnadsskede EF:** Första 36 månaderna kan jämförelseinkomst användas.
-
-### Pension
-
-- Egenföretagare saknar automatisk tjänstepension
-- Avdragsgillt sparande: Max 35% av inkomst, max ~573 000 kr/år
-- Rekommendation: Spara 4,5-6% av inkomst
-
----
-
-## 8. Dubbel struktur (EF + AB)
-
-### Användningsområden
-
-| EF används för | AB används för |
-|----------------|----------------|
-| Småuppdrag <50 000 kr | Större kampanjer >100 000 kr |
-| Lågriskuppdrag | Högriskkampanjer |
-| Konsultation | Huvudsaklig verksamhet |
-| Avvecklingsperiod | Ny huvudverksamhet |
-
-### Interntransaktioner
-
-- Armlängdsprissättning obligatorisk
-- Skriftliga avtal krävs
-- Moms på internfakturor
-- Separata bankkonton och bokföring
-
-### SGI vid dubbel struktur
-
-```
-Total SGI = Överskott EF + Lön från AB
-```
-
----
-
-## 9. Kritiska tröskelvärden
-
-| Belopp | Betydelse |
-|--------|-----------|
-| 1 800 kr | Skattefri tävlingsvinst |
-| 2 000 kr | Schablonavdrag arbetsrum EF |
-| 5 000 kr | Skattefritt friskvårdsbidrag AB |
-| 25 000 kr | Aktiekapital AB |
-| 80 000 kr | Momsbefrielse omsättning |
-| 99 680 kr | OSS-tröskel EU-privatpersoner |
-| 615 300 kr | Brytpunkt statlig skatt |
diff --git a/dev_docs/influencer_ai_info/02-scenariobibliotek.md b/dev_docs/influencer_ai_info/02-scenariobibliotek.md
deleted file mode 100644
index adb3a7bd..00000000
--- a/dev_docs/influencer_ai_info/02-scenariobibliotek.md
+++ /dev/null
@@ -1,678 +0,0 @@
-# Scenariobibliotek: Vanliga situationer
-
-## Produkter och barter
-
-### SCENARIO 001: Mottagen produkt med samarbetsavtal
-
-**Triggers:** "fick produkt", "samarbete", "ska posta om", "i utbyte mot"
-
-**Situation:** Influencer får produkt värd X kr mot att göra inlägg.
-
-**Beslutsträd:**
-```
-Finns skriftligt/muntligt avtal om motprestation?
- → Ja → Hela marknadsvärdet inkl. moms är skattepliktig intäkt
-```
-
-**Skattemässig hantering:**
-- Intäkt: Produktens marknadsvärde inkl. moms
-- Om EF: Bokför som intäkt + eget uttag om privat bruk
-- Om AB: Bokför som intäkt + förmån om privat bruk
-
-**Bokföringsexempel (EF):**
-```
-Produkt: Väska värd 8 000 kr inkl. moms
-
-Debet 4010 Inköp varor: 6 400 kr
-Debet 2640 Ingående moms: 1 600 kr
-Kredit 3010 Intäkter: 8 000 kr
-
-Om privat bruk:
-Debet 2013 Eget uttag: 8 000 kr
-Kredit 4010 Inköp varor: 6 400 kr
-Kredit 2640 Ingående moms: 1 600 kr
-```
-
-**Checklista:**
-- [ ] Dokumentera marknadsvärde (spara prislapp/screenshot)
-- [ ] Spara avtal/mailkonversation
-- [ ] Bokför som intäkt
-- [ ] Märk inlägg med REKLAM
-
----
-
-### SCENARIO 002: Oombett pressutskick (behålls)
-
-**Triggers:** "fick skickat", "pressutskick", "utan att fråga", "PR-paket"
-
-**Situation:** Influencer får produkt utan förfrågan, behåller och använder privat.
-
-**Beslutsträd:**
-```
-Fick du produkten oombedd?
- → Ja
- Behåller du den / använder privat?
- → Ja → Skattepliktig intäkt (marknadsvärde)
- → Nej (returnerar/slänger utan användning) → Ej skattepliktig
-```
-
-**Skattemässig hantering:**
-- Skattepliktig även utan motprestation om produkten behålls
-- Värderas till marknadsvärde inkl. moms
-
-**Dokumentationskrav:**
-- Fotografera produkten vid mottagande
-- Notera avsändare och datum
-- Om returnerad: Spara kvitto på returfrakten
-
----
-
-### SCENARIO 003: Oombett pressutskick (returneras/kastas)
-
-**Triggers:** "skickade tillbaka", "returnerade", "slängde", "gav bort"
-
-**Situation:** Influencer får produkt utan förfrågan, returnerar eller kastar.
-
-**Skattemässig hantering:**
-- Ej skattepliktigt om ingen privat användning skett
-- Bevisbördan ligger på influencern
-
-**Dokumentationskrav:**
-- Kvitto på returfrakten
-- Foto av kasserad produkt (om relevant)
-- Notering om när och hur produkten avyttrades
-
-**Varning:** Om produkten säljs på "bloppis" blir försäljningsintäkten skattepliktig.
-
----
-
-### SCENARIO 004: Rabattkod för eget bruk
-
-**Triggers:** "rabattkod", "köpte med rabatt", "fick X% rabatt"
-
-**Situation:** Influencer får personlig rabattkod som del av ersättning.
-
-**Beräkning:**
-```
-Skattepliktig inkomst = Marknadspris - Faktiskt betalt pris
-
-Exempel:
-Marknadspris: 5 000 kr
-Betalt: 0 kr
-Skattepliktig inkomst: 5 000 kr
-```
-
-**Bokföring:** Som intäkt i verksamheten.
-
----
-
-## Resor och evenemang
-
-### SCENARIO 005: Sponsrad resa (arbetsresa)
-
-**Triggers:** "pressresa", "influencer trip", "betald resa", "bjuden resa"
-
-**Situation:** Influencer bjuds på resa av varumärke.
-
-**Beslutsträd:**
-```
-Är resan nödvändig för verksamheten?
- → Nej → Helt skattepliktig
- → Ja
- Upptar arbete huvudsaklig tid (≥30h/vecka eller ≥6h/dag)?
- → Nej → Delvis/helt skattepliktig (nöjesandel)
- → Ja
- Är nöjesinslagen försumbara?
- → Nej → Nöjesandelen skattepliktig
- → Ja → Skattefri
-```
-
-**Skattefri resa kräver:**
-1. Nödvändig för verksamheten
-2. Arbete ≥30 timmar/vecka ELLER ≥6 timmar/dag
-3. Nöjesinslag försumbara
-
-**Dokumentationskrav:**
-- Detaljerat schema över arbetade timmar
-- Leverabler (antal inlägg, stories, videos)
-- Avtal som specificerar arbetsuppgifter
-
----
-
-### SCENARIO 006: Medföljande på resa
-
-**Triggers:** "tog med partner", "min sambo följde med", "vän fick följa med"
-
-**Situation:** Influencerns partner/vän följer med på sponsrad resa kostnadsfritt.
-
-**Skattemässig hantering:**
-- Medföljarens resekostnad är skattepliktig förmån för influencern
-- Gäller oavsett om influencerns egen resa är skattefri
-
-**Beräkning:**
-```
-Förmånsvärde = Flygbiljett + Hotell + Eventuella aktiviteter för medföljaren
-```
-
----
-
-## Plattformsintäkter
-
-### SCENARIO 007: YouTube AdSense-utbetalning
-
-**Triggers:** "YouTube betalade", "AdSense", "annonsintäkter YouTube"
-
-**Situation:** Månatlig utbetalning från Google/YouTube.
-
-**Fakta:**
-- Utbetalare: Google Ireland Ltd
-- VAT-nummer: IE6388047V
-- Valuta: USD (normalt)
-- Momsregel: Reverse Charge (EU B2B)
-
-**Bokföringsexempel:**
-```
-Mottaget: $3,200 USD
-Valutakurs vid inbetalning: 10.45 SEK/USD
-Belopp i SEK: 33,440 kr
-
-Debet 1940 Bank: 33,440 kr
-Kredit 3011 Försäljning tjänster EU: 33,440 kr
-```
-
-**Momsredovisning:**
-- Ruta 39: 33,440 kr
-- Periodisk sammanställning: Google Ireland Ltd, IE6388047V, 33,440 kr
-
----
-
-### SCENARIO 008: Twitch-utbetalning
-
-**Triggers:** "Twitch betalade", "subs", "bits", "Twitch revenue"
-
-**Situation:** Utbetalning från Twitch (prenumerationer, bits, annonser).
-
-**Fakta:**
-- Utbetalare: Twitch Interactive Inc
-- Säte: USA (San Francisco)
-- Momsregel: Export (utanför EU)
-
-**Bokföringsexempel:**
-```
-Mottaget: $1,500 USD
-Valutakurs vid inbetalning: 10.52 SEK/USD
-Belopp i SEK: 15,780 kr
-
-Debet 1940 Bank: 15,780 kr
-Kredit 3012 Försäljning tjänster utanför EU: 15,780 kr
-```
-
-**Momsredovisning:**
-- Ruta 40: 15,780 kr
-- Ingen periodisk sammanställning (ej EU)
-
----
-
-### SCENARIO 009: Instagram/Meta bonusar
-
-**Triggers:** "Instagram bonus", "Reels bonus", "Meta betalade"
-
-**Situation:** Bonusutbetalning från Meta för Reels-visningar etc.
-
-**Fakta:**
-- Utbetalare: Meta Platforms Ireland Ltd
-- VAT-nummer: IE9692928F
-- Momsregel: Reverse Charge (EU B2B)
-
-**Hantering:** Samma som YouTube (Scenario 007).
-
----
-
-### SCENARIO 010: TikTok Creator Fund
-
-**Triggers:** "TikTok betalade", "Creator Fund", "TikTok pengar"
-
-**Situation:** Utbetalning från TikTok Creator Fund.
-
-**Fakta:**
-- Utbetalare: TikTok Technology Ltd (ofta)
-- VAT-nummer: IE3434547SH
-- Säte: Irland
-- Momsregel: Reverse Charge (EU B2B)
-
-**OBS:** Kontrollera alltid aktuellt avtal då TikToks struktur varierar.
-
----
-
-### SCENARIO 011: Donations/Tips (Twitch, YouTube, etc.)
-
-**Triggers:** "donation", "tips", "någon donerade", "fick pengar av tittare"
-
-**Situation:** Tittare skickar pengar direkt via plattform.
-
-**Skattemässig hantering:**
-- INTE gåva i skatterättslig mening
-- Ersättning för prestation (underhållning)
-- Fullt skattepliktig inkomst i näringsverksamheten
-
-**Bokföring:**
-```
-Debet 1940 Bank: [belopp]
-Kredit 3010 Intäkter: [belopp]
-```
-
----
-
-## Affiliate och samarbeten
-
-### SCENARIO 012: Affiliate-provision
-
-**Triggers:** "affiliate", "provision", "trackad länk", "kommission"
-
-**Situation:** Influencer får provision på försäljning via spårningslänk.
-
-**Skattemässig hantering:**
-- Fullt skattepliktig intäkt
-- Momshantering beror på var affiliate-nätverket är baserat
-
-**Vanliga nätverk och momshantering:**
-
-| Nätverk | Säte | Momsregel |
-|---------|------|-----------|
-| Amazon Associates | Luxemburg (EU) | Reverse Charge |
-| Adtraction | Sverige | 25% moms |
-| Tradedoubler | Sverige | 25% moms |
-| AWIN | Varierar | Kontrollera avtal |
-
----
-
-### SCENARIO 013: Ambassadörsavtal med fast månadsersättning
-
-**Triggers:** "ambassadör", "fast ersättning", "månadsarvode", "retainer"
-
-**Situation:** Löpande avtal med fast månadsersättning.
-
-**Skattemässig hantering:**
-- Intäktsför månadsvis
-- Moms beroende på kundtyp (se momsregler)
-- Om svensk kund: Fakturera med 25% moms
-
-**Bokföring:**
-```
-Månadsersättning: 25,000 kr + moms
-
-Debet 1510 Kundfordringar: 31,250 kr
-Kredit 3010 Intäkter: 25,000 kr
-Kredit 2610 Utgående moms: 6,250 kr
-```
-
----
-
-## Teknik och utrustning
-
-### SCENARIO 014: Köp av kamera/utrustning
-
-**Triggers:** "köpte kamera", "ny utrustning", "investerade i teknik"
-
-**Situation:** Inköp av professionell utrustning.
-
-**Beslutsträd:**
-```
-Används utrustningen uteslutande i verksamheten?
- → Ja → Fullt avdrag + momsavdrag
- → Nej (även privat bruk)
- → Proportionera avdrag efter verksamhetsandel
- → Professionell utrustning: Ofta godtas helavdrag ändå
-```
-
-**Bokföringsexempel (kamera 45,000 kr inkl. moms):**
-```
-Debet 1220 Inventarier: 36,000 kr
-Debet 2640 Ingående moms: 9,000 kr
-Kredit 1940 Bank: 45,000 kr
-```
-
-**Avskrivning:**
-- Datorer, kameror: Normalt 3-5 år
-- Möjlighet till direktavdrag om <25,900 kr (halvt prisbasbelopp)
-
----
-
-### SCENARIO 015: Prenumerationer och mjukvara
-
-**Triggers:** "Adobe", "prenumeration", "programvara", "app-kostnad"
-
-**Situation:** Löpande kostnader för mjukvara.
-
-**Vanliga avdragsgilla prenumerationer:**
-- Adobe Creative Cloud
-- Final Cut Pro
-- Canva Pro
-- Notion, Airtable
-- Molnlagring (Google Drive, Dropbox)
-- Schemaläggningsverktyg (Later, Buffer)
-
-**Bokföring:** Kostnadsförs löpande som förbrukningsmaterial eller extern tjänst.
-
----
-
-## Kläder och utseende
-
-### SCENARIO 016: Köp av kläder för content
-
-**Triggers:** "köpte kläder", "outfit för video", "kläder till inlägg"
-
-**Situation:** Influencer köper kläder att visa i content.
-
-**Huvudregel:** Ej avdragsgillt om kläderna kan användas privat.
-
-**Undantag (avdragsgilla):**
-- Uniformer
-- Skyddskläder
-- Extrema scenkläder (ej användbara privat)
-- Specifik rekvisita (t.ex. historiska kostymer)
-
-**Dokumentationskrav för undantag:**
-- Fotografera plagget
-- Motivera varför det ej är användbart privat
-- Bevisbördan ligger på influencern
-
----
-
-### SCENARIO 017: Skönhetsbehandlingar
-
-**Triggers:** "filler", "botox", "behandling", "skönhetsingrepp"
-
-**Situation:** Influencer gör estetisk behandling.
-
-**Skattemässig hantering:**
-- Aldrig avdragsgillt
-- Klassas som privat levnadskostnad
-- Gäller även om utseendet är "del av varumärket"
-
----
-
-## Försäljning och merchandise
-
-### SCENARIO 018: Försäljning av egen merch till svenska kunder
-
-**Triggers:** "säljer merch", "egen kollektion", "t-shirts"
-
-**Situation:** Försäljning av varor till svenska privatpersoner.
-
-**Skattemässig hantering:**
-- Intäkt i verksamheten
-- 25% moms på försäljningen
-- Inköpskostnad för varorna avdragsgill
-
-**Bokföringsexempel:**
-```
-Såld t-shirt: 299 kr inkl. moms
-
-Debet 1940 Bank: 299 kr
-Kredit 3010 Försäljning varor: 239,20 kr
-Kredit 2610 Utgående moms: 59,80 kr
-```
-
----
-
-### SCENARIO 019: Försäljning av merch till EU-kunder
-
-**Triggers:** "kund i Tyskland", "säljer till EU", "europeisk kund"
-
-**Situation:** Försäljning av varor till privatpersoner i annat EU-land.
-
-**Beslutsträd:**
-```
-Total EU-privatpersonförsäljning under året:
- ≤99,680 kr → Valfritt: Svensk moms 25% ELLER mottagarlandets moms
- >99,680 kr → Obligatoriskt: Mottagarlandets moms via OSS
-```
-
-**OSS (One Stop Shop):**
-- Registrering via Skatteverket
-- Kvartalsvis deklaration
-- Samlar all utländsk EU-moms på ett ställe
-
----
-
-### SCENARIO 020: Försäljning av virtuella items (gaming)
-
-**Triggers:** "sålde skins", "CS:GO", "in-game items"
-
-**Situation:** Försäljning av virtuella föremål för riktiga pengar.
-
-**Beslutsträd:**
-```
-Sker försäljning yrkesmässigt och regelbundet?
- → Ja → Näringsverksamhet (inkomst av näring)
- → Nej (enstaka försäljningar) → Inkomst av kapital (30% på vinsten)
-```
-
-**OBS:** Gränsdragningen är svår. Vid regelbunden handel, behandla som näringsverksamhet.
-
----
-
-## Valuta och internationellt
-
-### SCENARIO 021: Valutakursdifferens
-
-**Triggers:** "kurs ändrades", "växlingskurs", "valutaförlust"
-
-**Situation:** Skillnad mellan fakturakurs och betalningskurs.
-
-**Beräkning:**
-```
-Fakturerat: $1,000 @ 10.20 = 10,200 kr
-Mottaget: $1,000 @ 10.45 = 10,450 kr
-Valutakursvinst: 250 kr
-```
-
-**Bokföring:**
-```
-Valutakursvinst:
-Debet 1940 Bank: 10,450 kr
-Kredit 1510 Kundfordringar: 10,200 kr
-Kredit 3960 Valutakursvinster: 250 kr
-
-Valutakursförlust:
-Debet 1940 Bank: 9,950 kr
-Debet 7960 Valutakursförluster: 250 kr
-Kredit 1510 Kundfordringar: 10,200 kr
-```
-
----
-
-## Sociala avgifter och trygghet
-
-### SCENARIO 022: Uppdrag utan F-skatt
-
-**Triggers:** "har inte F-skatt", "de drog skatt", "fick lön istället"
-
-**Situation:** Influencer utför uppdrag men saknar F-skatt.
-
-**Konsekvenser:**
-- Uppdragsgivaren ska dra A-skatt (~30%)
-- Uppdragsgivaren betalar arbetsgivaravgifter (31,42%)
-- Ersättningen behandlas som lön
-
-**Checklista:**
-- [ ] Begär kontrolluppgift från uppdragsgivaren
-- [ ] Kontrollera att skatt faktiskt dragits
-- [ ] Deklarera som inkomst av tjänst
-
----
-
-### SCENARIO 023: Beräkna SGI-konsekvens av utdelning vs lön
-
-**Triggers:** "sjukpenning", "VAB", "föräldraledighet", "SGI"
-
-**Situation:** Val mellan lön och utdelning påverkar socialförsäkring.
-
-**Beräkning:**
-```
-Alt 1: Lön 400,000 kr
- SGI: 400,000 kr
- Sjukpenning (80%): 320,000 kr/år
-
-Alt 2: Lön 100,000 kr + Utdelning 300,000 kr
- SGI: 100,000 kr
- Sjukpenning (80%): 80,000 kr/år
-
-Skillnad vid 6 månaders sjukskrivning: 120,000 kr
-```
-
----
-
-## Juridik och avtal
-
-### SCENARIO 024: Glömt reklammarkering
-
-**Triggers:** "glömde skriva reklam", "markerade inte", "fick klagomål"
-
-**Situation:** Inlägg publicerades utan korrekt reklammarkering.
-
-**Åtgärder:**
-1. Redigera inlägget omedelbart - lägg till "REKLAM" överst
-2. Dokumentera när rättelsen gjordes
-3. Informera uppdragsgivaren
-
-**Risker:**
-- Varning från Konsumentverket
-- Förbud vid vite
-- Marknadsstörningsavgift
-- Reputationsskada
-
----
-
-### SCENARIO 025: Använt musik utan licens
-
-**Triggers:** "använde låt", "bakgrundsmusik", "copyright claim"
-
-**Situation:** Musik användes i kommersiellt content utan tillstånd.
-
-**Konsekvenser:**
-- Upphovsrättsintrång
-- Skadeståndsskyldighet
-- Referens: ABBA-fallet (200,000 kr)
-
-**Förebyggande:**
-- Använd royalty-free musik
-- Köp licens via Epidemic Sound, Artlist etc.
-- Kontrollera rättigheter innan publicering
-
----
-
-## Bokslut och deklaration
-
-### SCENARIO 026: Periodiseringsfond (EF)
-
-**Triggers:** "skjuta upp skatt", "periodiseringsfond", "jämna ut resultat"
-
-**Situation:** Influencer vill jämna ut beskattning över år.
-
-**Regler:**
-- Max 30% av överskottet kan avsättas
-- Återförs senast år 6
-- Vid avveckling av EF: Omedelbar återföring
-
-**Exempel:**
-```
-År 1: Överskott 500,000 kr
- Avsättning (30%): 150,000 kr
- Beskattas: 350,000 kr
-
-År 3: Överskott 100,000 kr
- Återföring: 150,000 kr
- Beskattas: 250,000 kr
-```
-
----
-
-### SCENARIO 027: 3:12-utdelning (AB)
-
-**Triggers:** "utdelning", "gränsbelopp", "20% skatt"
-
-**Situation:** Ägare vill ta ut lågbeskattad utdelning från AB.
-
-**Gränsbelopp 2024:**
-- Schablonbelopp: 204,325 kr (2,75 x IBB)
-- ELLER lönebaserat utrymme (kräver minst 681,600 kr i egen lön)
-
-**Strategi:**
-1. Ta ut lön upp till brytpunkt statlig skatt (~615,300 kr)
-2. Ta ut utdelning inom gränsbelopp (20% skatt)
-3. Spara överskjutande i bolaget eller ta som lön
-
----
-
-### SCENARIO 028: Byta från EF till AB
-
-**Triggers:** "vill byta", "starta AB", "övergång"
-
-**Situation:** Influencer vill övergå från EF till AB.
-
-**Process:**
-1. Starta AB (25,000 kr aktiekapital)
-2. Inkråmsöverlåtelse: EF säljer tillgångar till AB
-3. Nya avtal tecknas med AB som part
-4. Uppdatera plattformar med nytt VAT-nummer
-5. Avveckla EF
-
-**Skattekonsekvenser:**
-- Inkråmsöverlåtelse till marknadsvärde
-- Moms på försäljningen
-- Periodiseringsfonder i EF återförs
-- Realisationsvinst i EF beskattas
-
----
-
-## Dubbel struktur
-
-### SCENARIO 029: Fördela uppdrag mellan EF och AB
-
-**Triggers:** "vilket företag", "ska jag fakturera från", "EF eller AB"
-
-**Situation:** Influencer har både EF och AB, nytt uppdrag inkommer.
-
-**Beslutsmatris:**
-
-| Faktor | → EF | → AB |
-|--------|------|------|
-| Ersättning <50,000 kr | ✓ | |
-| Ersättning >100,000 kr | | ✓ |
-| Hög juridisk risk | | ✓ |
-| Engångsuppdrag | ✓ | |
-| Långt ambassadörskap | | ✓ |
-| Behöver bygga SGI | ✓ | |
-
----
-
-### SCENARIO 030: Internfaktura mellan EF och AB
-
-**Triggers:** "fakturera mig själv", "mellan bolagen", "internfaktura"
-
-**Situation:** EF utför tjänst åt eget AB.
-
-**Krav:**
-- Armlängdsprissättning (marknadsmässigt pris)
-- Skriftligt avtal
-- Affärsmässig motivering
-- Moms på fakturan (25%)
-
-**Bokföringsexempel:**
-```
-EF fakturerar AB för videoproduktion: 20,000 kr + moms
-
-I EF:
-Debet 1510 Kundfordringar: 25,000 kr
-Kredit 3010 Intäkter: 20,000 kr
-Kredit 2610 Utgående moms: 5,000 kr
-
-I AB:
-Debet 4010 Köpta tjänster: 20,000 kr
-Debet 2640 Ingående moms: 5,000 kr
-Kredit 2440 Leverantörsskulder: 25,000 kr
-```
-
-**Varning:** Skatteverket granskar internprissättning. Avvikelse >20% från marknad flaggas.
diff --git a/dev_docs/influencer_ai_info/03-plattformskatalog.md b/dev_docs/influencer_ai_info/03-plattformskatalog.md
deleted file mode 100644
index e429ad28..00000000
--- a/dev_docs/influencer_ai_info/03-plattformskatalog.md
+++ /dev/null
@@ -1,398 +0,0 @@
-# Plattformskatalog
-
-## YouTube (Google AdSense)
-
-### Företagsinformation
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Google Ireland Ltd |
-| VAT-nummer | IE6388047V |
-| Adress | Gordon House, Barrow Street, Dublin 4, Ireland |
-| Säte | Irland (EU) |
-
-### Momshantering
-
-| Regel | Värde |
-|-------|-------|
-| Momstyp | Reverse Charge |
-| Svensk moms på faktura | Nej (0%) |
-| Momsdeklaration ruta | 39 |
-| Periodisk sammanställning | Ja, kvartalsvis |
-
-### Utbetalningar
-
-| Parameter | Värde |
-|-----------|-------|
-| Valuta | USD |
-| Utbetalningströskel | $100 |
-| Utbetalningsfrekvens | Månadsvis (21:a-26:e) |
-| Utbetalningsmetod | Banköverföring, check |
-
-### Var hittar jag underlag?
-
-1. YouTube Studio → Analytics → Revenue
-2. AdSense → Payments → Transaction history
-3. Ladda ner CSV för bokföringsunderlag
-
-### Bokföringskontering
-
-```
-Intäkt från YouTube:
-Debet 1940 Bank: [SEK-belopp]
-Kredit 3011 Försäljning tjänster EU: [SEK-belopp]
-```
-
----
-
-## Twitch
-
-### Företagsinformation
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Twitch Interactive Inc |
-| VAT-nummer | Inget (USA) |
-| Adress | 350 Bush Street, 2nd Floor, San Francisco, CA 94104, USA |
-| Säte | USA (utanför EU) |
-
-### Momshantering
-
-| Regel | Värde |
-|-------|-------|
-| Momstyp | Export |
-| Svensk moms på faktura | Nej (0%) |
-| Momsdeklaration ruta | 40 |
-| Periodisk sammanställning | Nej |
-
-### Utbetalningar
-
-| Parameter | Värde |
-|-----------|-------|
-| Valuta | USD |
-| Utbetalningströskel | $50 (Affiliate), $100 (Partner) |
-| Utbetalningsfrekvens | 15:e varje månad (för föregående månad) |
-| Net terms | 45 dagar |
-
-### Intäktsströmmar
-
-| Typ | Beskrivning |
-|-----|-------------|
-| Subscriptions | Prenumerationer (50% till streamer normalt) |
-| Bits | Virtuell valuta från tittare |
-| Ads | Annonsintäkter |
-| Bounties | Sponsrade kampanjer via Twitch |
-
-### Var hittar jag underlag?
-
-1. Creator Dashboard → Channel Analytics → Revenue
-2. Payout History för historiska utbetalningar
-3. Tax Interview måste fyllas i (W-8BEN)
-
-### Bokföringskontering
-
-```
-Intäkt från Twitch:
-Debet 1940 Bank: [SEK-belopp]
-Kredit 3012 Försäljning tjänster utanför EU: [SEK-belopp]
-```
-
----
-
-## Instagram / Meta
-
-### Företagsinformation
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Meta Platforms Ireland Ltd |
-| VAT-nummer | IE9692928F |
-| Adress | 4 Grand Canal Square, Grand Canal Harbour, Dublin 2, Ireland |
-| Säte | Irland (EU) |
-
-### Momshantering
-
-| Regel | Värde |
-|-------|-------|
-| Momstyp | Reverse Charge |
-| Svensk moms på faktura | Nej (0%) |
-| Momsdeklaration ruta | 39 |
-| Periodisk sammanställning | Ja, kvartalsvis |
-
-### Utbetalningar (Bonusprogram)
-
-| Parameter | Värde |
-|-----------|-------|
-| Valuta | USD eller EUR |
-| Utbetalningströskel | $100 |
-| Utbetalningsfrekvens | Månadsvis |
-| Utbetalningsmetod | Banköverföring, PayPal |
-
-### Intäktsströmmar
-
-| Typ | Beskrivning |
-|-----|-------------|
-| Reels Bonus | Prestationsbaserat på Reels-visningar |
-| Badges | Tittare köper badges under Live |
-| Subscriptions | Prenumerationer på exklusivt innehåll |
-| Branded Content | Märkta samarbeten (betalning från varumärke) |
-
-### Var hittar jag underlag?
-
-1. Professional Dashboard → Monetization → Payouts
-2. Meta Business Suite → Insights → Monetization
-3. Payout Settings för bankuppgifter och skatteinfo
-
-### Bokföringskontering
-
-```
-Intäkt från Instagram/Meta:
-Debet 1940 Bank: [SEK-belopp]
-Kredit 3011 Försäljning tjänster EU: [SEK-belopp]
-```
-
----
-
-## TikTok
-
-### Företagsinformation
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | TikTok Technology Ltd (EU) |
-| VAT-nummer | IE3434547SH |
-| Adress | 10 Earlsfort Terrace, Dublin 2, D02 T380, Ireland |
-| Säte | Irland (EU) |
-
-**OBS:** TikToks struktur varierar. Kontrollera alltid avtalet för korrekt entitet.
-
-### Momshantering
-
-| Regel | Värde |
-|-------|-------|
-| Momstyp | Reverse Charge |
-| Svensk moms på faktura | Nej (0%) |
-| Momsdeklaration ruta | 39 |
-| Periodisk sammanställning | Ja, kvartalsvis |
-
-### Utbetalningar
-
-| Parameter | Värde |
-|-----------|-------|
-| Valuta | USD |
-| Utbetalningströskel | $10 (Creator Fund) |
-| Utbetalningsfrekvens | Månadsvis |
-
-### Intäktsströmmar
-
-| Typ | Beskrivning |
-|-----|-------------|
-| Creator Fund | Prestationsbaserat på visningar |
-| Creator Rewards | Förbättrat program ersätter Creator Fund |
-| LIVE Gifts | Virtuella gåvor under livestream |
-| Series | Betalinnehåll |
-
-### Var hittar jag underlag?
-
-1. TikTok Creator Portal → Balance
-2. Transaction History för detaljer
-3. Tax Information måste fyllas i
-
----
-
-## Patreon
-
-### Företagsinformation
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Patreon Inc |
-| VAT-nummer | Inget (USA) |
-| Adress | 600 Townsend Street, Suite 500, San Francisco, CA 94103, USA |
-| Säte | USA (utanför EU) |
-
-### Momshantering
-
-| Regel | Värde |
-|-------|-------|
-| Momstyp | Export |
-| Svensk moms på faktura | Nej (0%) |
-| Momsdeklaration ruta | 40 |
-| Periodisk sammanställning | Nej |
-
-### Utbetalningar
-
-| Parameter | Värde |
-|-----------|-------|
-| Valuta | USD |
-| Utbetalningströskel | $25 |
-| Utbetalningsfrekvens | Månadsvis (1:a-5:e) |
-| Avgifter | 5-12% plattformsavgift + betalningsavgifter |
-
-### Var hittar jag underlag?
-
-1. Creator Dashboard → Income
-2. Payout History med CSV-export
-3. Tax Settings för W-8BEN
-
----
-
-## Spotify (Podcasters)
-
-### Företagsinformation
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Spotify AB |
-| VAT-nummer | SE556703748501 |
-| Adress | Regeringsgatan 19, 111 53 Stockholm, Sweden |
-| Säte | Sverige |
-
-### Momshantering
-
-| Regel | Värde |
-|-------|-------|
-| Momstyp | Svensk inrikes |
-| Svensk moms på faktura | Ja (25%) |
-| Momsdeklaration ruta | 05-08 |
-| Periodisk sammanställning | Nej |
-
-### Bokföringskontering
-
-```
-Intäkt från Spotify:
-Debet 1940 Bank: [totalbelopp]
-Kredit 3010 Försäljning tjänster Sverige: [nettobelopp]
-Kredit 2610 Utgående moms: [moms 25%]
-```
-
----
-
-## Amazon Associates (Affiliate)
-
-### Företagsinformation
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Amazon EU S.à r.l. |
-| VAT-nummer | LU26375245 |
-| Adress | 38 avenue John F. Kennedy, L-1855 Luxembourg |
-| Säte | Luxemburg (EU) |
-
-**OBS:** Amazon har flera entiteter. Kontrollera vilket program/land som är aktuellt.
-
-### Momshantering
-
-| Regel | Värde |
-|-------|-------|
-| Momstyp | Reverse Charge |
-| Svensk moms på faktura | Nej (0%) |
-| Momsdeklaration ruta | 39 |
-| Periodisk sammanställning | Ja, kvartalsvis |
-
-### Utbetalningar
-
-| Parameter | Värde |
-|-----------|-------|
-| Valuta | EUR/USD beroende på program |
-| Utbetalningströskel | €25/£25/$10 |
-| Utbetalningsfrekvens | ~60 dagar efter månadslut |
-
----
-
-## Svenska affiliate-nätverk
-
-### Adtraction
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Adtraction Marketing AB |
-| Organisationsnummer | 556748-8855 |
-| VAT-nummer | SE556748885501 |
-| Säte | Sverige |
-| Moms | 25% svensk moms |
-
-### Tradedoubler
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | Tradedoubler AB |
-| Organisationsnummer | 556575-7423 |
-| VAT-nummer | SE556575742301 |
-| Säte | Sverige |
-| Moms | 25% svensk moms |
-
-### Awin (Nordics)
-
-| Fält | Värde |
-|------|-------|
-| Juridiskt namn | AWIN AG (filial i UK ofta) |
-| Säte | Varierar |
-| Moms | Kontrollera avtal |
-
----
-
-## Sammanfattningstabell
-
-| Plattform | Säte | VAT-nummer | Momsregel | Ruta | Period. sammanst. |
-|-----------|------|------------|-----------|------|-------------------|
-| YouTube | Irland | IE6388047V | Reverse Charge | 39 | Ja |
-| Twitch | USA | - | Export | 40 | Nej |
-| Instagram/Meta | Irland | IE9692928F | Reverse Charge | 39 | Ja |
-| TikTok | Irland | IE3434547SH | Reverse Charge | 39 | Ja |
-| Patreon | USA | - | Export | 40 | Nej |
-| Spotify | Sverige | SE556703748501 | Svensk 25% | 05-08 | Nej |
-| Amazon EU | Luxemburg | LU26375245 | Reverse Charge | 39 | Ja |
-| Adtraction | Sverige | SE556748885501 | Svensk 25% | 05-08 | Nej |
-| Tradedoubler | Sverige | SE556575742301 | Svensk 25% | 05-08 | Nej |
-
----
-
-## Valutakurser
-
-### Huvudregel
-
-Använd valutakursen den dag inbetalningen sker till bankkontot.
-
-### Kurskällor
-
-- Riksbankens dagskurser (officiell)
-- Bankens faktiska växlingskurs (om tillgänglig)
-
-### Praktisk hantering
-
-```
-1. Notera belopp i originalvaluta
-2. Notera inbetalningsdatum
-3. Hämta kurs för det datumet
-4. Beräkna SEK-belopp
-5. Bokför i SEK
-6. Vid fakturadatum ≠ betalningsdatum: Bokför kursdifferens
-```
-
----
-
-## Skatteformulär per plattform
-
-| Plattform | Formulär | Beskrivning |
-|-----------|----------|-------------|
-| YouTube/Google | W-8BEN | US tax withholding |
-| Twitch | W-8BEN | US tax withholding |
-| TikTok | W-8BEN | US tax withholding |
-| Patreon | W-8BEN | US tax withholding |
-| Meta | Tax Information | I plattformen |
-
-**W-8BEN:** Formulär som intygar att du inte är amerikansk skattskyldig. Utan detta hålls 30% amerikansk skatt inne.
-
----
-
-## Utbetalningskalender (typisk)
-
-| Plattform | Intjäningsmånad | Utbetalning |
-|-----------|-----------------|-------------|
-| YouTube | Januari | 21-26 februari |
-| Twitch | Januari | 15 mars |
-| Instagram | Januari | Februari (varierar) |
-| TikTok | Januari | Februari (varierar) |
-| Patreon | Januari | 1-5 februari |
-| Amazon Associates | Januari | Mars (60 dagar) |
diff --git a/dev_docs/influencer_ai_info/04-berakningsexempel.md b/dev_docs/influencer_ai_info/04-berakningsexempel.md
deleted file mode 100644
index e30b4f8c..00000000
--- a/dev_docs/influencer_ai_info/04-berakningsexempel.md
+++ /dev/null
@@ -1,601 +0,0 @@
-# Beräkningsexempel
-
-## 1. Inkomstberäkningar
-
-### 1.1 YouTube-utbetalning med valutaomräkning
-
-**Scenario:** Influencer får månatlig AdSense-utbetalning.
-
-```
-Uppgifter:
-- Utbetalt: $2,847.63 USD
-- Inbetalningsdatum: 2024-02-23
-- Valutakurs (Riksbanken): 10.3842 SEK/USD
-
-Beräkning:
-$2,847.63 × 10.3842 = 29,571.87 SEK
-
-Bokföring:
-Debet 1940 Bank: 29,571.87 kr
-Kredit 3011 Försäljning tjänster EU: 29,571.87 kr
-
-Momsdeklaration:
-Ruta 39: 29,571.87 kr
-
-Periodisk sammanställning:
-Kund: Google Ireland Ltd
-VAT: IE6388047V
-Belopp: 29,571.87 kr
-```
-
----
-
-### 1.2 Barter-produkt med skatteberäkning
-
-**Scenario:** Influencer får väska värd 12,000 kr mot ett Instagram-inlägg.
-
-```
-Uppgifter:
-- Produkt: Designerväska
-- Marknadsvärde: 12,000 kr inkl. moms
-- Bolagsform: Enskild firma
-
-Beräkning skattepliktig inkomst:
-Intäkt: 12,000 kr
-
-Om privat bruk (eget uttag):
-Nettovärde: 12,000 / 1.25 = 9,600 kr
-Moms: 2,400 kr
-
-Bokföring (produkt mottagen):
-Debet 4010 Inköp varor: 9,600 kr
-Debet 2640 Ingående moms: 2,400 kr
-Kredit 3010 Intäkter: 12,000 kr
-
-Bokföring (eget uttag för privat bruk):
-Debet 2013 Eget uttag: 12,000 kr
-Kredit 4010 Inköp varor: 9,600 kr
-Kredit 2640 Ingående moms: 2,400 kr
-
-Skattekonsekvens (antagen marginalskatt 35%):
-Skatt på 12,000 kr: ~4,200 kr
-```
-
----
-
-### 1.3 Sponsrad resa med medföljande
-
-**Scenario:** Influencer bjuds på resa, partner följer med gratis.
-
-```
-Uppgifter:
-- Flyg influencer: 8,500 kr
-- Hotell influencer (5 nätter): 15,000 kr
-- Flyg medföljande: 8,500 kr
-- Hotell medföljande: ingår i dubbelrum
-- Aktiviteter (båda): 4,000 kr
-- Arbetade timmar: 35 timmar under 5 dagar (7h/dag)
-- Dokumenterat arbete: 12 Instagram-inlägg, 4 Stories/dag, 2 Reels
-
-Bedömning influencerns resa:
-- Arbete: 35 timmar = 7 timmar/dag ✓
-- Kriteriet "huvudsaklig arbetstid" uppfyllt
-- Skattefri om nöjesinslag försumbara
-
-Medföljandes resa:
-- Alltid skattepliktig förmån
-
-Beräkning förmånsvärde medföljande:
-Flyg: 8,500 kr
-Hotell: 0 kr (ingen merkostnad för dubbelrum i detta fall)
-Aktiviteter (50%): 2,000 kr
-Totalt förmånsvärde: 10,500 kr
-
-Skattekonsekvens (marginalskatt 35%):
-Skatt på 10,500 kr: ~3,675 kr
-```
-
----
-
-### 1.4 Donations/Tips från Twitch
-
-**Scenario:** Streamer får donations under månad.
-
-```
-Uppgifter:
-- Bits mottagna: 45,000 bits
-- Bits-värde: $0.01 per bit = $450
-- Direktdonationer via PayPal: $320
-- Subscriptions (50% av $4.99 × 85 subs): $212.08
-- Valutakurs: 10.55 SEK/USD
-
-Beräkning total intäkt:
-Bits: $450 × 10.55 = 4,747.50 kr
-Donations: $320 × 10.55 = 3,376.00 kr
-Subs: $212.08 × 10.55 = 2,237.44 kr
-Totalt: 10,360.94 kr
-
-Bokföring (Twitch-utbetalning från USA):
-Debet 1940 Bank: 10,360.94 kr
-Kredit 3012 Försäljning tjänster utanför EU: 10,360.94 kr
-
-Momsdeklaration:
-Ruta 40: 10,360.94 kr
-```
-
----
-
-## 2. Momsberäkningar
-
-### 2.1 Faktura till svenskt företag
-
-**Scenario:** Samarbete med svenskt klädmärke.
-
-```
-Uppgifter:
-- Arvode: 35,000 kr exkl. moms
-- Influencer har F-skatt och är momsregistrerad
-
-Fakturabelopp:
-Arvode: 35,000 kr
-Moms 25%: 8,750 kr
-Totalt att betala: 43,750 kr
-
-Bokföring vid fakturering:
-Debet 1510 Kundfordringar: 43,750 kr
-Kredit 3010 Intäkter: 35,000 kr
-Kredit 2610 Utgående moms: 8,750 kr
-
-Bokföring vid betalning:
-Debet 1940 Bank: 43,750 kr
-Kredit 1510 Kundfordringar: 43,750 kr
-```
-
----
-
-### 2.2 Faktura till EU-företag (Reverse Charge)
-
-**Scenario:** Samarbete med tyskt företag.
-
-```
-Uppgifter:
-- Arvode: €3,000 EUR
-- Valutakurs vid fakturadatum: 11.25 SEK/EUR
-- Kundens VAT-nummer: DE123456789
-
-Fakturabelopp:
-Arvode: €3,000 (33,750 SEK)
-Moms: €0 (Reverse Charge)
-Totalt: €3,000
-
-Obligatorisk text på faktura:
-"Reverse charge - VAT to be accounted for by the recipient"
-"Art. 196 Council Directive 2006/112/EC"
-
-Bokföring vid fakturering:
-Debet 1510 Kundfordringar: 33,750 kr
-Kredit 3011 Försäljning tjänster EU: 33,750 kr
-
-Momsdeklaration:
-Ruta 39: 33,750 kr
-
-Periodisk sammanställning:
-Land: DE
-VAT-nummer: DE123456789
-Belopp: 33,750 kr
-```
-
----
-
-### 2.3 Merch-försäljning till EU-privatperson
-
-**Scenario:** Säljer t-shirt till kund i Finland.
-
-```
-Uppgifter:
-- T-shirt pris: 349 kr inkl. moms
-- Kund: Privatperson i Finland
-- Total EU-privatpersonförsäljning hittills i år: 45,000 kr
-
-Bedömning:
-Under OSS-tröskel (99,680 kr) → Kan välja svensk moms
-
-Alternativ 1: Svensk moms
-Pris: 349 kr inkl. 25% svensk moms
-Netto: 279.20 kr
-Moms: 69.80 kr
-
-Alternativ 2: Finsk moms (24%)
-Netto: 349 / 1.24 = 281.45 kr
-Moms: 67.55 kr
-Redovisas via OSS
-
-Vid överskridande av tröskel:
-- Obligatoriskt mottagarlandets moms
-- Registrera för OSS hos Skatteverket
-```
-
----
-
-### 2.4 Kvartalsvis periodisk sammanställning
-
-**Scenario:** Sammanställning Q1.
-
-```
-EU-försäljning under Q1:
-- Google Ireland Ltd (IE6388047V): 87,450 kr
-- Meta Platforms Ireland Ltd (IE9692928F): 12,300 kr
-- TikTok Technology Ltd (IE3434547SH): 8,200 kr
-- Tyskt varumärke GmbH (DE987654321): 25,000 kr
-
-Periodisk sammanställning:
-┌─────────────────────────────────────────────────────┐
-│ Period: 2024-01-01 till 2024-03-31 │
-├──────────┬────────────────┬─────────────────────────┤
-│ Land │ VAT-nummer │ Belopp (SEK) │
-├──────────┼────────────────┼─────────────────────────┤
-│ IE │ IE6388047V │ 87,450 │
-│ IE │ IE9692928F │ 12,300 │
-│ IE │ IE3434547SH │ 8,200 │
-│ DE │ DE987654321 │ 25,000 │
-├──────────┴────────────────┼─────────────────────────┤
-│ SUMMA │ 132,950 │
-└───────────────────────────┴─────────────────────────┘
-
-Kontrollavstämning:
-Ruta 39 i momsdeklarationen Q1: 132,950 kr ✓
-```
-
----
-
-## 3. Skatteoptimering
-
-### 3.1 Lön vs utdelning i AB
-
-**Scenario:** AB med vinst 800,000 kr före lön.
-
-```
-Förutsättningar:
-- Vinst före lön: 800,000 kr
-- Gränsbelopp för lågbeskattad utdelning: 204,325 kr
-- Brytpunkt statlig skatt: 615,300 kr
-
-Alternativ 1: Endast lön 800,000 kr
-Arbetsgivaravgifter (31.42%): 251,360 kr
-Maximal lönekostnad: 800,000 kr
-Bruttolön: 800,000 / 1.3142 = 608,719 kr
-Inkomstskatt (~32%): 194,790 kr
-Netto till ägaren: 413,929 kr
-SGI: 608,719 kr ✓
-
-Alternativ 2: Lön 500,000 kr + Utdelning
-Lön brutto: 500,000 kr
-Arbetsgivaravgifter: 157,100 kr
-Total lönekostnad: 657,100 kr
-Kvar i bolaget: 142,900 kr
-Bolagsskatt (20.6%): 29,438 kr
-Tillgängligt för utdelning: 113,462 kr
-Utdelningsskatt (20%): 22,692 kr
-Netto utdelning: 90,770 kr
-
-Lön efter skatt (~32%): 340,000 kr
-Total netto: 430,770 kr
-SGI: 500,000 kr ✓
-
-Alternativ 3: Lön till brytpunkt + Max utdelning
-Lön brutto: 615,300 kr
-Arbetsgivaravgifter: 193,327 kr
-Total lönekostnad: 808,627 kr
-→ Överstiger vinst, ej genomförbart
-
-Rekommendation:
-Alternativ 2 ger högst netto OCH god SGI.
-```
-
----
-
-### 3.2 EF: Periodiseringsfond
-
-**Scenario:** Enskild firma med ojämna resultat.
-
-```
-År 1: Överskott 600,000 kr (viralt år)
-År 2: Överskott 150,000 kr (normalt år)
-År 3: Överskott 100,000 kr (svagt år)
-
-Utan periodiseringsfond:
-År 1 skatt (antagen 45% marginal på del): ~200,000 kr
-År 2 skatt (~32%): ~48,000 kr
-År 3 skatt (~32%): ~32,000 kr
-Total skatt: ~280,000 kr
-
-Med periodiseringsfond:
-År 1:
- Överskott: 600,000 kr
- Avsättning (30%): 180,000 kr
- Beskattas: 420,000 kr
- Skatt (~40% snitt): 168,000 kr
-
-År 2:
- Överskott: 150,000 kr
- Avsättning (30%): 45,000 kr
- Beskattas: 105,000 kr
- Skatt (~32%): 33,600 kr
-
-År 3:
- Överskott: 100,000 kr
- Återföring: 225,000 kr (180k + 45k)
- Beskattas: 325,000 kr
- Skatt (~38% snitt): 123,500 kr
-
-Total skatt: ~325,100 kr
-
-Analys:
-I detta fall blev det dyrare med periodiseringsfond!
-Fonden lönar sig när framtida inkomster förväntas vara LÄGRE.
-```
-
----
-
-### 3.3 SGI-optimering
-
-**Scenario:** Influencer planerar barn, vill maximera föräldrapenning.
-
-```
-Nuvarande struktur (AB):
-- Lön: 25,000 kr/månad = 300,000 kr/år
-- Utdelning: 400,000 kr/år
-- SGI: 300,000 kr
-
-Föräldrapenning vid SGI 300,000 kr:
-Dagpenning (80%): 657 kr/dag (tak)
-→ SGI under taket 599,250 kr, får 80% av faktisk SGI
-Faktisk dagpenning: 300,000 × 0.8 / 365 = 657 kr/dag
-
-Optimerad struktur (12 månader före barn):
-- Lön: 50,000 kr/månad = 600,000 kr/år
-- Utdelning: 100,000 kr/år
-- SGI: 600,000 kr
-
-Föräldrapenning vid SGI 600,000 kr:
-Dagpenning (80%): 1,315 kr/dag
-Men tak finns: 1,116 kr/dag (2024)
-
-Beräkning per 390 dagar föräldraledighet:
-Låg SGI (300k): 657 × 390 = 256,230 kr
-Hög SGI (600k): 1,116 × 390 = 435,240 kr
-Skillnad: 179,010 kr mer vid optimerad SGI
-
-Kostnad för omställning:
-Ökad lön 300,000 kr/år → ökad skatt ~100,000 kr
-Nettofördel efter 1 års planering: ~79,000 kr
-```
-
----
-
-## 4. Valutaberäkningar
-
-### 4.1 Kursdifferens vid försenad betalning
-
-**Scenario:** Faktura i EUR med betalning 45 dagar senare.
-
-```
-Fakturadatum: 2024-01-15
-Fakturabelopp: €5,000
-Kurs 2024-01-15: 11.35 SEK/EUR
-Fakturerat i SEK: 56,750 kr
-
-Betalningsdatum: 2024-03-01
-Kurs 2024-03-01: 11.52 SEK/EUR
-Mottaget i SEK: 57,600 kr
-
-Kursdifferens: 57,600 - 56,750 = 850 kr (vinst)
-
-Bokföring vid fakturering:
-Debet 1510 Kundfordringar: 56,750 kr
-Kredit 3011 Försäljning tjänster EU: 56,750 kr
-
-Bokföring vid betalning:
-Debet 1940 Bank: 57,600 kr
-Kredit 1510 Kundfordringar: 56,750 kr
-Kredit 3960 Valutakursvinster: 850 kr
-```
-
----
-
-### 4.2 Aggregerad månadsintäkt från flera plattformar
-
-**Scenario:** Månadssammanställning med blandade valutor.
-
-```
-Januari 2024 intäkter:
-
-YouTube (USD):
- Belopp: $3,245.00
- Inbetalning: 2024-02-22
- Kurs: 10.42
- SEK: 33,812.90
-
-Twitch (USD):
- Belopp: $1,876.50
- Inbetalning: 2024-02-15
- Kurs: 10.38
- SEK: 19,477.67
-
-TikTok (USD):
- Belopp: $456.00
- Inbetalning: 2024-02-28
- Kurs: 10.45
- SEK: 4,765.20
-
-Adtraction (SEK):
- Belopp: 8,450 kr
- SEK: 8,450.00
-
-Total intäkt januari: 66,505.77 kr
-
-Momsredovisning:
-Ruta 39 (EU - YouTube, TikTok): 38,578.10 kr
-Ruta 40 (Export - Twitch): 19,477.67 kr
-Ruta 05-08 (Sverige - Adtraction): 6,760 kr netto + 1,690 kr moms
-```
-
----
-
-## 5. Avdragsberäkningar
-
-### 5.1 Datorutrustning med blandad användning
-
-**Scenario:** Köp av MacBook Pro för video och privat.
-
-```
-Uppgifter:
-- Inköpspris: 35,000 kr inkl. moms
-- Bedömd verksamhetsanvändning: 80%
-- Bolagsform: Enskild firma
-
-Beräkning avdrag:
-Nettopris: 35,000 / 1.25 = 28,000 kr
-Moms: 7,000 kr
-
-Verksamhetsandel 80%:
-Avdragsgill kostnad: 28,000 × 0.80 = 22,400 kr
-Avdragsgill moms: 7,000 × 0.80 = 5,600 kr
-
-Bokföring:
-Debet 1220 Inventarier: 22,400 kr
-Debet 2640 Ingående moms: 5,600 kr
-Debet 2013 Eget uttag: 7,000 kr
-Kredit 1940 Bank: 35,000 kr
-
-Avskrivning (5 år):
-Årligt avdrag: 22,400 / 5 = 4,480 kr
-```
-
----
-
-### 5.2 Hemmakontor (schablon vs faktiskt)
-
-**Scenario:** Influencer arbetar i lägenhet.
-
-```
-Uppgifter:
-- Total hyra: 12,000 kr/månad
-- Lägenhetens yta: 75 kvm
-- Arbetsrummets yta: 12 kvm
-- Arbetade timmar hemma: 1,200 timmar/år
-
-Alternativ 1: Schablonavdrag
-Krav: >800 timmar/år ✓
-Avdrag: 2,000 kr/år
-
-Alternativ 2: Faktiskt avdrag (om kraven uppfylls)
-Krav: Separat rum, exklusiv verksamhetsanvändning
-Andel: 12/75 = 16%
-Årshyra: 12,000 × 12 = 144,000 kr
-Avdrag: 144,000 × 0.16 = 23,040 kr
-
-Skillnad: 21,040 kr/år
-
-VARNING: Faktiskt avdrag kräver att rummet INTE används
-för boende. Kraven är mycket stränga. Vid tveksamhet,
-använd schablon eller hyr extern lokal.
-```
-
----
-
-### 5.3 Resa med delvis privat syfte
-
-**Scenario:** Resa till New York för samarbete + privat.
-
-```
-Uppgifter:
-- Totalt 7 dagar
-- Arbetsdagar: 4 dagar (möten, inspelning)
-- Privata dagar: 3 dagar (sightseeing)
-- Flygbiljett: 9,500 kr
-- Hotell: 3,000 kr/natt × 7 = 21,000 kr
-- Traktamente utland (USA): 614 kr/dag
-
-Beräkning avdragsgill del:
-Flyg: 9,500 × (4/7) = 5,429 kr
-Hotell arbetsdagar: 3,000 × 4 = 12,000 kr
-Traktamente arbetsdagar: 614 × 4 = 2,456 kr
-
-Totalt avdragsgillt: 19,885 kr
-Ej avdragsgillt (privat): 9,500 - 5,429 + 9,000 = 13,071 kr
-```
-
----
-
-## 6. Jämförande beräkningar
-
-### 6.1 EF vs AB vid olika vinstnivåer
-
-**Scenario:** Jämförelse vid 400k, 600k och 1M kr vinst.
-
-```
-Vinst 400,000 kr:
-
-EF:
- Egenavgifter (~28%): 112,000 kr
- Skattepliktig inkomst: 288,000 kr
- Inkomstskatt (~32%): 92,160 kr
- Netto: 195,840 kr
-
-AB (lön 300k + utdelning):
- Lön brutto: 300,000 kr
- Arbetsgivaravgifter: 94,260 kr
- Kvar: 5,740 kr
- Bolagsskatt: 1,182 kr
- Lön efter skatt: 204,000 kr
- Utdelning: 4,558 kr × 0.8 = 3,646 kr
- Netto: 207,646 kr
-
-Fördel AB: 11,806 kr
-
----
-
-Vinst 600,000 kr:
-
-EF:
- Egenavgifter: 168,000 kr
- Skattepliktig: 432,000 kr
- Inkomstskatt (~35%): 151,200 kr
- Netto: 280,800 kr
-
-AB (lön 400k + utdelning):
- Lön brutto: 400,000 kr
- Arbetsgivaravgifter: 125,680 kr
- Kvar: 74,320 kr
- Bolagsskatt: 15,310 kr
- Lön efter skatt: 272,000 kr
- Utdelning: 59,010 kr × 0.8 = 47,208 kr
- Netto: 319,208 kr
-
-Fördel AB: 38,408 kr
-
----
-
-Vinst 1,000,000 kr:
-
-EF:
- Egenavgifter: 280,000 kr
- Skattepliktig: 720,000 kr
- Inkomstskatt (~42%): 302,400 kr
- Netto: 417,600 kr
-
-AB (lön 600k + utdelning):
- Lön brutto: 600,000 kr
- Arbetsgivaravgifter: 188,520 kr
- Kvar: 211,480 kr
- Bolagsskatt: 43,565 kr
- Lön efter skatt: 390,000 kr
- Utdelning: 167,915 kr × 0.8 = 134,332 kr
- Netto: 524,332 kr
-
-Fördel AB: 106,732 kr
-```
-
-**Slutsats:** AB blir mer fördelaktigt ju högre vinsten är.
-Brytpunkt ligger omkring 300-400k kr vinst.
diff --git a/dev_docs/influencer_ai_info/05-beslutstrад.md b/dev_docs/influencer_ai_info/05-beslutstrад.md
deleted file mode 100644
index 9f65de76..00000000
--- a/dev_docs/influencer_ai_info/05-beslutstrад.md
+++ /dev/null
@@ -1,554 +0,0 @@
-# Beslutsträd
-
-## 1. Produkter och förmåner
-
-### 1.1 Mottagen produkt
-
-```
-┌─ Fick du en produkt?
-│
-├─► Fanns avtal/överenskommelse om motprestation?
-│ │
-│ ├─► JA (samarbete)
-│ │ └─► SKATTEPLIKTIG INTÄKT
-│ │ Värde: Marknadspris inkl. moms
-│ │ Bokför som: Intäkt + eget uttag (om privat bruk)
-│ │
-│ └─► NEJ (oombett pressutskick)
-│ │
-│ ├─► Behåller du produkten?
-│ │ │
-│ │ ├─► JA
-│ │ │ └─► SKATTEPLIKTIG INTÄKT
-│ │ │ Värde: Marknadspris inkl. moms
-│ │ │
-│ │ └─► NEJ
-│ │ │
-│ │ ├─► Returnerade
-│ │ │ └─► EJ SKATTEPLIKTIG
-│ │ │ Krav: Spara returkvitto
-│ │ │
-│ │ ├─► Kastade/gav bort
-│ │ │ └─► EJ SKATTEPLIKTIG
-│ │ │ Krav: Ingen privat användning dessförinnan
-│ │ │
-│ │ └─► Sålde vidare
-│ │ └─► FÖRSÄLJNINGSINTÄKT SKATTEPLIKTIG
-│ │ (Ej ursprungsvärdet, utan säljpriset)
-```
-
----
-
-### 1.2 Sponsrad resa
-
-```
-┌─ Bjuden på resa av uppdragsgivare?
-│
-├─► Är resan nödvändig för verksamheten?
-│ │
-│ ├─► NEJ
-│ │ └─► HELA VÄRDET SKATTEPLIKTIGT
-│ │
-│ └─► JA
-│ │
-│ ├─► Arbetar du ≥30h/vecka ELLER ≥6h/dag under resan?
-│ │ │
-│ │ ├─► NEJ
-│ │ │ └─► DELVIS SKATTEPLIKTIGT
-│ │ │ Nöjesandelen beskattas
-│ │ │
-│ │ └─► JA
-│ │ │
-│ │ ├─► Är nöjesinslagen försumbara?
-│ │ │ │
-│ │ │ ├─► JA
-│ │ │ │ └─► SKATTEFRI RESA
-│ │ │ │
-│ │ │ └─► NEJ
-│ │ │ └─► DELVIS SKATTEPLIKTIGT
-│ │ │ Nöjesandelen beskattas
-│
-├─► Följer partner/vän med gratis?
-│ └─► JA
-│ └─► ALLTID SKATTEPLIKTIG FÖRMÅN
-│ Värde: Medföljarens faktiska reskostnad
-```
-
----
-
-### 1.3 Rabattkod/personalrabatt
-
-```
-┌─ Fick du rabatt som del av ersättning?
-│
-├─► Rabatt på produkter du ska marknadsföra?
-│ └─► SKATTEPLIKTIG
-│ Värde: Marknadspris - betalt pris
-│
-├─► Rabatt för eget bruk (ej kopplat till uppdrag)?
-│ │
-│ ├─► Erbjuds samma rabatt till allmänheten?
-│ │ └─► EJ SKATTEPLIKTIG (öppen kampanj)
-│ │
-│ └─► Exklusiv rabatt?
-│ └─► SKATTEPLIKTIG
-│ Värde: Normalrabatt till allmänheten jämförs
-```
-
----
-
-## 2. Momshantering
-
-### 2.1 Val av momsregel vid fakturering
-
-```
-┌─ Vem fakturerar du?
-│
-├─► Svenskt företag
-│ └─► SVENSK MOMS 25%
-│ Ruta: 05-08
-│ Periodisk sammanställning: Nej
-│
-├─► Företag i annat EU-land
-│ │
-│ ├─► Har kunden giltigt VAT-nummer?
-│ │ │
-│ │ ├─► JA
-│ │ │ └─► REVERSE CHARGE (0% moms)
-│ │ │ Ruta: 39
-│ │ │ Periodisk sammanställning: JA
-│ │ │ Text på faktura: "Reverse charge"
-│ │ │
-│ │ └─► NEJ
-│ │ └─► Behandla som privatperson
-│ │ → Se "Privatperson i EU"
-│ │
-├─► Företag utanför EU
-│ └─► EXPORT (0% moms)
-│ Ruta: 40
-│ Periodisk sammanställning: Nej
-│
-├─► Privatperson i Sverige
-│ └─► SVENSK MOMS 25%
-│ Ruta: 05-08
-│
-├─► Privatperson i annat EU-land
-│ │
-│ ├─► Total EU-privatförsäljning ≤99,680 kr/år?
-│ │ │
-│ │ ├─► JA
-│ │ │ └─► VALFRITT:
-│ │ │ • Svensk moms 25% (enklast)
-│ │ │ • ELLER mottagarlandets moms via OSS
-│ │ │
-│ │ └─► NEJ (över tröskeln)
-│ │ └─► OBLIGATORISKT mottagarlandets moms
-│ │ Redovisa via OSS
-│ │
-├─► Privatperson utanför EU
-│ └─► EXPORT (0% moms)
-│ Ruta: 40
-```
-
----
-
-### 2.2 Momsregistrering
-
-```
-┌─ Behöver jag momsregistrera mig?
-│
-├─► Bedriver du momspliktig verksamhet?
-│ │
-│ ├─► NEJ (t.ex. sjukvård, utbildning)
-│ │ └─► INGEN MOMSREGISTRERING
-│ │
-│ └─► JA
-│ │
-│ ├─► Omsättning >80,000 kr/år?
-│ │ │
-│ │ ├─► JA
-│ │ │ └─► OBLIGATORISK registrering
-│ │ │
-│ │ └─► NEJ
-│ │ │
-│ │ ├─► Säljer du till EU-företag (Reverse Charge)?
-│ │ │ │
-│ │ │ ├─► JA
-│ │ │ │ └─► REKOMMENDERAD registrering
-│ │ │ │ (för periodisk sammanställning)
-│ │ │ │
-│ │ │ └─► NEJ
-│ │ │ └─► FRIVILLIG registrering
-│ │ │ Fördel: Momsavdrag på inköp
-```
-
----
-
-## 3. Bolagsform
-
-### 3.1 EF eller AB?
-
-```
-┌─ Vilken bolagsform passar?
-│
-├─► Förväntad årlig vinst?
-│ │
-│ ├─► <300,000 kr
-│ │ └─► ENSKILD FIRMA
-│ │ • Enklare administration
-│ │ • Skattemässigt likvärdigt
-│ │
-│ ├─► 300,000 - 500,000 kr
-│ │ │
-│ │ ├─► Accepterar du personligt ansvar?
-│ │ │ │
-│ │ │ ├─► JA
-│ │ │ │ └─► EF kan fungera
-│ │ │ │ Överväg AB om växande
-│ │ │ │
-│ │ │ └─► NEJ
-│ │ │ └─► AKTIEBOLAG
-│ │ │
-│ ├─► >500,000 kr
-│ │ └─► AKTIEBOLAG
-│ │ • Betydande skattefördel via 3:12
-│ │ • Ansvarsbegränsning
-│ │
-├─► Juridisk risk i verksamheten?
-│ │
-│ ├─► HÖG (kontroversiellt innehåll, upphovsrättskänsligt)
-│ │ └─► AKTIEBOLAG
-│ │ Personlig ekonomi skyddad
-│ │
-│ └─► LÅG
-│ └─► Båda fungerar
-│
-├─► Planerar investerare/partners?
-│ │
-│ ├─► JA
-│ │ └─► AKTIEBOLAG
-│ │ Ägarandelar möjliga
-│ │
-│ └─► NEJ
-│ └─► Båda fungerar
-```
-
----
-
-### 3.2 När byta från EF till AB?
-
-```
-┌─ Ska jag byta till AB?
-│
-├─► Vinst >500,000 kr konsekvent (2+ år)?
-│ └─► JA → Stark indikation för AB
-│
-├─► Juridisk tvist eller risk?
-│ └─► JA → AB skyddar privatekonomin
-│
-├─► Vill ha utdelning istället för lön?
-│ └─► JA → AB möjliggör 20% skatt
-│
-├─► Vill anställa personal?
-│ └─► JA → AB ofta lämpligare
-│
-├─► Planerar sälja verksamheten?
-│ └─► JA → AB enklare att överlåta
-│
-Om 2+ JA → Överväg starkt att byta till AB
-```
-
----
-
-## 4. Avdrag
-
-### 4.1 Är kostnaden avdragsgill?
-
-```
-┌─ Är utgiften avdragsgill?
-│
-├─► Teknik (kamera, dator, mikrofon, ljus)
-│ │
-│ ├─► Används i verksamheten?
-│ │ │
-│ │ ├─► Uteslutande verksamhet
-│ │ │ └─► FULLT AVDRAG
-│ │ │
-│ │ ├─► Delvis privat
-│ │ │ └─► PROPORTIONELLT AVDRAG
-│ │ │ (Bedöm verksamhetsandel)
-│ │ │
-│ │ └─► Huvudsakligen privat
-│ │ └─► INGET/MARGINELLT AVDRAG
-│
-├─► Kläder
-│ │
-│ ├─► Kan användas privat?
-│ │ │
-│ │ ├─► JA (normala kläder)
-│ │ │ └─► EJ AVDRAGSGILL
-│ │ │
-│ │ └─► NEJ
-│ │ │
-│ │ ├─► Uniform/skyddskläder
-│ │ │ └─► AVDRAGSGILL
-│ │ │
-│ │ ├─► Extrem scenklädsel
-│ │ │ └─► AVDRAGSGILL
-│ │ │ (Dokumentera varför ej privat)
-│ │ │
-│ │ └─► Historisk kostym/rekvisita
-│ │ └─► AVDRAGSGILL
-│
-├─► Smink och skönhet
-│ │
-│ ├─► Vardagssmink/hudvård
-│ │ └─► EJ AVDRAGSGILL
-│ │
-│ ├─► Teatersmink/sfx
-│ │ └─► AVDRAGSGILL
-│ │
-│ └─► Skönhetsingrepp (filler, botox, kirurgi)
-│ └─► EJ AVDRAGSGILL
-│ (Oavsett "varumärkes"-argument)
-│
-├─► Resa
-│ │
-│ ├─► Arbetsresa med dokumenterat syfte?
-│ │ │
-│ │ ├─► JA, endast arbete
-│ │ │ └─► FULLT AVDRAG
-│ │ │
-│ │ ├─► JA, men även privata inslag
-│ │ │ └─► PROPORTIONELLT AVDRAG
-│ │ │ (Endast arbetsdagar)
-│ │ │
-│ │ └─► Huvudsakligen privat
-│ │ └─► EJ AVDRAGSGILL
-│ │
-│ └─► Pendling hem-arbete
-│ └─► EJ AVDRAGSGILL
-│
-├─► Hemmakontor
-│ │
-│ ├─► Separat rum, ej bostad, exklusiv användning?
-│ │ │
-│ │ ├─► JA
-│ │ │ └─► FAKTISKT AVDRAG
-│ │ │ (Andel av hyra)
-│ │ │
-│ │ └─► NEJ
-│ │ └─► SCHABLONAVDRAG 2,000 kr
-│ │ (Krav: >800 h arbete i bostad)
-│
-├─► Agentarvode/provision
-│ └─► FULLT AVDRAG
-│ (Direkt kopplat till intäkt)
-│
-├─► Programvara/prenumerationer
-│ │
-│ ├─► Verksamhetsrelaterad?
-│ │ │
-│ │ ├─► JA (Adobe, redigeringsprogram)
-│ │ │ └─► FULLT AVDRAG
-│ │ │
-│ │ └─► NEJ (Netflix, Spotify privat)
-│ │ └─► EJ AVDRAGSGILL
-```
-
----
-
-## 5. Social trygghet
-
-### 5.1 SGI-optimering
-
-```
-┌─ Hur optimerar jag SGI?
-│
-├─► Bolagsform?
-│ │
-│ ├─► Enskild firma
-│ │ │
-│ │ ├─► SGI = skattemässigt överskott
-│ │ │
-│ │ ├─► Gör du avdrag som sänker överskottet?
-│ │ │ │
-│ │ │ ├─► JA
-│ │ │ │ └─► VARNING: Lägre SGI!
-│ │ │ │ Överväg om avdragen är värda
-│ │ │ │ den lägre sjuk-/föräldrapenningen
-│ │ │ │
-│ │ │ └─► NEJ
-│ │ │ └─► OK
-│ │ │
-│ │ └─► Uppbyggnadsskede (<36 månader)?
-│ │ └─► JA → Kan få jämförelseinkomst
-│ │
-│ └─► Aktiebolag
-│ │
-│ ├─► SGI = endast utbetald lön
-│ │ (Utdelning räknas EJ)
-│ │
-│ ├─► Tar du ut tillräcklig lön?
-│ │ │
-│ │ ├─► JA (≥400,000 kr/år rekommenderat)
-│ │ │ └─► OK
-│ │ │
-│ │ └─► NEJ (låg lön + hög utdelning)
-│ │ └─► VARNING: Lågt skydd!
-│ │ Risk vid sjukdom/barn
-│
-├─► Planerar du barn inom 12 månader?
-│ │
-│ └─► JA
-│ └─► MAXIMERA SGI NU
-│ • EF: Minimera avdrag
-│ • AB: Höj lönen, sänk utdelning
-│ • SGI tar ~12 månader att bygga upp
-│
-├─► Befintligt SGI-skydd tillräckligt?
-│ │
-│ ├─► Test: Vad får du i sjukpenning?
-│ │ Sjukpenning = SGI × 0.8 / 365 per dag
-│ │
-│ └─► Rekommendation: SGI ≥400,000 kr
-│ → ~876 kr/dag i sjukpenning
-```
-
----
-
-## 6. Marknadsföringslagen
-
-### 6.1 Ska inlägget märkas som reklam?
-
-```
-┌─ Behöver jag märka med REKLAM?
-│
-├─► Fick du ersättning (pengar, produkter, tjänster)?
-│ │
-│ ├─► JA
-│ │ │
-│ │ ├─► Finns avtal/överenskommelse om publicering?
-│ │ │ │
-│ │ │ ├─► JA
-│ │ │ │ └─► MÄRKNING KRÄVS
-│ │ │ │ "REKLAM" eller "ANNONS"
-│ │ │ │ Placering: Överst i inlägg
-│ │ │ │
-│ │ │ └─► NEJ (spontan recension)
-│ │ │ │
-│ │ │ ├─► Behöll du produkten?
-│ │ │ │ │
-│ │ │ │ ├─► JA
-│ │ │ │ │ └─► REKOMMENDERAD märkning
-│ │ │ │ │ (Transparens)
-│ │ │ │ │
-│ │ │ │ └─► NEJ
-│ │ │ │ └─► Ingen märkning krävs
-│ │ │
-│ └─► NEJ (köpte själv, äkta rekommendation)
-│ │
-│ ├─► Affiliate-länk inkluderad?
-│ │ │
-│ │ ├─► JA
-│ │ │ └─► MÄRKNING KRÄVS
-│ │ │ (Du tjänar på klick/köp)
-│ │ │
-│ │ └─► NEJ
-│ │ └─► Ingen märkning krävs
-│
-├─► Är det osäkert?
-│ └─► JA
-│ └─► MÄRK ÄNDÅ
-│ Hellre för tydlig än otydlig
-```
-
----
-
-## 7. Dubbel struktur (EF + AB)
-
-### 7.1 Vilket företag för uppdraget?
-
-```
-┌─ Ska uppdraget faktureras från EF eller AB?
-│
-├─► Ersättningsnivå?
-│ │
-│ ├─► <50,000 kr
-│ │ └─► EF (enkelhet)
-│ │
-│ ├─► 50,000 - 100,000 kr
-│ │ └─► Bedöm övriga faktorer ↓
-│ │
-│ └─► >100,000 kr
-│ └─► AB (skatteoptimering)
-│
-├─► Juridisk risk?
-│ │
-│ ├─► Hög (kontroversiellt, oklara rättigheter)
-│ │ └─► AB (ansvarsbegränsning)
-│ │
-│ └─► Låg
-│ └─► Båda fungerar
-│
-├─► Avtalstyp?
-│ │
-│ ├─► Engångsuppdrag
-│ │ └─► EF (enkelhet)
-│ │
-│ └─► Långt ambassadörskap (6+ månader)
-│ └─► AB (stabilare struktur)
-│
-├─► Internationell klient?
-│ │
-│ ├─► JA
-│ │ └─► AB (tydligare för utländska parter)
-│ │
-│ └─► NEJ
-│ └─► Båda fungerar
-│
-├─► Behöver bygga SGI?
-│ │
-│ ├─► JA, via EF-överskott
-│ │ └─► EF
-│ │
-│ ├─► JA, via AB-lön
-│ │ └─► AB
-│ │
-│ └─► SGI tillräcklig
-│ └─► Optimera för skatt
-```
-
----
-
-### 7.2 Internfaktura mellan EF och AB
-
-```
-┌─ Ska EF fakturera AB (eller vice versa)?
-│
-├─► Finns verklig tjänst/vara som levereras?
-│ │
-│ ├─► JA
-│ │ │
-│ │ ├─► Är prissättningen marknadsmässig?
-│ │ │ │
-│ │ │ ├─► JA (inom ±20% av marknad)
-│ │ │ │ │
-│ │ │ │ ├─► Finns skriftligt avtal?
-│ │ │ │ │ │
-│ │ │ │ │ ├─► JA
-│ │ │ │ │ │ └─► OK - Internfaktura tillåten
-│ │ │ │ │ │ Glöm ej moms (25%)
-│ │ │ │ │ │
-│ │ │ │ │ └─► NEJ
-│ │ │ │ │ └─► UPPRÄTTA AVTAL
-│ │ │ │ │ Innan fakturering
-│ │ │ │ │
-│ │ │ └─► NEJ (avviker >20%)
-│ │ │ └─► JUSTERA PRISET
-│ │ │ Risk: Omklassificering av Skatteverket
-│ │ │
-│ └─► NEJ (ren skatteplanering)
-│ └─► EJ TILLÅTEN
-│ Risk: Förtäckt lön/utdelning
-```
diff --git a/dev_docs/influencer_ai_info/06-felsokningsguide.md b/dev_docs/influencer_ai_info/06-felsokningsguide.md
deleted file mode 100644
index e4bb2b41..00000000
--- a/dev_docs/influencer_ai_info/06-felsokningsguide.md
+++ /dev/null
@@ -1,500 +0,0 @@
-# Felsökningsguide
-
-## 1. Momsproblem
-
-### 1.1 Momsen stämmer inte
-
-**Symptom:** Momsdeklarationen balanserar inte eller Skatteverket ifrågasätter.
-
-**Kontrollpunkter:**
-
-```
-□ Har du separerat inhemsk/EU/export-försäljning korrekt?
- → Inhemsk (25%): Ruta 05-08
- → EU B2B (0%): Ruta 39
- → Export (0%): Ruta 40
-
-□ Matchar periodisk sammanställning Ruta 39?
- → Summorna MÅSTE vara identiska
- → Kontrollera att alla EU-kunder finns med
-
-□ Har du bokfört barter-produkter med moms?
- → Marknadsvärde INKL moms som intäkt
- → Momsandel ska redovisas
-
-□ Finns valutakursdifferenser som påverkar?
- → Kursen vid fakturering vs betalning
- → Differenser bokförs separat
-
-□ Har du blandat B2B och B2C inom EU?
- → B2B: Reverse Charge
- → B2C: OSS eller svensk moms
-```
-
-**Åtgärder:**
-1. Exportera alla försäljningsfakturor
-2. Kategorisera per momstyp
-3. Summera per kategori
-4. Jämför med momsdeklaration
-5. Korrigera differenser
-
----
-
-### 1.2 Periodisk sammanställning saknas eller är fel
-
-**Symptom:** Förseningsavgift eller ifrågasättande från Skatteverket.
-
-**Kontrollpunkter:**
-
-```
-□ Har du sålt tjänster till EU-företag under perioden?
- → Om ja, periodisk sammanställning obligatorisk
-
-□ Har du kundens korrekta VAT-nummer?
- → Verifiera på VIES: https://ec.europa.eu/taxation_customs/vies/
-
-□ Har du lämnat sammanställningen i tid?
- → Deadline: 20:e i månaden efter kvartalets slut
- → Q1: 20 april
- → Q2: 20 juli
- → Q3: 20 oktober
- → Q4: 20 januari
-
-□ Stämmer beloppen med Ruta 39?
- → Summorna MÅSTE matcha exakt
-```
-
-**Åtgärder vid miss:**
-1. Lämna in försenad sammanställning omedelbart
-2. Betala förseningsavgift (1,250 kr)
-3. Korrigera momsdeklaration om nödvändigt
-
----
-
-### 1.3 Osäker på vilken momsregel som gäller
-
-**Frågor att ställa:**
-
-```
-1. Vem är kunden?
- □ Företag → Var är de registrerade?
- □ Privatperson → Var bor de?
-
-2. Är det en vara eller tjänst?
- □ Vara → Leveransplats avgör
- □ Tjänst → Kundens säte avgör (B2B)
-
-3. Har kunden VAT-nummer?
- □ Ja → Verifiera det
- □ Nej → Behandla som privatperson
-```
-
----
-
-## 2. Bokföringsproblem
-
-### 2.1 Blandade privata och företagstransaktioner
-
-**Symptom:** Oklara verifikationer, sammanblandade konton.
-
-**Kontrollpunkter:**
-
-```
-□ Har du separata bankkonton?
- → Privat
- → EF (om tillämpligt)
- → AB (om tillämpligt)
-
-□ Har privata inköp betalats från företagskontot?
- → Bokför som eget uttag (EF) eller lån till ägare (AB)
-
-□ Har företagsinköp betalats privat?
- → Bokför som insättning eget kapital (EF) eller lån från ägare (AB)
-```
-
-**Åtgärder:**
-1. Gå igenom alla kontoutdrag
-2. Markera alla transaktioner som företag/privat
-3. Bokför korrigeringar för felaktiga
-4. Upprätta rutin för framtiden
-
----
-
-### 2.2 Saknar verifikationer
-
-**Symptom:** Transaktioner utan underlag.
-
-**Kontrollpunkter:**
-
-```
-□ Vilken typ av transaktion?
- → Plattformsintäkt: Ladda ner från plattformen
- → Inköp: Kontakta leverantör för kopia
- → Barter: Upprätta eget underlag
-
-□ Kan du rekonstruera underlaget?
- → Screenshot av beställning
- → E-postbekräftelse
- → Bankutdrag som stöd
-```
-
-**Barter-underlag som du själv upprättar:**
-```
-VERIFIKATION - MOTTAGEN PRODUKT
-
-Datum: [mottagningsdatum]
-Produkt: [beskrivning]
-Avsändare: [företag/person]
-Marknadsvärde inkl. moms: [belopp] kr
-Källa för värdering: [prislapp/webbshop/etc.]
-Motprestation: [beskrivning av inlägg/samarbete]
-
-Undertecknad av: [influencerns namn]
-```
-
----
-
-### 2.3 Valutaomräkning stämmer inte
-
-**Symptom:** Differenser mellan faktura och betalning.
-
-**Kontrollpunkter:**
-
-```
-□ Vilken kurs använde du vid fakturering?
- → Ska vara kurs vid fakturadatum
-
-□ Vilken kurs gällde vid betalning?
- → Kontrollera Riksbankens officiella kurs
-
-□ Har du bokfört kursdifferensen separat?
- → Vinst: Konto 3960
- → Förlust: Konto 7960
-```
-
-**Beräkningsexempel:**
-```
-Faktura: €1,000 @ 11.50 = 11,500 kr
-Betalning: €1,000 @ 11.35 = 11,350 kr
-Kursförlust: 150 kr
-
-Bokföring:
-Debet 1940 Bank: 11,350
-Debet 7960 Valutakursförluster: 150
-Kredit 1510 Kundfordringar: 11,500
-```
-
----
-
-## 3. Skattedeklarationsproblem
-
-### 3.1 Saknar F-skatt men har fakturerat
-
-**Symptom:** Uppdragsgivare har inte dragit skatt, eller faktura utställd utan F-skatt.
-
-**Kontrollpunkter:**
-
-```
-□ Hade du F-skatt när fakturan ställdes ut?
- → Om nej: Uppdragsgivaren ska ha dragit A-skatt
-
-□ Drog uppdragsgivaren skatt?
- → Kontrollera lönespecifikation/kontrolluppgift
-
-□ Betalade uppdragsgivaren arbetsgivaravgifter?
- → Ska synas på kontrolluppgift
-```
-
-**Åtgärder:**
-1. Om skatt EJ drogs: Deklarera inkomsten, du ansvarar för skatten
-2. Kontakta uppdragsgivaren för kontrolluppgift
-3. Ansök om F-skatt om du planerar fortsätta
-
----
-
-### 3.2 Fått preliminärskattebesked med fel belopp
-
-**Symptom:** Debiterad F-skatt stämmer inte med förväntad inkomst.
-
-**Kontrollpunkter:**
-
-```
-□ Baseras beskedet på gammal/felaktig uppgift?
- → Skatteverket använder senaste deklarationen
-
-□ Har din verksamhet förändrats väsentligt?
- → Ökade/minskade intäkter
-
-□ Har du redovisat alla intäkter korrekt?
-```
-
-**Åtgärder:**
-1. Logga in på Skatteverket
-2. Ändra preliminär inkomstdeklaration
-3. Ny debitering beräknas automatiskt
-
----
-
-### 3.3 Kvarskatt trots F-skatt
-
-**Symptom:** Slutskattebesked visar kvarskatt.
-
-**Vanliga orsaker:**
-
-```
-□ Debiterad F-skatt var för låg
- → Inkomsten blev högre än beräknat
-
-□ Egenavgifter ej medräknade korrekt
- → Särskilt relevant för EF
-
-□ Intäkter utan avdragen skatt
- → Utländska plattformar drar ej svensk skatt
- → Barter-produkter har ej skatt avdragen
-
-□ Kapitalvinster/utdelningar
- → Beskattas separat
-```
-
-**Åtgärder:**
-1. Analysera slutskattebeskedet
-2. Justera kommande års preliminärskatt
-3. Skapa buffert för kvarskatt
-
----
-
-## 4. SGI-problem
-
-### 4.1 SGI är 0 eller mycket låg
-
-**Symptom:** Försäkringskassan meddelar låg SGI.
-
-**Kontrollpunkter för EF:**
-
-```
-□ Vad visar NE-bilagan som överskott?
- → SGI = överskott
-
-□ Har du gjort stora avdrag?
- → Sänker överskottet och därmed SGI
-
-□ Är verksamheten i uppbyggnadsskede (<36 mån)?
- → Kan få jämförelseinkomst istället
-```
-
-**Kontrollpunkter för AB:**
-
-```
-□ Hur mycket lön har du tagit ut?
- → SGI = utbetald lön
-
-□ Tar du mest utdelning?
- → Utdelning räknas EJ i SGI
-
-□ Är lönen "marknadsmässig"?
- → För låg lön kan ifrågasättas
-```
-
-**Åtgärder:**
-1. Beräkna vilken SGI du behöver
-2. Justera lön/överskott för att nå nivån
-3. Kontakta Försäkringskassan för omprövning
-
----
-
-### 4.2 Väntar barn men har låg SGI
-
-**Symptom:** Oro för låg föräldrapenning.
-
-**Tidslinje:**
-```
-SGI fastställs vid:
-- Födsel (för föräldrapenning)
-- Baseras på inkomst ~12 månader bakåt
-
-Åtgärd om <12 månader kvar:
-→ Höj lön/överskott OMEDELBART
-→ Varje månad med högre inkomst hjälper
-
-Åtgärd om >12 månader kvar:
-→ Planera inkomstfördelning noggrant
-→ Sikta på SGI ≥599,250 kr för maximal föräldrapenning
-```
-
----
-
-## 5. Plattformsproblem
-
-### 5.1 Hittar inte fakturaunderlag
-
-**Per plattform:**
-
-| Plattform | Var hittar jag underlag? |
-|-----------|--------------------------|
-| YouTube | YouTube Studio → Analytics → Revenue → Transaction history i AdSense |
-| Twitch | Creator Dashboard → Channel Analytics → Revenue |
-| Instagram | Professional Dashboard → Monetization → Payouts |
-| TikTok | TikTok Creator Portal → Balance → Transaction History |
-| Patreon | Creator Dashboard → Income → Payout History |
-
-**Om underlag saknas:**
-1. Kontakta plattformens support
-2. Använd bankutdrag som stöd
-3. Upprätta egen verifikation med tillgänglig information
-
----
-
-### 5.2 Plattform har hållit inne skatt (W-8BEN)
-
-**Symptom:** 30% avdrag på USA-baserade plattformar.
-
-**Kontrollpunkter:**
-
-```
-□ Har du fyllt i W-8BEN korrekt?
- → Formulär som intygar icke-amerikansk skattestatus
-
-□ Har formuläret löpt ut?
- → Giltigt i 3 år
- → Måste förnyas
-
-□ Har du angett korrekt land?
- → Sverige har skatteavtal med USA
-```
-
-**Åtgärder:**
-1. Logga in på plattformen
-2. Gå till skatteuppgifter/tax information
-3. Fyll i nytt W-8BEN
-4. Kontakta support om innehållen skatt kan återbetalas
-
----
-
-## 6. Juridiska problem
-
-### 6.1 Klagomål om reklammarkering
-
-**Symptom:** Varning från Konsumentverket eller klagomål.
-
-**Omedelbara åtgärder:**
-
-```
-1. Redigera inlägget
- → Lägg till "REKLAM" överst
- → Se till att det är tydligt synligt
-
-2. Dokumentera
- → Ta screenshot av korrigerat inlägg
- → Notera datum och tid för ändring
-
-3. Informera uppdragsgivaren
- → De kan också bli ansvariga
-```
-
-**Förebyggande:**
-- Märk ALLA betalda samarbeten
-- Placera märkning ÖVERST
-- Vid osäkerhet: Märk ändå
-
----
-
-### 6.2 Upphovsrättskrav (musik, bilder)
-
-**Symptom:** Copyright claim, krav på ersättning, nedtagning.
-
-**Omedelbara åtgärder:**
-
-```
-1. Ta ner innehållet
- → Stoppar ytterligare intrång
-
-2. Svara INTE på krav utan juridisk rådgivning
- → Medge ingenting
-
-3. Dokumentera
- → Spara allt material
- → Notera publiceringsperiod
-```
-
-**Förebyggande:**
-- Använd endast licensierad musik
-- Epidemic Sound, Artlist = säkra alternativ
-- Kontrollera bildlicenser
-
----
-
-## 7. Dubbel struktur-problem
-
-### 7.1 Blandat EF och AB
-
-**Symptom:** Oklart vilket företag som fakturerat/betalat vad.
-
-**Kontrollpunkter:**
-
-```
-□ Finns transaktioner bokförda i fel företag?
- → Gå igenom alla verifikationer
-
-□ Har samma kostnad bokförts i båda?
- → Dubbelräkning ej tillåten
-
-□ Har internfakturor hanterats korrekt?
- → Moms ska vara med
- → Avtal ska finnas
-```
-
-**Åtgärder:**
-1. Gör fullständig genomgång av båda bokföringarna
-2. Upprätta lista över alla internfakturor
-3. Korrigera felaktiga bokningar
-4. Upprätta tydliga rutiner
-
----
-
-### 7.2 Skatteverket ifrågasätter internprissättning
-
-**Symptom:** Frågor om transaktioner mellan EF och AB.
-
-**Dokumentation som behövs:**
-
-```
-□ Skriftliga avtal för alla transaktioner
-□ Prissättningsunderlag (marknadsjämförelser)
-□ Affärsmässig motivering
-□ Faktiska leveranser/prestationer
-```
-
-**Försvar:**
-1. Visa att priset är marknadsmässigt
-2. Visa att verklig tjänst/vara levererades
-3. Visa affärsmässigt syfte (ej endast skatteplanering)
-
----
-
-## 8. Akuta situationer
-
-### 8.1 Missad deadline
-
-| Deadline | Konsekvens vid miss | Åtgärd |
-|----------|---------------------|--------|
-| Momsdeklaration | Förseningsavgift | Lämna in omedelbart |
-| Periodisk sammanställning | 1,250 kr avgift | Lämna in omedelbart |
-| Inkomstdeklaration | Förseningsavgift + skönstaxering | Kontakta Skatteverket |
-| F-skatt betalning | Ränta | Betala + kontakta Skatteverket |
-
-### 8.2 Kontrollbesked från Skatteverket
-
-**Steg:**
-1. Läs noggrant vad de frågar om
-2. Samla all relevant dokumentation
-3. Svara inom angiven tid
-4. Vid osäkerhet: Anlita rådgivare
-5. Var sanningsenlig men ange inte mer än vad som frågas
-
-### 8.3 Revision
-
-**Förberedelser:**
-1. Samla ALL bokföring för perioden
-2. Kontrollera att verifikationer finns
-3. Förbered förklaringar för ovanliga poster
-4. Anlita redovisningskonsult om möjligt
diff --git a/dev_docs/influencer_ai_info/07-kalender-deadlines.md b/dev_docs/influencer_ai_info/07-kalender-deadlines.md
deleted file mode 100644
index a611e487..00000000
--- a/dev_docs/influencer_ai_info/07-kalender-deadlines.md
+++ /dev/null
@@ -1,306 +0,0 @@
-# Kalender och deadlines
-
-## Årsöversikt
-
-### Januari
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) december | Månadsredovisare |
-| 12 | Arbetsgivardeklaration december | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 20 | Periodisk sammanställning Q4 | EU-försäljning |
-| 26 | Momsdeklaration Q4 (okt-dec) | Kvartalsredovisare |
-| 31 | Kontrolluppgifter till Skatteverket | AB (löner) |
-
-### Februari
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) januari | Månadsredovisare |
-| 12 | Arbetsgivardeklaration januari | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 28 | Preliminär inkomstdeklaration (ändring) | Om behov finns |
-
-### Mars
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) februari | Månadsredovisare |
-| 12 | Arbetsgivardeklaration februari | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 31 | Bokslut räkenskapsår (kalenderår) | AB |
-
-### April
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) mars | Månadsredovisare |
-| 12 | Arbetsgivardeklaration mars | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 20 | Periodisk sammanställning Q1 | EU-försäljning |
-| 26 | Momsdeklaration Q1 (jan-mar) | Kvartalsredovisare |
-
-### Maj
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 2 | Inkomstdeklaration privatperson + NE | EF |
-| 12 | Momsdeklaration (månads) april | Månadsredovisare |
-| 12 | Arbetsgivardeklaration april | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-
-### Juni
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) maj | Månadsredovisare |
-| 12 | Arbetsgivardeklaration maj | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 30 | Årsredovisning till Bolagsverket | AB (kalenderår) |
-
-### Juli
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 1 | Inkomstdeklaration AB (kalenderår) | AB |
-| 12 | Momsdeklaration (månads) juni | Månadsredovisare |
-| 12 | Arbetsgivardeklaration juni | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 20 | Periodisk sammanställning Q2 | EU-försäljning |
-| 26 | Momsdeklaration Q2 (apr-jun) | Kvartalsredovisare |
-
-### Augusti
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) juli | Månadsredovisare |
-| 12 | Arbetsgivardeklaration juli | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| ~15 | Slutskattebesked | Alla |
-
-### September
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) augusti | Månadsredovisare |
-| 12 | Arbetsgivardeklaration augusti | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| ~12 | Kvarskatt inbetalning 1 | Vid kvarskatt |
-
-### Oktober
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) september | Månadsredovisare |
-| 12 | Arbetsgivardeklaration september | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 20 | Periodisk sammanställning Q3 | EU-försäljning |
-| 26 | Momsdeklaration Q3 (jul-sep) | Kvartalsredovisare |
-
-### November
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) oktober | Månadsredovisare |
-| 12 | Arbetsgivardeklaration oktober | AB med anställda |
-| ~12 | Kvarskatt inbetalning 2 | Vid kvarskatt |
-| 17 | F-skatt inbetalning | EF och AB |
-
-### December
-
-| Dag | Händelse | Gäller |
-|-----|----------|--------|
-| 12 | Momsdeklaration (månads) november | Månadsredovisare |
-| 12 | Arbetsgivardeklaration november | AB med anställda |
-| 17 | F-skatt inbetalning | EF och AB |
-| 27 | Sista arbetsdag före jul (myndigheter) | Planering |
-| 31 | Räkenskapsårets slut | Kalenderår |
-
----
-
-## Kvartalsvisa deadlines
-
-### Momsdeklaration (kvartalsredovisare)
-
-| Kvartal | Period | Deadline |
-|---------|--------|----------|
-| Q1 | Jan-Mar | 12 maj (papper) / 26 april (e-tjänst) |
-| Q2 | Apr-Jun | 17 aug (papper) / 26 juli (e-tjänst) |
-| Q3 | Jul-Sep | 12 nov (papper) / 26 okt (e-tjänst) |
-| Q4 | Okt-Dec | 12 feb (papper) / 26 jan (e-tjänst) |
-
-### Periodisk sammanställning (EU-försäljning)
-
-| Kvartal | Period | Deadline |
-|---------|--------|----------|
-| Q1 | Jan-Mar | 20 april |
-| Q2 | Apr-Jun | 20 juli |
-| Q3 | Jul-Sep | 20 oktober |
-| Q4 | Okt-Dec | 20 januari |
-
-### OSS-deklaration (EU-privatpersonsförsäljning)
-
-| Kvartal | Period | Deadline |
-|---------|--------|----------|
-| Q1 | Jan-Mar | 30 april |
-| Q2 | Apr-Jun | 31 juli |
-| Q3 | Jul-Sep | 31 oktober |
-| Q4 | Okt-Dec | 31 januari |
-
----
-
-## F-skatt inbetalningsdatum
-
-| Månad | Inbetalningsdatum |
-|-------|-------------------|
-| Januari | 17 januari |
-| Februari | 17 februari |
-| Mars | 17 mars |
-| April | 17 april |
-| Maj | 17 maj |
-| Juni | 17 juni |
-| Juli | 17 juli |
-| Augusti | 17 augusti |
-| September | 17 september |
-| Oktober | 17 oktober |
-| November | 17 november |
-| December | 17 december |
-
-**OBS:** Om den 17:e infaller på helg, gäller närmast följande vardag.
-
----
-
-## Löpande uppgifter
-
-### Dagligen/Veckovis
-
-- [ ] Spara kvitton och verifikationer
-- [ ] Notera mottagna produkter (barter)
-- [ ] Dokumentera arbetsresor
-
-### Månadsvis
-
-- [ ] Stäm av bankkonton mot bokföring
-- [ ] Bokför månadens transaktioner
-- [ ] Kontrollera plattformsutbetalningar
-- [ ] Beräkna eventuella valutakursdifferenser
-- [ ] Momsdeklaration (om månadsredovisare)
-
-### Kvartalsvis
-
-- [ ] Momsdeklaration (om kvartalsredovisare)
-- [ ] Periodisk sammanställning (om EU-försäljning)
-- [ ] OSS-deklaration (om EU-privatpersonsförsäljning)
-- [ ] Resultatuppföljning
-- [ ] SGI-kontroll
-
-### Årligen
-
-**Januari-februari:**
-- [ ] Upprätta årsbokslut för föregående år
-- [ ] Sammanställ alla intäkter och kostnader
-- [ ] Beräkna avskrivningar
-- [ ] Hantera periodiseringsfonder (EF)
-
-**Mars-april:**
-- [ ] Förbered inkomstdeklaration
-- [ ] Kontrollera kontrolluppgifter
-- [ ] Granska förifylld deklaration
-
-**Maj:**
-- [ ] Lämna inkomstdeklaration (2 maj)
-- [ ] NE-bilaga (EF)
-
-**Juni-juli:**
-- [ ] Årsredovisning till Bolagsverket (AB)
-- [ ] Inkomstdeklaration AB (1 juli)
-
-**Augusti-september:**
-- [ ] Analysera slutskattebesked
-- [ ] Justera preliminärskatt för nästa år
-- [ ] Planera för eventuell kvarskatt
-
-**Oktober-december:**
-- [ ] Skatteplanering inför årsskiftet
-- [ ] 3:12-beräkning (AB)
-- [ ] Pensionssparande (avdragsgillt)
-- [ ] Friskvårdsbidrag (AB)
-
----
-
-## Påminnelser per bolagsform
-
-### Enskild firma (EF)
-
-| Tidpunkt | Uppgift |
-|----------|---------|
-| Månadsvis | Bokföring, avstämning |
-| Kvartalsvis | Moms, periodisk sammanställning |
-| 2 maj | Inkomstdeklaration + NE-bilaga |
-| Löpande | Dokumentera barter, resor, avdrag |
-
-### Aktiebolag (AB)
-
-| Tidpunkt | Uppgift |
-|----------|---------|
-| Månadsvis | Bokföring, lönehantering, arbetsgivardeklaration |
-| Kvartalsvis | Moms, periodisk sammanställning |
-| 31 mars | Bokslut (kalenderår) |
-| 30 juni | Årsredovisning till Bolagsverket |
-| 1 juli | Inkomstdeklaration AB |
-| December | 3:12-beräkning, utdelningsbeslut |
-
-### Dubbel struktur (EF + AB)
-
-| Tidpunkt | Uppgift |
-|----------|---------|
-| Månadsvis | Separat bokföring båda, internfakturor |
-| Kvartalsvis | Separata momsdeklarationer, periodiska sammanställningar |
-| 2 maj | Inkomstdeklaration privatperson + NE |
-| 30 juni | Årsredovisning AB |
-| 1 juli | Inkomstdeklaration AB |
-| Löpande | Avstämning interntransaktioner |
-
----
-
-## Kritiska datum att INTE missa
-
-### Förseningsavgifter
-
-| Uppgift | Avgift vid miss |
-|---------|-----------------|
-| Periodisk sammanställning | 1,250 kr |
-| Momsdeklaration | 625 kr (ökar vid upprepad försening) |
-| Inkomstdeklaration | 1,250 kr (kan öka) |
-| Årsredovisning | Förseningsavgift + risk för likvidation |
-
-### Viktiga gränsdatum
-
-| Datum | Händelse |
-|-------|----------|
-| 2 maj | Sista dag inkomstdeklaration privatperson |
-| 30 juni | Sista dag årsredovisning AB (6 mån efter bokslut) |
-| 1 juli | Sista dag inkomstdeklaration AB (kalenderår) |
-| 31 december | Räkenskapsårets slut, sista dag för avdragsgilla pensionsinbetalningar |
-
----
-
-## Platshållare för användarspecifika påminnelser
-
-### Min bolagsform: [EF / AB / Båda]
-
-### Mina deadlines:
-
-| Uppgift | Deadline | Status |
-|---------|----------|--------|
-| Momsdeklaration Q_ | | |
-| Periodisk sammanställning Q_ | | |
-| F-skatt månad | | |
-| Inkomstdeklaration | | |
-| Årsredovisning | | |
-
-### Mina återkommande uppgifter:
-
-- [ ] ...
-- [ ] ...
diff --git a/dev_docs/influencer_ai_info/08-varningsflaggor.md b/dev_docs/influencer_ai_info/08-varningsflaggor.md
deleted file mode 100644
index 16e57993..00000000
--- a/dev_docs/influencer_ai_info/08-varningsflaggor.md
+++ /dev/null
@@ -1,542 +0,0 @@
-# Varningsflaggor
-
-## 1. Bokföringsvarningar
-
-### 1.1 Sammanblandning av entiteter
-
-**Flagga:** Transaktion verkar bokförd i fel företag
-
-**Triggers:**
-- Samma fakturanummer i både EF och AB
-- Kostnad bokförd i AB men betald från EF-konto
-- Intäkt från plattform bokförd i båda entiteterna
-
-**AI-åtgärd:**
-```
-VARNING: Denna transaktion kan vara bokförd i fel entitet.
-Kontrollera:
-- Vilken entitet har avtalet med kunden?
-- Från vilket konto gjordes betalningen?
-- Har samma transaktion bokförts i den andra entiteten?
-```
-
----
-
-### 1.2 Privata kostnader i verksamheten
-
-**Flagga:** Misstänkt privat kostnad bokförd som företagskostnad
-
-**Triggers:**
-- Klädinköp (ej uniformer/rekvisita)
-- Smink och skönhetsprodukter
-- Gym/träningskort (i EF)
-- Restaurangbesök utan dokumenterad affärsanledning
-- Resor utan arbetssyfte
-
-**AI-åtgärd:**
-```
-VARNING: Denna kostnad kan vara privat och ej avdragsgill.
-[Typ av kostnad] kräver:
-- Dokumentation av affärssyfte
-- Kan endast dras av om [specifika villkor]
-Vill du fortsätta bokföra detta som företagskostnad?
-```
-
----
-
-### 1.3 Saknad verifikation
-
-**Flagga:** Transaktion utan tillräckligt underlag
-
-**Triggers:**
-- Inbetalning utan faktura/avtal
-- Barter-produkt utan värderingsunderlag
-- Resa utan syftesdokumentation
-
-**AI-åtgärd:**
-```
-VARNING: Verifikation saknas eller är ofullständig.
-För att bokföra behövs:
-- [Lista på kravd dokumentation]
-Vill du skapa ett eget underlag?
-```
-
----
-
-### 1.4 Orimliga belopp
-
-**Flagga:** Belopp avviker kraftigt från normalt
-
-**Triggers:**
-- Enskilt inköp >50,000 kr utan förklaring
-- Negativ intäkt (rättelse?)
-- Valutakurs utanför rimligt intervall
-
-**AI-åtgärd:**
-```
-VARNING: Beloppet verkar ovanligt.
-- Bokfört belopp: [X] kr
-- Normalt intervall: [Y-Z] kr
-Kontrollera att beloppet är korrekt.
-```
-
----
-
-## 2. Momsvarningar
-
-### 2.1 Periodisk sammanställning saknas
-
-**Flagga:** EU-försäljning utan periodisk sammanställning
-
-**Triggers:**
-- Försäljning bokförd i Ruta 39
-- Ingen periodisk sammanställning inlämnad för perioden
-- Periodisk sammanställning ≠ Ruta 39
-
-**AI-åtgärd:**
-```
-VARNING: Periodisk sammanställning krävs.
-Du har bokfört [X] kr i EU-försäljning under [kvartal].
-Deadline för periodisk sammanställning: [datum]
-Förseningsavgift vid miss: 1,250 kr
-
-Kunder att rapportera:
-- [Företag 1]: [VAT-nummer], [belopp]
-- [Företag 2]: [VAT-nummer], [belopp]
-```
-
----
-
-### 2.2 Felaktig momshantering
-
-**Flagga:** Moms hanterad inkonsekvent med kundtyp
-
-**Triggers:**
-- Svensk moms debiterad till EU-företag med VAT-nummer
-- Ingen moms debiterad till svensk kund
-- Export-moms på EU-försäljning
-
-**AI-åtgärd:**
-```
-VARNING: Momshanteringen verkar felaktig.
-Kund: [Kundnamn]
-Kundens säte: [Land]
-VAT-nummer: [Om finns]
-
-Korrekt momshantering:
-- [Regel som borde gälla]
-- Ruta i momsdeklaration: [X]
-
-Vill du korrigera?
-```
-
----
-
-### 2.3 OSS-tröskel överskriden
-
-**Flagga:** EU-privatpersonförsäljning överstiger 99,680 kr
-
-**Triggers:**
-- Summa B2C EU-försäljning >99,680 kr under året
-- Fortsatt svensk moms efter överskridande
-
-**AI-åtgärd:**
-```
-VARNING: OSS-tröskel överskriden.
-Total EU-privatpersonsförsäljning: [X] kr
-Tröskel: 99,680 kr
-
-Konsekvens:
-- Obligatoriskt att debitera mottagarlandets moms
-- Registrera för OSS hos Skatteverket
-- Lämna kvartalsvis OSS-deklaration
-
-Tidigare försäljning under året kan behöva korrigeras.
-```
-
----
-
-### 2.4 Ogiltigt VAT-nummer
-
-**Flagga:** VAT-nummer kunde inte verifieras
-
-**Triggers:**
-- VAT-nummer angivet men validering misslyckades
-- Format stämmer ej med landskod
-
-**AI-åtgärd:**
-```
-VARNING: VAT-nummer kunde inte verifieras.
-Angivet nummer: [VAT-nummer]
-Land: [Landkod]
-
-Verifiera på VIES: https://ec.europa.eu/taxation_customs/vies/
-
-Om ogiltigt:
-- Kunden behandlas som privatperson
-- Svensk moms eller OSS gäller
-```
-
----
-
-## 3. SGI-varningar
-
-### 3.1 Låg SGI-grund
-
-**Flagga:** SGI-grundande inkomst under rekommenderad nivå
-
-**Triggers:**
-- EF: Överskott <200,000 kr/år
-- AB: Lön <200,000 kr/år
-- Total SGI-grund <400,000 kr/år
-
-**AI-åtgärd:**
-```
-VARNING: Lågt socialförsäkringsskydd.
-Din SGI-grund: [X] kr/år
-Rekommenderad miniminivå: 400,000 kr/år
-
-Vid sjukdom:
-- Nuvarande sjukpenning: ~[Y] kr/dag
-- Med rekommenderad SGI: ~[Z] kr/dag
-
-Vid föräldraledighet (390 dagar):
-- Nu: [A] kr totalt
-- Rekommenderat: [B] kr totalt
-- Skillnad: [C] kr
-
-Överväg att:
-- EF: Minska avdrag / öka överskott
-- AB: Höja löneuttag
-```
-
----
-
-### 3.2 Hög utdelning, låg lön (AB)
-
-**Flagga:** Obalans mellan lön och utdelning
-
-**Triggers:**
-- Utdelning >3x lön
-- Lön under 300,000 kr med vinst >500,000 kr
-- SGI-konsekvens ej beaktad
-
-**AI-åtgärd:**
-```
-VARNING: Skatteoptimering påverkar ditt sociala skydd.
-Uttagen lön: [X] kr
-Planerad utdelning: [Y] kr
-Din SGI: [X] kr (endast lön räknas)
-
-Konsekvens:
-- Sjukpenning baseras på [X] kr
-- Föräldrapenning baseras på [X] kr
-- Utdelning [Y] kr ger INGET socialt skydd
-
-Rekommendation: Balansera lön och utdelning utifrån ditt behov av trygghet.
-```
-
----
-
-### 3.3 Planerad föräldraledighet
-
-**Flagga:** Användare nämner barn/föräldraledighet med låg SGI
-
-**Triggers:**
-- Nyckelord: "gravid", "barn", "föräldraledigt", "VAB"
-- Kombinerat med låg SGI-grund
-
-**AI-åtgärd:**
-```
-VIKTIGT: Föräldrapenning baseras på din SGI.
-Nuvarande SGI-grund: [X] kr
-
-Om barn planeras inom 12 månader:
-- SGI fastställs vid barnets födelse
-- Varje månad med högre inkomst höjer SGI
-
-Åtgärd NU:
-- EF: Redovisa högre överskott
-- AB: Höj månadslönen
-- Sikta på SGI ≥599,250 kr för maximal föräldrapenning
-```
-
----
-
-## 4. Strukturvarningar (dubbel struktur)
-
-### 4.1 Internprissättning avviker
-
-**Flagga:** Pris mellan EF och AB verkar icke-marknadsmässigt
-
-**Triggers:**
-- Timpris <300 kr eller >2,000 kr
-- Avvikelse >20% från jämförbar extern prissättning
-- Pris utan dokumenterad grund
-
-**AI-åtgärd:**
-```
-VARNING: Internprissättningen kan ifrågasättas.
-Transaktion: [Beskrivning]
-Pris: [X] kr
-Marknadsmässigt intervall: [Y-Z] kr
-
-Skatteverket kräver armlängdspris.
-Vid avvikelse:
-- Risk för omklassificering
-- Förtäckt lön/utdelning beskattas hårdare
-
-Rekommendation: Dokumentera varför priset är marknadsmässigt.
-```
-
----
-
-### 4.2 Avtal saknas för interntransaktion
-
-**Flagga:** Faktura mellan EF och AB utan avtal
-
-**Triggers:**
-- Internfaktura bokförd
-- Inget avtal registrerat i systemet
-
-**AI-åtgärd:**
-```
-VARNING: Avtal saknas för interntransaktion.
-Transaktion: [Beskrivning]
-Belopp: [X] kr
-
-Krav för godkänd interntransaktion:
-1. Skriftligt avtal
-2. Marknadsmässig prissättning
-3. Verklig tjänst/vara levererad
-4. Affärsmässig motivering
-
-Upprätta avtal FÖRE fakturering.
-```
-
----
-
-### 4.3 Alla kostnader i ett företag, alla intäkter i annat
-
-**Flagga:** Misstänkt resultatförflyttning
-
-**Triggers:**
-- EF har endast kostnader (förlust)
-- AB har endast intäkter (hög vinst)
-- Eller vice versa
-
-**AI-åtgärd:**
-```
-VARNING: Obalanserad resultatfördelning.
-EF resultat: [X] kr
-AB resultat: [Y] kr
-
-Detta mönster kan tyda på:
-- Felaktig allokering av kostnader
-- Resultatförflyttning (ej tillåtet utan affärsmässig grund)
-
-Kontrollera:
-- Är kostnaderna bokförda i rätt entitet?
-- Har rätt entitet fakturerat kunderna?
-- Finns underlag för fördelningen?
-```
-
----
-
-## 5. Juridiska varningar
-
-### 5.1 Reklammarkering saknas
-
-**Flagga:** Betalt samarbete utan tydlig reklammarkering
-
-**Triggers:**
-- Inkomst från varumärke/plattform
-- Ingen notering om reklammarkering
-- Samarbetsavtal registrerat
-
-**AI-åtgärd:**
-```
-PÅMINNELSE: Kontrollera reklammarkering.
-Samarbete med: [Företag]
-Ersättning: [X] kr
-
-Krav enligt Marknadsföringslagen:
-- "REKLAM" eller "ANNONS" överst i inlägg
-- Tydlig och omedelbart synlig
-- I video: Muntligt OCH/ELLER textgrafik
-
-Underlåtenhet kan leda till:
-- Varning från Konsumentverket
-- Förbud vid vite
-- Marknadsstörningsavgift
-```
-
----
-
-### 5.2 Upphovsrättskänsligt material
-
-**Flagga:** Risk för upphovsrättsintrång
-
-**Triggers:**
-- Video/musik-content i kommersiellt sammanhang
-- Ingen licensdokumentation
-- Känd låt/artist nämnd
-
-**AI-åtgärd:**
-```
-VARNING: Kontrollera upphovsrätt.
-Om du använder musik/bilder/video:
-- Har du licens?
-- Är materialet royalty-free?
-
-Utan licens:
-- Risk för skadestånd (referens: ABBA-fallet 200,000 kr)
-- Innehåll kan tas ner
-- Plattformskonto kan stängas
-
-Säkra alternativ:
-- Epidemic Sound
-- Artlist
-- Creative Commons
-```
-
----
-
-## 6. Administrativa varningar
-
-### 6.1 Deadline närmar sig
-
-**Flagga:** Viktig deadline inom 7 dagar
-
-**Triggers:**
-- Momsdeklaration oinlämnad
-- Periodisk sammanställning oinlämnad
-- F-skatt obetald
-- Inkomstdeklaration oinlämnad
-
-**AI-åtgärd:**
-```
-DEADLINE-VARNING: [Uppgift]
-Deadline: [Datum] ([X] dagar kvar)
-
-Status: [Ej påbörjad / Påbörjad / Klar]
-
-Förseningsavgift vid miss: [Belopp] kr
-
-[Länk/instruktion för att slutföra]
-```
-
----
-
-### 6.2 Saknad kontrolluppgift
-
-**Flagga:** Inkomst utan motsvarande kontrolluppgift
-
-**Triggers:**
-- Intäkt bokförd från svenskt företag
-- Ingen kontrolluppgift i förväg
-- Deklarationsperiod närmar sig
-
-**AI-åtgärd:**
-```
-VARNING: Kontrolluppgift kan saknas.
-Inkomst från: [Företag]
-Belopp: [X] kr
-Period: [År/Månad]
-
-Kontrollera:
-- Fick du kontrolluppgift?
-- Om nej, kontakta [Företag]
-
-Kontrolluppgifter ska finnas i e-tjänsten senast [datum].
-```
-
----
-
-### 6.3 Valutakurs ej dokumenterad
-
-**Flagga:** Utländsk transaktion utan kursdokumentation
-
-**Triggers:**
-- Belopp i USD/EUR/annan valuta
-- Ingen valutakurs angiven
-- Stor skillnad mellan möjliga kurser
-
-**AI-åtgärd:**
-```
-VARNING: Valutakurs behöver dokumenteras.
-Transaktion: [Beskrivning]
-Belopp: [Valuta] [Originalbelopp]
-Datum: [Inbetalningsdatum]
-
-Ange valutakurs eller hämta automatiskt:
-- Riksbankens kurs [datum]: [X.XX]
-- Beräknat SEK-belopp: [Y] kr
-
-Kursen ska vara den som gällde vid inbetalningsdatum.
-```
-
----
-
-## 7. Automatiska kontroller
-
-### 7.1 Periodiska avstämningar
-
-```
-MÅNATLIG KONTROLL:
-□ Summa intäkter plattformar = Summa bokförda intäkter?
-□ Banksaldo = Bokfört saldo?
-□ Ingående moms rimlig i förhållande till kostnader?
-□ Utgående moms rimlig i förhållande till intäkter?
-
-KVARTALSVIS KONTROLL:
-□ Periodisk sammanställning = Ruta 39?
-□ SGI-grund tillräcklig?
-□ Internfakturor avstämda mellan EF och AB?
-
-ÅRSVIS KONTROLL:
-□ Alla kontrolluppgifter mottagna?
-□ Preliminärskatt vs faktisk skatt?
-□ Periodiseringsfonder inom gränser?
-□ 3:12-gränsbelopp beräknat?
-```
-
----
-
-### 7.2 Flaggningströsklar
-
-| Kontroll | Flagga om |
-|----------|-----------|
-| SGI-grund | <200,000 kr/år |
-| Lön vs utdelning (AB) | Utdelning >3x lön |
-| Internpris | Avviker >20% från marknad |
-| Periodisk sammanställning | Saknas vid EU-försäljning |
-| Momsavvikelse | >5% differens |
-| Kostnad utan verifikation | Alltid |
-| Privat kostnad i företag | Alltid |
-| Deadline | <7 dagar kvar |
-
----
-
-## 8. Eskaleringsregler
-
-### När ska AI rekommendera extern rådgivning?
-
-```
-REKOMMENDERA REVISOR/REDOVISNINGSKONSULT:
-- Omsättning >3 MSEK/år
-- Komplex dubbel struktur
-- Internationella transaktioner med osäker momshantering
-- Skatteverket har skickat förfrågan
-
-REKOMMENDERA JURIST:
-- Upphovsrättskrav
-- Avtalsförhandling med stort värde (>100,000 kr)
-- Tvist med uppdragsgivare
-- Marknadsföringsrättslig varning
-
-REKOMMENDERA FÖRSÄKRINGSKASSAN:
-- SGI-relaterade frågor
-- Uppbyggnadsskede-bedömning
-- Omprövning av beslut
-```
diff --git a/lib/bookkeeping/category-mapping.ts b/lib/bookkeeping/category-mapping.ts
index 624dc88a..e399fcfa 100644
--- a/lib/bookkeeping/category-mapping.ts
+++ b/lib/bookkeeping/category-mapping.ts
@@ -1,4 +1,5 @@
-import type { TransactionCategory, MappingResult, VatJournalLine, Transaction, EntityType } from '@/types'
+import type { TransactionCategory, MappingResult, VatJournalLine, Transaction, EntityType, VatTreatment } from '@/types'
+import { getVatRate } from './vat-entries'
/**
* Maps TransactionCategory to BAS accounts for journal entry creation
@@ -45,7 +46,8 @@ export function getCategoryAccountMapping(
category: TransactionCategory,
amount: number,
isBusiness: boolean,
- entityType: EntityType = 'enskild_firma'
+ entityType: EntityType = 'enskild_firma',
+ vatTreatment?: VatTreatment
): CategoryAccountMapping {
// Private/owner transactions use entity-specific accounts
if (!isBusiness) {
@@ -77,7 +79,7 @@ export function getCategoryAccountMapping(
// Business income categories
const incomeMapping: Record = {
income_services: '3001', // Försäljning tjänster 25%
- income_products: '3001', // Försäljning varor 25%
+ income_products: '3002', // Försäljning varor 25%
income_other: '3900', // Övriga rörelseintäkter
}
@@ -89,11 +91,14 @@ export function getCategoryAccountMapping(
const vatExemptCategories = ['expense_bank_fees', 'expense_card_fees', 'expense_currency_exchange']
const isVatExempt = vatExemptCategories.includes(category)
+ // Use provided vatTreatment, or default based on category
+ const resolvedVat = vatTreatment ?? (isVatExempt ? null : 'standard_25')
+
return {
debitAccount: expenseAccount,
creditAccount: BANK_ACCOUNT,
- vatTreatment: isVatExempt ? null : 'standard_25',
- vatDebitAccount: isVatExempt ? null : '2641', // Debiterad ingående moms
+ vatTreatment: resolvedVat,
+ vatDebitAccount: resolvedVat ? '2641' : null, // Debiterad ingående moms
vatCreditAccount: null,
}
}
@@ -101,12 +106,33 @@ export function getCategoryAccountMapping(
// Check if it's an income category
if (category.startsWith('income_')) {
const incomeAccount = incomeMapping[category] || '3900'
+
+ // Use provided vatTreatment, or default to standard_25
+ const resolvedVat = vatTreatment ?? 'standard_25'
+
+ // Determine output VAT account based on rate
+ let outputVatAccount: string | null = null
+ switch (resolvedVat) {
+ case 'standard_25':
+ outputVatAccount = '2611' // Utgående moms försäljning 25%
+ break
+ case 'reduced_12':
+ outputVatAccount = '2621' // Utgående moms försäljning 12%
+ break
+ case 'reduced_6':
+ outputVatAccount = '2631' // Utgående moms försäljning 6%
+ break
+ default:
+ outputVatAccount = null
+ break
+ }
+
return {
debitAccount: BANK_ACCOUNT,
creditAccount: incomeAccount,
- vatTreatment: 'standard_25',
+ vatTreatment: resolvedVat,
vatDebitAccount: null,
- vatCreditAccount: '2610', // Utgående moms
+ vatCreditAccount: outputVatAccount,
}
}
@@ -138,34 +164,38 @@ export function buildMappingResultFromCategory(
category: TransactionCategory,
transaction: Transaction,
isBusiness: boolean,
- entityType: EntityType = 'enskild_firma'
+ entityType: EntityType = 'enskild_firma',
+ vatTreatment?: VatTreatment
): MappingResult {
- const mapping = getCategoryAccountMapping(category, transaction.amount, isBusiness, entityType)
+ const mapping = getCategoryAccountMapping(category, transaction.amount, isBusiness, entityType, vatTreatment)
const vatLines: VatJournalLine[] = []
- // Calculate VAT if applicable (Swedish standard: gross amount includes 25% VAT)
- // VAT = gross * 0.25 / 1.25 = gross * 0.20
- if (isBusiness && mapping.vatTreatment === 'standard_25') {
- const grossAmount = Math.abs(transaction.amount)
- const vatAmount = Math.round((grossAmount * 0.20) * 100) / 100 // Round to öre
+ // Calculate VAT if applicable using the resolved treatment from mapping
+ const treatment = mapping.vatTreatment as VatTreatment | null
+ if (isBusiness && treatment) {
+ const vatRate = getVatRate(treatment)
+ if (vatRate > 0) {
+ const grossAmount = Math.abs(transaction.amount)
+ const vatAmount = Math.round((grossAmount * vatRate / (1 + vatRate)) * 100) / 100
- if (transaction.amount < 0 && mapping.vatDebitAccount) {
- // Expense: Ingående moms (deductible VAT)
- vatLines.push({
- account_number: mapping.vatDebitAccount,
- debit_amount: vatAmount,
- credit_amount: 0,
- description: 'Ingående moms 25%',
- })
- } else if (transaction.amount > 0 && mapping.vatCreditAccount) {
- // Income: Utgående moms (output VAT)
- vatLines.push({
- account_number: mapping.vatCreditAccount,
- debit_amount: 0,
- credit_amount: vatAmount,
- description: 'Utgående moms 25%',
- })
+ if (transaction.amount < 0 && mapping.vatDebitAccount) {
+ // Expense: Ingående moms (deductible VAT)
+ vatLines.push({
+ account_number: mapping.vatDebitAccount,
+ debit_amount: vatAmount,
+ credit_amount: 0,
+ description: `Ingående moms ${vatRate * 100}%`,
+ })
+ } else if (transaction.amount > 0 && mapping.vatCreditAccount) {
+ // Income: Utgående moms (output VAT)
+ vatLines.push({
+ account_number: mapping.vatCreditAccount,
+ debit_amount: 0,
+ credit_amount: vatAmount,
+ description: `Utgående moms ${vatRate * 100}%`,
+ })
+ }
}
}
diff --git a/lib/bookkeeping/engine.ts b/lib/bookkeeping/engine.ts
index f330cfdc..f3de706d 100644
--- a/lib/bookkeeping/engine.ts
+++ b/lib/bookkeeping/engine.ts
@@ -125,9 +125,8 @@ function buildLineInserts(
amount_in_currency: line.amount_in_currency ? Math.round(line.amount_in_currency * 100) / 100 : null,
exchange_rate: line.exchange_rate || null,
line_description: line.line_description || null,
- tax_code: line.tax_code || null,
- cost_center: line.cost_center || null,
- project: line.project || null,
+ cost_center_id: line.cost_center || null,
+ project_id: line.project || null,
sort_order: index,
}))
}
diff --git a/lib/bookkeeping/invoice-entries.ts b/lib/bookkeeping/invoice-entries.ts
index 19295d25..fbdced96 100644
--- a/lib/bookkeeping/invoice-entries.ts
+++ b/lib/bookkeeping/invoice-entries.ts
@@ -187,10 +187,71 @@ export async function createCreditNoteJournalEntry(
return createJournalEntry(userId, input)
}
+/**
+ * Create journal entry for kontantmetoden (cash method) when payment is received.
+ * Combined entry: revenue + VAT recognised at payment.
+ *
+ * Debit 1930 Företagskonto [total]
+ * Credit 30xx Försäljning [subtotal]
+ * Credit 26xx Utgående moms [vat_amount] (if applicable)
+ */
+export async function createInvoiceCashEntry(
+ userId: string,
+ invoice: Invoice,
+ paymentDate: string
+): Promise {
+ const fiscalPeriodId = await findFiscalPeriod(userId, paymentDate)
+ if (!fiscalPeriodId) {
+ console.warn('No open fiscal period found for payment date:', paymentDate)
+ return null
+ }
+
+ const revenueAccount = getRevenueAccount(invoice.vat_treatment)
+ const lines: CreateJournalEntryLineInput[] = []
+
+ // Debit: Företagskonto (total received)
+ lines.push({
+ account_number: '1930',
+ debit_amount: invoice.total,
+ credit_amount: 0,
+ line_description: `Betalning faktura ${invoice.invoice_number}`,
+ })
+
+ // Credit: Revenue account (subtotal excl VAT)
+ lines.push({
+ account_number: revenueAccount,
+ debit_amount: 0,
+ credit_amount: invoice.subtotal,
+ line_description: `Försäljning faktura ${invoice.invoice_number}`,
+ })
+
+ // Credit: Output VAT (if applicable)
+ if (invoice.vat_amount > 0) {
+ const vatAccount = getOutputVatAccount(invoice.vat_treatment)
+ lines.push({
+ account_number: vatAccount,
+ debit_amount: 0,
+ credit_amount: invoice.vat_amount,
+ line_description: `Utgående moms faktura ${invoice.invoice_number}`,
+ })
+ }
+
+ const input: CreateJournalEntryInput = {
+ fiscal_period_id: fiscalPeriodId,
+ entry_date: paymentDate,
+ description: `Betalning faktura ${invoice.invoice_number} (kontantmetoden)`,
+ source_type: 'invoice_cash_payment',
+ source_id: invoice.id,
+ lines,
+ }
+
+ return createJournalEntry(userId, input)
+}
+
/**
* Get the appropriate revenue account based on VAT treatment
*/
-function getRevenueAccount(vatTreatment: VatTreatment): string {
+export function getRevenueAccount(vatTreatment: VatTreatment): string {
switch (vatTreatment) {
case 'standard_25':
return '3001' // Försäljning 25%
@@ -212,7 +273,7 @@ function getRevenueAccount(vatTreatment: VatTreatment): string {
/**
* Get the output VAT account based on VAT treatment
*/
-function getOutputVatAccount(vatTreatment: VatTreatment): string {
+export function getOutputVatAccount(vatTreatment: VatTreatment): string {
switch (vatTreatment) {
case 'standard_25':
return '2611'
diff --git a/lib/bookkeeping/supplier-invoice-entries.ts b/lib/bookkeeping/supplier-invoice-entries.ts
new file mode 100644
index 00000000..71176fb1
--- /dev/null
+++ b/lib/bookkeeping/supplier-invoice-entries.ts
@@ -0,0 +1,363 @@
+import { createJournalEntry, findFiscalPeriod } from './engine'
+import { generateReverseChargeLines } from './vat-entries'
+import type {
+ CreateJournalEntryInput,
+ CreateJournalEntryLineInput,
+ JournalEntry,
+ SupplierInvoice,
+ SupplierInvoiceItem,
+} from '@/types'
+
+/**
+ * Create journal entry when a supplier invoice is registered (accrual method)
+ *
+ * Swedish domestic (25% VAT):
+ * Debit 5xxx/6xxx (per item's account_number) [item line_total]
+ * Debit 2641 Ingående moms [total VAT]
+ * Credit 2440 Leverantörsskulder [total incl VAT]
+ *
+ * EU reverse charge (supplier_type = 'eu_business'):
+ * Debit 5xxx/6xxx (per item) [total]
+ * Debit 2645 Beräknad ingående moms [fiktiv VAT]
+ * Credit 2614 Utgående moms omvänd [fiktiv VAT]
+ * Credit 2440 Leverantörsskulder [total]
+ */
+export async function createSupplierInvoiceRegistrationEntry(
+ userId: string,
+ invoice: SupplierInvoice,
+ items: SupplierInvoiceItem[],
+ supplierType: string
+): Promise {
+ const fiscalPeriodId = await findFiscalPeriod(userId, invoice.invoice_date)
+ if (!fiscalPeriodId) {
+ console.warn('No open fiscal period found for invoice date:', invoice.invoice_date)
+ return null
+ }
+
+ const lines: CreateJournalEntryLineInput[] = []
+ const desc = `Lev.faktura ${invoice.supplier_invoice_number} (ankomst ${invoice.arrival_number})`
+
+ // Aggregate expense amounts by account number
+ const expenseByAccount = new Map()
+ for (const item of items) {
+ const current = expenseByAccount.get(item.account_number) || 0
+ expenseByAccount.set(item.account_number, current + item.line_total)
+ }
+
+ // Debit: Expense accounts
+ for (const [accountNumber, amount] of expenseByAccount) {
+ lines.push({
+ account_number: accountNumber,
+ debit_amount: Math.round(amount * 100) / 100,
+ credit_amount: 0,
+ line_description: desc,
+ })
+ }
+
+ if (supplierType === 'eu_business' && invoice.reverse_charge) {
+ // EU reverse charge: fiktiv moms entries
+ const vatRate = getDefaultVatRate(invoice.vat_treatment)
+ const reverseChargeLines = generateReverseChargeLines(invoice.subtotal, vatRate)
+ lines.push(...reverseChargeLines)
+ } else if (invoice.vat_amount > 0) {
+ // Domestic: Debit ingående moms
+ lines.push({
+ account_number: '2641',
+ debit_amount: Math.round(invoice.vat_amount * 100) / 100,
+ credit_amount: 0,
+ line_description: `Ingående moms ${desc}`,
+ })
+ }
+
+ // Credit: Leverantörsskulder
+ lines.push({
+ account_number: '2440',
+ debit_amount: 0,
+ credit_amount: Math.round(invoice.total * 100) / 100,
+ line_description: desc,
+ currency: invoice.currency !== 'SEK' ? invoice.currency : undefined,
+ amount_in_currency: invoice.currency !== 'SEK' ? invoice.total : undefined,
+ exchange_rate: invoice.exchange_rate || undefined,
+ })
+
+ const input: CreateJournalEntryInput = {
+ fiscal_period_id: fiscalPeriodId,
+ entry_date: invoice.invoice_date,
+ description: desc,
+ source_type: 'supplier_invoice_registered',
+ source_id: invoice.id,
+ lines,
+ }
+
+ return createJournalEntry(userId, input)
+}
+
+/**
+ * Create journal entry when a supplier invoice is paid (accrual method)
+ *
+ * Debit 2440 Leverantörsskulder [payment amount]
+ * Credit 1930 Företagskonto [payment amount]
+ *
+ * With exchange rate difference:
+ * Debit 2440 Leverantörsskulder [original SEK amount]
+ * Credit 1930 Företagskonto [actual SEK paid]
+ * Credit/Debit 3960/7960 [difference]
+ */
+export async function createSupplierInvoicePaymentEntry(
+ userId: string,
+ invoice: SupplierInvoice,
+ paymentAmount: number,
+ paymentDate: string,
+ exchangeRateDifference?: number
+): Promise {
+ const fiscalPeriodId = await findFiscalPeriod(userId, paymentDate)
+ if (!fiscalPeriodId) {
+ console.warn('No open fiscal period found for payment date:', paymentDate)
+ return null
+ }
+
+ const desc = `Betalning lev.faktura ${invoice.supplier_invoice_number} (ankomst ${invoice.arrival_number})`
+ const lines: CreateJournalEntryLineInput[] = []
+
+ if (exchangeRateDifference && exchangeRateDifference !== 0) {
+ // Foreign currency with exchange rate difference
+ const originalSekAmount = paymentAmount
+ const actualSekPaid = paymentAmount - exchangeRateDifference
+
+ // Debit: Clear leverantörsskulder at original booked SEK amount
+ lines.push({
+ account_number: '2440',
+ debit_amount: Math.round(originalSekAmount * 100) / 100,
+ credit_amount: 0,
+ line_description: desc,
+ })
+
+ // Credit: Bank at actual SEK paid
+ lines.push({
+ account_number: '1930',
+ debit_amount: 0,
+ credit_amount: Math.round(actualSekPaid * 100) / 100,
+ line_description: desc,
+ })
+
+ // Exchange rate difference
+ if (exchangeRateDifference > 0) {
+ // Gain: Credit 3960
+ lines.push({
+ account_number: '3960',
+ debit_amount: 0,
+ credit_amount: Math.round(Math.abs(exchangeRateDifference) * 100) / 100,
+ line_description: 'Valutakursvinst',
+ })
+ } else {
+ // Loss: Debit 7960
+ lines.push({
+ account_number: '7960',
+ debit_amount: Math.round(Math.abs(exchangeRateDifference) * 100) / 100,
+ credit_amount: 0,
+ line_description: 'Valutakursförlust',
+ })
+ }
+ } else {
+ // Standard SEK payment
+ lines.push({
+ account_number: '2440',
+ debit_amount: Math.round(paymentAmount * 100) / 100,
+ credit_amount: 0,
+ line_description: desc,
+ })
+
+ lines.push({
+ account_number: '1930',
+ debit_amount: 0,
+ credit_amount: Math.round(paymentAmount * 100) / 100,
+ line_description: desc,
+ })
+ }
+
+ const input: CreateJournalEntryInput = {
+ fiscal_period_id: fiscalPeriodId,
+ entry_date: paymentDate,
+ description: desc,
+ source_type: 'supplier_invoice_paid',
+ source_id: invoice.id,
+ lines,
+ }
+
+ return createJournalEntry(userId, input)
+}
+
+/**
+ * Create journal entry for cash method (kontantmetoden)
+ * Combined entry at payment time:
+ *
+ * Debit 5xxx/6xxx (per item) [line_total]
+ * Debit 2641 Ingående moms [total VAT]
+ * Credit 1930 Företagskonto [total incl VAT]
+ */
+export async function createSupplierInvoiceCashEntry(
+ userId: string,
+ invoice: SupplierInvoice,
+ items: SupplierInvoiceItem[],
+ paymentDate: string,
+ supplierType: string
+): Promise {
+ const fiscalPeriodId = await findFiscalPeriod(userId, paymentDate)
+ if (!fiscalPeriodId) {
+ console.warn('No open fiscal period found for payment date:', paymentDate)
+ return null
+ }
+
+ const desc = `Betalning lev.faktura ${invoice.supplier_invoice_number} (kontantmetoden)`
+ const lines: CreateJournalEntryLineInput[] = []
+
+ // Aggregate expense amounts by account number
+ const expenseByAccount = new Map()
+ for (const item of items) {
+ const current = expenseByAccount.get(item.account_number) || 0
+ expenseByAccount.set(item.account_number, current + item.line_total)
+ }
+
+ // Debit: Expense accounts
+ for (const [accountNumber, amount] of expenseByAccount) {
+ lines.push({
+ account_number: accountNumber,
+ debit_amount: Math.round(amount * 100) / 100,
+ credit_amount: 0,
+ line_description: desc,
+ })
+ }
+
+ if (supplierType === 'eu_business' && invoice.reverse_charge) {
+ // EU reverse charge: fiktiv moms entries
+ const vatRate = getDefaultVatRate(invoice.vat_treatment)
+ const reverseChargeLines = generateReverseChargeLines(invoice.subtotal, vatRate)
+ lines.push(...reverseChargeLines)
+ } else if (invoice.vat_amount > 0) {
+ // Domestic: Debit ingående moms
+ lines.push({
+ account_number: '2641',
+ debit_amount: Math.round(invoice.vat_amount * 100) / 100,
+ credit_amount: 0,
+ line_description: `Ingående moms ${desc}`,
+ })
+ }
+
+ // Credit: Företagskonto
+ lines.push({
+ account_number: '1930',
+ debit_amount: 0,
+ credit_amount: Math.round(invoice.total * 100) / 100,
+ line_description: desc,
+ })
+
+ const input: CreateJournalEntryInput = {
+ fiscal_period_id: fiscalPeriodId,
+ entry_date: paymentDate,
+ description: desc,
+ source_type: 'supplier_invoice_cash_payment',
+ source_id: invoice.id,
+ lines,
+ }
+
+ return createJournalEntry(userId, input)
+}
+
+/**
+ * Create journal entry for a supplier credit note (reversal of registration)
+ *
+ * Debit 2440 Leverantörsskulder [total]
+ * Credit 5xxx/6xxx (per item) [line_total]
+ * Credit 2641 Ingående moms [total VAT]
+ */
+export async function createSupplierCreditNoteEntry(
+ userId: string,
+ creditNote: SupplierInvoice,
+ items: SupplierInvoiceItem[],
+ supplierType: string
+): Promise {
+ const fiscalPeriodId = await findFiscalPeriod(userId, creditNote.invoice_date)
+ if (!fiscalPeriodId) {
+ console.warn('No open fiscal period found for credit note date:', creditNote.invoice_date)
+ return null
+ }
+
+ const desc = `Kreditfaktura lev. ${creditNote.supplier_invoice_number} (ankomst ${creditNote.arrival_number})`
+ const lines: CreateJournalEntryLineInput[] = []
+
+ const absTotal = Math.abs(creditNote.total)
+ const absVat = Math.abs(creditNote.vat_amount)
+
+ // Debit: Leverantörsskulder
+ lines.push({
+ account_number: '2440',
+ debit_amount: Math.round(absTotal * 100) / 100,
+ credit_amount: 0,
+ line_description: desc,
+ })
+
+ // Credit: Expense accounts (reverse)
+ const expenseByAccount = new Map()
+ for (const item of items) {
+ const current = expenseByAccount.get(item.account_number) || 0
+ expenseByAccount.set(item.account_number, current + Math.abs(item.line_total))
+ }
+
+ for (const [accountNumber, amount] of expenseByAccount) {
+ lines.push({
+ account_number: accountNumber,
+ debit_amount: 0,
+ credit_amount: Math.round(amount * 100) / 100,
+ line_description: desc,
+ })
+ }
+
+ if (supplierType === 'eu_business' && creditNote.reverse_charge) {
+ // Reverse the fiktiv moms (swap debit/credit from registration)
+ const vatRate = getDefaultVatRate(creditNote.vat_treatment)
+ const vatAmount = Math.round(Math.abs(creditNote.subtotal) * vatRate * 100) / 100
+ lines.push({
+ account_number: '2645',
+ debit_amount: 0,
+ credit_amount: vatAmount,
+ line_description: `Omvänd fiktiv ingående moms ${desc}`,
+ })
+ lines.push({
+ account_number: '2614',
+ debit_amount: vatAmount,
+ credit_amount: 0,
+ line_description: `Omvänd fiktiv utgående moms ${desc}`,
+ })
+ } else if (absVat > 0) {
+ // Credit: Ingående moms (reverse)
+ lines.push({
+ account_number: '2641',
+ debit_amount: 0,
+ credit_amount: Math.round(absVat * 100) / 100,
+ line_description: `Ingående moms ${desc}`,
+ })
+ }
+
+ const input: CreateJournalEntryInput = {
+ fiscal_period_id: fiscalPeriodId,
+ entry_date: creditNote.invoice_date,
+ description: desc,
+ source_type: 'supplier_credit_note',
+ source_id: creditNote.id,
+ lines,
+ }
+
+ return createJournalEntry(userId, input)
+}
+
+/**
+ * Get default VAT rate from treatment string
+ */
+function getDefaultVatRate(vatTreatment: string): number {
+ switch (vatTreatment) {
+ case 'standard_25': return 0.25
+ case 'reduced_12': return 0.12
+ case 'reduced_6': return 0.06
+ default: return 0.25
+ }
+}
diff --git a/lib/bookkeeping/transaction-entries.ts b/lib/bookkeeping/transaction-entries.ts
index 1e2f15fa..18d0c008 100644
--- a/lib/bookkeeping/transaction-entries.ts
+++ b/lib/bookkeeping/transaction-entries.ts
@@ -50,16 +50,16 @@ export async function createTransactionJournalEntry(
const lines: CreateJournalEntryLineInput[] = []
if (mappingResult.default_private) {
- // Private expense
+ // Private expense — use entity-specific account from mappingResult
lines.push(
{
- account_number: '2013', // Övriga egna uttag
+ account_number: mappingResult.debit_account,
debit_amount: absAmount,
credit_amount: 0,
line_description: `Privat: ${transaction.description}`,
},
{
- account_number: '1930', // Företagskonto
+ account_number: mappingResult.credit_account || '1930',
debit_amount: 0,
credit_amount: absAmount,
line_description: transaction.description,
@@ -116,20 +116,53 @@ export async function createTransactionJournalEntry(
const debitAccount = mappingResult.debit_account || '1930'
const creditAccount = mappingResult.credit_account
- lines.push(
- {
+ if (mappingResult.vat_lines.length > 0) {
+ // Has output VAT
+ const vatCredit = mappingResult.vat_lines
+ .filter(l => l.credit_amount > 0)
+ .reduce((sum, l) => sum + l.credit_amount, 0)
+ const netAmount = Math.round((absAmount - vatCredit) * 100) / 100
+
+ // Debit bank for gross amount
+ lines.push({
account_number: debitAccount,
debit_amount: absAmount,
credit_amount: 0,
line_description: transaction.description,
- },
- {
+ })
+ // Credit revenue for net amount
+ lines.push({
account_number: creditAccount,
debit_amount: 0,
- credit_amount: absAmount,
+ credit_amount: netAmount,
line_description: transaction.description,
+ })
+ // Credit output VAT
+ for (const vatLine of mappingResult.vat_lines) {
+ lines.push({
+ account_number: vatLine.account_number,
+ debit_amount: vatLine.debit_amount,
+ credit_amount: vatLine.credit_amount,
+ line_description: vatLine.description,
+ })
}
- )
+ } else {
+ // No VAT - simple two-line entry
+ lines.push(
+ {
+ account_number: debitAccount,
+ debit_amount: absAmount,
+ credit_amount: 0,
+ line_description: transaction.description,
+ },
+ {
+ account_number: creditAccount,
+ debit_amount: 0,
+ credit_amount: absAmount,
+ line_description: transaction.description,
+ }
+ )
+ }
}
const input: CreateJournalEntryInput = {
diff --git a/lib/core/documents/document-service.ts b/lib/core/documents/document-service.ts
index c410f8e1..01a3afc8 100644
--- a/lib/core/documents/document-service.ts
+++ b/lib/core/documents/document-service.ts
@@ -13,7 +13,7 @@ import type { DocumentAttachment, CreateDocumentAttachmentInput, DocumentUploadS
/**
* Compute SHA-256 hash of a file buffer
*/
-async function computeSHA256(buffer: ArrayBuffer): Promise {
+export async function computeSHA256(buffer: ArrayBuffer): Promise {
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer)
const hashArray = Array.from(new Uint8Array(hashBuffer))
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
@@ -91,6 +91,11 @@ export async function uploadDocument(
/**
* Create a new version of an existing document (WORM: old version is superseded)
+ *
+ * Uses the create_document_version RPC for atomic versioning with:
+ * - Row-level locking (prevents concurrent versioning race condition)
+ * - Cryptographic hash chain (prev_version_hash links to previous version)
+ * - Single transaction (insert new + mark old superseded)
*/
export async function createNewVersion(
userId: string,
@@ -99,28 +104,12 @@ export async function createNewVersion(
): Promise {
const supabase = await createClient()
- // Fetch the original/current version
- const { data: current, error: fetchError } = await supabase
- .from('document_attachments')
- .select('*')
- .eq('id', originalId)
- .eq('user_id', userId)
- .eq('is_current_version', true)
- .single()
-
- if (fetchError || !current) {
- throw new Error('Original document not found or not the current version')
- }
-
- const rootOriginalId = current.original_id || current.id
- const newVersion = current.version + 1
-
// Compute SHA-256 hash
const sha256Hash = await computeSHA256(file.buffer)
- // Upload new file
+ // Upload new file to Storage
const timestamp = Date.now()
- const storagePath = `documents/${userId}/${timestamp}_v${newVersion}_${file.name}`
+ const storagePath = `documents/${userId}/${timestamp}_${file.name}`
const { error: uploadError } = await supabase.storage
.from('documents')
@@ -133,41 +122,33 @@ export async function createNewVersion(
throw new Error(`Failed to upload new version: ${uploadError.message}`)
}
- // Create new version record
- const { data: newDoc, error: insertError } = await supabase
- .from('document_attachments')
- .insert({
- user_id: userId,
- storage_path: storagePath,
- file_name: file.name,
- file_size_bytes: file.buffer.byteLength,
- mime_type: file.type || null,
- sha256_hash: sha256Hash,
- version: newVersion,
- original_id: rootOriginalId,
- is_current_version: true,
- uploaded_by: userId,
- upload_source: current.upload_source,
- digitization_date: new Date().toISOString(),
- journal_entry_id: current.journal_entry_id,
- journal_entry_line_id: current.journal_entry_line_id,
- })
- .select()
- .single()
+ // Atomic version creation via RPC (row lock + hash chain + supersede in one tx)
+ const { data: newDocId, error: rpcError } = await supabase.rpc('create_document_version', {
+ p_user_id: userId,
+ p_original_doc_id: originalId,
+ p_storage_path: storagePath,
+ p_file_name: file.name,
+ p_file_size_bytes: file.buffer.byteLength,
+ p_mime_type: file.type || null,
+ p_sha256_hash: sha256Hash,
+ })
- if (insertError) {
+ if (rpcError) {
+ // Clean up uploaded file on RPC failure
await supabase.storage.from('documents').remove([storagePath])
- throw new Error(`Failed to create new version record: ${insertError.message}`)
+ throw new Error(`Failed to create new version: ${rpcError.message}`)
}
- // Mark old version as superseded
- await supabase
+ // Fetch the complete new version record
+ const { data: newDoc, error: fetchError } = await supabase
.from('document_attachments')
- .update({
- is_current_version: false,
- superseded_by_id: newDoc.id,
- })
- .eq('id', current.id)
+ .select('*')
+ .eq('id', newDocId)
+ .single()
+
+ if (fetchError || !newDoc) {
+ throw new Error('Failed to fetch new version record')
+ }
return newDoc as DocumentAttachment
}
diff --git a/lib/reports/supplier-ledger.ts b/lib/reports/supplier-ledger.ts
new file mode 100644
index 00000000..234504d0
--- /dev/null
+++ b/lib/reports/supplier-ledger.ts
@@ -0,0 +1,103 @@
+import { createClient } from '@/lib/supabase/server'
+
+export interface SupplierLedgerEntry {
+ supplier_id: string
+ supplier_name: string
+ current: number
+ days_1_30: number
+ days_31_60: number
+ days_61_90: number
+ days_90_plus: number
+ total_outstanding: number
+}
+
+export interface SupplierLedgerReport {
+ entries: SupplierLedgerEntry[]
+ total_outstanding: number
+ total_current: number
+ total_overdue: number
+ unpaid_count: number
+}
+
+/**
+ * Generate supplier ledger (leverantörsreskontra) with aging analysis
+ */
+export async function generateSupplierLedger(
+ userId: string,
+ asOfDate?: string
+): Promise {
+ const supabase = await createClient()
+ const refDate = asOfDate ? new Date(asOfDate) : new Date()
+
+ // Fetch all unpaid/partially_paid supplier invoices
+ const { data: invoices, error } = await supabase
+ .from('supplier_invoices')
+ .select('*, supplier:suppliers(id, name)')
+ .eq('user_id', userId)
+ .in('status', ['registered', 'approved', 'partially_paid', 'overdue'])
+
+ if (error || !invoices) {
+ return {
+ entries: [],
+ total_outstanding: 0,
+ total_current: 0,
+ total_overdue: 0,
+ unpaid_count: 0,
+ }
+ }
+
+ // Group by supplier and calculate aging
+ const bySupplier = new Map()
+
+ for (const inv of invoices) {
+ const supplierId = inv.supplier_id
+ const supplierName = inv.supplier?.name || 'Okänd leverantör'
+
+ if (!bySupplier.has(supplierId)) {
+ bySupplier.set(supplierId, {
+ supplier_id: supplierId,
+ supplier_name: supplierName,
+ current: 0,
+ days_1_30: 0,
+ days_31_60: 0,
+ days_61_90: 0,
+ days_90_plus: 0,
+ total_outstanding: 0,
+ })
+ }
+
+ const entry = bySupplier.get(supplierId)!
+ const dueDate = new Date(inv.due_date)
+ const daysOverdue = Math.floor((refDate.getTime() - dueDate.getTime()) / (1000 * 60 * 60 * 24))
+ const amount = inv.remaining_amount || 0
+
+ if (daysOverdue <= 0) {
+ entry.current += amount
+ } else if (daysOverdue <= 30) {
+ entry.days_1_30 += amount
+ } else if (daysOverdue <= 60) {
+ entry.days_31_60 += amount
+ } else if (daysOverdue <= 90) {
+ entry.days_61_90 += amount
+ } else {
+ entry.days_90_plus += amount
+ }
+
+ entry.total_outstanding += amount
+ }
+
+ const entries = Array.from(bySupplier.values())
+ .sort((a, b) => b.total_outstanding - a.total_outstanding)
+
+ const total_outstanding = entries.reduce((sum, e) => sum + e.total_outstanding, 0)
+ const total_current = entries.reduce((sum, e) => sum + e.current, 0)
+ const total_overdue = total_outstanding - total_current
+
+ return {
+ entries,
+ total_outstanding: Math.round(total_outstanding * 100) / 100,
+ total_current: Math.round(total_current * 100) / 100,
+ total_overdue: Math.round(total_overdue * 100) / 100,
+ unpaid_count: invoices.length,
+ }
+}
diff --git a/lib/reports/supplier-reconciliation.ts b/lib/reports/supplier-reconciliation.ts
new file mode 100644
index 00000000..51f56743
--- /dev/null
+++ b/lib/reports/supplier-reconciliation.ts
@@ -0,0 +1,53 @@
+import { createClient } from '@/lib/supabase/server'
+
+export interface ReconciliationResult {
+ supplier_ledger_total: number
+ account_2440_balance: number
+ difference: number
+ is_reconciled: boolean
+}
+
+/**
+ * Compare sum of open supplier invoices against account 2440 balance
+ */
+export async function generateReconciliation(
+ userId: string,
+ periodId: string
+): Promise {
+ const supabase = await createClient()
+
+ // Get total outstanding from supplier invoices
+ const { data: invoices } = await supabase
+ .from('supplier_invoices')
+ .select('remaining_amount')
+ .eq('user_id', userId)
+ .in('status', ['registered', 'approved', 'partially_paid', 'overdue'])
+
+ const supplierLedgerTotal = (invoices || [])
+ .reduce((sum, inv) => sum + (inv.remaining_amount || 0), 0)
+
+ // Get account 2440 balance from journal entry lines
+ const { data: journalLines } = await supabase
+ .from('journal_entry_lines')
+ .select('debit_amount, credit_amount, journal_entry_id')
+ .eq('account_number', '2440')
+
+ // Filter to posted entries in the period
+ let account2440Balance = 0
+ if (journalLines) {
+ // Account 2440 is a liability: credit normal balance
+ // Balance = credits - debits
+ for (const line of journalLines) {
+ account2440Balance += (line.credit_amount || 0) - (line.debit_amount || 0)
+ }
+ }
+
+ const difference = Math.round((supplierLedgerTotal - account2440Balance) * 100) / 100
+
+ return {
+ supplier_ledger_total: Math.round(supplierLedgerTotal * 100) / 100,
+ account_2440_balance: Math.round(account2440Balance * 100) / 100,
+ difference,
+ is_reconciled: Math.abs(difference) < 0.01,
+ }
+}
diff --git a/next.config.ts b/next.config.ts
index e9ffa308..31bd5634 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -1,7 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
- /* config options here */
+ allowedDevOrigins: ["nonpedagogically-sphinxlike-dalila.ngrok-free.dev"],
};
export default nextConfig;
diff --git a/public/file.svg b/public/file.svg
deleted file mode 100644
index 004145cd..00000000
--- a/public/file.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/globe.svg b/public/globe.svg
deleted file mode 100644
index 567f17b0..00000000
--- a/public/globe.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/icons/icon-128.png b/public/icons/icon-128.png
new file mode 100644
index 00000000..3deaf3e6
Binary files /dev/null and b/public/icons/icon-128.png differ
diff --git a/public/icons/icon-144.png b/public/icons/icon-144.png
new file mode 100644
index 00000000..0a46c994
Binary files /dev/null and b/public/icons/icon-144.png differ
diff --git a/public/icons/icon-152.png b/public/icons/icon-152.png
new file mode 100644
index 00000000..9c8633a1
Binary files /dev/null and b/public/icons/icon-152.png differ
diff --git a/public/icons/icon-192.png b/public/icons/icon-192.png
new file mode 100644
index 00000000..17df5681
Binary files /dev/null and b/public/icons/icon-192.png differ
diff --git a/public/icons/icon-384.png b/public/icons/icon-384.png
new file mode 100644
index 00000000..709c5248
Binary files /dev/null and b/public/icons/icon-384.png differ
diff --git a/public/icons/icon-512.png b/public/icons/icon-512.png
new file mode 100644
index 00000000..83bff4a6
Binary files /dev/null and b/public/icons/icon-512.png differ
diff --git a/public/icons/icon-72.png b/public/icons/icon-72.png
new file mode 100644
index 00000000..3e182011
Binary files /dev/null and b/public/icons/icon-72.png differ
diff --git a/public/icons/icon-96.png b/public/icons/icon-96.png
new file mode 100644
index 00000000..ac06a872
Binary files /dev/null and b/public/icons/icon-96.png differ
diff --git a/public/next.svg b/public/next.svg
deleted file mode 100644
index 5174b28c..00000000
--- a/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/vercel.svg b/public/vercel.svg
deleted file mode 100644
index 77053960..00000000
--- a/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/window.svg b/public/window.svg
deleted file mode 100644
index b2b2a44f..00000000
--- a/public/window.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/sections-functions.md b/sections-functions.md
deleted file mode 100644
index ff30c5be..00000000
--- a/sections-functions.md
+++ /dev/null
@@ -1,829 +0,0 @@
-# Företagsmoduler — Funktionskatalog per bransch
-
-Varje bransch har fyra lager:
-
-- **Bokföring & Skatt** — Branschanpassade BAS-kontoplan, momsinställningar, skatteregler och auto-kontosättning
-- **Branschrapporter** — KPI:er och analysverktyg specifika för sektorn
-- **Smart import** — Filimport (CSV/Excel/SIE) från branschens vanliga system med automatisk bokföring
-- **Operativa moduler** — Verksamhetsstöd som kan, men inte måste, koppla till bokföringen
-
-Modulantal varierar per bransch beroende på verklig bokföringskomplexitet.
-
----
-
-## 1. Restaurang & Café
-
-En av de mest bokföringskrävande branscherna. Blandad moms (12% mat, 25% alkohol/dryck), dagskassaavstämning, personalliggare, drickshantering och representation skapar många unika behov.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Restaurangkontoplan** | BAS-kontoplan förberedd för restaurang med uppdelning per intäktstyp | Separata konton för mat (3001), dryck (3002), alkohol (3003), take-away; auto-kontosättning från kassaimport |
-| **Momssplit mat/dryck** | Automatisk uppdelning av moms 12% (mat) vs 25% (alkohol, dryck) | Regelmotor för momsfördelning, hantering av blandade kvitton, månadsavstämning per momssats |
-| **Dagskassaavstämning** | Stäm av kassans Z-rapport mot faktisk kassa och bank | Z-rapport-import, avvikelseanalys (svinn, differens), verifikation per dag |
-| **Tipsbokföring** | Bokför dricks korrekt — arbetsgivaravgift på kartdricks, skattefri kontantdricks | Fördelning per anställd, arbetsgivaravgiftsberäkning, konto 7699/7010-koppling |
-| **Personalliggare** | Elektronisk personalliggare enligt krav från Skatteverket | Daglig registrering in/ut, exportformat för kontroll, koppla till lönekostnad |
-| **Alkoholpunktskatt** | Hantera punktskatt vid egenbrygd/import av alkohol | Accisberäkning, lagerrapportering, Tullverket-format |
-| **Representationsbokföring** | Bokför representation med rätt avdragsgränser | Automatisk split avdragsgill/ej avdragsgill del, 90 SEK-gräns internt, momsavdrag |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Matkostnad (Food Cost %)** | Livsmedelskostnad som andel av matintäkt | Daglig/veckovis/månadsvis %, mål vs utfall, trendkurva, larmgräns |
-| **Personalkostnad vs omsättning** | Spåra personalkostnad som andel av total omsättning | Målvärde (typiskt 30-35%), trend, jämförelse budget |
-| **Svinnrapport** | Analysera matsvinn i kronor och procent | Svinn per kategori, kostnad, svinn-till-omsättning |
-| **RevPASH** | Revenue per available seat hour | Intäkt per stolstimme, jämförelse per pass (lunch/middag), kapacitetsoptimering |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Z-rapport-import** | Importera dagskassarapport från kassasystem | CSV/Excel från iZettle, Trivec, Square, Orderbird; auto-bokför med momssplit och kontosättning |
-| **Leverantörsfaktura-import** | Importera leverantörsfakturor för matinköp | Parsning av leverantörsformat (Martin & Servera, Menigo), kostnadsfördelning per kategori |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Menyhantering** | Bygg och publicera menyer digitalt | Menybyggare, säsongsbyte, allergenmarkering, prissättning per kanal |
-| **Bordsbokning** | Online och manuell bordsreservation | Bokningswidget, no-show-hantering, sittningsplanering, kapacitetsvy |
-| **Receptkalkyl** | Beräkna kostnad per rätt utifrån inköpspriser | Receptbyggare, portionskostnad, marginalkalkyl, prisändringsanalys |
-| **Personalschema** | Schemalägg personal i skift | Skiftplanering, bytesförfrågningar, övertidsvarning, tillgänglighetsvy |
-| **Leverantörsbeställning** | Beställ varor direkt till leverantörer | Beställningsmallar, leveransbevakning, prishistorik |
-
----
-
-## 2. Hotell & Boende
-
-Moms 12% på boende, 25% på övriga tjänster. Förskottsbetalningar, channel manager-provisioner, säsongsprissättning och nattrevision skapar unik bokföringskomplexitet.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Hotellkontoplan** | BAS-konton uppdelade per intäktstyp: rum, konferens, F&B, tilläggstjänster | Konton 3010 (rumsintäkter), 3020 (konferens), 3030 (F&B); auto-kontosättning |
-| **Momssplit boende/tjänst** | Moms 12% på boende, 25% på frukost, minibar, spa, parkering | Automatisk split vid kombinationspaket (halvpension, konferenspaket), momsavstämning |
-| **Förskottsbetalning** | Bokför förskott/depositioner korrekt som förutbetald intäkt | Konto 2420, automatisk intäktsföring vid incheckning, avbokningsbokföring |
-| **Provisionshantering** | Bokför provision till Booking.com, Expedia, Airbnb som kostnad | Provisionsberäkning per kanal, nettointäkt per bokning, konto 6090 |
-| **Nattrevision** | Automatiserad nattlig avstämning av dagens intäkter | Dagsbokslut, kassaavstämning, no-show-debitering, verifikation per dygn |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **RevPAR** | Revenue per available room — branschens viktigaste KPI | Beläggningsgrad × ADR, jämförelse per månad/säsong, budget vs utfall |
-| **ADR (Average Daily Rate)** | Genomsnittlig rumspris | Pris per rumstyp, kanalfördelning, säsongsanalys |
-| **Beläggningsgrad** | Procent uthyrda rum | Daglig/veckovis/månadsvis, prognos baserad på bokningsläge |
-| **Kanallönsamhet** | Jämför nettointäkt per kanal efter provision | Direktbokning vs OTA, provision %, rekommendation |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **PMS-import** | Importera boknings- och intäktsdata från PMS (Mews, Protel, Hotellinx) | CSV/Excel, nattrevisionsrapport, auto-bokföring med momssplit |
-| **Channel Manager-rapport** | Importera provisionssammanställning per kanal | Booking/Expedia/Airbnb-rapporter, provisionsbokföring |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Rumsbokning** | Central bokningsmotor | Kalendervy, tillgänglighet, säsongspriser, min/max-nätter |
-| **Gästregister** | Gästprofiler och historik | Kontaktuppgifter, besökshistorik, preferenser, GDPR |
-| **Städschema** | Planera städning per rum | Status per rum, checklista, personalfördelning |
-| **Säsongsplanering** | Priser och kapacitet per säsong | Säsongsdefinition, dynamisk prissättning, beläggningsprognos |
-| **Gästkommunikation** | Automatiska meddelanden | Bekräftelse, incheckning, utcheckning, recensionsförfrågan |
-
----
-
-## 3. Tech & IT
-
-Tidrapportering som styr fakturering. Projektredovisning med WIP (Work in Progress). FoU-avdrag. Licensavskrivningar. Relativt enkel moms (25% tjänst, omvänd moms vid EU-försäljning).
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **IT-kontoplan** | BAS-konton anpassade för konsult/SaaS-bolag | Konton för konsultintäkter, licensintäkter, SaaS MRR; auto-kontosättning |
-| **Projektredovisning** | Intäkter och kostnader per kundprojekt | Successiv vinstavräkning, WIP-beräkning (konto 1470), projektbokslut |
-| **FoU-avdrag** | Beräkna avdrag för forskning och utveckling | Nedsättning av arbetsgivaravgifter, underlag per anställd, Skatteverket-krav |
-| **Licensavskrivning** | Hantera avskrivning av mjukvarulicenser och IP | Avskrivningsplan, konto 1010/1020, linjär vs degressiv avskrivning |
-| **EU-tjänstemoms** | Omvänd skattskyldighet vid försäljning till EU-kunder | Automatisk B2B-kontroll (VAT-nummer), konto 2614, EU-försäljningsrapport |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Debiteringsgrad** | Andel debiterbara timmar av total arbetstid | Per konsult/team, mål vs utfall, trend |
-| **Projektlönsamhet** | Intäkt minus kostnad per projekt | Timkostnad vs debiterat, överdrag-varning, jämförelse budget |
-| **MRR/ARR** | Monthly/Annual Recurring Revenue för SaaS | Tillväxttakt, churn, expansion revenue |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Tidrapport-import** | Importera tidrapporter från Harvest, Toggl, Clockify | CSV/Excel, auto-koppling till projekt, fakturaunderlag |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Projekthantering** | Överblick och styrning av kundprojekt | Projekttavla, milstolpar, tidslinje, budgetuppföljning |
-| **Tidrapportering** | Logga tid per projekt och kund | Timer, manuell inmatning, godkännandeflöde, debiterbara timmar |
-| **Ärendehantering** | Supportärenden och buggspårning | Ärendekö, SLA-prioritet, statusflöde, kundportal |
-| **Resursplanering** | Allokera personal till projekt | Beläggningsvy, kompetensfilter, överlappningsvarning |
-
----
-
-## 4. Bygg & Entreprenad
-
-Komplex bransch: omvänd skattskyldighet (moms) inom byggsektorn, ROT-avdrag, successiv vinstavräkning per projekt, ÄTA-hantering, UE-attestering och personalliggare.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Byggkontoplan** | BAS-konton med projektkontosättning och UE-konton | Separata konton per projekt, UE-kostnader (konto 4400), materialkostnader |
-| **Omvänd skattskyldighet bygg** | Automatisk hantering av omvänd moms (6 kap. ML) vid UE-tjänster | Automatisk kontroll köpare/säljare, fakturamärkning, momsdeklaration ruta 24 |
-| **ROT-avdrag** | Beräkna och rapportera ROT-avdrag per kund | Automatisk 30%-beräkning, maxbelopp 50 000 SEK, personnummervalidering, Skatteverket-format |
-| **Successiv vinstavräkning** | Periodisera projektintäkter efter färdigställandegrad | Beräkning av färdigställandegrad, intäktsperiodisering, konto 1470 WIP |
-| **UE-attestering** | Attestflöde för underentreprenörsfakturor | Godkännandeflöde, delavstämning, F-skatt-kontroll, försäkringsverifiering |
-| **Personalliggare** | Elektronisk personalliggare enligt Skatteverkets krav | In/ut-registrering, export vid kontroll, UE-personal inkluderad |
-| **ÄTA-bokföring** | Koppla ÄTA-arbeten till rätt projekt och faktura | ÄTA-registrering, kostnadseffekt på projektkalkyl, intäktsökning vid godkänd ÄTA |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Projektmarginal** | Kalkylerad vs verklig marginal per projekt | Budget vs utfall, ÄTA-påverkan, UE-kostnad vs plan |
-| **ÄTA-analys** | ÄTA som andel av ursprunglig kalkyl | ÄTA-andel per projekt, typ av ÄTA, kundgodkännandestatus |
-| **Likviditet per projekt** | Kassaflöde per projekt — fakturerat vs betalt vs kostnad | Faktureringsrytm, kundfordringsålder, UE-skulder |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **UE-fakturaimport** | Importera underentreprenörsfakturor | Parsning, projektkoppling, F-skatt-kontroll, auto-kontosättning |
-| **Materialkostnadsimport** | Importera materialinköp per projekt | Leverantörsformat (Beijer, Ahlsell), projektfördelning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Projektkalkyl** | Detaljerade kalkyler inför anbud | Arbete, material, maskiner, UE-kostnader, marginalpåslag |
-| **ÄTA-hantering** | Spåra ändringar, tillägg och avgående | Registrering, kundgodkännande, koppling till faktura |
-| **Byggdagbok** | Digital dagbok per projekt | Dagliga noteringar, foto, väderpåverkan, personallog |
-| **Ritningshantering** | Versionshantering av projektritningar | Uppladdning, versionsjämförelse, distribution till UE |
-| **Materialbeställning** | Beställ och spåra material | Materiallistor, leveransbevakning, kostnadsuppföljning |
-
----
-
-## 5. Hälsa & Sjukvård
-
-Sjukvårdstjänster är momsfria (3 kap. 4-5 § ML) men kompletterande tjänster (friskvård, kosmetisk) kan vara momspliktiga. Blandning av regionavtal, privata patienter och försäkringsersättningar.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Vårdkontoplan** | BAS-konton uppdelade per intäktstyp: regionavtal, privatpatienter, försäkring | Konton 3010 (regionersättning), 3020 (patientavgift), 3030 (försäkring) |
-| **Momsfrihet sjukvård** | Hantera momsfria vårdtjänster vs momspliktiga sidotjänster | Automatisk momsbedömning per tjänsttyp, korrekt moms vid blandad verksamhet |
-| **Försäkringsersättning** | Bokför ersättningar från försäkringsbolag korrekt | Intäktsföring vid godkännande, kundfordran per försäkringsbolag, avskrivning av nekade ärenden |
-| **Frikort & Högkostnadsskydd** | Hantera patienters frikort vid avgiftsberäkning | Automatisk kontroll mot högkostnadsgräns, rapportering till region |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Intäkt per behandlare** | Omsättning fördelat per vårdgivare | Per dag/vecka/månad, privatpatienter vs region, besökssnitt |
-| **Patientmix** | Fördelning region/privat/försäkring | Intäktsfördelning per betalarkategori, trend, lönsamhet per typ |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Regionersättningsimport** | Importera utbetalningsbesked från region | Periodisering, kontosättning, avstämning mot avtal |
-| **Försäkringsrapport-import** | Importera beslut och utbetalningar från försäkringsbolag | Auto-bokföring godkända/nekade ärenden |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Patientbokning** | Bokning av besök och behandlingar | Onlinebokning, kalendervy, SMS-påminnelse, väntelista |
-| **Journalhantering** | Strukturerade patientjournaler | Anteckningar, diagnoser, vårdplan, GDPR-efterlevnad |
-| **Remisshantering** | Skicka och ta emot remisser | Mallar, statusspårning, svarsbevakning |
-| **Kassasystem & Patientavgifter** | Debitera patientbetalningar | Avgiftskategorier, frikort-koll, kortbetalning |
-
----
-
-## 6. Detaljhandel
-
-Lagervärdering (FIFO/vägt genomsnitt) påverkar bokslut direkt. Kassaavstämning dagligen. Moms 25% standard men 6%/12% på vissa varor. Svinn påverkar lagerresultat. Personalliggare i livsmedelsbutik.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Detaljhandelskontoplan** | BAS-konton per produktkategori och momssats | Intäktskonton per varugrupp, separata konton 25%/12%/6% moms |
-| **Lagervärdering** | Löpande beräkning av lagervärde för bokslut | FIFO och vägt genomsnitt, månadsbokslut, inkuransbedömning, konto 1400 |
-| **Kassaavstämning** | Daglig avstämning kassa vs kassarapport | Z-rapport-import, avvikelse, kontant/kort-split, verifikation per dag |
-| **Svinnbokföring** | Bokför varusvinn korrekt som kostnad | Svinnregistrering, konto 4730, period-uppföljning |
-| **Personalliggare** | Elektronisk personalliggare (obligatorisk livsmedelsbutik) | In/ut-registrering, Skatteverket-export |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Bruttomarginal per varugrupp** | Inpris vs utpris per kategori | Marginal %, jämförelse kampanjperiod vs normal, trendvy |
-| **Lageromsättningshastighet** | Hur snabbt lagret omsätts | Per varugrupp, kapitalbindning, beställningspunkt-förslag |
-| **Svinnprocent** | Svinn i kronor och procent av omsättning | Per kategori, trend, benchmark mot branschsnitt |
-| **Försäljning per m²** | Butikseffektivitet | Intäkt per kvadratmeter, jämförelse butiker |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **POS Z-rapport-import** | Dagskassarapport från kassasystem | CSV/Excel från iZettle, Sitoo, Caspeco; auto-kontosättning med momssplit |
-| **Inventeringsimport** | Importera inventeringsresultat | Avvikelseberäkning, lageruppdatering, svinnbokföring |
-| **Leverantörsfaktura-import** | Importera leverantörsfakturor | Parsning, inprisuppdatering, auto-kontosättning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Lagerhantering** | Lagernivåer och rörelser | Inleverans, bristlista, beställningspunkt, lagerplatser |
-| **Kampanjer & Rabatter** | Priskampanjer och erbjudanden | Rabattregler, tidsbegränsade kampanjer, marginalbevakning |
-| **Kundklubb** | Lojalitetsprogram | Poängintjäning, belöningar, riktade kampanjer |
-| **Prishantering** | Centraliserad prissättning | Inpris vs utpris, marginalkalkyl, prisändringslogg |
-| **Butiksdrift & Schema** | Bemanning och öppettider | Schemaläggning, timrapport, budgetjämförelse |
-
----
-
-## 7. E-handel
-
-Plattformsimport (Shopify, Woo) → auto-bokföring. Returer som kreditering. Multi-currency med kursdifferens. EU-moms via OSS. Lagervärdering. Fraktbokföring.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **E-handelskontoplan** | BAS-konton för orderintäkter, fraktintäkt, returer, plattformsavgifter | Konton 3001 (varuförsäljning), 3540 (fraktintäkt), 3740 (returkostnad), 6590 (plattformsavgift) |
-| **Lagervärdering** | Löpande lagervärde för bokslut | FIFO, vägt genomsnitt, månadsbokslut, inkuransbedömning |
-| **Returbokföring** | Automatisk kreditering vid returer | Lageråterföring, konto 3740, momskorrigering, periodsummering |
-| **Multi-currency** | Bokför försäljning i utländsk valuta i SEK | Valutaomvandling via Riksbanken-kurs, kursdifferens konto 3960/7960 |
-| **EU-moms (OSS)** | One Stop Shop för moms vid EU-distansförsäljning | Moms per destinationsland, OSS-deklarationsunderlag, tröskelvärdebevakning |
-| **Plattformsavgifter** | Bokför avgifter från Shopify, Stripe, Klarna korrekt | Bruttoförsäljning → avgift → nettoutbetalning, periodisering |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Returprocent** | Returer som andel av försäljning | Per produktkategori, kostnad per retur, trend |
-| **Genomsnittligt ordervärde (AOV)** | Snittorder i kronor | Trend, kanalfördelning, kampanjeffekt |
-| **Kanalfördelning** | Intäkt per försäljningskanal | Egen webb vs marknadsplats, marginal per kanal |
-| **Fraktkostnad vs intäkt** | Fraktnetto per order | Fraktsubvention, break-even-analys |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Shopify/Woo-import** | Importera ordrar och utbetalningsrapporter | CSV-export, auto-bokföring per order inkl. moms, frakt, rabatter |
-| **Klarna-rapport-import** | Importera Klarna-utbetalningar och avgifter | Bruttobelopp, avgiftsavdrag, nettoutbetalning, periodmatchning |
-| **Fraktrapport-import** | Importera fraktkostnader per order | Postnord/DHL/Budbee-rapporter, kostnadsfördelning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Orderhantering** | Central ordervy | Orderstatus, plocklista, batch-hantering |
-| **Frakthantering** | Hantera frakt | Fraktsedlar, spårning, returlogistik |
-| **Returhantering** | Hantera returer och byten | Returgodkännande, lageråterföring, återbetalning |
-| **Produktdatahantering** | Central produktinfo | Beskrivningar, bilder, attribut |
-
----
-
-## 8. Frisör & Skönhet
-
-Provisionsberäkning som lönekostnad. Presentkort som förutbetald intäkt. Moms 25% på allt (tjänst + vara). Personalliggare obligatorisk. Kassaavstämning dagligen.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Salongkontoplan** | BAS-konton uppdelade: tjänsteintäkter, produktförsäljning, presentkort | Konton 3010 (behandling), 3020 (produktförsäljning), 2420 (presentkortsskuld) |
-| **Provisionsberäkning** | Räkna provision per frisör/terapeut och bokför som lönekostnad | Procent på tjänst/produkt, trappsteg, konto 7010/7210, månadssammanställning |
-| **Presentkort som skuld** | Bokför sålda presentkort som förutbetald intäkt tills inlösen | Konto 2420 (skuld), intäktsföring vid inlösen, förfallohantering |
-| **Kassaavstämning** | Daglig avstämning kort/Swish/kontant | Z-rapport, avvikelse, verifikation per dag |
-| **Personalliggare** | Elektronisk personalliggare enligt Skatteverket | In/ut-registrering, export vid kontroll |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Intäkt per stol** | Omsättning per arbetsstation | Per dag/vecka, beläggningsgrad, optimeringsförslag |
-| **Provisionsandel** | Provisionskostnad som andel av tjänsteintäkt | Per frisör, trend, lönsamhet per anställd |
-| **Produktförsäljning per besök** | Merförsäljning av produkter | Snitt per kund, andel av omsättning |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Kassarapport-import** | Importera dagskassa från kassasystem | CSV från iZettle/Zettle, auto-kontosättning |
-| **Bokningssystem-import** | Importera bokningsdata och intäkter | Export från Timma, Fresha, Planway; intäktsfördelning per behandlare |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Tidsbokning** | Online och receptionsbokning | Bokningswidget, SMS-påminnelse, väntelista |
-| **Kundkort** | Profil med behandlingshistorik | Favoritbehandlare, allergier, färgrecept |
-| **SMS-påminnelser** | Automatiska påminnelser | Bokningspåminnelse, återbesökspåminnelse |
-| **Skiftschema** | Schemalägg personal | Stolsfördelning, ledighetsönskemål |
-
----
-
-## 9. Transport & Logistik
-
-Fordonsavskrivningar, leasing, bränslekostnad per fordon, milersättning vs faktisk kostnad. Trängselskatt. Cabotageregler vid internationell transport.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Transportkontoplan** | BAS-konton per kostnadskategori: bränsle, leasing, underhåll, försäkring | Konton per fordon möjligt, kostnadskonton 5610/5620/5611/5612 |
-| **Fordonsavskrivning** | Hantera avskrivning per fordon | Linjär/degressiv, räkenskapsenlig avskrivning, konto 1240/7832 |
-| **Leasinghantering** | Bokför leasing korrekt (operationell vs finansiell) | Leasingavgift som driftskostnad, restvärde, avtalsperiod |
-| **Trängselskatt** | Bokför trängselskatt som avdragsgill kostnad | Auto-kontosättning konto 5615, per fordon, periodsammanställning |
-| **Milersättning vs faktisk kostnad** | Jämför schablon (25 kr/mil) mot verklig fordonskostnad | Per fordon, rekommendation avdragsmetod, Skatteverket-schabloner |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Kostnad per mil** | Total driftskostnad per mil och per fordon | Bränsle + underhåll + avskrivning + försäkring, trend |
-| **Intäkt per fordon** | Omsättning fördelad per fordon | Lönsamhet per fordon, underutnyttjade resurser |
-| **Bränsleeffektivitet** | Bränsleförbrukning per fordon och period | Liter/mil, trend, avvikelse mot förväntat |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Bränslekort-import** | Importera tankningar från bränslekort (Circle K, OKQ8, Preem) | CSV, auto-kontosättning per fordon |
-| **Vägtulls-import** | Importera trängselskatt och broavgifter | Transportstyrelsen-format, auto-kontosättning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Flottahantering** | Fordonsregister och översikt | Besiktning, försäkring, leasingperioder |
-| **Ruttplanering** | Optimera körrutter | Adressklustring, tidsestimering, kapacitet |
-| **Leveransspårning** | Realtidsspårning av leveranser | GPS, ETA, leveransbevis, kundnotifiering |
-| **Fordonsunderhåll** | Planera service och reparationer | Serviceintervall, reservdelshistorik |
-| **Chaufförshantering** | Personal och behörigheter | Körkortsklass, YKB, timrapport |
-| **Fraktsedlar & Dokument** | Generera fraktdokument | CMR, följesedel, digital signatur |
-
----
-
-## 10. Juridik & Redovisning
-
-Tidrapport → fakturering (löpande räkning). Klientmedelskonto. WIP-värdering. A conto-fakturering. Intressekonflikt påverkar inte bokföringen men är branschkrav.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Juristkontoplan** | BAS-konton för arvodesintäkter, klientmedel, utlägg | Konton 3010 (arvoden), 1690 (klientmedel i förvaltning), 6990 (utlägg för klients räkning) |
-| **Klientmedelskonto** | Separat hantering av klientmedel (disciplinnämndsregler) | Konto 1690/2890, klientmedelslista, avstämning mot bankkonto, rapportering |
-| **WIP-värdering** | Värdera pågående arbete (nedlagd tid ej fakturerad) | Beräkning av WIP, konto 1470, månatlig omvärdering |
-| **A conto-bokföring** | Bokför a conto-fakturor och slutavräkning | Förskottsbokföring konto 2420, avräkning vid slutfaktura |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Debiteringsgrad** | Andel debiterbara timmar av total arbetstid | Per jurist/konsult, mål vs utfall, trend |
-| **Realisationsgrad** | Fakturerat belopp vs tidvärde (nedskrivning av tid) | Per ärende, mönsteranalys, lönsamhet per ärendety |
-| **Genomsnittlig timintäkt** | Faktiskt fakturerat per timme | Per jurist, klient, ärendetyp; jämförelse mot prislista |
-| **WIP-rapport** | Totalt pågående arbete ej fakturerat | Per klient/ärende, åldringsanalys, risk för nedskrivning |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Tidrapport-import** | Importera tid från ärendehanteringssystem | CSV från Time, Clio, Maconomy; koppling till ärende och klient |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Ärendehantering** | Administrera klientärenden | Ärendetyper, statusflöde, deadline-bevakning |
-| **Tidrapportering** | Registrera tid per ärende | Debiterbara vs interna timmar, godkännande |
-| **Dokumenthantering** | Versionshanterade dokument per ärende | Mallbibliotek, e-signering, klientdelning |
-| **Deadlinebevakning** | Påminnelser för tidsfrister | Preskriptionstider, eskaleringsregler |
-| **Intressekonfliktskontroll** | Kontrollera jäv vid nya ärenden | Partsregister, automatisk sökning, logg |
-
----
-
-## 11. Utbildning & Förskola
-
-Maxtaxa-regler vid fakturering. Kommunala bidrag/peng som intäkt. Momsfri utbildning. Statsbidrag med krav på periodisering.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Utbildningskontoplan** | BAS-konton för kommunal peng, statsbidrag, föräldraavgift | Konton 3010 (kommunal ersättning), 3020 (föräldraavgift), 3910 (statsbidrag) |
-| **Maxtaxa-fakturering** | Automatisk beräkning av avgift enligt maxtaxa-reglerna | Inkomstkontroll, syskonrabatt, schema-avdrag, frånvaroavdrag |
-| **Statsbidragsperiodisering** | Periodisera statsbidrag korrekt över den period de avser | Konto 2970 (förutbetald intäkt), villkorsuppfyllnad, återbetalningsrisk |
-| **Momsfrihet utbildning** | Utbildningstjänster är momsfria | Korrekt momsbedömning, sidoverksamhet (cafeteria, uthyrning) kan vara momspliktig |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Kostnad per barn/elev** | Total driftskostnad per inskrivet barn | Personal, lokal, mat, material; jämförelse med kommunal peng |
-| **Personaltäthet** | Antal barn per heltidsanställd | Trend, lagkrav (förskolans riktlinje), schemaanalys |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Kommunal peng-import** | Importera utbetalningsbesked från kommun | Periodisering, kontosättning, avstämning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Schemaläggning** | Undervisningsschema | Per klass/lärare/sal, konfliktkontroll |
-| **Elevregister** | Elev- och barnuppgifter | Kontakt, vårdnadshavare, allergi, specialbehov |
-| **Närvarohantering** | Registrera frånvaro | Daglig närvaro, mönsteranalys, föräldraavisering |
-| **Föräldrakommunikation** | Meddelanden till vårdnadshavare | Push/e-post/SMS, nyhetsflöde |
-| **Matsedel & Allergikost** | Publicera matsedel | Veckomatsdel, allergiflaggor |
-| **Vikariebokning** | Hantera vikarier | Vikariepool, snabbbokning, kostnadsspårning |
-
----
-
-## 12. Jordbruk & Livsmedel
-
-Unik skatteposition: skogskonto, expansionsfond, räntefördelning (EF/NE). EU-stöd som intäkt (periodisering). Biologiska tillgångar. Moms 12% livsmedel vs 25% övriga varor.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Jordbrukskontoplan** | BAS-konton anpassade för gröda, djur, skogsbruk, EU-stöd | Konton 3010 (växtodling), 3020 (djurförsäljning), 3910 (EU-stöd), 1280 (biologiska tillgångar) |
-| **Skogskonto** | Hantera insättning och uttag från skogskonto | Insättning (max 60% av skogsintäkt), beskattning vid uttag, konto 1760 |
-| **Expansionsfond** | Beräkna avsättning till expansionsfond för enskild firma | Beräkning av underlag, expansionsfondsskatt 20,6%, NE-bilaga |
-| **Räntefördelning** | Positiv/negativ räntefördelning på kapital | Kapitalunderlag, statslåneränta, inkomstfördelning tjänst/kapital |
-| **EU-stöd som intäkt** | Periodisera EU-jordbruksstöd korrekt | Intäktsföring per period, villkorsskuld, jämförelse ansökt vs utbetalt |
-| **Biologiska tillgångar** | Värdera djur och grödor som tillgång | Anskaffningsvärde vs verkligt värde, konto 1280, årlig omvärdering |
-| **Momssplit livsmedel** | Moms 12% vid livsmedelsförsäljning, 25% övriga varor | Automatisk momskod per produkttyp |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Avkastning per hektar** | Intäkt minus kostnad per odlad yta | Per gröda, säsongsjämförelse, vädereffekt |
-| **Bidragsberoende** | EU-stöd som andel av total intäkt | Trend, risk vid policyändring |
-| **Djurkostnad per enhet** | Total kostnad per djur (foder, veterinär, stall) | Per djurtyp, jämförelse med intäkt vid slakt/försäljning |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **SAM-utbetalningsimport** | Importera utbetalningsbesked för EU-jordbruksstöd | Jordbruksverket-format, periodisering, auto-kontosättning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Skördeplanering** | Planera odlingscykler | Fältregister, grödor, sådd/skörd-datum |
-| **Djurhållning** | Register och uppföljning av besättning | Individregister, hälsologg, Jordbruksverket-rapportering |
-| **Spårbarhet** | Spåra livsmedel från jord till bord | Batchnummer, leveranskedja, återkallning |
-| **Maskinlogg** | Drifttid och underhåll | Maskinregister, timlogg, servicepåminnelse |
-| **Certifieringar** | KRAV, ekologisk, EU-ekologisk | Certifikatregister, giltighetstid, revisionsförberedelse |
-
----
-
-## 13. Media & Kommunikation
-
-Projektredovisning. Freelancer-fakturor (F-skatt-kontroll). Immateriella rättigheter som tillgång. Licensintäkter. Ofta blandad tjänstemoms (25%) och kulturmoms (6%).
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Mediakontoplan** | BAS-konton per intäktstyp: projektarvoden, licensintäkt, royalties | Konton 3010 (projektintäkt), 3020 (licensintäkt), 3910 (royalty) |
-| **Projektredovisning** | Intäkter och kostnader per kundprojekt | Budget vs utfall, WIP vid pågående projekt, projektbokslut |
-| **Freelancer-bokföring** | Hantera fakturor från frilansare korrekt | F-skatt-kontroll, auto-kontosättning konto 4010, kostnad per projekt |
-| **Kulturmoms** | Hantera moms 6% vid publicering, film, kultur | Korrekt momssats per tjänsttyp, blandad verksamhet |
-| **IP-tillgångar** | Aktivera och avskriva immateriella rättigheter | Aktivering, avskrivningsplan, konto 1010/1020 |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Projektlönsamhet** | Intäkt minus kostnad per projekt | Budget vs utfall, timkostnad vs debiterat |
-| **Freelancerandel** | Andel av produktionskostnad som går till freelancers | Trend, lönsamhetspåverkan, per projekttyp |
-| **Kundlönsamhet** | Intäkt och marginal per kund | Tidsförbrukning vs fakturerat, återkommande kunder |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Freelancer-fakturaimport** | Importera fakturor från frilansare | Parsning, F-skatt-verifiering, projektkoppling |
-| **Kampanjrapport-import** | Importera kampanjresultat | Intäkter per kampanj, provisionskostnader |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Projekthantering** | Styra kundprojekt | Projekttavla, tidslinje, kundgodkännande |
-| **Innehållsplanering** | Redaktionskalender | Kanalvy, statusflöde, deadlines |
-| **Mediebank** | Central lagring av media | Taggning, sök, rättighetsspårning |
-| **Tidrapport & Debitering** | Logga tid per kund | Timer, budget vs utfall, fakturaunderlag |
-
----
-
-## 14. Fitness & Sport
-
-Autogiro-intäkter (periodisering). Klippkort/förskott som skuld. Moms 6% på idrott, 25% på PT och spa. Friskvårdsbidragsproblematik.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Fitnesskontoplan** | BAS-konton per intäktstyp: medlemskap, PT, klippkort, shop | Konton 3010 (medlemsavgift), 3020 (PT), 2420 (klippkortsskuld), 3030 (shop) |
-| **Momssplit idrott/PT** | Moms 6% på idrottslig verksamhet, 25% på PT, spa, shop | Automatisk momssats per tjänsttyp, blandad verksamhet |
-| **Autogiro-periodisering** | Bokför autogiro-dragningar som intäkt rätt period | Förskottsbetalning, periodisering konto 2970, misslyckade dragningar |
-| **Klippkort som skuld** | Sålda klippkort/startpaket bokförs som förutbetald intäkt | Konto 2420, intäktsföring per nyttjat tillfälle, förfallohantering |
-| **Friskvårdsbidrag** | Hantera friskvårdsbidrag från arbetsgivare | Skatteverkets gräns (5 000 SEK), kvittogenerering, dokumentation |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Churn rate** | Medlemsavgång per månad | Trend, orsaksanalys, retention per avtalstyp |
-| **Intäkt per medlem** | Genomsnittlig intäkt per aktiv medlem | Inklusive PT, shop, extra tjänster |
-| **Beläggningsgrad klasser** | Fyllnadsgrad per gruppträningspass | Per klass/tid, optimering av schema |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Autogiro-rapport-import** | Importera autogiro-dragningsrapport (Bankgirot) | Lyckade/misslyckade, auto-kontosättning, period-matchning |
-| **Kassarapport-import** | Importera dagskassa | Drop-in, PT-paket, shop; auto-kontosättning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Medlemshantering** | Registrera och hantera medlemskap | Avtalstyper, förnyelse, uppsägning |
-| **Klassbokning** | Boka platser i träningspass | Schema, platsbegränsning, väntelista |
-| **PT-bokning** | Boka personlig tränare | Paket, kundhistorik, kalender |
-| **Tillträdeskontroll** | Inpassering till anläggning | Nyckelbricka/QR, besökslogg |
-
----
-
-## 15. Fordon & Verkstad
-
-Arbetsorder → faktura. Reservdelslager (lagervärdering). Garanti-avsättningar. VMB (vinstmarginalbeskattning) vid begagnade delar.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Verkstadskontoplan** | BAS-konton per intäktstyp: arbete, reservdelar, besiktning | Konton 3010 (arbetsintäkt), 3020 (reservdelar), 4010 (inköp reservdelar) |
-| **Arbetsorder → Faktura** | Generera faktura direkt från arbetsorder | Timpris + delar, automatisk summering, konto-koppling |
-| **Reservdelslager** | Lagervärdering av reservdelar | FIFO, konto 1460, månadsbokslut, inkuransavdrag |
-| **VMB (begagnade delar)** | Vinstmarginalbeskattning vid försäljning av begagnade reservdelar | Beräkning av vinstmarginal, moms enbart på marginalen, konto 2640 |
-| **Garantiavsättning** | Avsätt för framtida garantikostnader | Avsättning konto 2290, upplösning vid faktisk kostnad |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Genomsnittligt ordervärde** | Snittfaktura per arbetsorder | Arbete vs delar, trend, kundtypsanalys |
-| **Reservdelsmarginal** | Inpris vs utpris på delar | Per kategori, trend |
-| **Verkstadsbeläggning** | Utnyttjandegrad av lyftar och mekaniker | Per resurs, optimering |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Reservdelsleverantör-import** | Importera priser och leveranser | Mekonomen, Autoexperten-format, auto-kontosättning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Arbetsorder** | Skapa och hantera arbeten | Registrering, mekaniker-tilldelning, statusflöde |
-| **Fordonsregister** | Register med fordonshistorik | Regnummer, servicehistorik, besiktningsdatum |
-| **Verkstadsplanering** | Beläggning av lyftar och personal | Kalendervy, bokningstider, akut-slot |
-| **Besiktningspåminnelse** | Automatiska påminnelser | SMS/e-post, historik |
-
----
-
-## 16. Bemanning & HR
-
-Tidrapport → kundfaktura + löneunderlag (dubbelt flöde). Marginalberäkning per uppdrag. Socialavgiftsperiodisering. F-skatt-verifiering av underkonsulter.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Bemanningskontoplan** | BAS-konton per intäkts- och kostnadstyp: uthyrning, rekrytering, underkonsulter | Konton 3010 (uthyrningsintäkt), 3020 (rekryteringsarvode), 4010 (UE-kostnad), 7010 (löner) |
-| **Tidrapport → Dubbelbokföring** | Tidrapport genererar både kundfaktura och löneunderlag | Timrapport, kunddebitering, lönekostnad, marginalberäkning per uppdrag |
-| **Arbetsgivaravgifter-periodisering** | Periodisera arbetsgivaravgifter korrekt per månad | Beräkning per anställd, konto 7510, semesterlöneskuld, period-vy |
-| **UE-verifiering** | Kontrollera F-skatt och försäkring för underkonsulter | Skatteverkets API-kontroll, dokumentation, fakturamottagning |
-| **Traktamente vid uthyrning** | Beräkna traktamente för uthyrd personal | Skatteverkets schabloner, skattefri del, förmånsbeskattning vid övernattning |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Marginal per konsult** | Debiterat minus lönekostnad per uthyrd person | Per uppdrag, trend, jämförelse |
-| **Beläggningsgrad** | Andel uthyrd tid av total tid | Per konsult, team, totalt |
-| **Fakturerat per konsult** | Total fakturering per person och period | Ranking, budget vs utfall |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Tidrapport-import** | Importera timmar från kundsystem | CSV, kundgodkännande-status, auto-koppling till uppdrag |
-| **Lönesystem-import** | Importera löneunderlag | Export från Hogia, Visma Lön; auto-bokföring av lön + sociala avgifter |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Kandidatregister** | Rekryteringsdatabas | CV, kompetens, status, GDPR-rensning |
-| **Uppdragshantering** | Matcha kandidater med uppdrag | Kravprofil, matchning, förlängning |
-| **Avtalshantering** | Kundavtal och konsultavtal | Templates, förnyelsepåminnelser |
-| **Kompetensregister** | Certifieringar och utbildningar | Per person, giltighetstid |
-| **Compliance** | Lagar och branschkrav | ID06-kontroll, arbetstillstånd |
-
----
-
-## 17. Tillverkning & Industri
-
-BOM-kalkyl kopplat till lagervärdering. Tre lagernivåer (råvara/halvfabrikat/färdigvara). Produktionsavvikelse bokförs. Maskinavskrivningar. Energiskatteavdrag vid industriprocess.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Tillverkningskontoplan** | BAS-konton per lagertyp och kostnadsställe | Konton 1410 (råvarulager), 1420 (PIA), 1450 (färdigvarulager), 4010 (materialinköp) |
-| **Trestegslagervärdering** | Värdera råvaror, halvfabrikat (PIA) och färdigvaror separat | FIFO per lagernivå, omvärdering vid produktion, konto 1410/1420/1450 |
-| **BOM-kalkyl → Lagervärde** | Strukturlista (BOM) styr självkostnad per tillverkad enhet | Materialkomponenter, arbetskostnad, OH-pålägg, lagervärde per BOM |
-| **Produktionsavvikelse** | Bokför avvikelse mellan kalkylerad och faktisk kostnad | Standard- vs verklig kostnad, avvikelsekonto 4900 |
-| **Maskinavskrivning** | Avskrivningsplan för produktionsutrustning | Räkenskapsenlig avskrivning, konto 1210/7831, restvärdeavskrivning |
-| **Energiskatteavdrag** | Avdrag för energiskatt vid industriell tillverkning | Nedsättning av energiskatt, ansökan till Skatteverket, periodisering |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Materialeffektivitet** | Faktisk materialförbrukning vs BOM-kalkyl | Spill %, kostnad för avvikelse, trend |
-| **Kostnad per producerad enhet** | Total kostnad (material + arbete + OH) per enhet | Per produkt, period-jämförelse |
-| **OEE (Overall Equipment Effectiveness)** | Maskinutnyttjandegrad | Tillgänglighet × prestanda × kvalitet |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Produktionsrapport-import** | Importera utfallsdata per tillverkningsorder | Godkänt/kasserat, materialförbrukning, auto-kontosättning |
-| **Lagerexport-import** | Importera lagerförändringar | Per lagernivå, inventeringsresultat |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Produktionsplanering** | Schemalägga tillverkningsorder | Ordervy, maskinbeläggning, kapacitet |
-| **Strukturlista (BOM)** | Definiera materialstruktur | Komponenter, nivåer, alternativa delar |
-| **Kvalitetskontroll** | Säkerställ produktkvalitet | Kontrollplaner, mätprotokoll, avvikelser |
-| **Maskinunderhåll** | Förebyggande och avhjälpande underhåll | Schema, felanmälan, reservdelsförbrukning |
-| **Spårbarhet & Batch** | Spåra råvaror till färdig produkt | Batchnummer, komponentspårning, återkallning |
-
----
-
-## 18. Konsult & Rådgivning
-
-Enklare bokföring: tidrapport → faktura, traktamente, hemmakontor. Ofta enskild firma. WIP-bevakning vid löpande räkning.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Konsultkontoplan** | BAS-konton för konsultintäkt, utlägg, resor | Konton 3010 (konsultarvode), 5800 (resekostnad), 6990 (vidarefakturerade utlägg) |
-| **Traktamente** | Beräkna traktamente vid tjänsteresor enligt Skatteverkets schabloner | Hel/halvdag, reducering vid fri måltid, skattefri del, förmånsvärde |
-| **Hemmakontor-avdrag** | Schablonavdrag för hemmakontor | Fast belopp (2 000/4 000 SEK), alternativt verklig kostnad med yta-beräkning |
-| **WIP-bevakning** | Pågående ej fakturerat arbete | Konto 1470, per uppdrag, åldringsanalys |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Debiteringsgrad** | Debiterbara timmar / total arbetstid | Mål vs utfall, trend |
-| **Intäkt per konsult** | Total fakturering per person | Ranking, budget vs utfall |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Tidrapport-import** | Importera tid från Harvest, Toggl, Clockify | CSV, koppling till uppdrag, fakturaunderlag |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Uppdragshantering** | Administrera kunduppdrag | Milstolpar, statusvy, lönsamhetsanalys |
-| **Tidrapportering** | Detaljerad tidregistrering | Timer, kategorier, veckoöversikt |
-| **Offert & Avtal** | Skapa offerter | Mallar, godkännande, avtalsstatus |
-
----
-
-## 19. Event & Underhållning
-
-Biljettintäkter som förskott (periodisering). Moms 6% på kulturella evenemang. SINK-skatt vid utländska artister. Sponsorintäkter. Eventbudget.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Eventkontoplan** | BAS-konton per intäktstyp: biljetter, sponsring, F&B, merch | Konton 3010 (biljettintäkt), 3020 (sponsorintäkt), 3030 (F&B), 3040 (merch) |
-| **Biljettintäkt som förskott** | Bokför förskottssålda biljetter som skuld tills eventet äger rum | Konto 2420, intäktsföring vid genomfört event, avbokningshantering |
-| **Kulturmoms 6%** | Hantera reducerad moms på kulturella föreställningar | Moms 6% på biljetter, 25% på mat/dryck/merch, blandad verksamhet |
-| **Artistskatt (SINK)** | Hantera källskatt för utländska artister | Beräkning av SINK (15%), inbetalning till Skatteverket, underlag per artist |
-| **Sponsorintäktsbokföring** | Bokför sponsoravtal med motprestationsperiodisering | Periodisering per event, konto 3910, avtalsvärde vs motprestation |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Intäkt per besökare** | Total intäkt delat på antal besökare | Biljett + F&B + merch, jämförelse mellan event |
-| **Budget vs utfall** | Eventbudget jämfört med verkligt resultat | Per kostnadspost, totalt, vinstmarginal |
-| **Sponsorandel** | Sponsorintäkt som andel av total intäkt | Per event, trend, beroendeanalys |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Biljettsystem-import** | Importera försäljningsdata från biljettsystem | Ticketmaster, Eventbrite, NORTIC; auto-kontosättning inkl avgifter |
-| **POS-rapport-import** | Importera F&B- och merch-försäljning | Kassarapport från eventbar/shop, momssplit |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Evenemangsplanering** | Planera och koordinera event | Checklista, tidslinje, budget |
-| **Biljettförsäljning** | Sälj och hantera biljetter | Biljettyper, priskategorier, QR-validering |
-| **Artist- & Talangbokning** | Boka artister och föreläsare | Kontrakt, riderhantering, schema |
-| **Sponsorhantering** | Hantera sponsoravtal | Avtalsnivåer, motprestationer, uppföljning |
-| **Volontärhantering** | Koordinera frivilliga | Registrering, skifttilldelning, kommunikation |
-
----
-
-## 20. Fastighetsförvaltning
-
-Hyresintäkter (periodisering). Fastighetsskatt/avgift. Avskrivning fastigheter (lång tid). Underhållsfond. ROT vid renovering. Stämpelskatt vid köp.
-
-### Bokföring & Skatt
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Fastighetskontoplan** | BAS-konton per fastighet och kostnadstyp | Konton 1110 (byggnader), 3010 (hyresintäkt), 5010 (fastighetsskötsel), 7720 (fastighetsskatt) |
-| **Hyresintäkt-periodisering** | Periodisera hyresintäkter korrekt per månad | Förskottshyra (konto 2970), hyresrabatt, tomgångskostnad |
-| **Fastighetsskatt** | Beräkna och bokföra fastighetsskatt/avgift | Taxeringsvärde, skattesats per fastighetstyp, konto 7720, periodisering |
-| **Fastighetsavskrivning** | Avskrivningsplan per byggnad (lång löptid) | Komponentavskrivning (K3) eller linjär (K2), konto 1119/7820 |
-| **Underhållsfond** | Avsätt medel för planerat underhåll | Avsättning per år, upplösning vid genomfört underhåll, 10-årsplan kopplad |
-| **ROT vid renovering** | Hantera ROT-avdrag för hyresgäster vid renovering | Beräkning, personnummer, Skatteverket-rapportering |
-| **Indexuppräkning** | Automatisk beräkning av hyreshöjning vid index | KPI-koppling, beräkning per kontrakt, underlag för avisering |
-
-### Branschrapporter
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Driftnetto per fastighet** | Hyresintäkt minus driftskostnad | Per fastighet/objekt, jämförelse, trend |
-| **Vakansgrad** | Andel outhyrda ytor | Per fastighet, trendanalys, intäktsbortfall |
-| **Underhållskostnad per m²** | Total underhållskostnad per kvadratmeter | Plan vs utfall, per fastighet, kategori |
-
-### Smart import
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Hyresreskontra-import** | Importera hyresreskontra | Avier, betalningar, restbelopp; auto-kontosättning |
-| **Energirapport-import** | Importera energiförbrukning | El/vatten/fjärrvärme, per fastighet, kostnadsfördelning |
-
-### Operativa moduler
-
-| Modul | Beskrivning | Nyckelfunktioner |
-|---|---|---|
-| **Objektregister** | Fastighets- och lokalöversikt | Adresser, ytor, byggnadsår, dokument |
-| **Hyresgästhantering** | Administrera hyresavtal | Avtalstider, kontakt, uppsägningsflöde |
-| **Hyresavier** | Generera och skicka avier | Automatisk avisering, tillägg, autogiro |
-| **Felanmälan** | Hantera felanmälningar | Webformulär, prioritet, hantverkarstyrning |
-| **Underhållsplanering** | Långsiktig och akut | 10-årsplan, kostnadsprognos, status |
-| **Besiktning & Rondering** | Dokumentera besiktningar | Protokoll, foto, avvikelserapport |
-| **Energiövervakning** | Följ energiförbrukning | El/vatten/värme, jämförelse, energideklaration |
diff --git a/supabase/migrations/20240101000021_sru_codes.sql b/supabase/migrations/20240101000021_sru_codes.sql
index d366257e..153221bb 100644
--- a/supabase/migrations/20240101000021_sru_codes.sql
+++ b/supabase/migrations/20240101000021_sru_codes.sql
@@ -260,10 +260,14 @@ begin
insert into public.chart_of_accounts (user_id, account_number, account_name, account_class, account_group, account_type, normal_balance, plan_type, is_system_account, sru_code)
values
(p_user_id, '2440', 'Leverantorsskulder', 2, '24', 'liability', 'credit', 'k1', true, '7230'),
- (p_user_id, '2610', 'Utgaende moms 25%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
- (p_user_id, '2611', 'Utgaende moms 12%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
- (p_user_id, '2612', 'Utgaende moms 6%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
+ (p_user_id, '2611', 'Utgaende moms forsaljning 25%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
+ (p_user_id, '2621', 'Utgaende moms forsaljning 12%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
+ (p_user_id, '2631', 'Utgaende moms forsaljning 6%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
+ (p_user_id, '2614', 'Utg moms omvand skattskyldighet 25%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
+ (p_user_id, '2624', 'Utg moms omvand skattskyldighet 12%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
+ (p_user_id, '2634', 'Utg moms omvand skattskyldighet 6%', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
(p_user_id, '2641', 'Debiterad ingaende moms', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
+ (p_user_id, '2645', 'Beraknad ingaende moms forvarv utlandet', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
(p_user_id, '2650', 'Redovisningskonto for moms', 2, '26', 'liability', 'credit', 'k1', true, '7231'),
(p_user_id, '2710', 'Personalskatt', 2, '27', 'liability', 'credit', 'k1', true, '7231'),
(p_user_id, '2731', 'Avrakning socialavgifter', 2, '27', 'liability', 'credit', 'k1', true, '7231');
@@ -282,7 +286,10 @@ begin
values
(p_user_id, '3001', 'Forsaljning tjanster 25%', 3, '30', 'revenue', 'credit', 'k1', true, '7310'),
(p_user_id, '3002', 'Forsaljning varor 25%', 3, '30', 'revenue', 'credit', 'k1', true, '7310'),
+ (p_user_id, '3003', 'Forsaljning tjanster 6%', 3, '30', 'revenue', 'credit', 'k1', true, '7310'),
(p_user_id, '3100', 'Momsfri forsaljning', 3, '31', 'revenue', 'credit', 'k1', true, '7311'),
+ (p_user_id, '3305', 'Forsaljning tjanst export', 3, '33', 'revenue', 'credit', 'k1', true, '7310'),
+ (p_user_id, '3308', 'Forsaljning tjanst EU', 3, '33', 'revenue', 'credit', 'k1', true, '7310'),
(p_user_id, '3900', 'Ovriga rorelseintakter', 3, '39', 'revenue', 'credit', 'k1', true, '7311'),
(p_user_id, '3960', 'Valutakursvinster', 3, '39', 'revenue', 'credit', 'k1', true, '7310');
diff --git a/supabase/migrations/20240101000023_document_version_chain.sql b/supabase/migrations/20240101000023_document_version_chain.sql
new file mode 100644
index 00000000..f1496a38
--- /dev/null
+++ b/supabase/migrations/20240101000023_document_version_chain.sql
@@ -0,0 +1,163 @@
+-- Migration 23: Document Version Chain Hardening
+-- Adds cryptographic hash chain + atomic versioning via RPC
+-- Resolves: Gap 4 (no hash-chain) + Gap 5 (race condition in versioning)
+
+-- =============================================================================
+-- 1. New columns on document_attachments
+-- =============================================================================
+
+ALTER TABLE public.document_attachments
+ ADD COLUMN IF NOT EXISTS prev_version_hash text,
+ ADD COLUMN IF NOT EXISTS last_integrity_check_at timestamptz;
+
+COMMENT ON COLUMN public.document_attachments.prev_version_hash IS
+ 'SHA-256 hash of the previous version. NULL for version 1 (genesis). Creates tamper-evident chain.';
+
+COMMENT ON COLUMN public.document_attachments.last_integrity_check_at IS
+ 'Timestamp of the last batch integrity verification (set by cron job).';
+
+-- Index for cron job: prioritize documents never checked or least recently checked
+CREATE INDEX IF NOT EXISTS idx_doc_attachments_integrity_check
+ ON public.document_attachments (last_integrity_check_at NULLS FIRST)
+ WHERE is_current_version = true;
+
+-- =============================================================================
+-- 2. RPC: create_document_version (atomic versioning with row-level lock)
+-- Pattern follows next_voucher_number() from migration 016
+-- =============================================================================
+
+CREATE OR REPLACE FUNCTION public.create_document_version(
+ p_user_id uuid,
+ p_original_doc_id uuid,
+ p_storage_path text,
+ p_file_name text,
+ p_file_size_bytes bigint,
+ p_mime_type text,
+ p_sha256_hash text,
+ p_upload_source text DEFAULT NULL
+)
+RETURNS uuid
+LANGUAGE plpgsql
+SECURITY DEFINER
+AS $$
+DECLARE
+ v_current RECORD;
+ v_root_original_id uuid;
+ v_new_version integer;
+ v_new_id uuid;
+BEGIN
+ -- Lock the current version row (prevents concurrent versioning)
+ SELECT id, version, sha256_hash, original_id, journal_entry_id,
+ journal_entry_line_id, upload_source
+ INTO v_current
+ FROM public.document_attachments
+ WHERE id = p_original_doc_id
+ AND user_id = p_user_id
+ AND is_current_version = true
+ FOR UPDATE;
+
+ IF NOT FOUND THEN
+ RAISE EXCEPTION 'Document not found, not owned by user, or not the current version';
+ END IF;
+
+ v_root_original_id := COALESCE(v_current.original_id, v_current.id);
+ v_new_version := v_current.version + 1;
+
+ -- Insert new version with hash chain link
+ INSERT INTO public.document_attachments (
+ user_id,
+ storage_path,
+ file_name,
+ file_size_bytes,
+ mime_type,
+ sha256_hash,
+ version,
+ original_id,
+ is_current_version,
+ uploaded_by,
+ upload_source,
+ digitization_date,
+ journal_entry_id,
+ journal_entry_line_id,
+ prev_version_hash
+ ) VALUES (
+ p_user_id,
+ p_storage_path,
+ p_file_name,
+ p_file_size_bytes,
+ p_mime_type,
+ p_sha256_hash,
+ v_new_version,
+ v_root_original_id,
+ true,
+ p_user_id,
+ COALESCE(p_upload_source, v_current.upload_source),
+ now(),
+ v_current.journal_entry_id,
+ v_current.journal_entry_line_id,
+ v_current.sha256_hash -- cryptographic link to previous version
+ )
+ RETURNING id INTO v_new_id;
+
+ -- Mark old version as superseded (within same transaction = atomic)
+ UPDATE public.document_attachments
+ SET is_current_version = false,
+ superseded_by_id = v_new_id
+ WHERE id = v_current.id;
+
+ RETURN v_new_id;
+END;
+$$;
+
+GRANT EXECUTE ON FUNCTION public.create_document_version(uuid, uuid, text, text, bigint, text, text, text) TO authenticated;
+
+-- =============================================================================
+-- 3. RPC: validate_version_chain
+-- Verifies that prev_version_hash matches sha256_hash of the preceding version
+-- =============================================================================
+
+CREATE OR REPLACE FUNCTION public.validate_version_chain(
+ p_user_id uuid,
+ p_original_doc_id uuid
+)
+RETURNS TABLE (
+ doc_id uuid,
+ version integer,
+ sha256_hash text,
+ prev_version_hash text,
+ expected_prev_hash text,
+ chain_valid boolean
+)
+LANGUAGE plpgsql
+SECURITY DEFINER
+AS $$
+BEGIN
+ RETURN QUERY
+ WITH chain AS (
+ SELECT
+ da.id,
+ da.version,
+ da.sha256_hash AS current_hash,
+ da.prev_version_hash AS stored_prev_hash,
+ LAG(da.sha256_hash) OVER (ORDER BY da.version) AS computed_prev_hash
+ FROM public.document_attachments da
+ WHERE da.user_id = p_user_id
+ AND (da.id = p_original_doc_id OR da.original_id = p_original_doc_id)
+ ORDER BY da.version
+ )
+ SELECT
+ chain.id AS doc_id,
+ chain.version,
+ chain.current_hash AS sha256_hash,
+ chain.stored_prev_hash AS prev_version_hash,
+ chain.computed_prev_hash AS expected_prev_hash,
+ CASE
+ WHEN chain.version = 1 THEN (chain.stored_prev_hash IS NULL)
+ ELSE (chain.stored_prev_hash IS NOT NULL AND chain.stored_prev_hash = chain.computed_prev_hash)
+ END AS chain_valid
+ FROM chain
+ ORDER BY chain.version;
+END;
+$$;
+
+GRANT EXECUTE ON FUNCTION public.validate_version_chain(uuid, uuid) TO authenticated;
diff --git a/supabase/migrations/20240101000024_storage_bucket_policies.sql b/supabase/migrations/20240101000024_storage_bucket_policies.sql
new file mode 100644
index 00000000..b7192b74
--- /dev/null
+++ b/supabase/migrations/20240101000024_storage_bucket_policies.sql
@@ -0,0 +1,57 @@
+-- Migration 24: Storage Bucket Policies for WORM Document Archive
+-- Resolves: Gap 3 (no immutability on Storage level)
+--
+-- Creates a private 'documents' bucket with:
+-- - INSERT policy (authenticated users upload to their own folder)
+-- - SELECT policy (authenticated users read their own documents)
+-- - NO UPDATE policy (prevents overwriting files — WORM)
+-- - NO DELETE policy (prevents client-side deletion — WORM)
+--
+-- Service role (cron, admin) bypasses RLS and can still access everything.
+
+-- =============================================================================
+-- 1. Create the 'documents' bucket (private, 50MB file limit)
+-- =============================================================================
+
+INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
+VALUES (
+ 'documents',
+ 'documents',
+ false,
+ 52428800, -- 50 MB
+ NULL -- Allow all MIME types (PDFs, images, etc.)
+)
+ON CONFLICT (id) DO NOTHING;
+
+-- =============================================================================
+-- 2. INSERT policy: Authenticated users can upload to their own folder
+-- =============================================================================
+
+CREATE POLICY "documents_insert_own"
+ ON storage.objects
+ FOR INSERT
+ TO authenticated
+ WITH CHECK (
+ bucket_id = 'documents'
+ AND (storage.foldername(name))[1] = 'documents'
+ AND (storage.foldername(name))[2] = auth.uid()::text
+ );
+
+-- =============================================================================
+-- 3. SELECT policy: Authenticated users can read their own documents
+-- =============================================================================
+
+CREATE POLICY "documents_select_own"
+ ON storage.objects
+ FOR SELECT
+ TO authenticated
+ USING (
+ bucket_id = 'documents'
+ AND (storage.foldername(name))[1] = 'documents'
+ AND (storage.foldername(name))[2] = auth.uid()::text
+ );
+
+-- =============================================================================
+-- No UPDATE or DELETE policies — WORM compliance
+-- Service role bypasses RLS for admin/cron access
+-- =============================================================================
diff --git a/supabase/migrations/20240101000025_supplier_invoices.sql b/supabase/migrations/20240101000025_supplier_invoices.sql
new file mode 100644
index 00000000..056a8a57
--- /dev/null
+++ b/supabase/migrations/20240101000025_supplier_invoices.sql
@@ -0,0 +1,342 @@
+-- Migration 25: Leverantorsreskontra (Accounts Payable)
+-- Suppliers, supplier invoices, line items, partial payments
+-- BFL 5:6-9 verifikationskrav, ML 17:24 inkommande fakturor
+
+-- =============================================================================
+-- 1. suppliers table
+-- =============================================================================
+CREATE TABLE IF NOT EXISTS public.suppliers (
+ id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
+ user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
+
+ -- Basic info
+ name text NOT NULL,
+ supplier_type text NOT NULL DEFAULT 'swedish_business'
+ CHECK (supplier_type IN ('swedish_business', 'eu_business', 'non_eu_business')),
+ org_number text,
+ vat_number text,
+
+ -- Contact
+ email text,
+ phone text,
+
+ -- Address
+ address_line1 text,
+ address_line2 text,
+ postal_code text,
+ city text,
+ country text NOT NULL DEFAULT 'SE',
+
+ -- Payment details
+ bankgiro text,
+ plusgiro text,
+ bank_account text,
+ iban text,
+ bic text,
+
+ -- Defaults
+ default_expense_account text, -- e.g. '5010'
+ default_payment_terms integer NOT NULL DEFAULT 30,
+ default_currency text NOT NULL DEFAULT 'SEK',
+
+ -- Notes
+ notes text,
+
+ created_at timestamptz NOT NULL DEFAULT now(),
+ updated_at timestamptz NOT NULL DEFAULT now()
+);
+
+ALTER TABLE public.suppliers ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY "Users can view own suppliers"
+ ON public.suppliers FOR SELECT
+ USING (auth.uid() = user_id);
+
+CREATE POLICY "Users can insert own suppliers"
+ ON public.suppliers FOR INSERT
+ WITH CHECK (auth.uid() = user_id);
+
+CREATE POLICY "Users can update own suppliers"
+ ON public.suppliers FOR UPDATE
+ USING (auth.uid() = user_id);
+
+CREATE POLICY "Users can delete own suppliers"
+ ON public.suppliers FOR DELETE
+ USING (auth.uid() = user_id);
+
+CREATE INDEX idx_suppliers_user_id ON public.suppliers (user_id);
+CREATE INDEX idx_suppliers_name ON public.suppliers (user_id, name);
+
+-- =============================================================================
+-- 2. supplier_invoices table
+-- =============================================================================
+CREATE TABLE IF NOT EXISTS public.supplier_invoices (
+ id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
+ user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
+ supplier_id uuid NOT NULL REFERENCES public.suppliers(id) ON DELETE RESTRICT,
+
+ -- Ankomstnummer (BFL running number for incoming invoices)
+ arrival_number integer NOT NULL,
+
+ -- Supplier's reference
+ supplier_invoice_number text NOT NULL,
+
+ -- Dates (ML 17:24 requirements)
+ invoice_date date NOT NULL,
+ due_date date NOT NULL,
+ received_date date NOT NULL DEFAULT CURRENT_DATE,
+ delivery_date date, -- ML krav
+
+ -- Status
+ status text NOT NULL DEFAULT 'registered'
+ CHECK (status IN ('registered', 'approved', 'paid', 'partially_paid', 'overdue', 'disputed', 'credited')),
+
+ -- Currency
+ currency text NOT NULL DEFAULT 'SEK',
+ exchange_rate numeric,
+ exchange_rate_date date,
+
+ -- Amounts
+ subtotal numeric NOT NULL DEFAULT 0,
+ subtotal_sek numeric,
+ vat_amount numeric NOT NULL DEFAULT 0,
+ vat_amount_sek numeric,
+ total numeric NOT NULL DEFAULT 0,
+ total_sek numeric,
+
+ -- VAT
+ vat_treatment text NOT NULL DEFAULT 'standard_25',
+ reverse_charge boolean NOT NULL DEFAULT false,
+
+ -- Payment
+ payment_reference text, -- OCR-nummer
+ paid_at timestamptz,
+ paid_amount numeric NOT NULL DEFAULT 0,
+ remaining_amount numeric NOT NULL DEFAULT 0,
+
+ -- Credit note
+ is_credit_note boolean NOT NULL DEFAULT false,
+ credited_invoice_id uuid REFERENCES public.supplier_invoices(id) ON DELETE SET NULL,
+
+ -- Bookkeeping links
+ registration_journal_entry_id uuid REFERENCES public.journal_entries(id) ON DELETE SET NULL,
+ payment_journal_entry_id uuid REFERENCES public.journal_entries(id) ON DELETE SET NULL,
+
+ -- Transaction link
+ transaction_id uuid REFERENCES public.transactions(id) ON DELETE SET NULL,
+
+ -- Document (verifikationsunderlag)
+ document_id uuid REFERENCES public.document_attachments(id) ON DELETE SET NULL,
+
+ -- Notes
+ notes text,
+
+ created_at timestamptz NOT NULL DEFAULT now(),
+ updated_at timestamptz NOT NULL DEFAULT now(),
+
+ -- Constraints
+ CONSTRAINT uq_supplier_invoices_arrival UNIQUE (user_id, arrival_number),
+ CONSTRAINT uq_supplier_invoices_ref UNIQUE (user_id, supplier_id, supplier_invoice_number)
+);
+
+ALTER TABLE public.supplier_invoices ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY "Users can view own supplier invoices"
+ ON public.supplier_invoices FOR SELECT
+ USING (auth.uid() = user_id);
+
+CREATE POLICY "Users can insert own supplier invoices"
+ ON public.supplier_invoices FOR INSERT
+ WITH CHECK (auth.uid() = user_id);
+
+CREATE POLICY "Users can update own supplier invoices"
+ ON public.supplier_invoices FOR UPDATE
+ USING (auth.uid() = user_id);
+
+CREATE POLICY "Users can delete own supplier invoices"
+ ON public.supplier_invoices FOR DELETE
+ USING (auth.uid() = user_id);
+
+CREATE INDEX idx_supplier_invoices_user_id ON public.supplier_invoices (user_id);
+CREATE INDEX idx_supplier_invoices_supplier ON public.supplier_invoices (supplier_id);
+CREATE INDEX idx_supplier_invoices_status ON public.supplier_invoices (user_id, status);
+CREATE INDEX idx_supplier_invoices_due_date ON public.supplier_invoices (user_id, due_date);
+
+-- =============================================================================
+-- 3. Per-user arrival number generation (ankomstnummer)
+-- =============================================================================
+CREATE OR REPLACE FUNCTION public.get_next_arrival_number(p_user_id uuid)
+RETURNS integer AS $$
+DECLARE
+ next_num integer;
+BEGIN
+ SELECT COALESCE(MAX(arrival_number), 0) + 1 INTO next_num
+ FROM public.supplier_invoices
+ WHERE user_id = p_user_id;
+ RETURN next_num;
+END;
+$$ LANGUAGE plpgsql;
+
+-- =============================================================================
+-- 4. supplier_invoice_items table
+-- =============================================================================
+CREATE TABLE IF NOT EXISTS public.supplier_invoice_items (
+ id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
+ supplier_invoice_id uuid NOT NULL REFERENCES public.supplier_invoices(id) ON DELETE CASCADE,
+
+ sort_order integer NOT NULL DEFAULT 0,
+ description text NOT NULL,
+ quantity numeric NOT NULL DEFAULT 1,
+ unit text NOT NULL DEFAULT 'st',
+ unit_price numeric NOT NULL DEFAULT 0, -- exkl. moms (ML krav)
+ line_total numeric NOT NULL DEFAULT 0,
+
+ -- Bookkeeping
+ account_number text NOT NULL, -- BAS expense account (4xxx-6xxx)
+ vat_code text,
+ vat_rate numeric NOT NULL DEFAULT 0.25,
+ vat_amount numeric NOT NULL DEFAULT 0,
+
+ created_at timestamptz NOT NULL DEFAULT now()
+);
+
+ALTER TABLE public.supplier_invoice_items ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY "Users can view own supplier invoice items"
+ ON public.supplier_invoice_items FOR SELECT
+ USING (
+ EXISTS (
+ SELECT 1 FROM public.supplier_invoices si
+ WHERE si.id = supplier_invoice_id AND si.user_id = auth.uid()
+ )
+ );
+
+CREATE POLICY "Users can insert own supplier invoice items"
+ ON public.supplier_invoice_items FOR INSERT
+ WITH CHECK (
+ EXISTS (
+ SELECT 1 FROM public.supplier_invoices si
+ WHERE si.id = supplier_invoice_id AND si.user_id = auth.uid()
+ )
+ );
+
+CREATE POLICY "Users can update own supplier invoice items"
+ ON public.supplier_invoice_items FOR UPDATE
+ USING (
+ EXISTS (
+ SELECT 1 FROM public.supplier_invoices si
+ WHERE si.id = supplier_invoice_id AND si.user_id = auth.uid()
+ )
+ );
+
+CREATE POLICY "Users can delete own supplier invoice items"
+ ON public.supplier_invoice_items FOR DELETE
+ USING (
+ EXISTS (
+ SELECT 1 FROM public.supplier_invoices si
+ WHERE si.id = supplier_invoice_id AND si.user_id = auth.uid()
+ )
+ );
+
+CREATE INDEX idx_supplier_invoice_items_invoice ON public.supplier_invoice_items (supplier_invoice_id);
+
+-- =============================================================================
+-- 5. supplier_invoice_payments table (partial payments)
+-- =============================================================================
+CREATE TABLE IF NOT EXISTS public.supplier_invoice_payments (
+ id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
+ supplier_invoice_id uuid NOT NULL REFERENCES public.supplier_invoices(id) ON DELETE CASCADE,
+
+ payment_date date NOT NULL,
+ amount numeric NOT NULL,
+ currency text NOT NULL DEFAULT 'SEK',
+ exchange_rate numeric,
+ exchange_rate_difference numeric DEFAULT 0, -- kursdifferens
+
+ journal_entry_id uuid REFERENCES public.journal_entries(id) ON DELETE SET NULL,
+ transaction_id uuid REFERENCES public.transactions(id) ON DELETE SET NULL,
+ notes text,
+
+ created_at timestamptz NOT NULL DEFAULT now()
+);
+
+ALTER TABLE public.supplier_invoice_payments ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY "Users can view own supplier invoice payments"
+ ON public.supplier_invoice_payments FOR SELECT
+ USING (
+ EXISTS (
+ SELECT 1 FROM public.supplier_invoices si
+ WHERE si.id = supplier_invoice_id AND si.user_id = auth.uid()
+ )
+ );
+
+CREATE POLICY "Users can insert own supplier invoice payments"
+ ON public.supplier_invoice_payments FOR INSERT
+ WITH CHECK (
+ EXISTS (
+ SELECT 1 FROM public.supplier_invoices si
+ WHERE si.id = supplier_invoice_id AND si.user_id = auth.uid()
+ )
+ );
+
+CREATE INDEX idx_supplier_invoice_payments_invoice ON public.supplier_invoice_payments (supplier_invoice_id);
+
+-- =============================================================================
+-- 6. Add supplier_invoice_id to transactions
+-- =============================================================================
+ALTER TABLE public.transactions
+ ADD COLUMN IF NOT EXISTS supplier_invoice_id uuid REFERENCES public.supplier_invoices(id) ON DELETE SET NULL;
+
+CREATE INDEX IF NOT EXISTS idx_transactions_supplier_invoice ON public.transactions (supplier_invoice_id);
+
+-- =============================================================================
+-- 7. Expand journal_entries source_type constraint
+-- =============================================================================
+ALTER TABLE public.journal_entries
+ DROP CONSTRAINT IF EXISTS journal_entries_source_type_check;
+
+ALTER TABLE public.journal_entries
+ ADD CONSTRAINT journal_entries_source_type_check
+ CHECK (source_type IN (
+ 'manual', 'bank_transaction', 'invoice_created',
+ 'invoice_paid', 'invoice_cash_payment', 'credit_note', 'salary_payment',
+ 'opening_balance', 'year_end',
+ 'storno', 'correction', 'import', 'system',
+ 'supplier_invoice_registered', 'supplier_invoice_paid',
+ 'supplier_invoice_cash_payment', 'supplier_credit_note'
+ ));
+
+-- =============================================================================
+-- 8. Audit triggers for new tables
+-- =============================================================================
+CREATE TRIGGER audit_suppliers
+ AFTER INSERT OR UPDATE OR DELETE ON public.suppliers
+ FOR EACH ROW EXECUTE FUNCTION public.write_audit_log();
+
+CREATE TRIGGER audit_supplier_invoices
+ AFTER INSERT OR UPDATE OR DELETE ON public.supplier_invoices
+ FOR EACH ROW EXECUTE FUNCTION public.write_audit_log();
+
+CREATE TRIGGER audit_supplier_invoice_items
+ AFTER INSERT OR UPDATE OR DELETE ON public.supplier_invoice_items
+ FOR EACH ROW EXECUTE FUNCTION public.write_audit_log();
+
+-- =============================================================================
+-- 9. Updated_at triggers
+-- =============================================================================
+CREATE OR REPLACE FUNCTION public.update_updated_at_column()
+RETURNS trigger AS $$
+BEGIN
+ NEW.updated_at = now();
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER set_updated_at_suppliers
+ BEFORE UPDATE ON public.suppliers
+ FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
+
+CREATE TRIGGER set_updated_at_supplier_invoices
+ BEFORE UPDATE ON public.supplier_invoices
+ FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
diff --git a/supabase/migrations/20240101000026_drop_restaurant_module.sql b/supabase/migrations/20240101000026_drop_restaurant_module.sql
new file mode 100644
index 00000000..308c6428
--- /dev/null
+++ b/supabase/migrations/20240101000026_drop_restaurant_module.sql
@@ -0,0 +1,20 @@
+-- Drop 14 restaurant module tables — zero code references, zero rows.
+-- These are industry-specific tables that don't belong in base ERP.
+
+-- Children first
+DROP TABLE IF EXISTS public.recipe_ingredients CASCADE;
+DROP TABLE IF EXISTS public.supplier_order_items CASCADE;
+DROP TABLE IF EXISTS public.menu_items CASCADE;
+DROP TABLE IF EXISTS public.menu_categories CASCADE;
+DROP TABLE IF EXISTS public.reservations CASCADE;
+DROP TABLE IF EXISTS public.shifts CASCADE;
+
+-- Parents / standalone
+DROP TABLE IF EXISTS public.menus CASCADE;
+DROP TABLE IF EXISTS public.recipes CASCADE;
+DROP TABLE IF EXISTS public.ingredients CASCADE;
+DROP TABLE IF EXISTS public.staff_members CASCADE;
+DROP TABLE IF EXISTS public.supplier_orders CASCADE;
+DROP TABLE IF EXISTS public.restaurant_tables CASCADE;
+DROP TABLE IF EXISTS public.waste_entries CASCADE;
+DROP TABLE IF EXISTS public.restaurant_capacity CASCADE;
diff --git a/supabase/migrations/20240101000027_drop_unused_module_tables.sql b/supabase/migrations/20240101000027_drop_unused_module_tables.sql
new file mode 100644
index 00000000..420f298c
--- /dev/null
+++ b/supabase/migrations/20240101000027_drop_unused_module_tables.sql
@@ -0,0 +1,58 @@
+-- Drop 36 unused tables — zero .from() calls, zero rows.
+-- Grouped by module; children before parents.
+
+-- HR / Payroll
+DROP TABLE IF EXISTS public.salary_additions CASCADE;
+DROP TABLE IF EXISTS public.salary_run_items CASCADE;
+DROP TABLE IF EXISTS public.salary_payments CASCADE;
+DROP TABLE IF EXISTS public.salary_runs CASCADE;
+DROP TABLE IF EXISTS public.absence_records CASCADE;
+DROP TABLE IF EXISTS public.mileage_entries CASCADE;
+DROP TABLE IF EXISTS public.employees CASCADE;
+
+-- Asset Management
+DROP TABLE IF EXISTS public.depreciation_schedule CASCADE;
+DROP TABLE IF EXISTS public.assets CASCADE;
+DROP TABLE IF EXISTS public.asset_categories CASCADE;
+
+-- Bank Reconciliation
+DROP TABLE IF EXISTS public.bank_reconciliation_items CASCADE;
+DROP TABLE IF EXISTS public.bank_reconciliation_sessions CASCADE;
+DROP TABLE IF EXISTS public.account_balances CASCADE;
+
+-- Budgeting / Forecasting
+DROP TABLE IF EXISTS public.budget_entries CASCADE;
+DROP TABLE IF EXISTS public.budgets CASCADE;
+DROP TABLE IF EXISTS public.cash_flow_forecasts CASCADE;
+
+-- Orders / Quotes
+DROP TABLE IF EXISTS public.order_items CASCADE;
+DROP TABLE IF EXISTS public.orders CASCADE;
+DROP TABLE IF EXISTS public.quote_items CASCADE;
+DROP TABLE IF EXISTS public.quotes CASCADE;
+
+-- Analytics / KPI
+DROP TABLE IF EXISTS public.ai_insights_cache CASCADE;
+DROP TABLE IF EXISTS public.financial_insights CASCADE;
+DROP TABLE IF EXISTS public.kpi_snapshots CASCADE;
+
+-- Tax / Compliance
+DROP TABLE IF EXISTS public.agi_declarations CASCADE;
+DROP TABLE IF EXISTS public.annual_reports CASCADE;
+DROP TABLE IF EXISTS public.tax_rates CASCADE;
+DROP TABLE IF EXISTS public.year_end_closings CASCADE;
+
+-- Supplier Payments
+DROP TABLE IF EXISTS public.supplier_payment_items CASCADE;
+DROP TABLE IF EXISTS public.supplier_payments CASCADE;
+
+-- Module System
+DROP TABLE IF EXISTS public.module_configs CASCADE;
+DROP TABLE IF EXISTS public.module_imports CASCADE;
+DROP TABLE IF EXISTS public.module_kpi_targets CASCADE;
+
+-- Other
+DROP TABLE IF EXISTS public.onboarding_checklist CASCADE;
+DROP TABLE IF EXISTS public.payment_methods CASCADE;
+DROP TABLE IF EXISTS public.recurring_invoices CASCADE;
+DROP TABLE IF EXISTS public.supplier_invoice_attestations CASCADE;
diff --git a/tests/helpers.ts b/tests/helpers.ts
index 510aba58..2abd30e0 100644
--- a/tests/helpers.ts
+++ b/tests/helpers.ts
@@ -136,6 +136,7 @@ export function makeTransaction(overrides: Partial = {}): Transacti
category: 'uncategorized',
is_business: null,
invoice_id: null,
+ supplier_invoice_id: null,
potential_invoice_id: null,
journal_entry_id: null,
mcc_code: null,
@@ -235,6 +236,8 @@ export function makeDocumentAttachment(
digitization_date: '2024-06-15T14:30:00Z',
journal_entry_id: null,
journal_entry_line_id: null,
+ prev_version_hash: null,
+ last_integrity_check_at: null,
created_at: '2024-06-15T14:30:00Z',
updated_at: '2024-06-15T14:30:00Z',
...overrides,
diff --git a/types/index.ts b/types/index.ts
index 401013cf..1175f023 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -30,6 +30,12 @@ export type CustomerType =
// Invoice status
export type InvoiceStatus = 'draft' | 'sent' | 'paid' | 'overdue' | 'cancelled' | 'credited'
+// Supplier types
+export type SupplierType = 'swedish_business' | 'eu_business' | 'non_eu_business'
+
+// Supplier invoice status
+export type SupplierInvoiceStatus = 'registered' | 'approved' | 'paid' | 'partially_paid' | 'overdue' | 'disputed' | 'credited'
+
// VAT treatment
export type VatTreatment =
| 'standard_25' // 25% Swedish VAT
@@ -39,6 +45,9 @@ export type VatTreatment =
| 'export' // Non-EU export (0%)
| 'exempt' // VAT exempt
+// Accounting method (bokföringsmetod)
+export type AccountingMethod = 'accrual' | 'cash'
+
// Moms reporting period
export type MomsPeriod = 'monthly' | 'quarterly' | 'yearly'
@@ -97,6 +106,14 @@ export interface CompanySettings {
iban: string | null
bic: string | null
+ // Accounting method
+ accounting_method: AccountingMethod
+
+ // Invoice settings
+ invoice_prefix: string | null
+ next_invoice_number: number
+ invoice_default_days: number
+
// Onboarding
onboarding_step: number
onboarding_complete: boolean
@@ -112,20 +129,20 @@ export interface BankConnection {
user_id: string
bank_name: string
- bank_id: string
+ provider: string
// Enable Banking specific
session_id: string | null
authorization_id: string | null
// Account info
- accounts: BankAccount[]
+ accounts_data: BankAccount[]
// Status
status: BankConnectionStatus
// Consent
- consent_expires_at: string | null
+ consent_expires: string | null
last_synced_at: string | null
created_at: string
@@ -167,6 +184,9 @@ export interface Transaction {
// Linked invoice (for matching)
invoice_id: string | null
+ // Linked supplier invoice (for matching)
+ supplier_invoice_id: string | null
+
// Potential invoice match (suggested, not confirmed)
potential_invoice_id: string | null
@@ -221,6 +241,135 @@ export interface Customer {
updated_at: string
}
+// Supplier
+export interface Supplier {
+ id: string
+ user_id: string
+
+ name: string
+ supplier_type: SupplierType
+
+ email: string | null
+ phone: string | null
+
+ address_line1: string | null
+ address_line2: string | null
+ postal_code: string | null
+ city: string | null
+ country: string
+
+ org_number: string | null
+ vat_number: string | null
+
+ bankgiro: string | null
+ plusgiro: string | null
+ bank_account: string | null
+ iban: string | null
+ bic: string | null
+
+ default_expense_account: string | null
+ default_payment_terms: number
+ default_currency: string
+
+ notes: string | null
+
+ created_at: string
+ updated_at: string
+}
+
+// Supplier Invoice
+export interface SupplierInvoice {
+ id: string
+ user_id: string
+ supplier_id: string
+
+ arrival_number: number
+ supplier_invoice_number: string
+
+ invoice_date: string
+ due_date: string
+ received_date: string
+ delivery_date: string | null
+
+ status: SupplierInvoiceStatus
+
+ currency: string
+ exchange_rate: number | null
+ exchange_rate_date: string | null
+
+ subtotal: number
+ subtotal_sek: number | null
+ vat_amount: number
+ vat_amount_sek: number | null
+ total: number
+ total_sek: number | null
+
+ vat_treatment: VatTreatment
+ reverse_charge: boolean
+
+ payment_reference: string | null
+ paid_at: string | null
+ paid_amount: number
+ remaining_amount: number
+
+ is_credit_note: boolean
+ credited_invoice_id: string | null
+
+ registration_journal_entry_id: string | null
+ payment_journal_entry_id: string | null
+
+ transaction_id: string | null
+ document_id: string | null
+
+ notes: string | null
+
+ created_at: string
+ updated_at: string
+
+ // Relations (populated when fetched)
+ supplier?: Supplier
+ items?: SupplierInvoiceItem[]
+ payments?: SupplierInvoicePayment[]
+}
+
+// Supplier Invoice Item
+export interface SupplierInvoiceItem {
+ id: string
+ supplier_invoice_id: string
+
+ sort_order: number
+ description: string
+ quantity: number
+ unit: string
+ unit_price: number
+ line_total: number
+
+ account_number: string
+ vat_code: string | null
+ vat_rate: number
+ vat_amount: number
+
+ created_at: string
+}
+
+// Supplier Invoice Payment (partial payments)
+export interface SupplierInvoicePayment {
+ id: string
+ supplier_invoice_id: string
+
+ payment_date: string
+ amount: number
+ currency: string
+ exchange_rate: number | null
+ exchange_rate_difference: number
+
+ journal_entry_id: string | null
+ transaction_id: string | null
+ notes: string | null
+
+ created_at: string
+}
+
// Invoice
export interface Invoice {
id: string
@@ -372,6 +521,54 @@ export interface CreateCustomerInput {
notes?: string
}
+export interface CreateSupplierInput {
+ name: string
+ supplier_type: SupplierType
+ email?: string
+ phone?: string
+ address_line1?: string
+ address_line2?: string
+ postal_code?: string
+ city?: string
+ country?: string
+ org_number?: string
+ vat_number?: string
+ bankgiro?: string
+ plusgiro?: string
+ bank_account?: string
+ iban?: string
+ bic?: string
+ default_expense_account?: string
+ default_payment_terms?: number
+ default_currency?: string
+ notes?: string
+}
+
+export interface CreateSupplierInvoiceInput {
+ supplier_id: string
+ supplier_invoice_number: string
+ invoice_date: string
+ due_date: string
+ delivery_date?: string
+ currency?: string
+ exchange_rate?: number
+ vat_treatment?: VatTreatment
+ reverse_charge?: boolean
+ payment_reference?: string
+ notes?: string
+ items: CreateSupplierInvoiceItemInput[]
+}
+
+export interface CreateSupplierInvoiceItemInput {
+ description: string
+ quantity: number
+ unit?: string
+ unit_price: number
+ account_number: string
+ vat_code?: string
+ vat_rate?: number
+}
+
export interface CreateInvoiceInput {
customer_id: string
invoice_date: string
@@ -497,6 +694,7 @@ export type JournalEntrySourceType =
| 'bank_transaction'
| 'invoice_created'
| 'invoice_paid'
+ | 'invoice_cash_payment'
| 'credit_note'
| 'salary_payment'
| 'opening_balance'
@@ -505,6 +703,10 @@ export type JournalEntrySourceType =
| 'correction'
| 'import'
| 'system'
+ | 'supplier_invoice_registered'
+ | 'supplier_invoice_paid'
+ | 'supplier_invoice_cash_payment'
+ | 'supplier_credit_note'
// Journal entry status
export type JournalEntryStatus = 'draft' | 'posted' | 'reversed'
@@ -1203,6 +1405,8 @@ export interface DocumentAttachment {
digitization_date: string | null
journal_entry_id: string | null
journal_entry_line_id: string | null
+ prev_version_hash: string | null
+ last_integrity_check_at: string | null
created_at: string
updated_at: string
}
@@ -1234,6 +1438,7 @@ export type AuditAction =
| 'DOCUMENT_DELETE_BLOCKED'
| 'RETENTION_BLOCK'
| 'SECURITY_EVENT'
+ | 'INTEGRITY_FAILURE'
export interface AuditLogEntry {
id: string
diff --git a/vercel.json b/vercel.json
index 5267f667..65fea6ef 100644
--- a/vercel.json
+++ b/vercel.json
@@ -1,9 +1,5 @@
{
"crons": [
- {
- "path": "/api/tiktok/cron",
- "schedule": "0 7 * * *"
- },
{
"path": "/api/deadlines/status/cron",
"schedule": "0 6 * * *"
@@ -23,6 +19,10 @@
{
"path": "/api/banking/sync/cron",
"schedule": "0 5 * * *"
+ },
+ {
+ "path": "/api/documents/verify/cron",
+ "schedule": "0 3 * * 0"
}
]
}