feat: implement subscriber info retrieval

This commit is contained in:
Sérgio Salgado 2021-08-05 01:26:05 +01:00 committed by Josh Harvey
parent 149a2f99c8
commit a6eb4b904f
7 changed files with 110 additions and 11 deletions

View file

@ -21,6 +21,8 @@ const NUM_RESULTS = 1000
const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
const frontCameraBaseDir = _.get('frontCameraDir', options)
const operatorDataDir = _.get('operatorDataDir', options)
const sms = require('./sms')
const settingsLoader = require('./new-settings-loader')
const TX_PASSTHROUGH_ERROR_CODES = ['operatorCancel']
@ -118,12 +120,20 @@ async function updateCustomer (id, data, userToken) {
const enhancedUpdateData = enhanceAtFields(enhanceOverrideFields(formattedData, userToken))
const updateData = updateOverride(enhancedUpdateData)
if (!_.isEmpty(updateData)) {
const sql = Pgp.helpers.update(updateData, _.keys(updateData), 'customers') +
' where id=$1'
invalidateCustomerNotifications(id, formattedData)
await db.none(sql, [id])
}
if (data.subscriberInfo) {
Promise.all([getCustomerById(id), settingsLoader.loadLatest()])
.then(([customer, config]) => sms.getLookup(config, customer.phone))
.then(res => updateSubscriberData(id, res, userToken))
.catch(console.error)
}
invalidateCustomerNotifications(id, formattedData)
return getCustomerById(id)
}
@ -134,6 +144,11 @@ const invalidateCustomerNotifications = (id, data) => {
return notifierQueries.invalidateNotification(detailB, 'compliance')
}
const updateSubscriberData = (customerId, data, userToken) => {
const sql = `UPDATE customers SET subscriber_info=$1, subscriber_info_at=now(), subscriber_info_by=$2 WHERE id=$3`
return db.none(sql, [data, userToken, customerId])
}
/**
* Get customer by id
*
@ -508,7 +523,7 @@ function getCustomerById (id) {
phone, sms_override, id_card_data, id_card_data_override, id_card_data_expiration,
id_card_photo_path, id_card_photo_override, us_ssn, us_ssn_override, sanctions, sanctions_at,
sanctions_override, total_txs, total_spent, created as last_active, fiat as last_tx_fiat,
fiat_code as last_tx_fiat_code, tx_class as last_tx_class
fiat_code as last_tx_fiat_code, tx_class as last_tx_class, subscriber_info
from (
select c.id, c.authorized_override,
greatest(0, date_part('day', c.suspended_until - now())) as days_suspended,
@ -516,7 +531,7 @@ function getCustomerById (id) {
c.front_camera_path, c.front_camera_override,
c.phone, c.sms_override, c.id_card_data, c.id_card_data_override, c.id_card_data_expiration,
c.id_card_photo_path, c.id_card_photo_override, c.us_ssn, c.us_ssn_override, c.sanctions,
c.sanctions_at, c.sanctions_override, t.tx_class, t.fiat, t.fiat_code, t.created,
c.sanctions_at, c.sanctions_override, c.subscriber_info, t.tx_class, t.fiat, t.fiat_code, t.created,
row_number() over (partition by c.id order by t.created desc) as rn,
sum(case when t.id is not null then 1 else 0 end) over (partition by c.id) as total_txs,
sum(case when error_code is null or error_code not in ($1^) then t.fiat else 0 end) over (partition by c.id) as total_spent

View file

@ -28,6 +28,7 @@ const typeDef = gql`
lastTxFiatCode: String
lastTxClass: String
transactions: [Transaction]
subscriberInfo: JSONObject
}
input CustomerInput {
@ -53,6 +54,7 @@ const typeDef = gql`
lastTxFiatCode: String
lastTxClass: String
suspendedUntil: Date
subscriberInfo: Boolean
}
type Query {

View file

@ -1,8 +1,19 @@
const _ = require('lodash/fp')
exports.NAME = 'MockSMS'
const NAME = 'MockSMS'
exports.sendMessage = function sendMessage (account, rec) {
function getLookup (account, number) {
console.log('Looking up number: %j', number)
return new Promise((resolve, reject) => {
if (_.endsWith('666', number)) {
reject (new Error(`${exports.NAME} mocked error!`))
} else {
setTimeout(resolve, 1)
}
})
}
function sendMessage (account, rec) {
console.log('Sending SMS: %j', rec)
return new Promise((resolve, reject) => {
if (_.endsWith('666', _.getOr(false, 'sms.toNumber', rec))) {
@ -12,3 +23,9 @@ exports.sendMessage = function sendMessage (account, rec) {
}
})
}
module.exports = {
NAME,
sendMessage,
getLookup
}

View file

@ -37,7 +37,27 @@ function sendMessage (account, rec) {
})
}
function getLookup (account, number) {
return Promise.resolve()
.then(() => {
const client = twilio(account.accountSid, account.authToken)
return client.lookups.v1.phoneNumbers(number)
.fetch({ addOns: ['lamassu_ekata'] })
})
.then(info => info.addOns.results['lamassu_ekata'])
.catch(err => {
if (_.includes(err.code, BAD_NUMBER_CODES)) {
const badNumberError = new Error(err.message)
badNumberError.name = 'BadNumberError'
throw badNumberError
}
throw new Error(`Twilio error: ${err.message}`)
})
}
module.exports = {
NAME,
sendMessage
sendMessage,
getLookup
}

View file

@ -12,4 +12,15 @@ function sendMessage (settings, rec) {
})
}
module.exports = {sendMessage}
function getLookup (settings, number) {
return Promise.resolve()
.then(() => {
const pluginCode = argv.mockSms ? 'mock-sms' : 'twilio'
const plugin = ph.load(ph.SMS, pluginCode)
const account = settings.accounts[pluginCode]
return plugin.getLookup(account, number)
})
}
module.exports = { sendMessage, getLookup }

View file

@ -0,0 +1,15 @@
var db = require('./db')
exports.up = function (next) {
var sql = [
`ALTER TABLE customers ADD COLUMN subscriber_info JSON`,
`ALTER TABLE customers ADD COLUMN subscriber_info_at TIMESTAMPTZ`,
`ALTER TABLE customers ADD COLUMN subscriber_info_by UUID REFERENCES users(id)`
]
db.multi(sql, next)
}
exports.down = function (next) {
next()
}

View file

@ -97,6 +97,7 @@ const SET_CUSTOMER = gql`
lastTxFiat
lastTxFiatCode
lastTxClass
subscriberInfo
}
}
`
@ -202,6 +203,24 @@ const CustomerProfile = memo(() => {
}>
{`${blocked ? 'Authorize' : 'Block'} customer`}
</ActionButton>
<ActionButton
color="primary"
Icon={blocked ? AuthorizeIcon : BlockIcon}
InverseIcon={
blocked ? AuthorizeReversedIcon : BlockReversedIcon
}
onClick={() =>
setCustomer({
variables: {
customerId,
customerInput: {
subscriberInfo: true
}
}
})
}>
{`Retrieve information`}
</ActionButton>
</div>
</div>
)}