feat: sms data editable fields

This commit is contained in:
José Oliveira 2022-01-07 18:44:08 +00:00
parent 5406a3cfdd
commit 62284a1d33
5 changed files with 71 additions and 11 deletions

View file

@ -24,6 +24,7 @@ const operatorDataDir = _.get('operatorDataDir', options)
const sms = require('./sms') const sms = require('./sms')
const settingsLoader = require('./new-settings-loader') const settingsLoader = require('./new-settings-loader')
const logger = require('./logger') const logger = require('./logger')
const consoleLogLevel = require('console-log-level')
const TX_PASSTHROUGH_ERROR_CODES = ['operatorCancel'] const TX_PASSTHROUGH_ERROR_CODES = ['operatorCancel']
@ -121,7 +122,8 @@ async function updateCustomer (id, data, userToken) {
'us_ssn_override', 'us_ssn_override',
'sanctions_override', 'sanctions_override',
'front_camera_override', 'front_camera_override',
'suspended_until' 'suspended_until',
'subscriber_info_override'
], ],
_.mapKeys(_.snakeCase, data)) _.mapKeys(_.snakeCase, data))
@ -164,11 +166,13 @@ function edit (id, data, userToken) {
'id_card_photo', 'id_card_photo',
'us_ssn', 'us_ssn',
'subscriber_info', 'subscriber_info',
'name' 'name',
'phone'
] ]
const filteredData = _.pick(defaults, _.mapKeys(_.snakeCase, _.omitBy(_.isNil, data))) const filteredData = _.pick(defaults, _.mapKeys(_.snakeCase, _.omitBy(_.isNil, data)))
if (_.isEmpty(filteredData)) return getCustomerById(id) if (_.isEmpty(filteredData)) return getCustomerById(id)
const formattedData = enhanceEditedPhotos(enhanceEditedFields(filteredData, userToken)) const formattedData = enhanceEditedPhotos(enhanceEditedFields(filteredData, userToken))
const defaultDbData = { const defaultDbData = {
customer_id: id, customer_id: id,
created: new Date(), created: new Date(),
@ -688,16 +692,16 @@ function getCustomersList (phone = null, name = null, address = null, id = null)
function getCustomerById (id) { function getCustomerById (id) {
const passableErrorCodes = _.map(Pgp.as.text, TX_PASSTHROUGH_ERROR_CODES).join(',') const passableErrorCodes = _.map(Pgp.as.text, TX_PASSTHROUGH_ERROR_CODES).join(',')
const sql = `SELECT id, authorized_override, days_suspended, is_suspended, front_camera_path, front_camera_at, front_camera_override, const sql = `SELECT id, authorized_override, days_suspended, is_suspended, front_camera_path, front_camera_at, front_camera_override,
phone, sms_override, id_card_data_at, id_card_data, id_card_data_override, id_card_data_expiration, phone, phone_at, sms_override, id_card_data_at, id_card_data, id_card_data_override, id_card_data_expiration,
id_card_photo_path, id_card_photo_at, id_card_photo_override, us_ssn_at, us_ssn, us_ssn_override, sanctions, sanctions_at, id_card_photo_path, id_card_photo_at, id_card_photo_override, us_ssn_at, us_ssn, us_ssn_override, sanctions, sanctions_at,
sanctions_override, total_txs, total_spent, LEAST(created, last_transaction) AS last_active, fiat AS last_tx_fiat, sanctions_override, total_txs, total_spent, LEAST(created, last_transaction) AS last_active, fiat AS last_tx_fiat,
fiat_code AS last_tx_fiat_code, tx_class AS last_tx_class, subscriber_info, custom_fields, notes, is_test_customer fiat_code AS last_tx_fiat_code, tx_class AS last_tx_class, subscriber_info, subscriber_info_at, subscriber_info_override, custom_fields, notes, is_test_customer
FROM ( FROM (
SELECT c.id, c.authorized_override, SELECT c.id, c.authorized_override,
greatest(0, date_part('day', c.suspended_until - now())) AS days_suspended, greatest(0, date_part('day', c.suspended_until - now())) AS days_suspended,
c.suspended_until > now() AS is_suspended, c.suspended_until > now() AS is_suspended,
c.front_camera_path, c.front_camera_override, c.front_camera_at, c.front_camera_path, c.front_camera_override, c.front_camera_at,
c.phone, c.sms_override, c.id_card_data, c.id_card_data_at, c.id_card_data_override, c.id_card_data_expiration, c.phone, c.phone_at, c.sms_override, c.id_card_data, c.id_card_data_at, c.id_card_data_override, c.id_card_data_expiration,
c.id_card_photo_path, c.id_card_photo_at, c.id_card_photo_override, c.us_ssn, c.us_ssn_at, c.us_ssn_override, c.sanctions, c.id_card_photo_path, c.id_card_photo_at, c.id_card_photo_override, c.us_ssn, c.us_ssn_at, c.us_ssn_override, c.sanctions,
c.sanctions_at, c.sanctions_override, c.subscriber_info, c.is_test_customer, c.created, t.tx_class, t.fiat, t.fiat_code, t.created as last_transaction, cn.notes, c.sanctions_at, c.sanctions_override, c.subscriber_info, c.is_test_customer, c.created, t.tx_class, t.fiat, t.fiat_code, t.created as last_transaction, cn.notes,
row_number() OVER (PARTITION BY c.id ORDER BY t.created DESC) AS rn, row_number() OVER (PARTITION BY c.id ORDER BY t.created DESC) AS rn,
@ -750,7 +754,8 @@ function selectLatestData (customerData, customerEditedData) {
'id_card_photo', 'id_card_photo',
'us_ssn', 'us_ssn',
'subscriber_info', 'subscriber_info',
'name' 'name',
'phone'
] ]
_.map(field => { _.map(field => {
let fieldName = field let fieldName = field

View file

@ -33,6 +33,7 @@ const typeDef = gql`
lastTxClass: String lastTxClass: String
transactions: [Transaction] transactions: [Transaction]
subscriberInfo: JSONObject subscriberInfo: JSONObject
subscriberInfoOverride: String
customFields: [CustomerCustomField] customFields: [CustomerCustomField]
customInfoRequests: [CustomRequestData] customInfoRequests: [CustomRequestData]
notes: [CustomerNote] notes: [CustomerNote]
@ -63,12 +64,15 @@ const typeDef = gql`
lastTxClass: String lastTxClass: String
suspendedUntil: Date suspendedUntil: Date
subscriberInfo: Boolean subscriberInfo: Boolean
subscriberInfoOverride: String
} }
input CustomerEdit { input CustomerEdit {
idCardData: JSONObject idCardData: JSONObject
idCardPhoto: UploadGQL idCardPhoto: UploadGQL
usSsn: String usSsn: String
subscriberInfo: JSONObject
phone: String
} }
type CustomerNote { type CustomerNote {

View file

@ -0,0 +1,22 @@
var db = require('./db')
exports.up = function (next) {
var sql = [
`ALTER TABLE customers
ADD COLUMN subscriber_info_override VERIFICATION_TYPE,
ADD COLUMN subscriber_info_override_by UUID,
ADD COLUMN subscriber_info_override_at TIMESTAMPTZ
`,
`ALTER TABLE edited_customer_data
ADD COLUMN phone TEXT,
ADD COLUMN phone_at TIMESTAMPTZ,
ADD COLUMN phone_by UUID
`
]
db.multi(sql, next)
}
exports.down = function (next) {
next()
}

View file

@ -2,6 +2,7 @@ import { DialogActions, DialogContent, Dialog } from '@material-ui/core'
import Grid from '@material-ui/core/Grid' import Grid from '@material-ui/core/Grid'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import { parse, format } from 'date-fns/fp' import { parse, format } from 'date-fns/fp'
import { parsePhoneNumber } from 'libphonenumber-js'
import _ from 'lodash/fp' import _ from 'lodash/fp'
import * as R from 'ramda' import * as R from 'ramda'
import { useState, React } from 'react' import { useState, React } from 'react'
@ -25,6 +26,7 @@ import { ReactComponent as CustomerListViewIcon } from 'src/styling/icons/circle
import { ReactComponent as OverviewReversedIcon } from 'src/styling/icons/circle buttons/overview/white.svg' import { ReactComponent as OverviewReversedIcon } from 'src/styling/icons/circle buttons/overview/white.svg'
import { ReactComponent as OverviewIcon } from 'src/styling/icons/circle buttons/overview/zodiac.svg' import { ReactComponent as OverviewIcon } from 'src/styling/icons/circle buttons/overview/zodiac.svg'
import { URI } from 'src/utils/apollo' import { URI } from 'src/utils/apollo'
import { onlyFirstToUpper } from 'src/utils/string'
import styles from './CustomerData.styles.js' import styles from './CustomerData.styles.js'
import { EditableCard } from './components' import { EditableCard } from './components'
@ -103,7 +105,7 @@ const CustomerData = ({
) )
const phone = R.path(['phone'])(customer) const phone = R.path(['phone'])(customer)
const smsData = R.path(['subscriberInfo'])(customer) const smsData = R.path(['subscriberInfo', 'result'])(customer)
const isEven = elem => elem % 2 === 0 const isEven = elem => elem % 2 === 0
@ -163,14 +165,24 @@ const CustomerData = ({
fields: customerDataElements.smsData, fields: customerDataElements.smsData,
title: 'SMS data', title: 'SMS data',
titleIcon: <PhoneIcon className={classes.cardIcon} />, titleIcon: <PhoneIcon className={classes.cardIcon} />,
authorize: () => {}, state: R.path(['subscriberInfoOverride'])(customer),
reject: () => {}, authorize: () =>
save: () => {}, updateCustomer({ subscriberInfoOverride: OVERRIDE_AUTHORIZED }),
reject: () =>
updateCustomer({ subscriberInfoOverride: OVERRIDE_REJECTED }),
save: values => {
editCustomer({
phone: parsePhoneNumber(values.phoneNumber).number,
subscriberInfo: {
result: _.merge(smsData, R.omit(['phoneNumber'])(values))
}
})
},
retrieveAditionalData: () => setRetrieve(true), retrieveAditionalData: () => setRetrieve(true),
validationSchema: customerDataSchemas.smsData, validationSchema: customerDataSchemas.smsData,
initialValues: initialValues.smsData, initialValues: initialValues.smsData,
isAvailable: !_.isNil(phone), isAvailable: !_.isNil(phone),
hasAditionalData: !_.isNil(smsData) && !_.isEmpty(smsData.result) hasAditionalData: !_.isNil(smsData) && !_.isEmpty(smsData)
}, },
{ {
title: 'Name', title: 'Name',
@ -336,6 +348,21 @@ const CustomerData = ({
}) })
}, R.path(['customFields'])(customer) ?? []) }, R.path(['customFields'])(customer) ?? [])
R.forEach(it => {
initialValues.smsData[it] = smsData[it]
smsDataElements.push({
name: it,
label: onlyFirstToUpper(it),
component: TextInput
})
Yup.object()
.shape({
[it]: Yup.string()
})
.required()
.concat(schemas.smsData)
}, R.keys(smsData) ?? [])
const editableCard = ( const editableCard = (
{ {
title, title,

View file

@ -70,6 +70,7 @@ const GET_CUSTOMER = gql`
isSuspended isSuspended
isTestCustomer isTestCustomer
subscriberInfo subscriberInfo
subscriberInfoOverride
customFields { customFields {
id id
label label
@ -139,6 +140,7 @@ const SET_CUSTOMER = gql`
lastTxFiatCode lastTxFiatCode
lastTxClass lastTxClass
subscriberInfo subscriberInfo
subscriberInfoOverride
} }
} }
` `