Files
accounted/types/index.ts
T
Jakob WennbergandClaude Opus 4.6 91e2c1705a feat: per-line VAT, invoice document types, ledger-based VAT declaration, bank reconciliation, and pagination
Per-line VAT rates:
- Add generatePerRateLines() to group invoice items by vat_rate with separate
  revenue + VAT lines per rate group (invoice-entries.ts)
- Add getAvailableVatRates() and getVatTreatmentForRate() (vat-rules.ts)
- PDF template shows per-line VAT column and per-rate totals for mixed-rate invoices
- Invoice create/review UI supports per-line rate selection
- Types: add vat_rate/vat_amount to InvoiceItem, vat_rate to CreateInvoiceItemInput

Invoice document types (proforma, delivery note):
- Add InvoiceDocumentType, document_type and converted_from_id to Invoice type
- PDF hides prices for delivery notes, adds proforma notice
- Email templates support all document types
- mark-paid skips journal entries for non-invoice document types
- Migration 031: invoice_document_type

Accounting method support:
- Add AccountingMethod type (accrual/cash)
- Migration 032: add_accounting_method column to company_settings

VAT declaration rewrite:
- Rewrite to read directly from general ledger (26xx/3xxx account lines)
  instead of aggregating invoices/transactions/receipts
- ACCOUNT_RUTA mapping drives momsdeklaration boxes from GL balances

Bank reconciliation:
- Transaction ingest now pre-fetches unlinked GL lines and attempts
  auto-reconciliation during import
- Add transaction.reconciled event type
- Add ReconciliationMethod type and reconciliation_method on Transaction
- Migration 030: bank_reconciliation
- New reconciliation engine, API routes, and BankReconciliationView component

Pagination (fetchAllRows):
- New lib/supabase/fetch-all.ts overcomes PostgREST 1000-row limit
- Adopted in all report generators, SIE/SRU export, account list APIs

Fiscal period validation:
- New validate-period-duration.ts enforces max 18 months per BFL 3 kap.
- Applied in period-service.ts and fiscal-periods API

Account mapper simplification:
- Remove Levenshtein/fuzzy matching, use exact account number match only

Swedbank parser improvements:
- Support abbreviated headers (Clnr, Bokfdag, Radnr)
- Use Referens column as counterparty

Chart of accounts management:
- Add DELETE endpoint with system account and usage protection
- PUT uses partial updates
- New AccountCombobox, AddAccountDialog, EditAccountDialog, ChartOfAccountsManager

Tax deadline corrections:
- Rewrite inkomstdeklaration_ab using Skatteverket lookup table
- Rewrite arsredovisning deadline to 7 months after FY end per ÅRL 8:3

Onboarding first fiscal year:
- Add first fiscal year toggle with date pickers and 18-month validation

UI terminology:
- Change "okategoriserad/kategorisera" to "obokförd/bokföra" throughout

Report column fix:
- Fix start_date/end_date to period_start/period_end in report queries

Supplier invoice input:
- CreateSupplierInvoiceItemInput uses amount field (legacy quantity/unit_price kept)

Misc:
- SIE import uses upsert for idempotent account creation
- account-descriptions.ts falls back to BAS reference data
- Add invoice_default_notes to CompanySettings
- Update CLAUDE.md to reflect current project state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:57:15 +01:00

1629 lines
38 KiB
TypeScript

// Entity types
export type EntityType = 'enskild_firma' | 'aktiebolag'
// Transaction categories
export type TransactionCategory =
| 'income_services'
| 'income_products'
| 'income_other'
| 'expense_equipment'
| 'expense_software'
| 'expense_travel'
| 'expense_office'
| 'expense_marketing'
| 'expense_professional_services'
| 'expense_education'
| 'expense_bank_fees'
| 'expense_card_fees'
| 'expense_currency_exchange'
| 'expense_other'
| 'private'
| 'uncategorized'
// Customer types for VAT handling
export type CustomerType =
| 'individual' // Swedish private person
| 'swedish_business' // Swedish company
| 'eu_business' // EU company (needs VAT validation)
| 'non_eu_business' // Non-EU company
// Invoice status
export type InvoiceStatus = 'draft' | 'sent' | 'paid' | 'overdue' | 'cancelled' | 'credited'
// Invoice document type
export type InvoiceDocumentType = 'invoice' | 'proforma' | 'delivery_note'
// 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
| 'reduced_12' // 12% reduced rate
| 'reduced_6' // 6% reduced rate
| 'reverse_charge' // EU reverse charge (0%)
| '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'
// Reconciliation method
export type ReconciliationMethod = 'auto_exact' | 'auto_date_range' | 'auto_reference' | 'auto_fuzzy' | 'manual'
// Bank connection status
export type BankConnectionStatus = 'pending' | 'active' | 'expired' | 'revoked' | 'error'
// Salary payment status
export type SalaryPaymentStatus = 'planned' | 'paid' | 'reported'
// Currency types
export type Currency = 'SEK' | 'EUR' | 'USD' | 'GBP' | 'NOK' | 'DKK'
// Profile (extends auth.users)
export interface Profile {
id: string
email: string
full_name: string | null
avatar_url: string | null
created_at: string
updated_at: string
}
// Company Settings
export interface CompanySettings {
id: string
user_id: string
// Entity info
entity_type: EntityType
company_name: string | null
org_number: string | null
// Address
address_line1: string | null
address_line2: string | null
postal_code: string | null
city: string | null
country: string
// Tax registration
f_skatt: boolean
vat_registered: boolean
vat_number: string | null
moms_period: MomsPeriod | null
// Fiscal year
fiscal_year_start_month: number // 1-12
// Transient first-year fields (used during onboarding, not persisted in DB)
is_first_fiscal_year?: boolean
first_year_start?: string
first_year_end?: string
// Preliminary tax
preliminary_tax_monthly: number | null
// Bank details for invoices
bank_name: string | null
clearing_number: string | null
account_number: string | null
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
invoice_default_notes: string | null
// Onboarding
onboarding_step: number
onboarding_complete: boolean
// Timestamps
created_at: string
updated_at: string
}
// Bank Connection
export interface BankConnection {
id: string
user_id: string
bank_name: string
provider: string
// Enable Banking specific
session_id: string | null
authorization_id: string | null
// Account info
accounts_data: BankAccount[]
// Status
status: BankConnectionStatus
// Consent
consent_expires: string | null
last_synced_at: string | null
created_at: string
updated_at: string
}
export interface BankAccount {
uid: string // Enable Banking account UID
iban: string | null
name: string | null
currency: Currency
balance: number | null
}
// Import source identifiers
export type ImportSource =
| 'enable_banking'
| 'csv_nordea'
| 'csv_seb'
| 'csv_swedbank'
| 'csv_handelsbanken'
| 'csv_generic'
| 'camt053'
| 'manual'
// Transaction
export interface Transaction {
id: string
user_id: string
// Source
bank_connection_id: string | null
external_id: string | null // For deduplication
// Details
date: string
description: string
amount: number // Positive = income, negative = expense
currency: Currency
// For non-SEK transactions
amount_sek: number | null
exchange_rate: number | null
exchange_rate_date: string | null
// Categorization
category: TransactionCategory
is_business: boolean | null // null = uncategorized
// 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
// Bookkeeping
journal_entry_id: string | null
mcc_code: number | null
merchant_name: string | null
// Receipt link
receipt_id: string | null
// Reconciliation
reconciliation_method: ReconciliationMethod | null
// Import tracking
import_source: string | null
reference: string | null // OCR number, Bankgiro reference
// Notes
notes: string | null
created_at: string
updated_at: string
}
// Bank File Import (tracking table for file-based imports)
export type BankFileImportStatus = 'pending' | 'processing' | 'completed' | 'failed'
export interface BankFileImport {
id: string
user_id: string
filename: string
file_hash: string
file_format: string
transaction_count: number
imported_count: number
duplicate_count: number
matched_count: number
date_from: string | null
date_to: string | null
status: BankFileImportStatus
error_message: string | null
created_at: string
updated_at: string
}
// Customer
export interface Customer {
id: string
user_id: string
// Basic info
name: string
customer_type: CustomerType
// Contact
email: string | null
phone: string | null
// Address
address_line1: string | null
address_line2: string | null
postal_code: string | null
city: string | null
country: string
// Tax info
org_number: string | null
vat_number: string | null
vat_number_validated: boolean
vat_number_validated_at: string | null
// Payment
default_payment_terms: number // Days
// Notes
notes: string | null
created_at: string
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
user_id: string
customer_id: string
// Invoice number (auto-generated)
invoice_number: string
// Dates
invoice_date: string
due_date: string
// Status
status: InvoiceStatus
// Currency
currency: Currency
// Exchange rate (if non-SEK)
exchange_rate: number | null
exchange_rate_date: string | null
// Amounts
subtotal: number
subtotal_sek: number | null
vat_amount: number
vat_amount_sek: number | null
total: number
total_sek: number | null
// VAT
vat_treatment: VatTreatment
vat_rate: number
moms_ruta: string | null // For Swedish VAT reporting (05, 39, 40, etc.)
// Reference
your_reference: string | null
our_reference: string | null
// Notes
notes: string | null
// Reverse charge text (auto-added for EU B2B)
reverse_charge_text: string | null
// Credit note reference
credited_invoice_id: string | null
// Document type (invoice, proforma, delivery_note)
document_type: InvoiceDocumentType
// Conversion tracking (proforma -> invoice)
converted_from_id: string | null
// Payment tracking
paid_at: string | null
paid_amount: number | null
created_at: string
updated_at: string
// Relations (populated when fetched)
customer?: Customer
items?: InvoiceItem[]
}
// Invoice Item
export interface InvoiceItem {
id: string
invoice_id: string
// Order
sort_order: number
// Description
description: string
// Quantity
quantity: number
unit: string // 'st', 'tim', 'dag', etc.
// Price
unit_price: number
// Calculated
line_total: number
// Per-line VAT
vat_rate: number
vat_amount: number
created_at: string
}
// Salary Payment (for AB)
export interface SalaryPayment {
id: string
user_id: string
// Payment details
gross_amount: number
net_amount: number
// Employer costs
employer_tax: number // Arbetsgivaravgifter (31.42%)
preliminary_tax: number // Employee preliminary tax
// Dates
payment_date: string
period_start: string
period_end: string
// Status
status: SalaryPaymentStatus
// Notes
notes: string | null
created_at: string
updated_at: string
}
// Tax Rates (reference table)
export interface TaxRate {
id: string
// Type
rate_type: 'egenavgifter' | 'bolagsskatt' | 'arbetsgivaravgifter' | 'vat' | 'municipal'
// Rate
rate: number
// Validity
valid_from: string
valid_to: string | null
// Description
description: string
}
// Form types for creating/updating
export interface CreateCustomerInput {
name: string
customer_type: CustomerType
email?: string
phone?: string
address_line1?: string
address_line2?: string
postal_code?: string
city?: string
country?: string
org_number?: string
vat_number?: string
default_payment_terms?: number
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
amount: number
account_number: string
vat_rate?: number
vat_code?: string
// Legacy fields (backward compat, ignored when amount is set)
quantity?: number
unit?: string
unit_price?: number
}
export interface CreateInvoiceInput {
customer_id: string
invoice_date: string
due_date: string
currency: Currency
document_type?: InvoiceDocumentType
your_reference?: string
our_reference?: string
notes?: string
items: CreateInvoiceItemInput[]
}
export interface CreateInvoiceItemInput {
description: string
quantity: number
unit: string
unit_price: number
vat_rate?: number
}
export interface CreateTransactionInput {
date: string
description: string
amount: number
currency: Currency
category?: TransactionCategory
is_business?: boolean
notes?: string
}
// API Response types
export interface ApiResponse<T> {
data?: T
error?: string
}
export interface PaginatedResponse<T> {
data: T[]
count: number
page: number
pageSize: number
totalPages: number
}
// VAT validation response
export interface VatValidationResult {
valid: boolean
name?: string
address?: string
country_code?: string
vat_number?: string
error?: string
}
// Exchange rate response
export interface ExchangeRate {
currency: Currency
rate: number
date: string
}
// Dashboard summary types
export interface DashboardSummary {
// Income
total_income_ytd: number
total_income_mtd: number
// Expenses
total_expenses_ytd: number
total_expenses_mtd: number
// Net
net_income_ytd: number
net_income_mtd: number
// Tax estimates
estimated_tax: TaxEstimate
// Alerts
uncategorized_count: number
unpaid_invoices_count: number
unpaid_invoices_total: number
overdue_invoices_count: number
// Bank
bank_balance: number | null
available_balance: number | null // After tax reservations
}
export interface TaxEstimate {
// For EF
egenavgifter?: number
income_tax?: number // Municipal tax (kommunalskatt)
state_tax?: number // State tax (statlig skatt) - 20% on high incomes
grundavdrag?: number // Basic deduction applied
// For AB
bolagsskatt?: number
// Common
moms_to_pay: number
total_tax_liability: number
// Comparison with preliminary
preliminary_paid_ytd: number
difference: number // Positive = underpaying
}
// ============================================================
// BAS Kontoplan & Bookkeeping Types
// ============================================================
// Risk levels for mapping rules
export type RiskLevel = 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'VERY_HIGH'
// Account types
export type AccountType = 'asset' | 'equity' | 'liability' | 'revenue' | 'expense'
export type NormalBalance = 'debit' | 'credit'
export type PlanType = 'k1' | 'full_bas'
// Journal entry source
export type JournalEntrySourceType =
| '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'
// Journal entry status
export type JournalEntryStatus = 'draft' | 'posted' | 'reversed'
// Mapping rule type
export type MappingRuleType =
| 'mcc_code'
| 'merchant_name'
| 'description_pattern'
| 'amount_threshold'
| 'combined'
// BAS Account
export interface BASAccount {
id: string
user_id: string
account_number: string
account_name: string
account_class: number
account_group: string
account_type: AccountType
normal_balance: NormalBalance
plan_type: PlanType
is_active: boolean
is_system_account: boolean
default_vat_code: string | null
description: string | null
sru_code: string | null
sort_order: number
created_at: string
updated_at: string
}
// Fiscal Period (Räkenskapsår)
export interface FiscalPeriod {
id: string
user_id: string
name: string
period_start: string
period_end: string
is_closed: boolean
closed_at: string | null
locked_at: string | null
retention_expires_at: string | null
opening_balances_set: boolean
closing_entry_id: string | null
opening_balance_entry_id: string | null
previous_period_id: string | null
created_at: string
updated_at: string
}
// Journal Entry (Verifikation)
export interface JournalEntry {
id: string
user_id: string
fiscal_period_id: string
voucher_number: number
voucher_series: string
entry_date: string
description: string
source_type: JournalEntrySourceType
source_id: string | null
status: JournalEntryStatus
committed_at: string | null
reversed_by_id: string | null
reverses_id: string | null
correction_of_id: string | null
attachment_urls: string[] | null
created_at: string
updated_at: string
// Relations
lines?: JournalEntryLine[]
}
// Journal Entry Line
export interface JournalEntryLine {
id: string
journal_entry_id: string
account_number: string
account_id: string | null
debit_amount: number
credit_amount: number
currency: string
amount_in_currency: number | null
exchange_rate: number | null
line_description: string | null
tax_code: string | null
cost_center: string | null
project: string | null
sort_order: number
created_at: string
}
// Mapping Rule
export interface MappingRule {
id: string
user_id: string | null
rule_name: string
rule_type: MappingRuleType
priority: number
// Matching
mcc_codes: number[] | null
merchant_pattern: string | null
description_pattern: string | null
amount_min: number | null
amount_max: number | null
// Targets
debit_account: string | null
credit_account: string | null
vat_treatment: string | null
vat_debit_account: string | null
vat_credit_account: string | null
// Risk
risk_level: RiskLevel
default_private: boolean
requires_review: boolean
confidence_score: number
// Capitalization
capitalization_threshold: number | null
capitalized_debit_account: string | null
// Meta
is_active: boolean
created_at: string
updated_at: string
}
// Mapping engine result
export interface MappingResult {
rule: MappingRule | null
debit_account: string
credit_account: string
risk_level: RiskLevel
confidence: number
requires_review: boolean
default_private: boolean
vat_lines: VatJournalLine[]
description: string
}
// VAT journal line (auto-generated)
export interface VatJournalLine {
account_number: string
debit_amount: number
credit_amount: number
description: string
}
// Account Balance (cached)
export interface AccountBalance {
id: string
user_id: string
fiscal_period_id: string
account_number: string
account_id: string | null
opening_debit: number
opening_credit: number
period_debit: number
period_credit: number
closing_debit: number
closing_credit: number
created_at: string
updated_at: string
}
// Report types
export interface TrialBalanceRow {
account_number: string
account_name: string
account_class: number
opening_debit: number
opening_credit: number
period_debit: number
period_credit: number
closing_debit: number
closing_credit: number
}
export interface IncomeStatementSection {
title: string
rows: { account_number: string; account_name: string; amount: number }[]
subtotal: number
}
export interface IncomeStatementReport {
revenue_sections: IncomeStatementSection[]
total_revenue: number
expense_sections: IncomeStatementSection[]
total_expenses: number
financial_sections: IncomeStatementSection[]
total_financial: number
net_result: number
period: { start: string; end: string }
}
export interface BalanceSheetSection {
title: string
rows: { account_number: string; account_name: string; amount: number }[]
subtotal: number
}
export interface BalanceSheetReport {
asset_sections: BalanceSheetSection[]
total_assets: number
equity_liability_sections: BalanceSheetSection[]
total_equity_liabilities: number
period: { start: string; end: string }
}
export interface SIEExportOptions {
fiscal_period_id: string
company_name: string
org_number: string | null
program_name?: string
}
// Input types for creating entries
export interface CreateJournalEntryInput {
fiscal_period_id: string
entry_date: string
description: string
source_type: JournalEntrySourceType
source_id?: string
voucher_series?: string
lines: CreateJournalEntryLineInput[]
}
export interface CreateJournalEntryLineInput {
account_number: string
debit_amount: number
credit_amount: number
line_description?: string
currency?: string
amount_in_currency?: number
exchange_rate?: number
tax_code?: string
cost_center?: string
project?: string
}
export interface CreateFiscalPeriodInput {
name: string
period_start: string
period_end: string
}
// Tax warning levels
export type TaxWarningLevel = 'safe' | 'info' | 'warning' | 'danger'
// Onboarding progress for new user checklist
export interface OnboardingProgress {
hasCustomers: boolean
hasInvoices: boolean
hasReceipts: boolean
hasBankConnected: boolean
}
// Enhanced tax warning status
export interface TaxWarningStatus {
level: TaxWarningLevel
message: string
percentageDifference: number
yearEndProjection?: {
estimatedTotalTax: number
projectedPreliminaryPayments: number
projectedDifference: number
}
recommendation?: string
}
// Onboarding step data
export interface OnboardingStepData {
step1?: {
entity_type: EntityType
}
step2?: {
company_name: string
org_number?: string
address_line1?: string
postal_code?: string
city?: string
}
step3?: {
f_skatt: boolean
fiscal_year_start_month: number
is_first_fiscal_year?: boolean
first_year_start?: string
first_year_end?: string
vat_registered: boolean
vat_number?: string
moms_period?: MomsPeriod
}
step4?: {
preliminary_tax_monthly?: number
}
step5?: {
bank_name?: string
clearing_number?: string
account_number?: string
iban?: string
bic?: string
}
step6?: {
bank_connected: boolean
bank_connection_id?: string
}
}
// ============================================================
// Calendar & Deadline Types
// ============================================================
// Calendar view mode
export type CalendarViewMode = 'month' | 'week' | 'day'
// Payment calendar day (for invoice due date tracking)
export interface PaymentCalendarDay {
date: string
invoices: Invoice[]
totalExpected: number
overdueCount: number
}
// Tax deadline types (Swedish Skatteverket)
export type TaxDeadlineType =
| 'moms_monthly'
| 'moms_quarterly'
| 'moms_yearly'
| 'f_skatt'
| 'arbetsgivardeklaration'
| 'inkomstdeklaration_ef'
| 'inkomstdeklaration_ab'
| 'arsredovisning'
| 'periodisk_sammanstallning'
| 'bokslut'
// Deadline status workflow
export type DeadlineStatus =
| 'upcoming' // More than 14 days away
| 'action_needed' // Within 14 days, needs attention
| 'in_progress' // User is working on it
| 'submitted' // Submitted to Skatteverket
| 'confirmed' // Confirmed/acknowledged
| 'overdue' // Past due date without submission
// Deadline source
export type DeadlineSource = 'system' | 'user'
// Deadline types
export type DeadlineType = 'delivery' | 'invoicing' | 'report' | 'tax' | 'other'
export type DeadlinePriority = 'critical' | 'important' | 'normal'
// Deadline record
export interface Deadline {
id: string
user_id: string
title: string
due_date: string
due_time: string | null
deadline_type: DeadlineType
priority: DeadlinePriority
is_completed: boolean
completed_at: string | null
customer_id: string | null
is_auto_generated: boolean
notes: string | null
created_at: string
updated_at: string
// Tax deadline fields
tax_deadline_type: TaxDeadlineType | null
tax_period: string | null
source: DeadlineSource
reminder_offsets: number[] | null
status: DeadlineStatus
status_changed_at: string
linked_report_type: string | null
linked_report_period: Record<string, unknown> | null
// Relations
customer?: Customer
}
// Input for creating a deadline
export interface CreateDeadlineInput {
title: string
due_date: string
due_time?: string
deadline_type: DeadlineType
priority?: DeadlinePriority
customer_id?: string
notes?: string
// Tax deadline fields
tax_deadline_type?: TaxDeadlineType
tax_period?: string
source?: DeadlineSource
linked_report_type?: string
linked_report_period?: Record<string, unknown>
}
// ============================================================
// Push Notification Types (canonical source: extensions/push-notifications/types.ts)
// ============================================================
export type { PushSubscription, NotificationSettings, NotificationType, NotificationLog } from '@/extensions/push-notifications/types'
// ============================================================
// Calendar Feed Types (ICS)
// ============================================================
// Calendar feed for Apple Calendar / Google Calendar sync
export interface CalendarFeed {
id: string
user_id: string
feed_token: string
is_active: boolean
include_tax_deadlines: boolean
include_invoices: boolean
last_accessed_at: string | null
access_count: number
created_at: string
updated_at: string
}
// Input for creating/updating calendar feed
export interface UpdateCalendarFeedInput {
include_tax_deadlines?: boolean
include_invoices?: boolean
}
// Swedish labels for deadline status
export const DEADLINE_STATUS_LABELS: Record<DeadlineStatus, string> = {
upcoming: 'Kommande',
action_needed: 'Åtgärd krävs',
in_progress: 'Pågår',
submitted: 'Inskickad',
confirmed: 'Bekräftad',
overdue: 'Försenad'
}
// Swedish labels for tax deadline types
export const TAX_DEADLINE_TYPE_LABELS: Record<TaxDeadlineType, string> = {
moms_monthly: 'Momsdeklaration (månad)',
moms_quarterly: 'Momsdeklaration (kvartal)',
moms_yearly: 'Momsdeklaration (år)',
f_skatt: 'F-skatt',
arbetsgivardeklaration: 'Arbetsgivardeklaration',
inkomstdeklaration_ef: 'Inkomstdeklaration EF',
inkomstdeklaration_ab: 'Inkomstdeklaration AB',
arsredovisning: 'Årsredovisning',
periodisk_sammanstallning: 'Periodisk sammanställning',
bokslut: 'Bokslut'
}
// ============================================================
// SIE Import Types
// ============================================================
// SIE import status
export type SIEImportStatus = 'pending' | 'mapped' | 'completed' | 'failed'
// SIE import record
export interface SIEImport {
id: string
user_id: string
filename: string
file_hash: string
org_number: string | null
company_name: string | null
sie_type: number
fiscal_year_start: string | null
fiscal_year_end: string | null
accounts_count: number
transactions_count: number
opening_balance_total: number | null
status: SIEImportStatus
error_message: string | null
fiscal_period_id: string | null
opening_balance_entry_id: string | null
imported_at: string | null
created_at: string
updated_at: string
}
// SIE account mapping record
export interface SIEAccountMapping {
id: string
user_id: string
source_account: string
source_name: string | null
target_account: string
confidence: number
match_type: 'exact' | 'name' | 'class' | 'manual'
created_at: string
updated_at: string
}
// ============================================================
// Receipt Types (canonical source: extensions/receipt-ocr/types.ts)
// ============================================================
export type { ReceiptStatus, Receipt, ReceiptLineItem, ReceiptExtractionResult, ExtractedLineItem, ReceiptMatchCandidate, CreateReceiptInput, ConfirmReceiptInput, ConfirmLineItemInput, ReceiptQueueSummary, CameraQualityFeedback } from '@/extensions/receipt-ocr/types'
export { RECEIPT_STATUS_LABELS } from '@/extensions/receipt-ocr/types'
// ============================================================
// VAT Declaration Types (Momsdeklaration)
// ============================================================
// VAT period type
export type VatPeriodType = 'monthly' | 'quarterly' | 'yearly'
// VAT declaration rutor (boxes) according to Swedish tax authority
export interface VatDeclarationRutor {
// Utgående moms (Output VAT)
ruta05: number // Utgående moms 25%
ruta06: number // Utgående moms 12%
ruta07: number // Utgående moms 6%
// Momspliktigt underlag (VAT-liable base amounts)
ruta10: number // Momspliktigt underlag 25%
ruta11: number // Momspliktigt underlag 12%
ruta12: number // Momspliktigt underlag 6%
// EU och export
ruta39: number // Försäljning av tjänster till annat EU-land (reverse charge)
ruta40: number // Export utanför EU
// Ingående moms (Input VAT)
ruta48: number // Ingående moms att dra av
// Moms att betala eller få tillbaka
ruta49: number // Moms att betala (positive) eller återfå (negative)
}
// VAT declaration response
export interface VatDeclaration {
period: {
type: VatPeriodType
year: number
period: number // 1-12 for monthly, 1-4 for quarterly, 1 for yearly
start: string // YYYY-MM-DD
end: string // YYYY-MM-DD
}
rutor: VatDeclarationRutor
// Supporting data
invoiceCount: number
transactionCount: number
// Breakdown by source
breakdown: {
invoices: {
ruta05: number
ruta06: number
ruta07: number
ruta10: number
ruta11: number
ruta12: number
ruta39: number
ruta40: number
}
transactions: {
ruta48: number // Ingående moms from categorized expenses
}
receipts: {
ruta48: number // Ingående moms from receipts
}
}
}
// VAT declaration request parameters
export interface VatDeclarationRequest {
periodType: VatPeriodType
year: number
period: number
}
// ============================================================
// NE Declaration Types (canonical source: extensions/ne-bilaga/types.ts)
// ============================================================
export type { NEDeclarationRutor, NEAccountMapping, NEDeclaration, SRURecord, SRUFile } from '@/extensions/ne-bilaga/types'
export { NE_RUTA_LABELS } from '@/extensions/ne-bilaga/types'
// ============================================================
// SRU Export Types (canonical source: extensions/sru-export/types.ts)
// ============================================================
export type { SRUExportResult, SRUCoverageStats } from '@/extensions/sru-export/types'
// Labels for VAT rutor
export const VAT_RUTA_LABELS: Record<keyof VatDeclarationRutor, string> = {
ruta05: 'Utgående moms 25%',
ruta06: 'Utgående moms 12%',
ruta07: 'Utgående moms 6%',
ruta10: 'Momspliktigt underlag 25%',
ruta11: 'Momspliktigt underlag 12%',
ruta12: 'Momspliktigt underlag 6%',
ruta39: 'Försäljning av tjänster till EU-land',
ruta40: 'Export utanför EU',
ruta48: 'Ingående moms att dra av',
ruta49: 'Moms att betala/återfå'
}
// ============================================================
// Event Payload Placeholder Types
// ============================================================
/** Credit note is an invoice with a credited_invoice_id */
export interface CreditNote extends Invoice {
credited_invoice_id: string
}
/** CAMT.053 bank statement (placeholder — CAMT parsing not yet implemented) */
export interface CAMT053Statement {
messageId: string
statements: unknown[]
}
/** CAMT.054 payment notification (placeholder — CAMT parsing not yet implemented) */
export interface CAMT054Notification {
messageId: string
notifications: unknown[]
}
/** Security event payload for audit events */
export interface AuditSecurityEvent {
eventType: string
description: string
metadata: Record<string, unknown>
}
/** Generic key-value store record for extensions */
export interface ExtensionDataRecord {
id: string
user_id: string
extension_id: string
key: string
value: Record<string, unknown>
created_at: string
updated_at: string
}
// ============================================================
// Tax Code Types
// ============================================================
// Tax code identifiers (standard Swedish codes)
export type TaxCodeId =
| 'MP1' | 'MP2' | 'MP3' // Output VAT 25%, 12%, 6%
| 'MPI' | 'MPI12' | 'MPI6' // Input VAT 25%, 12%, 6%
| 'IV' // Intra-EU acquisition
| 'EUS' // EU sale (reverse charge)
| 'IP' // Import
| 'EXP' // Export outside EU
| 'OSS' // One Stop Shop
| 'NONE' // VAT exempt
export interface TaxCode {
id: string
user_id: string | null
code: string
description: string
rate: number
moms_basis_boxes: string[]
moms_tax_boxes: string[]
moms_input_boxes: string[]
is_output_vat: boolean
is_reverse_charge: boolean
is_eu: boolean
is_export: boolean
is_oss: boolean
is_system: boolean
created_at: string
updated_at: string
}
// ============================================================
// Document Archive Types
// ============================================================
export type DocumentUploadSource =
| 'camera'
| 'file_upload'
| 'email'
| 'e_invoice'
| 'scan'
| 'api'
| 'system'
export interface DocumentAttachment {
id: string
user_id: string
storage_path: string
file_name: string
file_size_bytes: number | null
mime_type: string | null
sha256_hash: string
version: number
original_id: string | null
superseded_by_id: string | null
is_current_version: boolean
uploaded_by: string | null
upload_source: DocumentUploadSource | null
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
}
export interface CreateDocumentAttachmentInput {
storage_path: string
file_name: string
file_size_bytes?: number
mime_type?: string
sha256_hash: string
upload_source?: DocumentUploadSource
journal_entry_id?: string
journal_entry_line_id?: string
}
// ============================================================
// Audit Log Types
// ============================================================
export type AuditAction =
| 'INSERT'
| 'UPDATE'
| 'DELETE'
| 'COMMIT'
| 'REVERSE'
| 'CORRECT'
| 'LOCK_PERIOD'
| 'CLOSE_PERIOD'
| 'DOCUMENT_DELETE_BLOCKED'
| 'RETENTION_BLOCK'
| 'SECURITY_EVENT'
| 'INTEGRITY_FAILURE'
export interface AuditLogEntry {
id: string
user_id: string
action: AuditAction
table_name: string | null
record_id: string | null
actor_id: string | null
old_state: Record<string, unknown> | null
new_state: Record<string, unknown> | null
description: string | null
created_at: string
}
// ============================================================
// Dimension Types (Kostnadsställen & Projekt)
// ============================================================
export interface CostCenter {
id: string
user_id: string
code: string
name: string
is_active: boolean
created_at: string
updated_at: string
}
export interface Project {
id: string
user_id: string
code: string
name: string
is_active: boolean
start_date: string | null
end_date: string | null
created_at: string
updated_at: string
}
// ============================================================
// Voucher Gap Detection
// ============================================================
export interface VoucherGap {
gap_start: number
gap_end: number
}
// ============================================================
// Year-End Closing Types (Årsbokslut)
// ============================================================
export interface YearEndValidation {
ready: boolean
errors: string[]
warnings: string[]
draftCount: number
voucherGaps: VoucherGap[]
trialBalanceBalanced: boolean
}
export interface YearEndPreview {
netResult: number
closingAccount: string
closingAccountName: string
closingLines: CreateJournalEntryLineInput[]
resultAccountSummary: { account_number: string; account_name: string; amount: number }[]
}
export interface YearEndResult {
closingEntry: JournalEntry
nextPeriod: FiscalPeriod
openingBalanceEntry: JournalEntry
}
export interface PeriodStatus {
is_locked: boolean
is_closed: boolean
has_closing_entry: boolean
has_opening_balances: boolean
draft_count: number
next_period_exists: boolean
}
// ============================================================
// Invoice Reminder Types (Betalningspåminnelser)
// ============================================================
// Response type from customer action
export type ReminderResponseType = 'marked_paid' | 'disputed'
// Invoice reminder record
export interface InvoiceReminder {
id: string
invoice_id: string
user_id: string
reminder_level: 1 | 2 | 3
sent_at: string
email_to: string
response_type: ReminderResponseType | null
response_at: string | null
action_token: string
action_token_used: boolean
created_at: string
}
// Swedish labels for reminder levels
export const REMINDER_LEVEL_LABELS: Record<1 | 2 | 3, string> = {
1: 'Vänlig påminnelse',
2: 'Andra påminnelsen',
3: 'Slutlig påminnelse'
}
// Reminder level descriptions
export const REMINDER_LEVEL_DESCRIPTIONS: Record<1 | 2 | 3, string> = {
1: '15 dagar efter förfallodatum',
2: '30 dagar efter förfallodatum',
3: '45 dagar efter förfallodatum'
}