actual-transaction-recorder/reporter.js
2026-03-26 00:05:22 +09:00

64 lines
1.9 KiB
JavaScript

// Expects a JSON config file to be passed in the env variable CONFIG_FILE.
// The file should contain:
// "dataDir": path
// "serverURL": where to point the requests
// "password": The password for logging in
// "budgetId": The ID of the budget containing the account to write transactions into.
// "accountId": UUID for the account to add transactions to.
import express from 'express'
import AsyncLock from 'async-lock';
import cors from 'cors'
import api from '@actual-app/api';
import fs from 'fs';
import { makeTransaction, parse } from './helpers.cjs';
async function addTransaction(config, transaction) {
try {
await api.init({
dataDir: config.dataDir,
serverURL: config.serverURL,
password: config.password,
});
await api.downloadBudget(config.budgetId);
await api.sync();
await api.addTransactions(config.accountId, [transaction]);
} finally {
await api.shutdown();
}
}
async function init() {
const config = JSON.parse(fs.readFileSync(process.env.CONFIG_FILE));
const app = express();
const lock = new AsyncLock();
// Adds headers: Access-Control-Allow-Origin: *
app.use(cors())
app.use(express.json());
app.post('/actual-api/transaction', async function (req, res, _next) {
await lock.acquire('transaction', async () => {
console.debug('Executing Transaction');
try {
const transaction = makeTransaction(parse(req.body), config.accountId);
console.log(transaction);
await addTransaction(config, transaction)
console.log(`Successfully logged "${transaction.payee_name} - ¥${transaction.amount}"`);
return res.json({ result: 'success' });
} catch (e) {
console.log('Transaction failed...');
console.log(e);
console.log(e.message);
return res.json({ result: 'failure', error: e.message });
}
});
});
app.listen(12467, function () {
console.log('Starting AMEX Transaction Writer');
});
}
init();