* feat: separate AR/AP/accounting into distinct nav groups (#92) Split the flat "Finans" sidebar group into three visually distinct sections — Försäljning (AR), Inköp (AP), and Redovisning — so users coming from Fortnox immediately find customer invoicing and supplier invoices as top-level concepts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: journal entry detail view, correction chain, and account name display - Add journal entry detail page at /bookkeeping/[id] with full entry view - Add correction chain API and component showing storno relationships - Add JournalEntryStatusBadge component for entry status display - Show debit/credit account names in template picker and review dialogs - Expand client-side BAS account name mapping with additional accounts - Show account codes on transaction inbox suggestion buttons Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address review feedback — N+1 query, duplicate name, nav dedup - Batch reverse-lookup into single query per BFS iteration (was N+1) - Differentiate account 2393 from 2893 in display names - Extract shared loop for desktop/mobile nav group rendering Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: counterparty templates, Skatteverket extension, VAT form completeness, and UI cleanup - Add counterparty-based categorization templates (learned from user approvals and auto-ingestion) with fuzzy matching in the mapping engine - Add Skatteverket extension for direct VAT declaration submission via API - Complete VAT declaration form with all 30 SKV 4700 boxes (ruta 08, 35-42, 50, 60-62) - Fix ruta 49 formula to include import VAT (ruta 60+61+62) - Simplify dashboard UI: remove redundant icons from stat cards, customer cards, invoice list, supplier invoices; use Badge variants consistently - Add SkatteverketPanel component to reports page - Add categorization_templates and skatteverket_tokens migrations - Update tests and helpers for new types Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review feedback — VAT detection, migration timestamps, dedup - Fix detectVatTreatment to derive actual rate (12%/6%) from VAT line description instead of hardcoding standard_25 - Rename skatteverket_tokens migration to 20260324120001 to avoid duplicate timestamp with categorization_templates (fixes Supabase deployment failure) - Make refreshAccessToken accept previousRefreshCount param to enforce refresh limit contract at the type level - Fix rate limiter TOCTOU by claiming slot before await - Extract formatRedovisare/formatRedovisningsperiod to shared lib/skatteverket/format.ts — eliminates duplication between mappers.ts and SkatteverketPanel.tsx Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import type { VatPeriodType } from '@/types'
|
|
|
|
/**
|
|
* Convert a gnubok org_number to Skatteverket's 12-digit "redovisare" format.
|
|
*
|
|
* Rules:
|
|
* - Organisationsnummer (10 digits, e.g. 5020000013): prefix with "16" → 165020000013
|
|
* - Personnummer (10 digits, e.g. 8501011234): prefix with "19" or "20" based on century
|
|
* - Strip any hyphens before processing
|
|
*/
|
|
export function formatRedovisare(
|
|
orgNumber: string,
|
|
entityType: 'enskild_firma' | 'aktiebolag'
|
|
): string {
|
|
const clean = orgNumber.replace(/-/g, '')
|
|
|
|
if (clean.length === 12) return clean
|
|
|
|
if (clean.length !== 10) {
|
|
throw new Error(`Ogiltigt organisationsnummer: ${orgNumber} (förväntar 10 eller 12 siffror)`)
|
|
}
|
|
|
|
if (entityType === 'aktiebolag') return `16${clean}`
|
|
|
|
// Enskild firma — personnummer
|
|
const yearDigits = parseInt(clean.substring(0, 2), 10)
|
|
const currentTwoDigitYear = new Date().getFullYear() % 100
|
|
const prefix = yearDigits > currentTwoDigitYear ? '19' : '20'
|
|
return `${prefix}${clean}`
|
|
}
|
|
|
|
/**
|
|
* Convert gnubok period parameters to Skatteverket's YYYYMM format.
|
|
*
|
|
* Skatteverket expects the last month of the period.
|
|
* - monthly period 3, year 2025 → "202503"
|
|
* - quarterly period 1, year 2025 → "202503" (Q1 ends in March)
|
|
* - yearly period 1, year 2025 → "202512"
|
|
*/
|
|
export function formatRedovisningsperiod(
|
|
periodType: VatPeriodType,
|
|
year: number,
|
|
period: number
|
|
): string {
|
|
let lastMonth: number
|
|
|
|
switch (periodType) {
|
|
case 'monthly':
|
|
lastMonth = period
|
|
break
|
|
case 'quarterly':
|
|
lastMonth = period * 3
|
|
break
|
|
case 'yearly':
|
|
lastMonth = 12
|
|
break
|
|
}
|
|
|
|
return `${year}${String(lastMonth).padStart(2, '0')}`
|
|
}
|