# 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 } ```