diff --git a/package.nix b/package.nix index dfc58ee..0b4b0d5 100644 --- a/package.nix +++ b/package.nix @@ -10,7 +10,7 @@ in pname = "actual-importer"; version = "0.0.1"; src = ./.; - npmDepsHash = "sha256-yU3LzlExba2hq4EfuEb05TWaIS3gza1r8lu9Q/myXqE="; + npmDepsHash = "sha256-GHNfMeFg5UB/A031NYYjne9M8rXr1zeYCmBH2/FARt8="; postInstall = '' mkdir -p $out/lib/node_modules/actual-importer/public diff --git a/src/backend/index.ts b/src/backend/index.ts index 4d983b4..402cd88 100644 --- a/src/backend/index.ts +++ b/src/backend/index.ts @@ -14,9 +14,9 @@ export type SubmitOptions = type ActualTransaction = { id?: string; - account?: string; + account: string; date: string; - amount?: number; + amount: number; payee?: string; payee_name?: string; imported_payee?: string; @@ -51,7 +51,7 @@ export class Actual { } #map(transaction: Transaction, accounts: ActualAccount[], payees: ActualPayee[]): ActualTransaction { - const actualTransaction: ActualTransaction = { + const actualTransaction: Omit & { account?: string } = { imported_id: transaction.id, date: transaction.date, amount: utils.amountToInteger(transaction.amount), @@ -94,7 +94,7 @@ export class Actual { break; } - return actualTransaction; + return actualTransaction as ActualTransaction; } async #api(fn: () => Promise): Promise { @@ -194,7 +194,8 @@ export class Actual { const query = api.q('transactions') .limit(limit) - .select(['*']); + .select(['*']) + .options({ splits: 'grouped' }); const { data } = await api.runQuery(query) as { data: ActualTransaction[] }; @@ -209,7 +210,8 @@ export class Actual { const query = api.q('transactions') .filter({ date: [{ $gte: start }, { $lte: end }] }) - .select(['*']); + .select(['*']) + .options({ splits: 'grouped' }); const { data } = await api.runQuery(query) as { data: ActualTransaction[] }; diff --git a/src/server/index.ts b/src/server/index.ts index e6760c9..2deb39f 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -4,6 +4,7 @@ import express from "express"; import multer from "multer"; import { Readable } from "stream"; import path from 'path'; +import { Transaction } from "@/types/transaction"; export function serve(config: Config, port: number) { @@ -22,18 +23,23 @@ export function serve(config: Config, port: number) { app.get("/servers/:server/transactions", async (req, res) => { const { start, end } = req.query; + let data: Transaction[]|undefined; if (start && end) { - const data = await getTransactionsFromRange(req.params.server, config, start.toString(), end.toString()); - res.json(data); + data = await getTransactionsFromRange(req.params.server, config, start.toString(), end.toString()); } else { const limitParam = req.query.limit?.toString(); const limit = (limitParam && Number.parseInt(limitParam)) || undefined; - const data = await getTransactions(req.params.server, config, limit); - res.json(data); + data = await getTransactions(req.params.server, config, limit); } + + const profile = req.query.profile?.toString() || undefined; + const supportedAccounts = profile !== undefined ? config.profiles[profile].supportedAccounts : undefined; + const filterAccounts = supportedAccounts !== undefined ? (t: Transaction) => supportedAccounts.includes(t.from) || supportedAccounts.includes(t.to) : () => true; + + res.json(data.filter(filterAccounts)) }); app.post("/prepare", upload.single("file"), async (req, res) => { diff --git a/src/types/config.ts b/src/types/config.ts index baf9184..39cd0fb 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -11,6 +11,7 @@ export type ProfileConfig = { encoding?: string; config?: ParserConfig; csv?: Record; + supportedAccounts?: string[]; }; export type ParserConfig = { diff --git a/web/package.nix b/web/package.nix index da2021a..9600066 100644 --- a/web/package.nix +++ b/web/package.nix @@ -7,5 +7,5 @@ buildNpmPackage { pname = "actual-importer-frontend"; version = "0.0.1"; src = ./.; - npmDepsHash = "sha256-/G8OZBAkCuc0LTmpB1v8HTgaWdYd9AJfZTC0/eUQIx0="; + npmDepsHash = "sha256-Xh+zpYX8u+wKuvBjGc4hxUI2Ed4tiXKC3zk8kFExBbc="; } diff --git a/web/src/pages/PrepareTransactionsPage/PrepareTransactionsPage.tsx b/web/src/pages/PrepareTransactionsPage/PrepareTransactionsPage.tsx index bb358b8..203515b 100644 --- a/web/src/pages/PrepareTransactionsPage/PrepareTransactionsPage.tsx +++ b/web/src/pages/PrepareTransactionsPage/PrepareTransactionsPage.tsx @@ -79,7 +79,7 @@ export default function PrepareTransactionsPage() { // If no "from" filter active, pull the latest 10 transactions if (!debouncedUserFilter.from) { - const transactions = await getLatestTransactions(state.server, 10); + const transactions = await getLatestTransactions(state.server, 10, state.profile); setExistingTransactions(transactions); return; } @@ -87,7 +87,7 @@ export default function PrepareTransactionsPage() { const start = debouncedUserFilter.from.format("YYYY-MM-DD"); const end = (debouncedUserFilter.to ?? dayjs()).format("YYYY-MM-DD"); - const transactions = await getDateRangedTransactions(state.server, start, end); + const transactions = await getDateRangedTransactions(state.server, start, end, state.profile); setExistingTransactions(transactions); }, [enabledExistingTransactions, state.server, debouncedUserFilter]); diff --git a/web/src/services/api.service.ts b/web/src/services/api.service.ts index b9a0ecb..83cf7f9 100644 --- a/web/src/services/api.service.ts +++ b/web/src/services/api.service.ts @@ -40,21 +40,29 @@ export async function submitTransactions(transactions: Transaction[], server: st return data as SubmitResponse; } -export async function getLatestTransactions(server: string, limit: number = 5): Promise { +export async function getLatestTransactions(server: string, limit: number = 5, profile?: string): Promise { const params = new URLSearchParams(); params.append('limit', limit.toString()); + if (profile !== undefined) { + params.append('profile', profile); + } + const response = await fetch(`/servers/${server}/transactions?${params.toString()}`); const data = await response.json(); return data as Transaction[]; } -export async function getDateRangedTransactions(server: string, start: string, end: string): Promise { +export async function getDateRangedTransactions(server: string, start: string, end: string, profile?: string): Promise { const params = new URLSearchParams(); params.append('start', start); params.append('end', end); + if (profile !== undefined) { + params.append('profile', profile); + } + const response = await fetch(`/servers/${server}/transactions?${params.toString()}`); const data = await response.json(); return data as Transaction[];