Cleared status from API, docker script
All checks were successful
Deploy application / deploy (push) Successful in 6s

This commit is contained in:
Martin Berg Alstad 2025-01-27 21:30:56 +01:00
parent 61f0153319
commit 752bdbceb4
Signed by: martials
GPG Key ID: A3824877B269F2E2
5 changed files with 18 additions and 9 deletions

View File

@ -9,6 +9,7 @@
"start-prod": "node --import=tsx ./src/main.ts", "start-prod": "node --import=tsx ./src/main.ts",
"run-once": "ONCE=true dotenvx run --env-file=.env.local -- node --import=tsx ./src/main.ts | pino-pretty", "run-once": "ONCE=true dotenvx run --env-file=.env.local -- node --import=tsx ./src/main.ts | pino-pretty",
"test": "dotenvx run --env-file=.env.test.local -- node --experimental-vm-modules node_modules/jest/bin/jest.js | pino-pretty", "test": "dotenvx run --env-file=.env.test.local -- node --experimental-vm-modules node_modules/jest/bin/jest.js | pino-pretty",
"docker-build": "DB_DIRECTORY=data docker compose --env-file .env.local up -d --build",
"format": "prettier --write \"./**/*.{js,mjs,ts,md,json}\"" "format": "prettier --write \"./**/*.{js,mjs,ts,md,json}\""
}, },
"keywords": [], "keywords": [],

View File

@ -18,6 +18,8 @@ export interface OAuthTokenResponse {
refresh_token: string refresh_token: string
} }
export type BookingStatus = "PENDING" | "BOOKED"
export interface Transaction { export interface Transaction {
id: string id: string
nonUniqueId: string nonUniqueId: string
@ -25,6 +27,7 @@ export interface Transaction {
amount: number // Amount in NOK amount: number // Amount in NOK
cleanedDescription: string cleanedDescription: string
remoteAccountName: string remoteAccountName: string
bookingStatus: BookingStatus
[key: string]: string | number | boolean | unknown [key: string]: string | number | boolean | unknown
} }
@ -33,15 +36,13 @@ export interface TransactionResponse {
transactions: ReadonlyArray<Transaction> transactions: ReadonlyArray<Transaction>
} }
export type Bank = Sparebank1 export interface Bank {
export interface Sparebank1 {
transactionsPastDay: ( transactionsPastDay: (
...accountKeys: ReadonlyArray<string> ...accountKeys: ReadonlyArray<string>
) => Promise<TransactionResponse> ) => Promise<TransactionResponse>
} }
export class Sparebank1Impl implements Sparebank1 { export class Sparebank1Impl implements Bank {
private readonly db: Database private readonly db: Database
constructor(db: Database) { constructor(db: Database) {
@ -93,7 +94,6 @@ export class Sparebank1Impl implements Sparebank1 {
async transactionsPastDay( async transactionsPastDay(
...accountKeys: ReadonlyArray<string> ...accountKeys: ReadonlyArray<string>
): Promise<TransactionResponse> { ): Promise<TransactionResponse> {
// TODO API is inclusive, today should equal lastDay
const today = dayjs() const today = dayjs()
const lastDay = today.subtract(1, "day") const lastDay = today.subtract(1, "day")
return await Api.transactions(await this.getAccessToken(), accountKeys, { return await Api.transactions(await this.getAccessToken(), accountKeys, {

View File

@ -36,10 +36,10 @@ export async function daily(actual: Actual, bank: Bank): Promise<void> {
bankTransactionIntoActualTransaction(transaction, accountId), bankTransactionIntoActualTransaction(transaction, accountId),
) )
logger.trace({ logger.debug({
aMessage: "Mapped from Bank to Actual", aMessage: "Mapped from Bank to Actual",
from: JSON.stringify(transactions), from: transactions,
to: JSON.stringify(actualTransactions), to: actualTransactions,
}) })
// TODO Import transactions into Actual // TODO Import transactions into Actual
@ -92,6 +92,7 @@ async function main(): Promise<void> {
} }
logger.info("Waiting for CRON job to start") logger.info("Waiting for CRON job to start")
// TODO init and shutdown resources when job runs?
cronJob = cronJobDaily(async () => await daily(actual, bank)) cronJob = cronJobDaily(async () => await daily(actual, bank))
async function shutdown(): Promise<void> { async function shutdown(): Promise<void> {

View File

@ -17,6 +17,8 @@ export function bankTransactionIntoActualTransaction(
amount: transaction.amount * 100, amount: transaction.amount * 100,
date: toISODateString(dayjs(transaction.date)), date: toISODateString(dayjs(transaction.date)),
payee_name: transaction.cleanedDescription, payee_name: transaction.cleanedDescription,
// TODO if not cleared, rerun later
cleared: transaction.bookingStatus === "BOOKED",
} }
} }

View File

@ -1,4 +1,8 @@
import type { Bank, TransactionResponse } from "@/bank/sparebank1.ts" import type {
Bank,
BookingStatus,
TransactionResponse,
} from "@/bank/sparebank1.ts"
import dayjs from "dayjs" import dayjs from "dayjs"
export class BankStub implements Bank { export class BankStub implements Bank {
@ -9,6 +13,7 @@ export class BankStub implements Bank {
date: dayjs("2019-08-20").unix(), date: dayjs("2019-08-20").unix(),
cleanedDescription: "Test transaction", cleanedDescription: "Test transaction",
remoteAccountName: "Test account", remoteAccountName: "Test account",
bookingStatus: "BOOKED" as BookingStatus,
} }
return { return {
transactions: [ transactions: [