Files
accounted/lib/providers/dto.ts
T
Jakob Wennberg f266c386f3 chore: repo-wide bloat sweep, remove dead code and fold duplicate helpers (#2150)
* chore: repo-wide bloat sweep, remove dead code and fold duplicate helpers

Remove 33 dead files, ~270 unreferenced exports/types, 13 dead i18n
namespaces and 4 unused dependencies; fold byte-identical helper copies
into one canonical home each (lib/utils chunk/sleep/utcDateStamp,
lib/dates/iso, lib/invariants/uuid, lib/xml/escape, lib/reports/sru/format,
lib/pdf/number-text, lib/browser/panel-request, lib/api/v1/body +
v1ValidationError rolled out to ~55 v1 routes, booking-template schemas).

No behaviour change: v1 bodies and status codes, MCP tool schemas, DB
writes and money math are untouched. Naive ore rounding was deliberately
not swapped for roundOre; see DECISIONS.md 2026-09-02 for the full list
of things left alone on purpose.

tsc, lint, 19588 unit tests and check:guards green; antipattern baseline
ratcheted (naive-ore-round 622 -> 620, hand-rolled-invariant 115 -> 113).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(transactions): import RawTransaction from @/types after the ingest re-export removal

CI's type ratchet (check:types, full tsconfig) caught the one test file
that still imported the type through lib/transactions/ingest.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 11:51:16 +02:00

371 lines
9.2 KiB
TypeScript

// Canonical DTO types for provider data normalization
// ============================================
// Resource Type
// ============================================
export const ResourceType = {
SalesInvoices: 'salesinvoices',
SupplierInvoices: 'supplierinvoices',
Customers: 'customers',
Suppliers: 'suppliers',
Journals: 'journals',
AccountingAccounts: 'accountingaccounts',
CompanyInformation: 'companyinformation',
AccountingPeriods: 'accountingperiods',
FinancialDimensions: 'financialdimensions',
BalanceSheet: 'balancesheet',
IncomeStatement: 'incomestatement',
TrialBalances: 'trialbalances',
Payments: 'payments',
Attachments: 'attachments',
} as const;
export type ResourceType = (typeof ResourceType)[keyof typeof ResourceType];
// ============================================
// Common
// ============================================
export interface AmountType {
value: number;
currencyCode: string;
}
export interface PostalAddress {
streetName?: string;
additionalStreetName?: string;
buildingNumber?: string;
cityName?: string;
postalZone?: string;
countrySubentity?: string;
countryCode?: string;
}
export interface Contact {
name?: string;
telephone?: string;
email?: string;
website?: string;
}
export interface PartyIdentification {
id: string;
schemeId?: string;
}
export interface PartyLegalEntity {
registrationName: string;
companyId?: string;
companyIdSchemeId?: string;
}
export interface PartyDto {
name: string;
identifications: PartyIdentification[];
postalAddress?: PostalAddress;
legalEntity?: PartyLegalEntity;
contact?: Contact;
}
export interface FinancialDimensionRef {
dimensionId: string;
dimensionValueId: string;
name?: string;
}
export interface AllowanceChargeDto {
chargeIndicator: boolean;
reason?: string;
amount: AmountType;
taxPercent?: number;
}
export interface TaxTotalDto {
taxAmount: AmountType;
taxSubtotals?: TaxSubtotalDto[];
}
export interface TaxSubtotalDto {
taxableAmount: AmountType;
taxAmount: AmountType;
taxCategory?: string;
percent?: number;
}
export interface PaginatedResponse<T> {
data: T[];
page: number;
pageSize: number;
totalCount: number;
hasMore: boolean;
}
/**
* The verifikat that booked the invoice in the SOURCE system, as the provider
* reports it ("A329"). Optional: only providers that expose it (Visma
* eAccounting, Fortnox) set it, and only on booked invoices. The migration
* uses it to link the imported invoice to the SIE-imported registration
* voucher; see lib/providers/source-voucher.ts for the parsing rules.
*/
export interface SourceVoucherRefDto {
series: string | null;
number: number;
}
// ============================================
// Sales Invoice
// ============================================
export type InvoiceStatusCode = 'draft' | 'sent' | 'booked' | 'paid' | 'overdue' | 'cancelled' | 'credited';
export interface LegalMonetaryTotalDto {
/**
* Sum of the line amounts, excluding VAT.
*
* Optional because several providers omit it from their list payloads
* (Fortnox `Net`, Briox `net_amount`) and one never exposes it at all.
* Absent means "the net was not established", NOT "the net equals the
* gross": mappers must leave it undefined rather than fall back to
* `payableAmount`, which silently turns every such invoice into a 0 kr VAT
* record that still balances and so goes unnoticed.
*/
lineExtensionAmount?: AmountType;
taxExclusiveAmount?: AmountType;
taxInclusiveAmount?: AmountType;
allowanceTotalAmount?: AmountType;
chargeTotalAmount?: AmountType;
payableRoundingAmount?: AmountType;
payableAmount: AmountType;
}
export interface PaymentStatusDto {
paid: boolean;
balance: AmountType;
lastPaymentDate?: string;
}
export interface SalesInvoiceLineDto {
id: string;
description?: string;
quantity?: number;
unitCode?: string;
unitPrice?: AmountType;
lineExtensionAmount: AmountType;
taxPercent?: number;
taxAmount?: AmountType;
accountNumber?: string;
itemName?: string;
articleNumber?: string;
financialDimensions?: FinancialDimensionRef[];
}
export interface SalesInvoiceDto {
id: string;
invoiceNumber: string;
issueDate: string;
dueDate?: string;
deliveryDate?: string;
invoiceTypeCode?: string;
currencyCode: string;
status: InvoiceStatusCode;
supplier: PartyDto;
customer: PartyDto;
lines: SalesInvoiceLineDto[];
allowanceCharges?: AllowanceChargeDto[];
taxTotal?: TaxTotalDto;
legalMonetaryTotal: LegalMonetaryTotalDto;
paymentStatus: PaymentStatusDto;
paymentTerms?: string;
note?: string;
buyerReference?: string;
orderReference?: string;
financialDimensions?: FinancialDimensionRef[];
sourceVoucher?: SourceVoucherRefDto;
createdAt?: string;
updatedAt?: string;
_raw?: Record<string, unknown>;
}
// ============================================
// Supplier Invoice
// ============================================
export interface SupplierInvoiceLineDto {
id: string;
description?: string;
quantity?: number;
unitCode?: string;
unitPrice?: AmountType;
lineExtensionAmount: AmountType;
taxPercent?: number;
taxAmount?: AmountType;
accountNumber?: string;
itemName?: string;
articleNumber?: string;
financialDimensions?: FinancialDimensionRef[];
}
export interface SupplierInvoiceDto {
id: string;
invoiceNumber: string;
issueDate: string;
dueDate?: string;
deliveryDate?: string;
invoiceTypeCode?: string;
currencyCode: string;
status: InvoiceStatusCode;
supplier: PartyDto;
buyer: PartyDto;
lines: SupplierInvoiceLineDto[];
allowanceCharges?: AllowanceChargeDto[];
taxTotal?: TaxTotalDto;
legalMonetaryTotal: LegalMonetaryTotalDto;
paymentStatus: PaymentStatusDto;
paymentTerms?: string;
note?: string;
ocrNumber?: string;
financialDimensions?: FinancialDimensionRef[];
sourceVoucher?: SourceVoucherRefDto;
createdAt?: string;
updatedAt?: string;
_raw?: Record<string, unknown>;
}
// ============================================
// Customer
// ============================================
export type CustomerType = 'company' | 'private';
export interface CustomerDto {
id: string;
customerNumber: string;
type?: CustomerType;
party: PartyDto;
invoiceEmailCcAddresses?: string[];
invoiceEmailBccAddresses?: string[];
deliveryAddresses?: PostalAddress[];
financialDimensions?: FinancialDimensionRef[];
active: boolean;
vatNumber?: string;
defaultPaymentTermsDays?: number;
note?: string;
createdAt?: string;
updatedAt?: string;
_raw?: Record<string, unknown>;
}
// ============================================
// Supplier
// ============================================
export interface SupplierDto {
id: string;
supplierNumber: string;
party: PartyDto;
deliveryAddresses?: PostalAddress[];
financialDimensions?: FinancialDimensionRef[];
active: boolean;
vatNumber?: string;
bankAccount?: string;
bankGiro?: string;
plusGiro?: string;
defaultPaymentTermsDays?: number;
note?: string;
createdAt?: string;
updatedAt?: string;
_raw?: Record<string, unknown>;
}
// ============================================
// Journal
// ============================================
export interface AccountingEntryDto {
accountNumber: string;
accountName?: string;
debit: number;
credit: number;
transactionDate?: string;
description?: string;
financialDimensions?: FinancialDimensionRef[];
}
export interface AccountingSeriesDto {
id: string;
description?: string;
}
export interface JournalDto {
id: string;
journalNumber: string;
series?: AccountingSeriesDto;
description?: string;
registrationDate: string;
fiscalYear?: number;
entries: AccountingEntryDto[];
totalDebit?: AmountType;
totalCredit?: AmountType;
createdAt?: string;
updatedAt?: string;
_raw?: Record<string, unknown>;
}
// ============================================
// Accounting Account
// ============================================
export type AccountType = 'asset' | 'liability' | 'equity' | 'revenue' | 'expense' | 'other';
export interface AccountingAccountDto {
accountNumber: string;
name: string;
description?: string;
type?: AccountType;
vatCode?: string;
active: boolean;
balanceBroughtForward?: number;
balanceCarriedForward?: number;
sruCode?: string;
createdAt?: string;
updatedAt?: string;
_raw?: Record<string, unknown>;
}
// ============================================
// Company Information
// ============================================
export interface CompanyInformationDto {
companyName: string;
organizationNumber?: string;
legalEntity?: PartyLegalEntity;
address?: PostalAddress;
contact?: Contact;
vatNumber?: string;
fiscalYearStart?: string;
baseCurrency?: string;
_raw?: Record<string, unknown>;
}
// ============================================
// Payment
// ============================================
export type PaymentMethodCode = 'bank_transfer' | 'card' | 'cash' | 'autogiro' | 'bankgiro' | 'plusgiro' | 'swish' | 'other';
export interface PaymentDto {
id: string;
paymentNumber?: string;
invoiceId: string;
paymentDate: string;
amount: AmountType;
paymentMethod?: PaymentMethodCode;
reference?: string;
note?: string;
createdAt?: string;
updatedAt?: string;
_raw?: Record<string, unknown>;
}