refactor: use recyclers instead of stackers
This commit is contained in:
parent
dc52cf4414
commit
21b88f182e
37 changed files with 2868 additions and 9599 deletions
|
|
@ -50,17 +50,17 @@ function insertNewBills (t, billRows, machineTx) {
|
|||
const columns = ['id', 'fiat', 'fiat_code', 'crypto_code', 'cash_in_fee', 'cash_in_txs_id', 'device_time', 'destination_unit']
|
||||
const sql = pgp.helpers.insert(dbBills, columns, 'bills')
|
||||
const deviceID = machineTx.deviceId
|
||||
const sql2 = `update devices set stacker1f = stacker1f + $2, stacker1r = stacker1r + $3, stacker2f = stacker2f + $4, stacker2r = stacker2r + $5, stacker3f = stacker3f + $6, stacker3r = stacker3r + $7
|
||||
const sql2 = `update devices set recycler1 = recycler1 + $2, recycler2 = recycler2 + $3, recycler3 = recycler3 + $4, recycler4 = recycler4 + $5, recycler5 = recycler5 + $6, recycler6 = recycler6 + $7
|
||||
where device_id = $1`
|
||||
|
||||
return t.none(sql2, [
|
||||
deviceID,
|
||||
getBillsByDestination('stacker1f').length,
|
||||
getBillsByDestination('stacker1r').length,
|
||||
getBillsByDestination('stacker2f').length,
|
||||
getBillsByDestination('stacker2r').length,
|
||||
getBillsByDestination('stacker3f').length,
|
||||
getBillsByDestination('stacker3r').length
|
||||
getBillsByDestination('recycler1').length,
|
||||
getBillsByDestination('recycler2').length,
|
||||
getBillsByDestination('recycler3').length,
|
||||
getBillsByDestination('recycler4').length,
|
||||
getBillsByDestination('recycler5').length,
|
||||
getBillsByDestination('recycler6').length
|
||||
])
|
||||
.then(() => {
|
||||
return t.none(sql)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ function mapDispense (tx) {
|
|||
const res = {}
|
||||
|
||||
_.forEach(it => {
|
||||
const suffix = bills[it].name.replace(/cassette|stacker/gi, '')
|
||||
const suffix = _.snakeCase(bills[it].name.replace(/cassette/gi, ''))
|
||||
res[`provisioned_${suffix}`] = bills[it].provisioned
|
||||
res[`denomination_${suffix}`] = bills[it].denomination
|
||||
res[`dispensed_${suffix}`] = bills[it].dispensed
|
||||
|
|
|
|||
|
|
@ -18,31 +18,33 @@ case
|
|||
end`
|
||||
|
||||
const MAX_CASSETTES = 4
|
||||
const MAX_STACKERS = 3
|
||||
const MAX_RECYCLERS = 6
|
||||
|
||||
const BILL_FIELDS = [
|
||||
'denomination1',
|
||||
'denomination2',
|
||||
'denomination3',
|
||||
'denomination4',
|
||||
'denomination1f',
|
||||
'denomination1r',
|
||||
'denomination2f',
|
||||
'denomination2r',
|
||||
'denomination3f',
|
||||
'denomination3r',
|
||||
'provisioned1',
|
||||
'provisioned2',
|
||||
'provisioned3',
|
||||
'provisioned4',
|
||||
'provisioned1f',
|
||||
'provisioned1r',
|
||||
'provisioned2f',
|
||||
'provisioned2r',
|
||||
'provisioned3f',
|
||||
'provisioned3r'
|
||||
const SNAKE_CASE_BILL_FIELDS = [
|
||||
'denomination_1',
|
||||
'denomination_2',
|
||||
'denomination_3',
|
||||
'denomination_4',
|
||||
'denomination_recycler_1',
|
||||
'denomination_recycler_2',
|
||||
'denomination_recycler_3',
|
||||
'denomination_recycler_4',
|
||||
'denomination_recycler_5',
|
||||
'denomination_recycler_6',
|
||||
'provisioned_1',
|
||||
'provisioned_2',
|
||||
'provisioned_3',
|
||||
'provisioned_4',
|
||||
'provisioned_recycler_1',
|
||||
'provisioned_recycler_2',
|
||||
'provisioned_recycler_3',
|
||||
'provisioned_recycler_4',
|
||||
'provisioned_recycler_5',
|
||||
'provisioned_recycler_6'
|
||||
]
|
||||
|
||||
const BILL_FIELDS = _.map(_.camelCase, BILL_FIELDS)
|
||||
|
||||
module.exports = { redeemableTxs, toObj, toDb, REDEEMABLE_AGE, CASH_OUT_TRANSACTION_STATES }
|
||||
|
||||
const mapValuesWithKey = _.mapValues.convert({cap: false})
|
||||
|
|
@ -69,19 +71,17 @@ function convertBigNumFields (obj) {
|
|||
}
|
||||
|
||||
function convertField (key) {
|
||||
return _.includes('denomination', key) || _.includes('provisioned', key) ? key : _.snakeCase(key)
|
||||
return _.snakeCase(key)
|
||||
}
|
||||
|
||||
function addDbBills (tx) {
|
||||
const bills = tx.bills
|
||||
if (_.isEmpty(bills)) return tx
|
||||
|
||||
const billFields = _.map(it => _.replace(/(denomination|provisioned)/g, '$1_')(it), BILL_FIELDS)
|
||||
|
||||
const billsObj = _.flow(
|
||||
_.reduce(
|
||||
(acc, value) => {
|
||||
const suffix = value.name.replace(/cassette|stacker/gi, '')
|
||||
const suffix = _.snakeCase(value.name.replace(/cassette/gi, ''))
|
||||
return {
|
||||
...acc,
|
||||
[`provisioned_${suffix}`]: value.provisioned,
|
||||
|
|
@ -96,7 +96,7 @@ function addDbBills (tx) {
|
|||
return _.assign({ [value]: 0 })(acc)
|
||||
},
|
||||
{}
|
||||
)(_.difference(billFields, _.keys(it)))
|
||||
)(_.difference(SNAKE_CASE_BILL_FIELDS, _.keys(it)))
|
||||
return _.assign(missingKeys, it)
|
||||
}
|
||||
)(bills)
|
||||
|
|
@ -118,7 +118,7 @@ function toObj (row) {
|
|||
let newObj = {}
|
||||
|
||||
keys.forEach(key => {
|
||||
const objKey = key.match(/denomination|provisioned/g) ? key.replace(/_/g, '') : _.camelCase(key)
|
||||
const objKey = _.camelCase(key)
|
||||
if (key === 'received_crypto_atoms' && row[key]) {
|
||||
newObj[objKey] = new BN(row[key])
|
||||
return
|
||||
|
|
@ -138,16 +138,7 @@ function toObj (row) {
|
|||
|
||||
const billFieldsArr = _.concat(
|
||||
_.map(it => ({ name: `cassette${it + 1}`, denomination: newObj[`denomination${it + 1}`], provisioned: newObj[`provisioned${it + 1}`] }))(_.range(0, MAX_CASSETTES)),
|
||||
_.reduce(
|
||||
(acc, value) => {
|
||||
acc.push(
|
||||
{ name: `stacker${value + 1}f`, denomination: newObj[`denomination${value + 1}f`], provisioned: newObj[`provisioned${value + 1}f`] },
|
||||
{ name: `stacker${value + 1}r`, denomination: newObj[`denomination${value + 1}r`], provisioned: newObj[`provisioned${value + 1}r`] }
|
||||
)
|
||||
return acc
|
||||
},
|
||||
[]
|
||||
)(_.range(0, MAX_STACKERS))
|
||||
_.map(it => ({ name: `recycler${it + 1}`, denomination: newObj[`denomination_recycler${it + 1}`], provisioned: newObj[`provisioned_recycler${it + 1}`] }))(_.range(0, MAX_RECYCLERS)),
|
||||
)
|
||||
|
||||
// There can't be bills with denomination === 0.
|
||||
|
|
@ -164,7 +155,9 @@ function redeemableTxs (deviceId) {
|
|||
and dispense=$3
|
||||
and (
|
||||
provisioned_1 is not null or provisioned_2 is not null or provisioned_3 is not null or provisioned_4 is not null or
|
||||
provisioned_1f is not null or provisioned_1r is not null or provisioned_2f is not null or provisioned_2r is not null or provisioned_3f is not null or provisioned_3r is not null
|
||||
provisioned_recycler_1 is not null or provisioned_recycler_2 is not null or
|
||||
provisioned_recycler_3 is not null or provisioned_recycler_4 is not null or
|
||||
provisioned_recycler_5 is not null or provisioned_recycler_6 is not null
|
||||
)
|
||||
and extract(epoch from (now() - greatest(created, confirmed_at))) < $4`
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ function postProcess (txVector, justAuthorized, pi) {
|
|||
if ((newTx.dispense && !oldTx.dispense) || (newTx.redeem && !oldTx.redeem)) {
|
||||
return pi.buildAvailableUnits(newTx.id)
|
||||
.then(_units => {
|
||||
const units = _.concat(_units.cassettes, _units.stackers)
|
||||
const units = _.concat(_units.cassettes, _units.recyclers)
|
||||
logger.silly('Computing bills to dispense:', {
|
||||
txId: newTx.id,
|
||||
units: units,
|
||||
|
|
@ -74,7 +74,7 @@ function postProcess (txVector, justAuthorized, pi) {
|
|||
const rec = {}
|
||||
|
||||
_.forEach(it => {
|
||||
const suffix = bills[it].name.replace(/cassette|stacker/gi, '')
|
||||
const suffix = _.snakeCase(bills[it].name.replace(/cassette/gi, ''))
|
||||
rec[`provisioned_${suffix}`] = bills[it].provisioned
|
||||
rec[`denomination_${suffix}`] = bills[it].denomination
|
||||
}, _.times(_.identity(), _.size(bills)))
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ function createCashboxBatch (deviceId, cashboxCount) {
|
|||
|
||||
function updateMachineWithBatch (machineContext, oldCashboxCount) {
|
||||
const cashUnits = machineContext.cashUnits
|
||||
const isValidContext = _.has(['deviceId', 'cashUnits'], machineContext) && _.has(['cashbox', 'cassette1', 'cassette2', 'cassette3', 'cassette4', 'stacker1f', 'stacker1r', 'stacker2f', 'stacker2r', 'stacker3f', 'stacker3r'], cashUnits)
|
||||
const cashUnitNames = ['cashbox', 'cassette1', 'cassette2', 'cassette3', 'cassette4', 'recycler1', 'recycler2', 'recycler3', 'recycler4', 'recycler5', 'recycler6']
|
||||
const isValidContext = _.has(['deviceId', 'cashUnits'], machineContext) && _.has(cashUnitNames, cashUnits)
|
||||
const cassettes = _.filter(it => !_.isNil(it))([cashUnits.cassette1, cashUnits.cassette2, cashUnits.cassette3, cashUnits.cassette4])
|
||||
const isCassetteAmountWithinRange = _.inRange(constants.CASH_OUT_MINIMUM_AMOUNT_OF_CASSETTES, constants.CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES + 1, _.size(cassettes))
|
||||
if (!isValidContext && !isCassetteAmountWithinRange)
|
||||
|
|
@ -48,17 +49,17 @@ function updateMachineWithBatch (machineContext, oldCashboxCount) {
|
|||
bills.cashbox_batch_id IS NULL`, [batchId, deviceId])
|
||||
const q3 = t.none(`UPDATE empty_unit_bills SET cashbox_batch_id=$1
|
||||
WHERE empty_unit_bills.device_id = $2 AND empty_unit_bills.cashbox_batch_id IS NULL`, [batchId, deviceId])
|
||||
const q4 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, stacker1f=$5, stacker1r=$6, stacker2f=$7, stacker2r=$8, stacker3f=$9, stacker3r=$10 WHERE device_id=$11`, [
|
||||
const q4 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler3=$8, recycler4=$9, recycler5=$10 WHERE device_id=$11`, [
|
||||
cashUnits.cassette1,
|
||||
cashUnits.cassette2,
|
||||
cashUnits.cassette3,
|
||||
cashUnits.cassette4,
|
||||
cashUnits.stacker1f,
|
||||
cashUnits.stacker1r,
|
||||
cashUnits.stacker2f,
|
||||
cashUnits.stacker2r,
|
||||
cashUnits.stacker3f,
|
||||
cashUnits.stacker3r,
|
||||
cashUnits.recycler1,
|
||||
cashUnits.recycler2,
|
||||
cashUnits.recycler3,
|
||||
cashUnits.recycler4,
|
||||
cashUnits.recycler5,
|
||||
cashUnits.recycler6,
|
||||
machineContext.deviceId
|
||||
])
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const CASH_UNIT_CAPACITY = {
|
|||
},
|
||||
aveiro: {
|
||||
cashbox: 1500,
|
||||
stacker: 60,
|
||||
recycler: 60,
|
||||
cassette: 500
|
||||
},
|
||||
tejo: {
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ const staticConfig = ({ currentConfigVersion, deviceId, deviceName, pq, settings
|
|||
operatorInfo,
|
||||
receiptInfo,
|
||||
twoWayMode,
|
||||
{ numberOfCassettes, numberOfStackers },
|
||||
{ numberOfCassettes, numberOfRecyclers },
|
||||
]) =>
|
||||
(currentConfigVersion && currentConfigVersion >= staticConf.configVersion) ?
|
||||
null :
|
||||
|
|
@ -142,7 +142,7 @@ const staticConfig = ({ currentConfigVersion, deviceId, deviceName, pq, settings
|
|||
languages: localeInfo.languages,
|
||||
fiatCode: localeInfo.fiatCurrency
|
||||
},
|
||||
machineInfo: { deviceId, deviceName, numberOfCassettes, numberOfStackers },
|
||||
machineInfo: { deviceId, deviceName, numberOfCassettes, numberOfRecyclers },
|
||||
twoWayMode,
|
||||
speedtestFiles,
|
||||
urlsToPing,
|
||||
|
|
@ -171,24 +171,24 @@ const dynamicConfig = ({ deviceId, operatorId, pid, pq, settings, }) => {
|
|||
)(cassettes) :
|
||||
null
|
||||
|
||||
const massageStackers = stackers =>
|
||||
stackers ?
|
||||
const massageRecyclers = recyclers =>
|
||||
recyclers ?
|
||||
_.flow(
|
||||
stackers => _.set('physical', _.get('stackers', stackers), stackers),
|
||||
stackers => _.set('virtual', _.get('virtualStackers', stackers), stackers),
|
||||
_.unset('stackers'),
|
||||
_.unset('virtualStackers')
|
||||
)(stackers) :
|
||||
recyclers => _.set('physical', _.get('recyclers', recyclers), recyclers),
|
||||
recyclers => _.set('virtual', _.get('virtualRecyclers', recyclers), recyclers),
|
||||
_.unset('recyclers'),
|
||||
_.unset('virtualRecyclers')
|
||||
)(recyclers) :
|
||||
null
|
||||
|
||||
state.pids = _.update(operatorId, _.set(deviceId, { pid, ts: Date.now() }), state.pids)
|
||||
|
||||
const res = _.flow(
|
||||
_.pick(['areThereAvailablePromoCodes', 'balances', 'cassettes', 'stackers', 'coins', 'rates']),
|
||||
_.pick(['areThereAvailablePromoCodes', 'balances', 'cassettes', 'recyclers', 'coins', 'rates']),
|
||||
|
||||
_.update('cassettes', massageCassettes),
|
||||
|
||||
_.update('stackers', massageStackers),
|
||||
_.update('recyclers', massageRecyclers),
|
||||
|
||||
/* [{ cryptoCode, rates }, ...] => [[cryptoCode, rates], ...] */
|
||||
_.update('coins', _.map(({ cryptoCode, rates }) => [cryptoCode, rates])),
|
||||
|
|
@ -201,10 +201,10 @@ const dynamicConfig = ({ deviceId, operatorId, pid, pq, settings, }) => {
|
|||
|
||||
/* Group the separate objects by cryptoCode */
|
||||
/* { balances, coins, rates } => { cryptoCode: { balance, ask, bid, cashIn, cashOut }, ... } */
|
||||
({ areThereAvailablePromoCodes, balances, cassettes, stackers, coins, rates }) => ({
|
||||
({ areThereAvailablePromoCodes, balances, cassettes, recyclers, coins, rates }) => ({
|
||||
areThereAvailablePromoCodes,
|
||||
cassettes,
|
||||
stackers,
|
||||
recyclers,
|
||||
coins: _.flow(
|
||||
_.reduce(
|
||||
(ret, [cryptoCode, obj]) => _.update(cryptoCode, _.assign(obj), ret),
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ type MachineInfo {
|
|||
deviceId: String!
|
||||
deviceName: String
|
||||
numberOfCassettes: Int
|
||||
numberOfStackers: Int
|
||||
numberOfRecyclers: Int
|
||||
}
|
||||
|
||||
type ReceiptInfo {
|
||||
|
|
@ -173,7 +173,7 @@ type PhysicalCassette {
|
|||
count: Int!
|
||||
}
|
||||
|
||||
type PhysicalStacker {
|
||||
type PhysicalRecycler {
|
||||
name: String!
|
||||
number: Int!
|
||||
denomination: Int!
|
||||
|
|
@ -185,15 +185,15 @@ type Cassettes {
|
|||
virtual: [Int!]!
|
||||
}
|
||||
|
||||
type Stackers {
|
||||
physical: [PhysicalStacker!]!
|
||||
type Recyclers {
|
||||
physical: [PhysicalRecycler!]!
|
||||
virtual: [Int!]!
|
||||
}
|
||||
|
||||
type DynamicConfig {
|
||||
areThereAvailablePromoCodes: Boolean!
|
||||
cassettes: Cassettes
|
||||
stackers: Stackers
|
||||
recyclers: Recyclers
|
||||
coins: [DynamicCoinValues!]!
|
||||
reboot: Boolean!
|
||||
shutdown: Boolean!
|
||||
|
|
|
|||
|
|
@ -42,15 +42,15 @@ function toMachineObject (r) {
|
|||
cassette2: r.cassette2,
|
||||
cassette3: r.cassette3,
|
||||
cassette4: r.cassette4,
|
||||
stacker1f: r.stacker1f,
|
||||
stacker1r: r.stacker1r,
|
||||
stacker2f: r.stacker2f,
|
||||
stacker2r: r.stacker2r,
|
||||
stacker3f: r.stacker3f,
|
||||
stacker3r: r.stacker3r
|
||||
recycler1: r.recycler1,
|
||||
recycler2: r.recycler2,
|
||||
recycler3: r.recycler3,
|
||||
recycler4: r.recycler4,
|
||||
recycler5: r.recycler5,
|
||||
recycler6: r.recycler6
|
||||
},
|
||||
numberOfCassettes: r.number_of_cassettes,
|
||||
numberOfStackers: r.number_of_stackers,
|
||||
numberOfRecyclers: r.number_of_recyclers,
|
||||
version: r.version,
|
||||
model: r.model,
|
||||
pairedAt: new Date(r.created),
|
||||
|
|
@ -172,19 +172,19 @@ function renameMachine (rec) {
|
|||
|
||||
function resetCashOutBills (rec) {
|
||||
const detailB = notifierUtils.buildDetail({ deviceId: rec.deviceId })
|
||||
const { cassette1, cassette2, cassette3, cassette4, stacker1f, stacker1r, stacker2f, stacker2r, stacker3f, stacker3r } = rec.cashUnits
|
||||
const sql = `UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, stacker1f=$5, stacker1r=$6, stacker2f=$7, stacker2r=$8, stacker3f=$9, stacker3r=$10 WHERE device_id=$11;`
|
||||
return db.none(sql, [cassette1, cassette2, cassette3, cassette4, stacker1f, stacker1r, stacker2f, stacker2r, stacker3f, stacker3r, rec.deviceId]).then(() => notifierQueries.invalidateNotification(detailB, 'fiatBalance'))
|
||||
const { cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6 } = rec.cashUnits
|
||||
const sql = `UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler4=$8, recycler5=$9, recycler6=$10 WHERE device_id=$11;`
|
||||
return db.none(sql, [cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6, rec.deviceId]).then(() => notifierQueries.invalidateNotification(detailB, 'fiatBalance'))
|
||||
}
|
||||
|
||||
function setCassetteBills (rec) {
|
||||
const { cashbox, cassette1, cassette2, cassette3, cassette4, stacker1f, stacker1r, stacker2f, stacker2r, stacker3f, stacker3r } = rec.cashUnits
|
||||
const { cashbox, cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6 } = rec.cashUnits
|
||||
return getMachine(rec.deviceId)
|
||||
.then(machine => {
|
||||
const oldCashboxCount = machine?.cashUnits?.cashbox
|
||||
if (_.isNil(oldCashboxCount) || cashbox === oldCashboxCount) {
|
||||
const sql = 'UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, stacker1f=$5, stacker1r=$6, stacker2f=$7, stacker2r=$8, stacker3f=$9, stacker3r=$10 WHERE device_id=$11'
|
||||
return db.none(sql, [cassette1, cassette2, cassette3, cassette4, stacker1f, stacker1r, stacker2f, stacker2r, stacker3f, stacker3r, rec.deviceId])
|
||||
const sql = 'UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler4=$8, recycler5=$9, recycler6=$10 WHERE device_id=$11'
|
||||
return db.none(sql, [cassette1, cassette2, cassette3, cassette4, recycler1, recycler2, recycler3, recycler4, recycler5, recycler6, rec.deviceId])
|
||||
}
|
||||
|
||||
return batching.updateMachineWithBatch({ ...rec, oldCashboxValue: oldCashboxCount })
|
||||
|
|
@ -199,7 +199,7 @@ function emptyMachineUnits ({ deviceId, newUnits, fiatCode }) {
|
|||
(acc, value) => ({
|
||||
...acc,
|
||||
[value]: {
|
||||
operationName: `cash-${_.replace(/(cassette|stacker)/g, '$1-')(value)}-empty`,
|
||||
operationName: `cash-${_.replace(/(cassette|recycler)/g, '$1-')(value)}-empty`,
|
||||
delta: newUnits[value] - machine.cashUnits[value],
|
||||
denomination: value !== 'cashbox' ? cashoutSettings[value] : null
|
||||
}
|
||||
|
|
@ -224,7 +224,7 @@ function emptyMachineUnits ({ deviceId, newUnits, fiatCode }) {
|
|||
fiat_code: fiatCode,
|
||||
device_id: deviceId
|
||||
// TODO: Uncomment this if we decide to keep track of bills across multiple operations. For now, we'll just create the emptying operations for each unit affected, but not relate these events with individual bills and just use the field for the cashbox batch event
|
||||
// cash_unit_operation_id: _.find(it => it.operation_type === `cash-${_.replace(/(cassette|stacker)/g, '$1-')(value)}-empty`, operationsToCreate).id
|
||||
// cash_unit_operation_id: _.find(it => it.operation_type === `cash-${_.replace(/(cassette|recycler)/g, '$1-')(value)}-empty`, operationsToCreate).id
|
||||
}), Math.abs(unit.delta)))
|
||||
},
|
||||
[],
|
||||
|
|
@ -241,17 +241,17 @@ function emptyMachineUnits ({ deviceId, newUnits, fiatCode }) {
|
|||
const q1= t.none(pgp.helpers.insert(operationsToCreate, q1Cols, 'cash_unit_operation'))
|
||||
const q2Cols = ['id', 'fiat', 'fiat_code', 'device_id']
|
||||
const q2 = t.none(pgp.helpers.insert(billArr, q2Cols, 'empty_unit_bills'))
|
||||
const q3 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, stacker1f=$5, stacker1r=$6, stacker2f=$7, stacker2r=$8, stacker3f=$9, stacker3r=$10 WHERE device_id=$11`, [
|
||||
const q3 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler4=$8, recycler5=$9, recycler6=$10 WHERE device_id=$11`, [
|
||||
_.defaultTo(machine.cashUnits.cassette1, newUnits.cassette1),
|
||||
_.defaultTo(machine.cashUnits.cassette2, newUnits.cassette2),
|
||||
_.defaultTo(machine.cashUnits.cassette3, newUnits.cassette3),
|
||||
_.defaultTo(machine.cashUnits.cassette4, newUnits.cassette4),
|
||||
_.defaultTo(machine.cashUnits.stacker1f, newUnits.stacker1f),
|
||||
_.defaultTo(machine.cashUnits.stacker1r, newUnits.stacker1r),
|
||||
_.defaultTo(machine.cashUnits.stacker2f, newUnits.stacker2f),
|
||||
_.defaultTo(machine.cashUnits.stacker2r, newUnits.stacker2r),
|
||||
_.defaultTo(machine.cashUnits.stacker3f, newUnits.stacker3f),
|
||||
_.defaultTo(machine.cashUnits.stacker3r, newUnits.stacker3r),
|
||||
_.defaultTo(machine.cashUnits.recycler1, newUnits.recycler1),
|
||||
_.defaultTo(machine.cashUnits.recycler2, newUnits.recycler2),
|
||||
_.defaultTo(machine.cashUnits.recycler3, newUnits.recycler3),
|
||||
_.defaultTo(machine.cashUnits.recycler4, newUnits.recycler4),
|
||||
_.defaultTo(machine.cashUnits.recycler5, newUnits.recycler5),
|
||||
_.defaultTo(machine.cashUnits.recycler6, newUnits.recycler6),
|
||||
deviceId
|
||||
])
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ function refillMachineUnits ({ deviceId, newUnits }) {
|
|||
(acc, value) => ({
|
||||
...acc,
|
||||
[value]: {
|
||||
operationName: `cash-${_.replace(/(stacker)/g, '$1-')(value)}-refill`,
|
||||
operationName: `cash-${_.replace(/(recycler)/g, '$1-')(value)}-refill`,
|
||||
delta: newUnits[value] - machine.cashUnits[value]
|
||||
}
|
||||
}),
|
||||
|
|
@ -290,17 +290,17 @@ function refillMachineUnits ({ deviceId, newUnits }) {
|
|||
return db.tx(t => {
|
||||
const q1Cols = ['id', 'device_id', 'operation_type']
|
||||
const q1= t.none(pgp.helpers.insert(operationsToCreate, q1Cols, 'cash_unit_operation'))
|
||||
const q2 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, stacker1f=$5, stacker1r=$6, stacker2f=$7, stacker2r=$8, stacker3f=$9, stacker3r=$10 WHERE device_id=$11`, [
|
||||
const q2 = t.none(`UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4, recycler1=$5, recycler2=$6, recycler3=$7, recycler4=$8, recycler5=$9, recycler6=$10 WHERE device_id=$11`, [
|
||||
_.defaultTo(machine.cashUnits.cassette1, newUnits.cassette1),
|
||||
_.defaultTo(machine.cashUnits.cassette2, newUnits.cassette2),
|
||||
_.defaultTo(machine.cashUnits.cassette3, newUnits.cassette3),
|
||||
_.defaultTo(machine.cashUnits.cassette4, newUnits.cassette4),
|
||||
_.defaultTo(machine.cashUnits.stacker1f, newUnits.stacker1f),
|
||||
_.defaultTo(machine.cashUnits.stacker1r, newUnits.stacker1r),
|
||||
_.defaultTo(machine.cashUnits.stacker2f, newUnits.stacker2f),
|
||||
_.defaultTo(machine.cashUnits.stacker2r, newUnits.stacker2r),
|
||||
_.defaultTo(machine.cashUnits.stacker3f, newUnits.stacker3f),
|
||||
_.defaultTo(machine.cashUnits.stacker3r, newUnits.stacker3r),
|
||||
_.defaultTo(machine.cashUnits.recycler1, newUnits.recycler1),
|
||||
_.defaultTo(machine.cashUnits.recycler2, newUnits.recycler2),
|
||||
_.defaultTo(machine.cashUnits.recycler3, newUnits.recycler3),
|
||||
_.defaultTo(machine.cashUnits.recycler4, newUnits.recycler4),
|
||||
_.defaultTo(machine.cashUnits.recycler5, newUnits.recycler5),
|
||||
_.defaultTo(machine.cashUnits.recycler6, newUnits.recycler6),
|
||||
deviceId
|
||||
])
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ function machineAction (type, value) {
|
|||
state.emptyUnit[operatorId] = { [deviceId]: pid }
|
||||
break
|
||||
case 'refillUnit':
|
||||
logger.debug(`Refilling stackers from machine '${deviceId}' from operator ${operatorId}`)
|
||||
logger.debug(`Refilling recyclers from machine '${deviceId}' from operator ${operatorId}`)
|
||||
state.refillUnit[operatorId] = { [deviceId]: pid }
|
||||
break
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const typeDef = gql`
|
|||
model: String
|
||||
cashUnits: CashUnits
|
||||
numberOfCassettes: Int
|
||||
numberOfStackers: Int
|
||||
numberOfRecyclers: Int
|
||||
statuses: [MachineStatus]
|
||||
latestEvent: MachineEvent
|
||||
downloadSpeed: String
|
||||
|
|
@ -30,12 +30,12 @@ const typeDef = gql`
|
|||
cassette2: Int
|
||||
cassette3: Int
|
||||
cassette4: Int
|
||||
stacker1f: Int
|
||||
stacker1r: Int
|
||||
stacker2f: Int
|
||||
stacker2r: Int
|
||||
stacker3f: Int
|
||||
stacker3r: Int
|
||||
recycler1: Int
|
||||
recycler2: Int
|
||||
recycler3: Int
|
||||
recycler4: Int
|
||||
recycler5: Int
|
||||
recycler6: Int
|
||||
}
|
||||
|
||||
input CashUnitsInput {
|
||||
|
|
@ -44,12 +44,12 @@ const typeDef = gql`
|
|||
cassette2: Int
|
||||
cassette3: Int
|
||||
cassette4: Int
|
||||
stacker1f: Int
|
||||
stacker1r: Int
|
||||
stacker2f: Int
|
||||
stacker2r: Int
|
||||
stacker3f: Int
|
||||
stacker3r: Int
|
||||
recycler1: Int
|
||||
recycler2: Int
|
||||
recycler3: Int
|
||||
recycler4: Int
|
||||
recycler5: Int
|
||||
recycler6: Int
|
||||
}
|
||||
|
||||
type UnpairedMachine {
|
||||
|
|
|
|||
|
|
@ -154,9 +154,9 @@ function advancedBatch (data) {
|
|||
'dispense', 'notified', 'redeem', 'phone', 'error',
|
||||
'created', 'confirmedAt', 'hdIndex', 'swept', 'timedout',
|
||||
'dispenseConfirmed', 'provisioned1', 'provisioned2', 'provisioned3', 'provisioned4',
|
||||
'provisioned1f', 'provisioned1r', 'provisioned2f', 'provisioned2r', 'provisioned3f', 'provisioned3r',
|
||||
'provisionedRecycler1', 'provisionedRecycler2', 'provisionedRecycler3', 'provisionedRecycler4', 'provisionedRecycler5', 'provisionedRecycler6',
|
||||
'denomination1', 'denomination2', 'denomination3', 'denomination4',
|
||||
'denomination1f', 'denomination1r', 'denomination2f', 'denomination2r', 'denomination3f', 'denomination3r',
|
||||
'denominationRecycler1', 'denominationRecycler2', 'denominationRecycler3', 'denominationRecycler4', 'denominationRecycler5', 'denominationRecycler6',
|
||||
'errorCode', 'customerId', 'txVersion', 'publishedAt', 'termsAccepted', 'layer2Address',
|
||||
'commissionPercentage', 'rawTickerPrice', 'receivedCryptoAtoms',
|
||||
'discount', 'txHash', 'customerPhone', 'customerIdCardDataNumber',
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const CA_PATH = process.env.CA_PATH
|
|||
// A machine on an older version (no multicassette code) could be paired with a server with multicassette code.
|
||||
// This makes sure that the server stores a default value
|
||||
const DEFAULT_NUMBER_OF_CASSETTES = 2
|
||||
const DEFAULT_NUMBER_OF_STACKERS = 0
|
||||
const DEFAULT_NUMBER_OF_RECYCLERS = 0
|
||||
|
||||
function pullToken (token) {
|
||||
const sql = `delete from pairing_tokens
|
||||
|
|
@ -37,16 +37,16 @@ function unpair (deviceId) {
|
|||
)
|
||||
}
|
||||
|
||||
function pair (token, deviceId, machineModel, numOfCassettes = DEFAULT_NUMBER_OF_CASSETTES, numOfStackers = DEFAULT_NUMBER_OF_STACKERS) {
|
||||
function pair (token, deviceId, machineModel, numOfCassettes = DEFAULT_NUMBER_OF_CASSETTES, numOfRecyclers = DEFAULT_NUMBER_OF_RECYCLERS) {
|
||||
return pullToken(token)
|
||||
.then(r => {
|
||||
if (r.expired) return false
|
||||
|
||||
const insertSql = `insert into devices (device_id, name, number_of_cassettes, number_of_stackers) values ($1, $2, $3, $4)
|
||||
const insertSql = `insert into devices (device_id, name, number_of_cassettes, number_of_recyclers) values ($1, $2, $3, $4)
|
||||
on conflict (device_id)
|
||||
do update set paired=TRUE, display=TRUE`
|
||||
|
||||
return db.none(insertSql, [deviceId, r.name, numOfCassettes, numOfStackers])
|
||||
return db.none(insertSql, [deviceId, r.name, numOfCassettes, numOfRecyclers])
|
||||
.then(() => true)
|
||||
})
|
||||
.catch(err => {
|
||||
|
|
|
|||
145
lib/plugins.js
145
lib/plugins.js
|
|
@ -147,42 +147,42 @@ function plugins (settings, deviceId) {
|
|||
return computedCassettes
|
||||
}
|
||||
|
||||
function computeAvailableStackers (stackers, redeemableTxs) {
|
||||
if (_.isEmpty(redeemableTxs)) return stackers
|
||||
function computeAvailableRecyclers (recyclers, redeemableTxs) {
|
||||
if (_.isEmpty(redeemableTxs)) return recyclers
|
||||
|
||||
const sumTxs = (sum, tx) => {
|
||||
// cash-out-helper sends 0 as fallback value, need to filter it out as there are no '0' denominations
|
||||
const bills = _.filter(it => _.includes('stacker', it.name) && it.denomination > 0, tx.bills)
|
||||
const bills = _.filter(it => _.includes('recycler', it.name) && it.denomination > 0, tx.bills)
|
||||
const sameDenominations = a => a[0]?.denomination === a[1]?.denomination
|
||||
|
||||
const doDenominationsMatch = _.every(sameDenominations, _.zip(stackers, bills))
|
||||
const doDenominationsMatch = _.every(sameDenominations, _.zip(recyclers, bills))
|
||||
|
||||
if (!doDenominationsMatch) {
|
||||
throw new Error('Denominations don\'t add up, stackers were changed.')
|
||||
throw new Error('Denominations don\'t add up, recyclers were changed.')
|
||||
}
|
||||
|
||||
return _.map(r => r[0] + r[1].provisioned, _.zip(sum, tx.bills))
|
||||
}
|
||||
|
||||
const provisioned = _.reduce(sumTxs, _.times(_.constant(0), _.size(stackers)), redeemableTxs)
|
||||
const zipped = _.zip(_.map('count', stackers), provisioned)
|
||||
const provisioned = _.reduce(sumTxs, _.times(_.constant(0), _.size(recyclers)), redeemableTxs)
|
||||
const zipped = _.zip(_.map('count', recyclers), provisioned)
|
||||
const counts = _.map(r => r[0] - r[1], zipped)
|
||||
|
||||
if (_.some(_.lt(_, 0), counts)) {
|
||||
throw new Error('Negative note count: %j', counts)
|
||||
}
|
||||
|
||||
const computedStackers = []
|
||||
const computedRecyclers = []
|
||||
_.forEach(it => {
|
||||
computedStackers.push({
|
||||
number: stackers[it].number,
|
||||
name: stackers[it].name,
|
||||
denomination: stackers[it].denomination,
|
||||
computedRecyclers.push({
|
||||
number: recyclers[it].number,
|
||||
name: recyclers[it].name,
|
||||
denomination: recyclers[it].denomination,
|
||||
count: counts[it]
|
||||
})
|
||||
}, _.times(_.identity(), _.size(stackers)))
|
||||
}, _.times(_.identity(), _.size(recyclers)))
|
||||
|
||||
return computedStackers
|
||||
return computedRecyclers
|
||||
}
|
||||
|
||||
function buildAvailableCassettes (excludeTxId) {
|
||||
|
|
@ -231,62 +231,57 @@ function plugins (settings, deviceId) {
|
|||
})
|
||||
}
|
||||
|
||||
function buildAvailableStackers (excludeTxId) {
|
||||
function buildAvailableRecyclers (excludeTxId) {
|
||||
const cashOutConfig = configManager.getCashOut(deviceId, settings.config)
|
||||
|
||||
if (!cashOutConfig.active) return Promise.resolve()
|
||||
|
||||
return Promise.all([dbm.stackerCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)])
|
||||
.then(([_stackers, _redeemableTxs]) => {
|
||||
return Promise.all([dbm.recyclerCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)])
|
||||
.then(([_recyclers, _redeemableTxs]) => {
|
||||
const redeemableTxs = _.reject(_.matchesProperty('id', excludeTxId), _redeemableTxs)
|
||||
|
||||
const denominations = []
|
||||
_.forEach(it => {
|
||||
denominations.push([cashOutConfig[`stacker${it + 1}f`], cashOutConfig[`stacker${it + 1}r`]])
|
||||
}, _.times(_.identity(), _stackers.numberOfStackers))
|
||||
|
||||
const virtualStackers = denominations.length ? [Math.max(..._.flatten(denominations)) * 2] : []
|
||||
|
||||
const counts = _stackers.counts
|
||||
_.forEach(it => {
|
||||
denominations.push(cashOutConfig[`recycler${it + 1}`])
|
||||
}, _.times(_.identity(), _recyclers.numberOfRecyclers))
|
||||
|
||||
const virtualRecyclers = denominations.length ? [Math.max(..._.flatten(denominations)) * 2] : []
|
||||
|
||||
const counts = _recyclers.counts
|
||||
|
||||
if (counts.length !== denominations.length) {
|
||||
throw new Error('Denominations and respective counts do not match!')
|
||||
}
|
||||
|
||||
const stackers = []
|
||||
const recyclers = []
|
||||
_.forEach(it => {
|
||||
stackers.push({
|
||||
number: 1 + it * 2,
|
||||
name: `stacker${it + 1}f`,
|
||||
denomination: parseInt(denominations[it][0], 10),
|
||||
count: parseInt(counts[it][0], 10)
|
||||
recyclers.push({
|
||||
number: it + 1,
|
||||
name: `recycler${it + 1}`,
|
||||
denomination: parseInt(denominations[it], 10),
|
||||
count: parseInt(counts[it], 10)
|
||||
})
|
||||
stackers.push({
|
||||
number: 2 + it * 2,
|
||||
name: `stacker${it + 1}r`,
|
||||
denomination: parseInt(denominations[it][1], 10),
|
||||
count: parseInt(counts[it][1], 10)
|
||||
})
|
||||
}, _.times(_.identity(), _stackers.numberOfStackers))
|
||||
}, _.times(_.identity(), _recyclers.numberOfRecyclers))
|
||||
|
||||
try {
|
||||
return {
|
||||
stackers: computeAvailableStackers(stackers, redeemableTxs),
|
||||
virtualStackers
|
||||
recyclers: computeAvailableRecyclers(recyclers, redeemableTxs),
|
||||
virtualRecyclers
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
return {
|
||||
stackers,
|
||||
virtualStackers
|
||||
recyclers,
|
||||
virtualRecyclers
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function buildAvailableUnits (excludeTxId) {
|
||||
return Promise.all([buildAvailableCassettes(excludeTxId), buildAvailableStackers(excludeTxId)])
|
||||
.then(([cassettes, stackers]) => ({ cassettes: cassettes.cassettes, stackers: stackers.stackers }))
|
||||
return Promise.all([buildAvailableCassettes(excludeTxId), buildAvailableRecyclers(excludeTxId)])
|
||||
.then(([cassettes, recyclers]) => ({ cassettes: cassettes.cassettes, recyclers: recyclers.recyclers }))
|
||||
}
|
||||
|
||||
function fetchCurrentConfigVersion () {
|
||||
|
|
@ -336,7 +331,7 @@ function plugins (settings, deviceId) {
|
|||
|
||||
return Promise.all([
|
||||
buildAvailableCassettes(),
|
||||
buildAvailableStackers(),
|
||||
buildAvailableRecyclers(),
|
||||
fetchCurrentConfigVersion(),
|
||||
millisecondsToMinutes(getTimezoneOffset(localeConfig.timezone)),
|
||||
loyalty.getNumberOfAvailablePromoCodes(),
|
||||
|
|
@ -347,7 +342,7 @@ function plugins (settings, deviceId) {
|
|||
])
|
||||
.then(([
|
||||
cassettes,
|
||||
stackers,
|
||||
recyclers,
|
||||
configVersion,
|
||||
timezone,
|
||||
numberOfAvailablePromoCodes,
|
||||
|
|
@ -371,7 +366,7 @@ function plugins (settings, deviceId) {
|
|||
|
||||
return {
|
||||
cassettes,
|
||||
stackers,
|
||||
recyclers: recyclers,
|
||||
rates: buildRates(tickers),
|
||||
balances: buildBalances(balances),
|
||||
coins,
|
||||
|
|
@ -744,12 +739,12 @@ function plugins (settings, deviceId) {
|
|||
const denomination2 = cashOutConfig.cassette2
|
||||
const denomination3 = cashOutConfig.cassette3
|
||||
const denomination4 = cashOutConfig.cassette4
|
||||
const denomination1f = cashOutConfig.stacker1f
|
||||
const denomination1r = cashOutConfig.stacker1r
|
||||
const denomination2f = cashOutConfig.stacker2f
|
||||
const denomination2r = cashOutConfig.stacker2r
|
||||
const denomination3f = cashOutConfig.stacker3f
|
||||
const denomination3r = cashOutConfig.stacker3r
|
||||
const denominationRecycler1 = cashOutConfig.recycler1
|
||||
const denominationRecycler2 = cashOutConfig.recycler2
|
||||
const denominationRecycler3 = cashOutConfig.recycler3
|
||||
const denominationRecycler4 = cashOutConfig.recycler4
|
||||
const denominationRecycler5 = cashOutConfig.recycler5
|
||||
const denominationRecycler6 = cashOutConfig.recycler6
|
||||
const cashOutEnabled = cashOutConfig.active
|
||||
const isUnitLow = (have, max, limit) => cashOutEnabled && ((have / max) * 100) < limit
|
||||
// const isUnitHigh = (have, max, limit) => cashOutEnabled && ((have / max) * 100) > limit
|
||||
|
|
@ -817,74 +812,74 @@ function plugins (settings, deviceId) {
|
|||
}
|
||||
: null
|
||||
|
||||
const stacker1fAlert = device.numberOfStackers >= 1 && isUnitLow(device.cashUnits.stacker1f, getCashUnitCapacity(device.model, 'stacker'), notifications.fillingPercentageStacker1f)
|
||||
const recycler1Alert = device.numberOfRecyclers >= 1 && isUnitLow(device.cashUnits.recycler1, getCashUnitCapacity(device.model, 'recycler'), notifications.fillingPercentageRecycler1)
|
||||
? {
|
||||
code: 'LOW_RECYCLER_STACKER',
|
||||
cassette: 4,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cashUnits.stacker1f,
|
||||
denomination: denomination1f,
|
||||
notes: device.cashUnits.recycler1,
|
||||
denomination: denominationRecycler1,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
||||
const stacker1rAlert = device.numberOfStackers >= 1 && isUnitLow(device.cashUnits.stacker1r, getCashUnitCapacity(device.model, 'stacker'), notifications.fillingPercentageStacker1r)
|
||||
const recycler2Alert = device.numberOfRecyclers >= 2 && isUnitLow(device.cashUnits.recycler2, getCashUnitCapacity(device.model, 'recycler'), notifications.fillingPercentageRecycler2)
|
||||
? {
|
||||
code: 'LOW_RECYCLER_STACKER',
|
||||
cassette: 4,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cashUnits.stacker1r,
|
||||
denomination: denomination1r,
|
||||
notes: device.cashUnits.recycler2,
|
||||
denomination: denominationRecycler2,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
||||
const stacker2fAlert = device.numberOfStackers >= 2 && isUnitLow(device.cashUnits.stacker2f, getCashUnitCapacity(device.model, 'stacker'), notifications.fillingPercentageStacker2f)
|
||||
const recycler3Alert = device.numberOfRecyclers >= 3 && isUnitLow(device.cashUnits.recycler3, getCashUnitCapacity(device.model, 'recycler'), notifications.fillingPercentageRecycler3)
|
||||
? {
|
||||
code: 'LOW_RECYCLER_STACKER',
|
||||
cassette: 4,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cashUnits.stacker2f,
|
||||
denomination: denomination2f,
|
||||
notes: device.cashUnits.recycler3,
|
||||
denomination: denominatinoRecycler3,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
||||
const stacker2rAlert = device.numberOfStackers >= 2 && isUnitLow(device.cashUnits.stacker2r, getCashUnitCapacity(device.model, 'stacker'), notifications.fillingPercentageStacker2r)
|
||||
const recycler4Alert = device.numberOfRecyclers >= 4 && isUnitLow(device.cashUnits.recycler4, getCashUnitCapacity(device.model, 'recycler'), notifications.fillingPercentageRecycler4)
|
||||
? {
|
||||
code: 'LOW_RECYCLER_STACKER',
|
||||
cassette: 4,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cashUnits.stacker2r,
|
||||
denomination: denomination2r,
|
||||
notes: device.cashUnits.recycler4,
|
||||
denomination: denominationRecycler4,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
||||
const stacker3fAlert = device.numberOfStackers >= 3 && isUnitLow(device.cashUnits.stacker3f, getCashUnitCapacity(device.model, 'stacker'), notifications.fillingPercentageStacker3f)
|
||||
const recycler5Alert = device.numberOfRecyclers >= 5 && isUnitLow(device.cashUnits.recycler5, getCashUnitCapacity(device.model, 'recycler'), notifications.fillingPercentageRecycler5)
|
||||
? {
|
||||
code: 'LOW_RECYCLER_STACKER',
|
||||
cassette: 4,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cashUnits.stacker3f,
|
||||
denomination: denomination3f,
|
||||
notes: device.cashUnits.recycler5,
|
||||
denomination: denominationRecycler5,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
||||
const stacker3rAlert = device.numberOfStackers >= 3 && isUnitLow(device.cashUnits.stacker3r, getCashUnitCapacity(device.model, 'stacker'), notifications.fillingPercentageStacker3r)
|
||||
const recycler6Alert = device.numberOfRecyclers >= 6 && isUnitLow(device.cashUnits.recycler6, getCashUnitCapacity(device.model, 'recycler'), notifications.fillingPercentageRecycler6)
|
||||
? {
|
||||
code: 'LOW_RECYCLER_STACKER',
|
||||
cassette: 4,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cashUnits.stacker3r,
|
||||
denomination: denomination3r,
|
||||
notes: device.cashUnits.recycler6,
|
||||
denomination: denominationRecycler6,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
|
@ -895,12 +890,12 @@ function plugins (settings, deviceId) {
|
|||
cassette2Alert,
|
||||
cassette3Alert,
|
||||
cassette4Alert,
|
||||
stacker1fAlert,
|
||||
stacker1rAlert,
|
||||
stacker2fAlert,
|
||||
stacker2rAlert,
|
||||
stacker3fAlert,
|
||||
stacker3rAlert
|
||||
recycler1Alert,
|
||||
recycler2Alert,
|
||||
recycler3Alert,
|
||||
recycler4Alert,
|
||||
recycler5Alert,
|
||||
recycler6Alert
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,18 +40,18 @@ exports.cassetteCounts = function cassetteCounts (deviceId) {
|
|||
})
|
||||
}
|
||||
|
||||
exports.stackerCounts = function stackerCounts (deviceId) {
|
||||
const sql = 'SELECT stacker1f, stacker1r, stacker2f, stacker2r, stacker3f, stacker3r, number_of_stackers FROM devices ' +
|
||||
exports.recyclerCounts = function recyclerCounts (deviceId) {
|
||||
const sql = 'SELECT recycler1, recycler2, recycler3, recycler4, recycler5, recycler6, number_of_recyclers FROM devices ' +
|
||||
'WHERE device_id=$1'
|
||||
|
||||
return db.one(sql, [deviceId])
|
||||
.then(row => {
|
||||
const counts = []
|
||||
_.forEach(it => {
|
||||
counts.push([row[`stacker${it + 1}f`], row[`stacker${it + 1}r`]])
|
||||
}, _.times(_.identity(), row.number_of_stackers))
|
||||
counts.push(row[`recycler${it + 1}`])
|
||||
}, _.times(_.identity(), row.number_of_recyclers))
|
||||
|
||||
return { numberOfStackers: row.number_of_stackers, counts }
|
||||
return { numberOfRecyclers: row.number_of_recyclers, counts }
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ function pair (req, res, next) {
|
|||
const deviceId = req.deviceId
|
||||
const model = req.query.model
|
||||
const numOfCassettes = req.query.numOfCassettes
|
||||
const numOfStackers = req.query.numOfStackers
|
||||
const numOfRecyclers = req.query.numOfRecyclers
|
||||
|
||||
return pairing.pair(token, deviceId, model, numOfCassettes, numOfStackers)
|
||||
return pairing.pair(token, deviceId, model, numOfCassettes, numOfRecyclers)
|
||||
.then(isValid => {
|
||||
if (isValid) return res.json({ status: 'paired' })
|
||||
throw httpError('Pairing failed')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue