aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/lib/server/actual.ts
blob: ca4d9c4e26cd00899b6ff6ae0ee3e947da069ccd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { ACTUAL_FILE_ID, ACTUAL_HOST, ACTUAL_PASS } from "$env/static/private";
import * as actualApi from "@actual-app/api"
import { existsSync, mkdirSync } from "node:fs";
import path from "node:path"
import process from "node:process";
import type { ImportTransactionEntity } from "@actual-app/api/@types/loot-core/src/types/models/import-transaction";
import { Temporal } from "temporal-polyfill";
import type { Sb1Transaction } from "$lib/shared";

let inited = false

async function init() {
    if (inited) return
    const dataDir = path.resolve(process.cwd(), "data/actualDataDir")
    if (!existsSync(dataDir)) mkdirSync(dataDir, { recursive: true });
    await actualApi.init({
        password: ACTUAL_PASS,
        serverURL: ACTUAL_HOST,
        dataDir
    })
    await actualApi.downloadBudget(ACTUAL_FILE_ID)
    await actualApi.sync()
    inited = true
}

const budget = {
    async get_budgets() {
        await init()
        return actualApi.getBudgets()
    },

    async get_accounts() {
        await init()
        return actualApi.getAccounts()
    },

    async import_transactions(account: string, transactions: Sb1Transaction[], dryRun: boolean) {
        await init()

        function parsedDate(date: number) {
            return Temporal.Instant.fromEpochMilliseconds(date)
                .toString({ timeZone: "Europe/Oslo" })
                .split("T")[0]
        }

        function notes(transaction: Sb1Transaction) {
            const { description, cleanedDescription } = transaction
            if (description?.toLowerCase().trim() === cleanedDescription?.toLowerCase().trim()) return undefined
            return description
        }

        function amount(amount: number) {
            const res = Math.round(amount * 10000)
            console.log(`${amount}->${res}`)
            return res
        }

        const mapped: ImportTransactionEntity[] = transactions
            .filter(c => c.bookingStatus === "BOOKED")
            .map(c => ({
                account,
                date: parsedDate(c.date),
                amount: amount(c.amount),
                notes: notes(c),
                payee_name: c.cleanedDescription
            }))

        return actualApi.importTransactions(account, mapped, { dryRun })
    }
}

export default { init, budget }