aboutsummaryrefslogtreecommitdiffstats
path: root/cli/src/actual.ts
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/actual.ts')
-rw-r--r--cli/src/actual.ts51
1 files changed, 51 insertions, 0 deletions
diff --git a/cli/src/actual.ts b/cli/src/actual.ts
new file mode 100644
index 0000000..a236013
--- /dev/null
+++ b/cli/src/actual.ts
@@ -0,0 +1,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 })
+}