Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e6f1f4780 | ||
|
|
470be2880c | ||
|
|
4e4760b55a |
6 changed files with 4364 additions and 35 deletions
9
.envrc
Normal file
9
.envrc
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# the shebang is ignored, but nice for editors
|
||||||
|
|
||||||
|
if type -P lorri &>/dev/null; then
|
||||||
|
eval "$(lorri direnv)"
|
||||||
|
else
|
||||||
|
echo 'while direnv evaluated .envrc, could not find the command "lorri" [https://github.com/nix-community/lorri]'
|
||||||
|
use nix
|
||||||
|
fi
|
||||||
39
helpers.cjs
Normal file
39
helpers.cjs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
function parse(data) {
|
||||||
|
if (typeof data !== 'object' || data === null) {
|
||||||
|
throw new Error(`Bad Data, expected an object, got: ${data === null ? null : typeof data}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((typeof data.title) !== 'string') {
|
||||||
|
throw new Error(`Bad Title: ${data.title}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!['string', 'number'].includes(typeof data.amount)) {
|
||||||
|
throw new Error(`Bad amount: ${data.amount}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data.amount === 'string') {
|
||||||
|
const value = Number(data.amount.replaceAll(/[^\d]/g, ''));
|
||||||
|
data.amount = Number.isNaN(value) ? 0 : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeTransaction(data, account) {
|
||||||
|
return {
|
||||||
|
account,
|
||||||
|
date: new Date().toLocaleDateString('sv-SE'), // "YYYY-MM-DD"
|
||||||
|
payee_name: data.title,
|
||||||
|
// Actual considers this an integer representing a decimal value so the last two digits of the integer
|
||||||
|
// are placed after the decimal point (unclear why but okay...)
|
||||||
|
// It has to be negative or actual will think it's a deposit
|
||||||
|
amount: data.amount * -100,
|
||||||
|
cleared: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
makeTransaction,
|
||||||
|
parse
|
||||||
|
};
|
||||||
49
helpers.spec.js
Normal file
49
helpers.spec.js
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
const { describe, expect, test } = require('@jest/globals');
|
||||||
|
const { parse } = require('./helpers');
|
||||||
|
|
||||||
|
describe(parse.name, () => {
|
||||||
|
const TEST_DATA = {
|
||||||
|
title: 'test',
|
||||||
|
amount: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
[
|
||||||
|
['number title', { ...TEST_DATA, title: 11 }],
|
||||||
|
['boolean title', { ...TEST_DATA, title: false }],
|
||||||
|
['object title', { ...TEST_DATA, title: {} }],
|
||||||
|
['null title', { ...TEST_DATA, title: null }],
|
||||||
|
['boolean amount', { ...TEST_DATA, amount: true }],
|
||||||
|
['object amount', { ...TEST_DATA, amount: {} }],
|
||||||
|
].forEach(([tag, badData]) => {
|
||||||
|
test(`it rejects ${tag} as bad data`, () => {
|
||||||
|
expect(() => parse(badData)).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('it accepts a regular value', () => {
|
||||||
|
let result;
|
||||||
|
expect(() => {
|
||||||
|
result = parse(TEST_DATA);
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(result).toEqual(TEST_DATA);
|
||||||
|
});
|
||||||
|
test('it parses yen', () => {
|
||||||
|
let result;
|
||||||
|
expect(() => {
|
||||||
|
result = parse({ title: 'test', amount: '¥3,746'});
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(result).toEqual({
|
||||||
|
amount: 3746,
|
||||||
|
title: 'test',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('it strips out non-number values from strings', () => {
|
||||||
|
let result;
|
||||||
|
expect(() => {
|
||||||
|
result = parse({ title: 'test', amount: '¥3,7~4j6.1t1'});
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(result).toEqual({
|
||||||
|
amount: 374611,
|
||||||
|
title: 'test',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
4259
package-lock.json
generated
4259
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +1,17 @@
|
||||||
{
|
{
|
||||||
|
"type": "module",
|
||||||
"name": "reporter.js",
|
"name": "reporter.js",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actual-app/api": "^26.3.0",
|
"@actual-app/api": "^26.3.0",
|
||||||
"async-lock": "^1.4.1",
|
"async-lock": "^1.4.1",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
"express": "^5.2.1"
|
"express": "^5.2.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"jest": "^30.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
36
reporter.js
36
reporter.js
|
|
@ -11,41 +11,7 @@ import AsyncLock from 'async-lock';
|
||||||
import cors from 'cors'
|
import cors from 'cors'
|
||||||
import api from '@actual-app/api';
|
import api from '@actual-app/api';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { makeTransaction, parse } from './helpers.cjs';
|
||||||
function parse(data) {
|
|
||||||
if (typeof data !== 'object' || data === null) {
|
|
||||||
throw new Error(`Bad Data, expected an object, got: ${data === null ? null : typeof data}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.title !== 'string') {
|
|
||||||
throw new Error(`Bad Title: ${data.title}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.amount !== 'number' || typeof data.amount !== 'string') {
|
|
||||||
throw new Error(`Bad amount: ${data.amount}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.amount === 'string') {
|
|
||||||
const value = Number(data.amount.replaceAll(/[^\d]/g, ''));
|
|
||||||
data.amount = Number.isNaN(value) ? 0 : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeTransaction(data, account) {
|
|
||||||
return {
|
|
||||||
account,
|
|
||||||
date: new Date().toLocaleDateString('sv-SE'), // "YYYY-MM-DD"
|
|
||||||
payee_name: data.title,
|
|
||||||
// Actual considers this an integer representing a decimal value so the last two digits of the integer
|
|
||||||
// are placed after the decimal point (unclear why but okay...)
|
|
||||||
// It has to be negative or actual will think it's a deposit
|
|
||||||
amount: data.amount * -100,
|
|
||||||
cleared: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function addTransaction(config, transaction) {
|
async function addTransaction(config, transaction) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue