feat: implement subscriber info retrieval
This commit is contained in:
parent
149a2f99c8
commit
a6eb4b904f
7 changed files with 110 additions and 11 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
13
lib/sms.js
13
lib/sms.js
|
|
@ -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 }
|
||||
|
|
|
|||
15
migrations/1628100660620-subscriber-info.js
Normal file
15
migrations/1628100660620-subscriber-info.js
Normal 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()
|
||||
}
|
||||
|
|
@ -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>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue