Files
AnnasRechnungsManager/tests/lib/afa.test.ts
T
hwinkel db953b1e28 Add comprehensive tests for client validation, revenue and expense categories, invoice generation, and schemas
- Implement tests for client validation functions including tax ID, VAT ID, IBAN, BIC, website, and company form validation.
- Create tests for revenue and expense categories ensuring all expected categories and labels are present.
- Add tests for invoice number generation with various scenarios including prefix handling and sequence padding.
- Introduce tests for default categories and their integration, ensuring no overlaps and consistent naming conventions.
- Implement Zod schema validation tests for currency, tax rates, IBAN, tax ID, VAT ID, invoices, companies, and customers.
- Add utility tests for tax calculations, including item amounts and invoice totals, ensuring correct handling of tax rates and formatting.
- Set up Vitest configuration and global test setup for consistent testing environment.
2026-05-08 16:03:05 +02:00

160 lines
5.4 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
jahresAfa,
erwerbsjahrAfa,
afaFuerJahr,
kumulierteAfa,
buchwert,
assetStatus,
AnlagegutRaw,
} from "@/lib/afa";
describe("afa.ts - Asset Depreciation (§7 EStG)", () => {
const sampleAsset: AnlagegutRaw = {
anschaffungskosten: 12000,
nutzungsdauerJahre: 3,
restwert: 0,
anschaffungsdatum: "2024-03-15", // March 15, 2024
aktiv: true,
};
describe("jahresAfa", () => {
it("should calculate full annual depreciation", () => {
// 12000 over 3 years = 4000 per year
expect(jahresAfa(12000, 0, 3)).toBe(4000);
});
it("should handle residual value (restwert)", () => {
// 12000 - 2000 restwert = 10000 over 3 years
expect(jahresAfa(12000, 2000, 3)).toBe(3333.33);
});
it("should handle different depreciation periods", () => {
// 24000 over 8 years = 3000 per year
expect(jahresAfa(24000, 0, 8)).toBe(3000);
});
});
describe("erwerbsjahrAfa", () => {
it("should calculate pro-rata depreciation in acquisition year", () => {
// Acquired March 15 = 10 months remaining (Mar-Dec, inclusive) = 10/12
// 4000 * (10/12) = 3333.33
const acqDate = new Date("2024-03-15");
const result = erwerbsjahrAfa(12000, 0, 3, acqDate);
expect(result).toBe(3333.33);
});
it("should calculate full year if acquired in January", () => {
const acqDate = new Date("2024-01-01");
const result = erwerbsjahrAfa(12000, 0, 3, acqDate);
expect(result).toBe(4000);
});
it("should calculate 1/12 if acquired in December", () => {
const acqDate = new Date("2024-12-01");
const result = erwerbsjahrAfa(12000, 0, 3, acqDate);
expect(result).toBe(333.33);
});
});
describe("afaFuerJahr", () => {
it("should return 0 for years before acquisition", () => {
expect(afaFuerJahr(sampleAsset, 2023)).toBe(0);
});
it("should return pro-rata for acquisition year", () => {
// 2024 acquisition, 10 months = 3333.33
const result = afaFuerJahr(sampleAsset, 2024);
expect(result).toBe(3333.33);
});
it("should return full annual amount for middle years", () => {
expect(afaFuerJahr(sampleAsset, 2025)).toBe(4000);
expect(afaFuerJahr(sampleAsset, 2026)).toBe(4000);
});
it("should return 0 after full depreciation period", () => {
// 3 years: 2024, 2025, 2026 -> after 2026 = 0
expect(afaFuerJahr(sampleAsset, 2027)).toBe(0);
});
it("should handle asset with residual value", () => {
const assetWithRestwert: AnlagegutRaw = {
anschaffungskosten: 5000,
nutzungsdauerJahre: 5,
restwert: 500,
anschaffungsdatum: "2024-01-01",
aktiv: true,
};
// (5000-500) / 5 = 900 per year
expect(afaFuerJahr(assetWithRestwert, 2024)).toBe(900);
expect(afaFuerJahr(assetWithRestwert, 2028)).toBe(900);
expect(afaFuerJahr(assetWithRestwert, 2029)).toBe(0);
});
});
describe("kumulierteAfa", () => {
it("should calculate cumulative depreciation correctly", () => {
// 2024: 3333.33, 2025: 4000, 2026: 4000 = 11333.33
expect(kumulierteAfa(sampleAsset, 2026)).toBe(11333.33);
});
it("should return 0 for year before acquisition", () => {
expect(kumulierteAfa(sampleAsset, 2023)).toBe(0);
});
it("should return full depreciation after end of period", () => {
// After 3 years: 3333.33 + 4000 + 4000 = 11333.33
// But asset cost is 12000, so 12000 - 11333.33 = 666.67 remaining
const result = kumulierteAfa(sampleAsset, 2027);
expect(result).toBe(11333.33);
});
});
describe("buchwert", () => {
it("should calculate book value correctly", () => {
// 2024: 3333.33 depreciation -> 12000 - 3333.33 = 8666.67
expect(buchwert(sampleAsset, 2024)).toBe(8666.67);
// 2025: another 4000 -> 8666.67 - 4000 = 4666.67
expect(buchwert(sampleAsset, 2025)).toBe(4666.67);
// 2026: another 4000 -> 4666.67 - 4000 = 666.67
expect(buchwert(sampleAsset, 2026)).toBe(666.67);
});
it("should not go below residual value", () => {
const assetWithRestwert: AnlagegutRaw = {
anschaffungskosten: 5000,
nutzungsdauerJahre: 5,
restwert: 500,
anschaffungsdatum: "2024-01-01",
aktiv: true,
};
// After full depreciation: 5000 - (900 * 5) = 500
expect(buchwert(assetWithRestwert, 2028)).toBe(500);
expect(buchwert(assetWithRestwert, 2030)).toBe(500);
});
it("should return acquisition cost for year before acquisition", () => {
expect(buchwert(sampleAsset, 2023)).toBe(12000);
});
});
describe("assetStatus", () => {
it("should return 'inaktiv' for inactive assets", () => {
const inactive: AnlagegutRaw = { ...sampleAsset, aktiv: false };
expect(assetStatus(inactive, 2025)).toBe("inaktiv");
});
it("should return 'aktiv' for active assets within depreciation period", () => {
expect(assetStatus(sampleAsset, 2024)).toBe("aktiv");
expect(assetStatus(sampleAsset, 2025)).toBe("aktiv");
expect(assetStatus(sampleAsset, 2026)).toBe("aktiv");
});
it("should return 'vollständig abgeschrieben' after depreciation period", () => {
expect(assetStatus(sampleAsset, 2027)).toBe("vollständig abgeschrieben");
expect(assetStatus(sampleAsset, 2030)).toBe("vollständig abgeschrieben");
});
});
});