lamassu-server/lib/routes/customerRoutes.js
csrapr ba8cac60f8 Chore: Add basic screen and toggle
Chore: form skeleton

Feat: wizard step 1 and 2

Feat: toggle button group for formik

Feat: select input type Form and styling

Feat: text entry page

Feat: Choice list and CSS

Fix: scroll to bottom on Add choice button click

Feat: format data at end of wizard

Feat: wizard toggle button and background blur

Feat: data table for custom info requests

Feat: editing and deleting custom info request

Feat: add icons

Fix: Wizard changes

Feat: custom requests migrations

Feat: fetch custom info requests

Feat: add mutations

Feat: add custom request option in trigger wizard

Feat: show customrequests on table

Feat: Triggers page code refactor

Feat: integrate custom info requests on Customer graphql type

Feat: Show custom info requests on user page

Fix: use normal table instead of datatable

Feat: modal for custom information request details

Feat: poller returns custom request information details

Feat: send customer custom info requests to machine

Chore: add field CustomInfoRequestsData on customer updates

Feat: customer custom info request data saving

Chore: variable name changes and lots of fixes

Feat: remove default value in query, sort request on customer profile

Signed-off-by: csrapr <26280794+csrapr@users.noreply.github.com>

Fix: return promise when array of ids is empty

Feat: TitleSection can receive more than one button
2021-12-08 18:28:51 +00:00

190 lines
7.1 KiB
JavaScript

const express = require('express')
const router = express.Router()
const semver = require('semver')
const sms = require('../sms')
const _ = require('lodash/fp')
const BN = require('../bn')
const { zonedTimeToUtc, utcToZonedTime } = require('date-fns-tz/fp')
const compliance = require('../compliance')
const complianceTriggers = require('../compliance-triggers')
const configManager = require('../new-config-manager')
const customers = require('../customers')
const txs = require('../new-admin/services/transactions')
const httpError = require('../route-helpers').httpError
const notifier = require('../notifier')
const respond = require('../respond')
const { getTx } = require('../new-admin/services/transactions.js')
const { getCustomerById } = require('../customers')
const machineLoader = require('../machine-loader')
const { loadLatestConfig } = require('../new-settings-loader')
const customInfoRequestQueries = require('../new-admin/services/customInfoRequests')
function updateCustomerCustomInfoRequest (customerId, dataToSave, req, res) {
return customInfoRequestQueries.setCustomerData(customerId, dataToSave.info_request_id, dataToSave)
.then(() => customers.getById(customerId))
.then(customer => respond(req, res, { customer }))
}
function updateCustomer (req, res, next) {
const id = req.params.id
const machineVersion = req.query.version
const txId = req.query.txId
const patch = req.body
const triggers = configManager.getTriggers(req.settings.config)
const compatTriggers = complianceTriggers.getBackwardsCompatibleTriggers(triggers)
if (patch.customRequestPatch) {
return updateCustomerCustomInfoRequest(id, patch.dataToSave, req, res).catch(next)
}
customers.getById(id)
.then(customer => {
if (!customer) { throw httpError('Not Found', 404) }
const mergedCustomer = _.merge(customer, patch)
// BACKWARDS_COMPATIBILITY 7.5
// machines before 7.5 expect customer with sanctions result
const isOlderMachineVersion = !machineVersion || semver.lt(machineVersion, '7.5.0-beta.0')
return Promise.resolve({})
.then(emptyObj => {
if (!isOlderMachineVersion) return Promise.resolve(emptyObj)
return compliance.validationPatch(req.deviceId, !!compatTriggers.sanctions, mergedCustomer)
})
.then(_.merge(patch))
.then(newPatch => customers.updatePhotoCard(id, newPatch))
.then(newPatch => customers.updateFrontCamera(id, newPatch))
.then(newPatch => customers.update(id, newPatch, null, txId))
})
.then(customer => respond(req, res, { customer }))
.catch(next)
}
function updateIdCardData (req, res, next) {
const id = req.params.id
const patch = req.body
customers.getById(id)
.then(customer => {
if (!customer) { throw httpError('Not Found', 404) }
return customers.updateIdCardData(patch, id)
.then(() => customer)
})
.then(customer => respond(req, res, { customer }))
.catch(next)
}
function triggerSanctions (req, res, next) {
const id = req.params.id
customers.getById(id)
.then(customer => {
if (!customer) { throw httpError('Not Found', 404) }
return compliance.validationPatch(req.deviceId, true, customer)
.then(patch => customers.update(id, patch))
})
.then(customer => respond(req, res, { customer }))
.catch(next)
}
function triggerBlock (req, res, next) {
const id = req.params.id
customers.update(id, { authorizedOverride: 'blocked' })
.then(customer => {
notifier.complianceNotify(customer, req.deviceId, 'BLOCKED')
return respond(req, res, { customer })
})
.catch(next)
}
function triggerSuspend (req, res, next) {
const id = req.params.id
const triggerId = req.body.triggerId
const triggers = configManager.getTriggers(req.settings.config)
const getSuspendDays = _.compose(_.get('suspensionDays'), _.find(_.matches({ id: triggerId })))
const days = triggerId === 'no-ff-camera' ? 1 : getSuspendDays(triggers)
const date = new Date()
date.setDate(date.getDate() + days)
customers.update(id, { suspendedUntil: date })
.then(customer => {
notifier.complianceNotify(customer, req.deviceId, 'SUSPENDED', days)
return respond(req, res, { customer })
})
.catch(next)
}
function updateTxCustomerPhoto (req, res, next) {
const customerId = req.params.id
const txId = req.params.txId
const tcPhotoData = req.body.tcPhotoData
const direction = req.body.direction
Promise.all([customers.getById(customerId), txs.getTx(txId, direction)])
.then(([customer, tx]) => {
if (!customer || !tx) return
return customers.updateTxCustomerPhoto(tcPhotoData)
.then(newPatch => txs.updateTxCustomerPhoto(customerId, txId, direction, newPatch))
})
.then(() => respond(req, res, {}))
.catch(next)
}
function buildSms (data, receiptOptions) {
return Promise.all([getTx(data.session, data.txClass), loadLatestConfig()])
.then(([tx, config]) => {
return Promise.all([getCustomerById(tx.customer_id), machineLoader.getMachine(tx.device_id, config)])
.then(([customer, deviceConfig]) => {
const formattedTx = _.mapKeys(_.camelCase)(tx)
const localeConfig = configManager.getLocale(formattedTx.deviceId, config)
const timezone = localeConfig.timezone
const cashInCommission = new BN(1).plus(new BN(formattedTx.commissionPercentage))
const rate = new BN(formattedTx.rawTickerPrice).multipliedBy(cashInCommission).decimalPlaces(2)
const date = utcToZonedTime(timezone, zonedTimeToUtc(process.env.TZ, new Date()))
const dateString = `${date.toISOString().replace('T', ' ').slice(0, 19)}`
const data = {
operatorInfo: configManager.getOperatorInfo(config),
location: deviceConfig.machineLocation,
customerName: customer.name,
customerPhone: customer.phone,
session: formattedTx.id,
time: dateString,
direction: formattedTx.direction === 'cashIn' ? 'Cash-in' : 'Cash-out',
fiat: `${formattedTx.fiat.toString()} ${formattedTx.fiatCode}`,
crypto: `${sms.toCryptoUnits(BN(formattedTx.cryptoAtoms), formattedTx.cryptoCode)} ${formattedTx.cryptoCode}`,
rate: `1 ${formattedTx.cryptoCode} = ${rate} ${formattedTx.fiatCode}`,
address: formattedTx.toAddress,
txId: formattedTx.txHash
}
return sms.formatSmsReceipt(data, receiptOptions)
})
})
}
function sendSmsReceipt (req, res, next) {
const receiptOptions = _.omit(['active', 'sms'], configManager.getReceipt(req.settings.config))
buildSms(req.body.data, receiptOptions)
.then(smsRequest => {
sms.sendMessage(req.settings, smsRequest)
.then(() => respond(req, res, {}))
.catch(next)
})
}
router.patch('/:id', updateCustomer)
router.patch('/:id/sanctions', triggerSanctions)
router.patch('/:id/block', triggerBlock)
router.patch('/:id/suspend', triggerSuspend)
router.patch('/:id/photos/idcarddata', updateIdCardData)
router.patch('/:id/:txId/photos/customerphoto', updateTxCustomerPhoto)
router.patch('/:id/smsreceipt', sendSmsReceipt)
module.exports = router