Below is a command to the clone the source code for the application used in this tutorial
git clone --branch v1.2.0 https://github.com/redis-developer/mobile-banking-solutions
An account dashboard is a page in a mobile banking app that instantly renders account highlights to users. A customer can click on any of the accounts on the dashboard to see the real-time account details, such as latest transactions, mortgage amount they have left to pay, checking and savings, etc.
An account dashboard makes a customer's finances easily visible in one place. It reduces financial complexity for the customer and fosters customer loyalty.
The following diagram is an example data architecture for an account dashboard:
Redis Stack supports the JSON data type and allows you to index and querying JSON and more. So your Redis data is not limited to simple key-value stringified data.
Below is a command to the clone the source code for the application used in this tutorial
git clone --branch v1.2.0 https://github.com/redis-developer/mobile-banking-solutions
Download the above source code and run following command to start the demo application
docker compose up -d
After docker up & running, open http://localhost:8080/ url in browser to view application
This application leverages Redis core data structures, JSON, TimeSeries, Search and Query features. The data seeded is later used to show a searchable transaction overview with realtime updates as well as a personal finance management overview with realtime balance and biggest spenders updates.
On application startup in app/server.js
, a cron is scheduled to create random bank transactions at regular intervals and seed those transactions in to Redis.
//cron job to trigger createBankTransaction() at regular intervals
cron.schedule('*/10 * * * * *', async () => {
const userName = process.env.REDIS_USERNAME;
createBankTransaction(userName);
//...
});
balanceAfter
value is recorded in a TimeSeries with the key balance_ts
for every transaction.fromAccountName
member within the sorted set bigspenders
is incremented by the transaction amount. Note that this amount can be positive or negative.let balance = 100000.0;
const BALANCE_TS = 'balance_ts';
const SORTED_SET_KEY = 'bigspenders';
export const createBankTransaction = async () => {
//to create random bank transaction
let vendorsList = source.source; //app/transactions/transaction_sources.js
const random = Math.floor(Math.random() * 9999999999);
const vendor = vendorsList[random % vendorsList.length]; //random vendor from the list
const amount = createTransactionAmount(vendor.fromAccountName, random);
const transaction = {
id: random * random,
fromAccount: Math.floor((random / 2) * 3).toString(),
fromAccountName: vendor.fromAccountName,
toAccount: '1580783161',
toAccountName: 'bob',
amount: amount,
description: vendor.description,
transactionDate: new Date(),
transactionType: vendor.type,
balanceAfter: balance,
};
//redis json feature
const bankTransaction = await bankTransactionRepository.save(transaction);
console.log('Created bankTransaction!');
// ...
};
const createTransactionAmount = (vendor, random) => {
let amount = createAmount(); //random amount
balance += amount;
balance = parseFloat(balance.toFixed(2));
//redis time series feature
redis.ts.add(BALANCE_TS, '*', balance, { DUPLICATE_POLICY: 'first' });
//redis sorted set as secondary index
redis.zIncrBy(SORTED_SET_KEY, amount * -1, vendor);
return amount;
};
Sample bankTransaction data view using RedisInsight
Download RedisInsight to view your Redis data or to play with raw Redis commands in the workbench.
Dashboard widget
API endpoint
Endpoint | /transaction/balance |
Code location | /routers/transaction-router.js |
Parameters | none |
Return value | [{x: timestamp, y: value}, ...] |
The balance endpoint leverages Time Series, It returns the range of all values from the time series object balance_ts
. The resulting range is converted to an array of objects with each object containing an x
property containing the timestamp and a y
property containing the associated value. This endpoint supplies the time series chart with coordinates to plot a visualization of the balance over time.
const BALANCE_TS = 'balance_ts';
/* fetch transactions up to sometime ago */
transactionRouter.get('/balance', async (req, res) => {
//time series range
const balance = await redis.ts.range(
BALANCE_TS,
Date.now() - 1000 * 60 * 5, //from
Date.now(), //to
);
let balancePayload = balance.map((entry) => {
return {
x: entry.timestamp,
y: entry.value,
};
});
res.send(balancePayload);
});
Dashboard widget
API end point
Endpoint | /transaction//biggestspenders |
Code Location | /routers/transaction-router.js |
Parameters | none |
Return value | {labels:[...], series:[...] } |
The biggest spenders endpoint leverages sorted sets as a secondary index, It retrieves all members of the sorted set bigspenders
that have scores greater than zero. The top five or fewer are returned to provide the UI pie chart with data. The labels array contains the names of the biggest spenders and the series array contains the numeric values associated with each member name.
const SORTED_SET_KEY = 'bigspenders';
/* fetch top 5 biggest spenders */
transactionRouter.get('/biggestspenders', async (req, res) => {
const range = await redis.zRangeByScoreWithScores(
SORTED_SET_KEY,
0,
Infinity,
);
let series = [];
let labels = [];
range.slice(0, 5).forEach((spender) => {
series.push(parseFloat(spender.score.toFixed(2)));
labels.push(spender.value);
});
res.send({ series, labels });
});
Dashboard widget
API end point
Endpoint | /transaction/search |
Code Location | /routers/transaction-router.js |
Query Parameters | term |
Return value | array of results matching term |
The search endpoint leverages Search and Query, It receives a term
query parameter from the UI. A Redis om Node query for the fields description
, fromAccountName
, and accountType
will trigger and return results.
transactionRouter.get('/search', async (req, res) => {
const term = req.query.term;
let results;
if (term.length >= 3) {
results = await bankRepo
.search()
.where('description')
.matches(term)
.or('fromAccountName')
.matches(term)
.or('transactionType')
.equals(term)
.return.all({ pageSize: 1000 });
}
res.send(results);
});
Dashboard widget
API end point
Endpoint | /transaction/transactions |
Code Location | /routers/transaction-router.js |
Parameters | none |
Return value | array of results |
Even the transactions endpoint leverages Search and Query. A Redis om Node query will trigger and return ten most recent transactions.
/* return ten most recent transactions */
transactionRouter.get('/transactions', async (req, res) => {
const transactions = await bankRepo
.search()
.sortBy('transactionDate', 'DESC')
.return.all({ pageSize: 10 });
res.send(transactions.slice(0, 10));
});
Hopefully, this tutorial has helped you visualize how to use Redis for account dashboard, specifically in the context of mobile banking. For additional resources related to this topic, check out the links below: