# 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