Skip to content
This repository has been archived by the owner on Feb 10, 2025. It is now read-only.

Commit

Permalink
Added release notes and lint cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
zachwhelchel committed Jan 11, 2024
1 parent c608daa commit bca5dc3
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 88 deletions.
210 changes: 122 additions & 88 deletions src/app-simplefin/app-simplefin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import express from 'express';
import path from 'path';
import { inspect } from 'util';
import https from 'https';
import { SecretName, secretsService } from '../services/secrets-service.js';
Expand All @@ -9,13 +8,10 @@ export { app as handlers };
app.use(express.json());

app.post('/status', async (req, res) => {

let configured = false;

let token = secretsService.get(SecretName.simplefin_token);
if (token === null || token === undefined || token === "Forbidden") {

} else {
if (token !== null || token !== undefined || token !== 'Forbidden') {
configured = true;
}

Expand All @@ -28,60 +24,76 @@ app.post('/status', async (req, res) => {
});

app.post('/accounts', async (req, res) => {

let accessKey = secretsService.get(SecretName.simplefin_accessKey);

if (accessKey === null || accessKey === undefined || accessKey === "Forbidden") {
if (
accessKey === null ||
accessKey === undefined ||
accessKey === 'Forbidden'
) {
let token = secretsService.get(SecretName.simplefin_token);
if (token === null || token === undefined || token === "Forbidden") {
if (token === null || token === undefined || token === 'Forbidden') {
return;
} else {
accessKey = await getAccessKey(token);
secretsService.set(SecretName.simplefin_accessKey, accessKey);
}
}

const now = new Date()
let startDate = new Date(now.getFullYear(), now.getMonth(), 1)
let endDate = new Date(now.getFullYear(), now.getMonth() + 1, 1)
const now = new Date();
let startDate = new Date(now.getFullYear(), now.getMonth(), 1);
let endDate = new Date(now.getFullYear(), now.getMonth() + 1, 1);

let accounts = await getAccounts(accessKey, startDate, endDate)
let accounts = await getAccounts(accessKey, startDate, endDate);

res.send({
status: 'ok',
data: {
accounts: accounts,
accounts: accounts.accounts,
},
});
});

app.post('/transactions', async (req, res) => {

const { accountId, startDate } = req.body;

let accessKey = secretsService.get(SecretName.simplefin_accessKey);

if (accessKey === null || accessKey === undefined || accessKey === "Forbidden") {
if (
accessKey === null ||
accessKey === undefined ||
accessKey === 'Forbidden'
) {
return;
}

try {
let results = await getTransactions(
accessKey,
new Date(startDate),
);
let results = await getTransactions(accessKey, new Date(startDate));

let account = results.accounts.find(a => a.id === accountId);
let account = results.accounts.find((a) => a.id === accountId);

let response = {};

let balance = parseInt(account.balance.replace('.', ''))
let date = new Date(account["balance-date"] * 1000).toISOString().split('T')[0]

response.balances = [{balanceAmount: {amount: account.balance, currency: account.currency}, balanceType: "expected", referenceDate: date}, {balanceAmount: {amount: account.balance, currency: account.currency}, balanceType: "interimAvailable", referenceDate: date}]
response.iban = "thisismadeup"
response.institutionId = "thisismadeup"
response.startingBalance = balance // should be named differently in this use case.
let balance = parseInt(account.balance.replace('.', ''));
let date = new Date(account['balance-date'] * 1000)
.toISOString()
.split('T')[0];

response.balances = [
{
balanceAmount: { amount: account.balance, currency: account.currency },
balanceType: 'expected',
referenceDate: date,
},
{
balanceAmount: { amount: account.balance, currency: account.currency },
balanceType: 'interimAvailable',
referenceDate: date,
},
];
response.iban = 'thisismadeup';
response.institutionId = 'thisismadeup';
response.startingBalance = balance; // should be named differently in this use case.

let allTransactions = [];

Expand All @@ -91,19 +103,27 @@ app.post('/transactions', async (req, res) => {

//newTrans.bankTransactionCode = don't have, not sure if issue.
newTrans.booked = true;
newTrans.bookingDate = new Date(trans.posted * 1000).toISOString().split('T')[0]
newTrans.date = new Date(trans.posted * 1000).toISOString().split('T')[0]
newTrans.bookingDate = new Date(trans.posted * 1000)
.toISOString()
.split('T')[0];
newTrans.date = new Date(trans.posted * 1000).toISOString().split('T')[0];
newTrans.debtorName = trans.payee;
//newTrans.debtorAccount = don't have, not sure if issue.
newTrans.remittanceInformationUnstructured = trans.description;
newTrans.transactionAmount = {amount: trans.amount, currency: "USD"};
newTrans.transactionAmount = { amount: trans.amount, currency: 'USD' };
newTrans.transactionId = trans.id;
newTrans.valueDate = new Date(trans.posted * 1000).toISOString().split('T')[0]
newTrans.valueDate = new Date(trans.posted * 1000)
.toISOString()
.split('T')[0];

allTransactions.push(newTrans);
}

response.transactions = {all: allTransactions, booked: allTransactions, pending: []}
response.transactions = {
all: allTransactions,
booked: allTransactions,
pending: [],
};

res.send({
status: 'ok',
Expand All @@ -112,91 +132,105 @@ app.post('/transactions', async (req, res) => {
} catch (error) {
const sendErrorResponse = (data) =>
res.send({ status: 'ok', data: { ...data, details: error.details } });
console.log('Something went wrong', inspect(error, { depth: null }));
console.log(
'Something went wrong',
inspect(error, { depth: null }),
sendErrorResponse,
);
}
});

function parseAccessKey (accessKey) {
let scheme = null
let rest = null
let auth = null
let username = null
let password = null
let baseUrl = null
;[scheme, rest] = accessKey.split('//')
;[auth, rest] = rest.split('@')
;[username, password] = auth.split(':')
baseUrl = `${scheme}//${rest}`
function parseAccessKey(accessKey) {
let scheme = null;
let rest = null;
let auth = null;
let username = null;
let password = null;
let baseUrl = null;
[scheme, rest] = accessKey.split('//');
[auth, rest] = rest.split('@');
[username, password] = auth.split(':');
baseUrl = `${scheme}//${rest}`;
return {
baseUrl: baseUrl,
username: username,
password: password
}
password: password,
};
}

async function getAccessKey (base64Token) {
const token = Buffer.from(base64Token, 'base64').toString()
async function getAccessKey(base64Token) {
const token = Buffer.from(base64Token, 'base64').toString();
const options = {
method: 'POST',
port: 443,
headers: { 'Content-Length': 0 }
}
headers: { 'Content-Length': 0 },
};
return new Promise((resolve, reject) => {
const req = https.request(new URL(token), options, (res) => {
res.on('data', (d) => {
resolve(d.toString())
})
})
resolve(d.toString());
});
});
req.on('error', (e) => {
reject(e)
})
req.end()
})
reject(e);
});
req.end();
});
}

async function getTransactions (accessKey, startDate, endDate) {
const now = new Date()
startDate = startDate || new Date(now.getFullYear(), now.getMonth(), 1)
endDate = endDate || new Date(now.getFullYear(), now.getMonth() + 1, 1)
console.log(`${startDate.toISOString().split('T')[0]} - ${endDate.toISOString().split('T')[0]}`)
return await getAccounts(accessKey, startDate, endDate)
async function getTransactions(accessKey, startDate, endDate) {
const now = new Date();
startDate = startDate || new Date(now.getFullYear(), now.getMonth(), 1);
endDate = endDate || new Date(now.getFullYear(), now.getMonth() + 1, 1);
console.log(
`${startDate.toISOString().split('T')[0]} - ${
endDate.toISOString().split('T')[0]
}`,
);
return await getAccounts(accessKey, startDate, endDate);
}

function normalizeDate (date) {
return (date.valueOf() - date.getTimezoneOffset() * 60 * 1000) / 1000
function normalizeDate(date) {
return (date.valueOf() - date.getTimezoneOffset() * 60 * 1000) / 1000;
}

async function getAccounts (accessKey, startDate, endDate) {
const sfin = parseAccessKey(accessKey)
async function getAccounts(accessKey, startDate, endDate) {
const sfin = parseAccessKey(accessKey);
const options = {
headers: {
Authorization: `Basic ${Buffer.from(`${sfin.username}:${sfin.password}`).toString('base64')}`
}
}
const params = []
let queryString = ''
Authorization: `Basic ${Buffer.from(
`${sfin.username}:${sfin.password}`,
).toString('base64')}`,
},
};
const params = [];
let queryString = '';
if (startDate) {
params.push(`start-date=${normalizeDate(startDate)}`)
params.push(`start-date=${normalizeDate(startDate)}`);
}
if (endDate) {
params.push(`end-date=${normalizeDate(endDate)}`)
params.push(`end-date=${normalizeDate(endDate)}`);
}
if (params.length > 0) {
queryString += '?' + params.join('&')
queryString += '?' + params.join('&');
}
return new Promise((resolve, reject) => {
const req = https.request(new URL(`${sfin.baseUrl}/accounts${queryString}`), options, (res) => {
let data = ''
res.on('data', (d) => {
data += d
})
res.on('end', () => {
resolve(JSON.parse(data))
})
})
const req = https.request(
new URL(`${sfin.baseUrl}/accounts${queryString}`),
options,
(res) => {
let data = '';
res.on('data', (d) => {
data += d;
});
res.on('end', () => {
resolve(JSON.parse(data));
});
},
);
req.on('error', (e) => {
reject(e)
})
req.end()
})
reject(e);
});
req.end();
});
}
6 changes: 6 additions & 0 deletions upcoming-release-notes/296.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [zachwhelchel,duplaja,lancepick,latetedemelon]
---

Add option to link an account to SimpleFIN for syncing transactions.

0 comments on commit bca5dc3

Please sign in to comment.