Files
accounted/lib/reports/__tests__/financial-statement-pdf-template.test.ts
T
MattssonandClaude Opus 4.7 3fa871c742 Bug/accounting suggestion (#456)
* feat: add bike benefit handling and optional vacation accrual

- Introduced bike benefit (cykelförmån) with calculations for annual market value and monthly taxable value.
- Updated schemas to include new benefit types and validation rules.
- Implemented API routes for creating, updating, and deleting employee benefits.
- Enhanced salary calculation logic to accommodate new vacation rule options, including a 'none' option for no accrual.
- Added UI components for managing employee benefits, including input for bike benefit specifics.
- Created database migrations for employee benefits and updated salary line items to support new benefit types.

* chore: remove Langfuse env var checks

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: enhance OAuth callback URL handling and update default scopes for Visma integration

* feat: remove trade_name field and simplify company naming in invoices

* refactor: destructure canWrite from useCanWrite for consistency across components

* feat: enhance PATCH endpoint to validate existing benefits and handle bike benefit updates

* feat: add missing label for bike benefit in salary line item types

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 00:26:04 +02:00

140 lines
4.1 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { renderToBuffer } from '@react-pdf/renderer'
import { FinancialStatementPDF } from '../financial-statement-pdf-template'
import type { CompanySettings } from '@/types'
function fakeCompany(): CompanySettings {
return {
company_name: 'Gnubok',
org_number: '5566778899',
vat_number: 'SE556677889901',
address_line1: 'Kungsgatan 1',
postal_code: '11143',
city: 'Stockholm',
country: 'SE',
entity_type: 'aktiebolag',
} as unknown as CompanySettings
}
describe('FinancialStatementPDF', () => {
it('renders a balance-sheet-shaped document to a PDF buffer', async () => {
const doc = FinancialStatementPDF({
title: 'Balansräkning',
groups: [
{
heading: 'Tillgångar',
sections: [
{
title: 'Kassa och bank',
rows: [
{ account_number: '1930', account_name: 'Företagskonto', amount: 125_432.5 },
],
subtotal: 125_432.5,
},
],
totalLabel: 'Summa tillgångar',
total: 125_432.5,
},
{
heading: 'Eget kapital och skulder',
sections: [
{
title: 'Eget kapital',
rows: [
{ account_number: '2010', account_name: 'Eget kapital', amount: 100_000 },
{ account_number: '2091', account_name: 'Balanserat resultat', amount: 25_432.5 },
],
subtotal: 125_432.5,
},
],
totalLabel: 'Summa eget kapital och skulder',
total: 125_432.5,
},
],
period: { start: '2026-01-01', end: '2026-12-31' },
company: fakeCompany(),
generatedAt: '2026-04-21T10:00:00Z',
})
const buffer = await renderToBuffer(doc)
expect(buffer).toBeInstanceOf(Buffer)
expect(buffer.length).toBeGreaterThan(1000)
// PDF files always start with "%PDF-"
expect(buffer.slice(0, 5).toString()).toBe('%PDF-')
})
it('renders an income-statement-shaped document with a summary block', async () => {
const doc = FinancialStatementPDF({
title: 'Resultaträkning',
groups: [
{
heading: 'Rörelseintäkter',
sections: [
{
title: 'Huvudintäkter',
rows: [
{ account_number: '3001', account_name: 'Försäljning 25%', amount: 500_000 },
],
subtotal: 500_000,
},
],
totalLabel: 'Summa rörelseintäkter',
total: 500_000,
},
{
heading: 'Rörelsekostnader',
sections: [
{
title: 'Lokalkostnader',
rows: [
{ account_number: '5010', account_name: 'Lokalhyra', amount: 120_000 },
],
subtotal: 120_000,
},
],
totalLabel: 'Summa rörelsekostnader',
total: 120_000,
negate: true,
},
],
summary: [
{ label: 'Rörelseresultat', amount: 380_000 },
{ label: 'Årets resultat', amount: 380_000, emphasis: true },
],
period: { start: '2026-01-01', end: '2026-12-31' },
company: fakeCompany(),
generatedAt: '2026-04-21T10:00:00Z',
})
const buffer = await renderToBuffer(doc)
expect(buffer).toBeInstanceOf(Buffer)
expect(buffer.slice(0, 5).toString()).toBe('%PDF-')
})
it('handles empty section groups gracefully', async () => {
const doc = FinancialStatementPDF({
title: 'Balansräkning',
groups: [
{
heading: 'Tillgångar',
sections: [],
totalLabel: 'Summa tillgångar',
total: 0,
},
{
heading: 'Eget kapital och skulder',
sections: [],
totalLabel: 'Summa eget kapital och skulder',
total: 0,
},
],
period: { start: '', end: '' },
company: fakeCompany(),
generatedAt: '2026-04-21T10:00:00Z',
})
const buffer = await renderToBuffer(doc)
expect(buffer.slice(0, 5).toString()).toBe('%PDF-')
})
})