Merge pull request #1749 from RafaelTaranto/backport/ofac-button
LAM-470 backport: OFAC button
This commit is contained in:
commit
d272e98b7a
9 changed files with 112 additions and 4 deletions
|
|
@ -114,6 +114,7 @@ function update (id, data, userToken) {
|
|||
async function updateCustomer (id, data, userToken) {
|
||||
const formattedData = _.pick(
|
||||
[
|
||||
'sanctions',
|
||||
'authorized_override',
|
||||
'id_card_photo_override',
|
||||
'id_card_data_override',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ const machine = require('./machine.resolver')
|
|||
const notification = require('./notification.resolver')
|
||||
const pairing = require('./pairing.resolver')
|
||||
const rates = require('./rates.resolver')
|
||||
const sanctions = require('./sanctions.resolver')
|
||||
const scalar = require('./scalar.resolver')
|
||||
const settings = require('./settings.resolver')
|
||||
const sms = require('./sms.resolver')
|
||||
|
|
@ -37,6 +38,7 @@ const resolvers = [
|
|||
notification,
|
||||
pairing,
|
||||
rates,
|
||||
sanctions,
|
||||
scalar,
|
||||
settings,
|
||||
sms,
|
||||
|
|
|
|||
13
lib/new-admin/graphql/resolvers/sanctions.resolver.js
Normal file
13
lib/new-admin/graphql/resolvers/sanctions.resolver.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
const sanctions = require('../../../sanctions')
|
||||
const authentication = require('../modules/userManagement')
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
checkAgainstSanctions: (...[, { customerId }, context]) => {
|
||||
const token = authentication.getToken(context)
|
||||
return sanctions.checkByUser(customerId, token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = resolvers
|
||||
|
|
@ -14,6 +14,7 @@ const machine = require('./machine.type')
|
|||
const notification = require('./notification.type')
|
||||
const pairing = require('./pairing.type')
|
||||
const rates = require('./rates.type')
|
||||
const sanctions = require('./sanctions.type')
|
||||
const scalar = require('./scalar.type')
|
||||
const settings = require('./settings.type')
|
||||
const sms = require('./sms.type')
|
||||
|
|
@ -37,6 +38,7 @@ const types = [
|
|||
notification,
|
||||
pairing,
|
||||
rates,
|
||||
sanctions,
|
||||
scalar,
|
||||
settings,
|
||||
sms,
|
||||
|
|
|
|||
13
lib/new-admin/graphql/types/sanctions.type.js
Normal file
13
lib/new-admin/graphql/types/sanctions.type.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
const { gql } = require('apollo-server-express')
|
||||
|
||||
const typeDef = gql`
|
||||
type SanctionMatches {
|
||||
ofacSanctioned: Boolean
|
||||
}
|
||||
|
||||
type Query {
|
||||
checkAgainstSanctions(customerId: ID): SanctionMatches @auth
|
||||
}
|
||||
`
|
||||
|
||||
module.exports = typeDef
|
||||
44
lib/sanctions.js
Normal file
44
lib/sanctions.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
const _ = require('lodash/fp')
|
||||
const ofac = require('./ofac')
|
||||
const T = require('./time')
|
||||
const logger = require('./logger')
|
||||
const customers = require('./customers')
|
||||
|
||||
const sanctionStatus = {
|
||||
loaded: false,
|
||||
timestamp: null
|
||||
}
|
||||
|
||||
const loadOrUpdateSanctions = () => {
|
||||
if (!sanctionStatus.loaded || (sanctionStatus.timestamp && Date.now() > sanctionStatus.timestamp + T.day)) {
|
||||
logger.info('No sanction lists loaded. Loading sanctions...')
|
||||
return ofac.load()
|
||||
.then(() => {
|
||||
logger.info('OFAC sanction list loaded!')
|
||||
sanctionStatus.loaded = true
|
||||
sanctionStatus.timestamp = Date.now()
|
||||
})
|
||||
.catch(e => {
|
||||
logger.error('Couldn\'t load OFAC sanction list!')
|
||||
})
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const checkByUser = (customerId, userToken) => {
|
||||
return Promise.all([loadOrUpdateSanctions(), customers.getCustomerById(customerId)])
|
||||
.then(([, customer]) => {
|
||||
const { firstName, lastName, dateOfBirth } = customer?.idCardData
|
||||
const birthdate = _.replace(/-/g, '')(dateOfBirth)
|
||||
const ofacMatches = ofac.match({ firstName, lastName }, birthdate, { threshold: 0.85, fullNameThreshold: 0.95, debug: false })
|
||||
const isOfacSanctioned = _.size(ofacMatches) > 0
|
||||
customers.updateCustomer(customerId, { sanctions: !isOfacSanctioned }, userToken)
|
||||
|
||||
return { ofacSanctioned: isOfacSanctioned }
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
checkByUser
|
||||
}
|
||||
|
|
@ -73,7 +73,8 @@ const CustomerData = ({
|
|||
authorizeCustomRequest,
|
||||
updateCustomEntry,
|
||||
retrieveAdditionalDataDialog,
|
||||
setRetrieve
|
||||
setRetrieve,
|
||||
checkAgainstSanctions
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
const [listView, setListView] = useState(false)
|
||||
|
|
@ -174,6 +175,12 @@ const CustomerData = ({
|
|||
idCardData: R.merge(idData, formatDates(values))
|
||||
}),
|
||||
validationSchema: customerDataSchemas.idCardData,
|
||||
checkAgainstSanctions: () =>
|
||||
checkAgainstSanctions({
|
||||
variables: {
|
||||
customerId: R.path(['id'])(customer)
|
||||
}
|
||||
}),
|
||||
initialValues: initialValues.idCardData,
|
||||
isAvailable: !R.isNil(idData),
|
||||
editable: true
|
||||
|
|
@ -463,7 +470,8 @@ const CustomerData = ({
|
|||
initialValues,
|
||||
hasImage,
|
||||
hasAdditionalData,
|
||||
editable
|
||||
editable,
|
||||
checkAgainstSanctions
|
||||
},
|
||||
idx
|
||||
) => {
|
||||
|
|
@ -485,6 +493,7 @@ const CustomerData = ({
|
|||
cancel={cancel}
|
||||
deleteEditedData={deleteEditedData}
|
||||
retrieveAdditionalData={retrieveAdditionalData}
|
||||
checkAgainstSanctions={checkAgainstSanctions}
|
||||
editable={editable}></EditableCard>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||
import { useQuery, useMutation, useLazyQuery } from '@apollo/react-hooks'
|
||||
import {
|
||||
makeStyles,
|
||||
Breadcrumbs,
|
||||
|
|
@ -292,6 +292,14 @@ const GET_ACTIVE_CUSTOM_REQUESTS = gql`
|
|||
}
|
||||
`
|
||||
|
||||
const CHECK_AGAINST_SANCTIONS = gql`
|
||||
query checkAgainstSanctions($customerId: ID) {
|
||||
checkAgainstSanctions(customerId: $customerId) {
|
||||
ofacSanctioned
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const CustomerProfile = memo(() => {
|
||||
const history = useHistory()
|
||||
|
||||
|
|
@ -400,6 +408,10 @@ const CustomerProfile = memo(() => {
|
|||
onCompleted: () => getCustomer()
|
||||
})
|
||||
|
||||
const [checkAgainstSanctions] = useLazyQuery(CHECK_AGAINST_SANCTIONS, {
|
||||
onCompleted: () => getCustomer()
|
||||
})
|
||||
|
||||
const updateCustomer = it =>
|
||||
setCustomer({
|
||||
variables: {
|
||||
|
|
@ -662,6 +674,7 @@ const CustomerProfile = memo(() => {
|
|||
authorizeCustomRequest={authorizeCustomRequest}
|
||||
updateCustomEntry={updateCustomEntry}
|
||||
setRetrieve={setRetrieve}
|
||||
checkAgainstSanctions={checkAgainstSanctions}
|
||||
retrieveAdditionalDataDialog={
|
||||
<RetrieveDataDialog
|
||||
onDismissed={() => {
|
||||
|
|
|
|||
|
|
@ -146,7 +146,8 @@ const EditableCard = ({
|
|||
deleteEditedData,
|
||||
retrieveAdditionalData,
|
||||
hasAdditionalData = true,
|
||||
editable
|
||||
editable,
|
||||
checkAgainstSanctions
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
|
||||
|
|
@ -277,6 +278,16 @@ const EditableCard = ({
|
|||
Retrieve API data
|
||||
</ActionButton>
|
||||
)}
|
||||
{checkAgainstSanctions && (
|
||||
<ActionButton
|
||||
color="primary"
|
||||
type="button"
|
||||
Icon={DataIcon}
|
||||
InverseIcon={DataReversedIcon}
|
||||
onClick={() => checkAgainstSanctions()}>
|
||||
Check against OFAC sanction list
|
||||
</ActionButton>
|
||||
)}
|
||||
</div>
|
||||
{editable && (
|
||||
<ActionButton
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue