Feat: save cash balance notifications in DB

Feat: add "detail" row in notifications table migration

This makes searching for specific notifications in the
code like cashbox number easier because we don't need
to scrub the notification message column anymore to search
for notifications relating the cashbox 1 for example.

Feat: clear notifications on cash cassette balance update
This commit is contained in:
Cesar 2020-12-10 11:49:01 +00:00 committed by Josh Harvey
parent 2ced230020
commit 196a05549f
5 changed files with 64 additions and 6 deletions

View file

@ -9,6 +9,8 @@ const helper = require('./cash-out-helper')
const cashOutActions = require('./cash-out-actions')
const cashOutLow = require('./cash-out-low')
const notifier = require("../notifier/index")
const toObj = helper.toObj
module.exports = {atomic}
@ -122,8 +124,10 @@ function updateCassettes (t, tx) {
tx.deviceId
]
return t.one(sql, values)
.then(r => socket.emit(_.assign(r, {op: 'cassetteUpdate', deviceId: tx.deviceId})))
return t.one(sql, values).then(r => {
notifier.cashCassettesNotify(r, tx.deviceId)
return socket.emit(_.assign(r, {op: 'cassetteUpdate', deviceId: tx.deviceId}))
})
}
function wasJustAuthorized (oldTx, newTx, isZeroConf) {

View file

@ -99,7 +99,10 @@ function renameMachine (rec) {
}
function resetCashOutBills (rec) {
const sql = 'update devices set cassette1=$1, cassette2=$2 where device_id=$3'
const sql = `
update devices set cassette1=$1, cassette2=$2 where device_id=$3;
update notifications set read = 't' where device_id = $3 AND type = 'fiatBalance' AND read = 'f';
`
return db.none(sql, [rec.cassettes[0], rec.cassettes[1], rec.deviceId])
}

View file

@ -143,7 +143,7 @@ async function transactionNotify (tx, rec) {
const isCashOut = tx.direction === 'cashOut'
// high value tx on database
if(highValueTx) {
if(highValueTx && tx.direction === 'cashIn' || highValueTx && tx.direction === 'cashOut' && rec.isRedemption) {
queries.addHighValueTx(tx)
}
@ -205,10 +205,40 @@ async function sendTransactionMessage(rec, isHighValueTx) {
return Promise.all(promises)
}
const cashCassettesNotify = (cassettes, deviceId) => {
settingsLoader.loadLatest()
.then(settings =>
[
configManager.getNotifications(null, deviceId, settings.config),
configManager.getCashOut(deviceId,settings.config).active
])
.then(([notifications, cashOutEnabled]) => {
const cassette1Count = cassettes.cassette1
const cassette2Count = cassettes.cassette2
const cassette1Threshold = notifications.fiatBalanceCassette1
const cassette2Threshold = notifications.fiatBalanceCassette2
if(cashOutEnabled) {
// we only want to add this notification if there isn't one already set and unread in the database
Promise.all([queries.getUnreadCassetteNotifications(1), queries.getUnreadCassetteNotifications(2)]).then(res => {
if(res[0].length === 0 && cassette1Count < cassette1Threshold) {
console.log("Adding fiatBalance alert for cashbox 1 in database - count & threshold: ", cassette1Count, cassette1Threshold )
queries.addCashCassetteWarning(1, deviceId)
}
if(res[1].length === 0 && cassette2Count < cassette2Threshold) {
console.log("Adding fiatBalance alert for cashbox 2 in database - count & threshold: ", cassette2Count, cassette2Threshold )
queries.addCashCassetteWarning(2, deviceId)
}
})
}
})
}
module.exports = {
transactionNotify,
checkNotification,
checkPings,
checkStuckScreen,
sendRedemptionMessage
sendRedemptionMessage,
cashCassettesNotify
}

View file

@ -2,6 +2,15 @@ const dbm = require('../postgresql_interface')
const db = require('../db')
const { v4: uuidv4 } = require('uuid')
// types of notifications able to be inserted into db:
/*
highValueTransaction - for transactions of value higher than threshold
fiatBalance - when the number of notes in cash cassettes falls below threshold
cryptoBalance - when ammount of crypto balance in fiat falls below or above low/high threshold
compliance - notifications related to warnings triggered by compliance settings
error - notifications related to errors
*/
const addHighValueTx = (tx) => {
const sql = `INSERT INTO notifications (id, type, device_id, message, created) values($1, $2, $3, $4, CURRENT_TIMESTAMP)`
const direction = tx.direction === "cashOut" ? 'cash-out' : 'cash-in'
@ -9,4 +18,15 @@ const addHighValueTx = (tx) => {
return db.oneOrNone(sql, [uuidv4(), 'highValueTransaction', tx.deviceId, message])
}
module.exports = { machineEvents: dbm.machineEvents, addHighValueTx }
const addCashCassetteWarning = (cassetteNumber, deviceId) => {
const sql = `INSERT INTO notifications (id, type, detail, device_id, message, created) values($1, $2, $3, $4, $5, CURRENT_TIMESTAMP)`
const message = `Cash-out cassette ${cassetteNumber} almost empty!`
return db.oneOrNone(sql, [uuidv4(), 'fiatBalance', cassetteNumber, deviceId, message])
}
const getUnreadCassetteNotifications = (cassetteNumber) => {
const sql = `SELECT * FROM notifications WHERE read = 'f' AND TYPE = 'fiatBalance' AND detail = '$1'`
return db.any(sql, [cassetteNumber])
}
module.exports = { machineEvents: dbm.machineEvents, addHighValueTx, addCashCassetteWarning, getUnreadCassetteNotifications }

View file

@ -21,6 +21,7 @@ exports.up = function (next) {
CREATE TABLE IF NOT EXISTS "notifications" (
"id" uuid NOT NULL PRIMARY KEY,
"type" notification_type NOT NULL,
"detail" TEXT,
"device_id" TEXT NOT NULL,
"message" TEXT NOT NULL,
"created" time with time zone NOT NULL,