aboutsummaryrefslogtreecommitdiffstats
path: root/cli/src/actual.ts
blob: a2360131a4ff72df47093b8f4fd169a9199d8ad1 (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
import * as actualApi from "@actual-app/api"
import { existsSync, mkdirSync } from "node:fs"
import { join } from "node:path"
import { Temporal } from "temporal-polyfill"
import { CONFIG_DIR } from "./config"
import type { Config } from "./config"
import type { Sb1Transaction, ActualAccount } from "./types"
import type { ImportTransactionEntity } from "@actual-app/api/@types/loot-core/src/types/models/import-transaction"

let inited = false

export async function initActual(config: Config["actual"]) {
    if (inited) return
    const dataDir = join(CONFIG_DIR, "actualDataDir")
    if (!existsSync(dataDir)) mkdirSync(dataDir, { recursive: true })
    process.env.ACTUAL_DATA_DIR = dataDir
    await actualApi.init({ password: config.password, serverURL: config.host, dataDir })
    await actualApi.downloadBudget(config.fileId)
    await actualApi.sync()
    inited = true
}

export async function getAccounts(config: Config["actual"]): Promise<ActualAccount[]> {
    await initActual(config)
    return actualApi.getAccounts() as Promise<ActualAccount[]>
}

export async function importTransactions(
    config: Config["actual"],
    accountId: string,
    transactions: Sb1Transaction[],
    dryRun: boolean
) {
    await initActual(config)

    const mapped: ImportTransactionEntity[] = transactions
        .filter(t => t.bookingStatus === "BOOKED")
        .map(t => ({
            account: accountId,
            date: Temporal.Instant.fromEpochMilliseconds(t.date)
                .toString({ timeZone: "Europe/Oslo" })
                .split("T")[0],
            amount: Math.round(t.amount * 100),
            payee_name: t.cleanedDescription,
            notes: t.description?.toLowerCase().trim() !== t.cleanedDescription?.toLowerCase().trim()
                ? t.description
                : undefined
        }))

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