Skip to content

Commit

Permalink
feat: Add a generic web storage (#317)
Browse files Browse the repository at this point in the history
* Add a generic web storage
  • Loading branch information
daniel-hauser authored Aug 6, 2024
1 parent 72f25b9 commit 9b550b5
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 19 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,38 @@ Use the following env vars to setup:
| -------------------- | ---------------------------------------------------------------------------------------------- |
| `LOCAL_JSON_STORAGE` | If truthy, all transaction will be saved to a `<process cwd>/output/<ISO timestamp>.json` file |

### Export to web address

Export transactions as a POST request to a web address.

The transactions will be sent as a JSON array in the body of the request with the following structure:

```
{
date: string, // "dd/mm/yyyy"
amount: number,
description: string,
memo: string,
category: string,
account: string,
hash: string,
comment: string | undefined,
"scraped at": string, // "YYYY-MM-DD"
"scraped by": string,
identifier: string,
chargedCurrency: string | undefined,
}
```

Use the following env vars to setup:

| env variable name | description |
| ----------------- | ------------------ |
| `WEB_POST_URL ` | The URL to post to |

> [!IMPORTANT]
> Be sure to post only to a trusted server.
### Export to excel on OneDrive

WIP
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const {
BUXFER_PASSWORD = "",
BUXFER_ACCOUNTS = "",
TRANSACTION_HASH_TYPE = "",
WEB_POST_URL = "",
} = process.env;

/**
Expand All @@ -49,6 +50,7 @@ export {
BUXFER_PASSWORD,
BUXFER_ACCOUNTS,
TRANSACTION_HASH_TYPE,
WEB_POST_URL,
};
export const systemName = "moneyman";
export const currentDate = format(Date.now(), "yyyy-MM-dd");
Expand Down
2 changes: 2 additions & 0 deletions src/storage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { AzureDataExplorerStorage } from "./azure-data-explorer.js";
import { transactionHash, transactionUniqueId } from "./utils.js";
import { YNABStorage } from "./ynab.js";
import { BuxferStorage } from "./buxfer.js";
import { WebPostStorage } from "./web-post.js";

export const storages = [
new LocalJsonStorage(),
new GoogleSheetsStorage(),
new AzureDataExplorerStorage(),
new YNABStorage(),
new BuxferStorage(),
new WebPostStorage(),
].filter((s) => s.canSave());

export async function initializeStorage() {
Expand Down
38 changes: 19 additions & 19 deletions src/storage/sheets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { normalizeCurrency } from "../utils/currency.js";

const logger = createLogger("GoogleSheetsStorage");

type SheetRow = {
export type SheetRow = {
date: string;
amount: number;
description: string;
Expand All @@ -38,6 +38,23 @@ type SheetRow = {
chargedCurrency: string;
};

export function transactionRow(tx: TransactionRow): SheetRow {
return {
date: format(parseISO(tx.date), "dd/MM/yyyy", {}),
amount: tx.chargedAmount,
description: tx.description,
memo: tx.memo ?? "",
category: tx.category ?? "",
account: tx.account,
hash: TRANSACTION_HASH_TYPE === "moneyman" ? tx.uniqueId : tx.hash,
comment: "",
"scraped at": currentDate,
"scraped by": systemName,
identifier: `${tx.identifier ?? ""}`,
chargedCurrency: normalizeCurrency(tx.chargedCurrency),
};
}

export class GoogleSheetsStorage implements TransactionStorage {
static FileHeaders: Array<keyof SheetRow> = [
"date",
Expand Down Expand Up @@ -127,7 +144,7 @@ export class GoogleSheetsStorage implements TransactionStorage {
continue;
}

rows.push(this.transactionRow(tx));
rows.push(transactionRow(tx));
stats.highlightedTransactions.Added.push(tx);
}

Expand Down Expand Up @@ -185,21 +202,4 @@ export class GoogleSheetsStorage implements TransactionStorage {

this.sheet = doc.sheetsByTitle[worksheetName];
}

private transactionRow(tx: TransactionRow): SheetRow {
return {
date: format(parseISO(tx.date), "dd/MM/yyyy", {}),
amount: tx.chargedAmount,
description: tx.description,
memo: tx.memo ?? "",
category: tx.category ?? "",
account: tx.account,
hash: TRANSACTION_HASH_TYPE === "moneyman" ? tx.uniqueId : tx.hash,
comment: "",
"scraped at": currentDate,
"scraped by": systemName,
identifier: `${tx.identifier ?? ""}`,
chargedCurrency: normalizeCurrency(tx.chargedCurrency),
};
}
}
63 changes: 63 additions & 0 deletions src/storage/web-post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { createLogger } from "../utils/logger.js";
import type {
TransactionRow,
TransactionStorage,
SaveStats,
} from "../types.js";
import { WEB_POST_URL } from "../config.js";
import { TransactionStatuses } from "israeli-bank-scrapers/lib/transactions.js";
import { transactionRow } from "./sheets.js";

const logger = createLogger("WebPostStorage");

export class WebPostStorage implements TransactionStorage {
private url = WEB_POST_URL;

async init() {
logger("init");
}

canSave() {
return Boolean(this.url) && URL.canParse(this.url);
}

async saveTransactions(txns: Array<TransactionRow>) {
logger("saveTransactions");
await this.init();

const nonPendingTxns = txns.filter(
(txn) => txn.status !== TransactionStatuses.Pending,
);

logger(`Posting ${nonPendingTxns.length} transactions to ${this.url}`);

const response = await fetch(this.url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(nonPendingTxns.map((tx) => transactionRow(tx))),
});

if (!response.ok) {
logger(`Failed to post transactions: ${response.statusText}`);
throw new Error(`Failed to post transactions: ${response.statusText}`);
}

const { added = nonPendingTxns.length, skipped = NaN } =
await response.json();

const pending = txns.length - nonPendingTxns.length;
const stats: SaveStats = {
name: "WebPostStorage",
table: "web-post",
total: txns.length,
added,
pending,
skipped: skipped + pending,
existing: skipped,
};

return stats;
}
}

0 comments on commit 9b550b5

Please sign in to comment.