diff --git a/lib/new-admin/graphql/resolvers/customInfoRequests.resolver.js b/lib/new-admin/graphql/resolvers/customInfoRequests.resolver.js
index 897b415c..fefdcf6b 100644
--- a/lib/new-admin/graphql/resolvers/customInfoRequests.resolver.js
+++ b/lib/new-admin/graphql/resolvers/customInfoRequests.resolver.js
@@ -1,3 +1,4 @@
+const authentication = require('../modules/userManagement')
const queries = require('../../services/customInfoRequests')
const DataLoader = require('dataloader')
@@ -21,7 +22,10 @@ const resolvers = {
insertCustomInfoRequest: (...[, { customRequest }]) => queries.addCustomInfoRequest(customRequest),
removeCustomInfoRequest: (...[, { id }]) => queries.removeCustomInfoRequest(id),
editCustomInfoRequest: (...[, { id, customRequest }]) => queries.editCustomInfoRequest(id, customRequest),
- setAuthorizedCustomRequest: (...[, { customerId, infoRequestId, isAuthorized }]) => queries.setAuthorizedCustomRequest(customerId, infoRequestId, isAuthorized),
+ setAuthorizedCustomRequest: (...[, { customerId, infoRequestId, override }, context]) => {
+ const token = authentication.getToken(context)
+ return queries.setAuthorizedCustomRequest(customerId, infoRequestId, override, token)
+ },
setCustomerCustomInfoRequest: (...[, { customerId, infoRequestId, data }]) => queries.setCustomerData(customerId, infoRequestId, data)
}
}
diff --git a/lib/new-admin/graphql/types/customInfoRequests.type.js b/lib/new-admin/graphql/types/customInfoRequests.type.js
index 5a9ed909..917c9f6f 100644
--- a/lib/new-admin/graphql/types/customInfoRequests.type.js
+++ b/lib/new-admin/graphql/types/customInfoRequests.type.js
@@ -32,7 +32,9 @@ const typeDef = gql`
type CustomRequestData {
customerId: ID
infoRequestId: ID
- approved: Boolean
+ override: String
+ overrideAt: Date
+ overrideBy: ID
customerData: JSON
customInfoRequest: CustomInfoRequest
}
@@ -47,7 +49,7 @@ const typeDef = gql`
insertCustomInfoRequest(customRequest: CustomRequestInput!): CustomInfoRequest @auth
removeCustomInfoRequest(id: ID!): CustomInfoRequest @auth
editCustomInfoRequest(id: ID!, customRequest: CustomRequestInput!): CustomInfoRequest @auth
- setAuthorizedCustomRequest(customerId: ID!, infoRequestId: ID!, isAuthorized: Boolean!): Boolean @auth
+ setAuthorizedCustomRequest(customerId: ID!, infoRequestId: ID!, override: String!): Boolean @auth
setCustomerCustomInfoRequest(customerId: ID!, infoRequestId: ID!, data: JSON!): Boolean @auth
}
`
diff --git a/lib/new-admin/services/customInfoRequests.js b/lib/new-admin/services/customInfoRequests.js
index c19c112a..7c703443 100644
--- a/lib/new-admin/services/customInfoRequests.js
+++ b/lib/new-admin/services/customInfoRequests.js
@@ -35,8 +35,10 @@ const getAllCustomInfoRequestsForCustomer = (customerId) => {
return db.any(sql, [customerId]).then(res => res.map(item => ({
customerId: item.customer_id,
infoRequestId: item.info_request_id,
- approved: item.approved,
- customerData: item.customer_data
+ customerData: item.customer_data,
+ override: item.override,
+ overrideAt: item.override_at,
+ overrideBy: item.override_by
})))
}
@@ -46,8 +48,10 @@ const getCustomInfoRequestForCustomer = (customerId, infoRequestId) => {
return {
customerId: item.customer_id,
infoRequestId: item.info_request_id,
- approved: item.approved,
- customerData: item.customer_data
+ customerData: item.customer_data,
+ override: item.override,
+ overrideAt: item.override_at,
+ overrideBy: item.override_by
}
})
}
@@ -61,8 +65,10 @@ const batchGetAllCustomInfoRequestsForCustomer = (customerIds) => {
return items.map(item => ({
customerId: item.customer_id,
infoRequestId: item.info_request_id,
- approved: item.approved,
- customerData: item.customer_data
+ customerData: item.customer_data,
+ override: item.override,
+ overrideAt: item.override_at,
+ overrideBy: item.override_by
}))
})
})
@@ -93,9 +99,9 @@ const batchGetCustomInfoRequest = (infoRequestIds) => {
})
}
-const setAuthorizedCustomRequest = (customerId, infoRequestId, isAuthorized) => {
- const sql = `UPDATE customers_custom_info_requests SET approved = $1 WHERE customer_id = $2 AND info_request_id = $3`
- return db.none(sql, [isAuthorized, customerId, infoRequestId]).then(() => true)
+const setAuthorizedCustomRequest = (customerId, infoRequestId, override, token) => {
+ const sql = `UPDATE customers_custom_info_requests SET override = $1, override_by = $2, override_at = now() WHERE customer_id = $3 AND info_request_id = $4`
+ return db.none(sql, [override, token, customerId, infoRequestId]).then(() => true)
}
const setCustomerData = (customerId, infoRequestId, data) => {
@@ -103,7 +109,7 @@ const setCustomerData = (customerId, infoRequestId, data) => {
INSERT INTO customers_custom_info_requests (customer_id, info_request_id, customer_data)
VALUES ($1, $2, $3)
ON CONFLICT (customer_id, info_request_id)
- DO UPDATE SET customer_data = $3, approved = null`
+ DO UPDATE SET customer_data = $3`
return db.none(sql, [customerId, infoRequestId, data])
}
diff --git a/lib/new-config-manager.js b/lib/new-config-manager.js
index 531186ea..0e721736 100644
--- a/lib/new-config-manager.js
+++ b/lib/new-config-manager.js
@@ -1,4 +1,5 @@
const _ = require('lodash/fp')
+const { getCustomInfoRequests } = require('./new-admin/services/customInfoRequests')
const namespaces = {
WALLETS: 'wallets',
@@ -107,22 +108,29 @@ const getGlobalNotifications = config => getNotifications(null, null, config)
const getTriggers = _.get('triggers')
const getTriggersAutomation = config => {
- const defaultAutomation = _.get('triggersConfig_automation')(config)
- const requirements = {
- sanctions: defaultAutomation,
- idCardPhoto: defaultAutomation,
- idCardData: defaultAutomation,
- facephoto: defaultAutomation,
- usSsn: defaultAutomation
- }
+ return getCustomInfoRequests(true)
+ .then(infoRequests => {
+ const defaultAutomation = _.get('triggersConfig_automation')(config)
+ const requirements = {
+ sanctions: defaultAutomation,
+ idCardPhoto: defaultAutomation,
+ idCardData: defaultAutomation,
+ facephoto: defaultAutomation,
+ usSsn: defaultAutomation
+ }
- const overrides = _.get('triggersConfig_overrides')(config)
+ _.forEach(it => {
+ requirements[it.id] = defaultAutomation
+ }, infoRequests)
- const requirementsOverrides = _.reduce((acc, override) => {
- return _.assign(acc, { [override.requirement]: override.automation })
- }, {}, overrides)
+ const overrides = _.get('triggersConfig_overrides')(config)
- return _.assign(requirements, requirementsOverrides)
+ const requirementsOverrides = _.reduce((acc, override) => {
+ return _.assign(acc, { [override.requirement]: override.automation })
+ }, {}, overrides)
+
+ return _.assign(requirements, requirementsOverrides)
+ })
}
const splitGetFirst = _.compose(_.head, _.split('_'))
diff --git a/lib/routes/pollingRoutes.js b/lib/routes/pollingRoutes.js
index b4089d54..c4568233 100644
--- a/lib/routes/pollingRoutes.js
+++ b/lib/routes/pollingRoutes.js
@@ -73,7 +73,7 @@ function poll (req, res, next) {
const pi = plugins(settings, deviceId)
const hasLightning = checkHasLightning(settings)
- const triggersAutomation = configManager.getTriggersAutomation(settings.config)
+ const triggersAutomationPromise = configManager.getTriggersAutomation(settings.config)
const triggersPromise = buildTriggers(configManager.getTriggers(settings.config))
const operatorInfo = configManager.getOperatorInfo(settings.config)
@@ -84,8 +84,8 @@ function poll (req, res, next) {
state.pids[operatorId] = { [deviceId]: { pid, ts: Date.now() } }
- return Promise.all([pi.pollQueries(serialNumber, deviceTime, req.query, machineVersion, machineModel), triggersPromise])
- .then(([results, triggers]) => {
+ return Promise.all([pi.pollQueries(serialNumber, deviceTime, req.query, machineVersion, machineModel), triggersPromise, triggersAutomationPromise])
+ .then(([results, triggers, triggersAutomation]) => {
const cassettes = results.cassettes
const reboot = pid && state.reboots?.[operatorId]?.[deviceId] === pid
diff --git a/migrations/1642518884925-manual-custom-info-requests.js b/migrations/1642518884925-manual-custom-info-requests.js
new file mode 100644
index 00000000..9a912c6d
--- /dev/null
+++ b/migrations/1642518884925-manual-custom-info-requests.js
@@ -0,0 +1,16 @@
+var db = require('./db')
+
+exports.up = function (next) {
+ var sql = [
+ `ALTER TABLE customers_custom_info_requests DROP COLUMN approved`,
+ `ALTER TABLE customers_custom_info_requests ADD COLUMN override verification_type NOT NULL DEFAULT 'automatic'`,
+ `ALTER TABLE customers_custom_info_requests ADD COLUMN override_by UUID REFERENCES users(id)`,
+ `ALTER TABLE customers_custom_info_requests ADD COLUMN override_at TIMESTAMPTZ`
+ ]
+
+ db.multi(sql, next)
+}
+
+exports.down = function (next) {
+ next()
+}
diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.js b/new-lamassu-admin/src/pages/Customers/CustomerData.js
index 18a53cac..dde30bef 100644
--- a/new-lamassu-admin/src/pages/Customers/CustomerData.js
+++ b/new-lamassu-admin/src/pages/Customers/CustomerData.js
@@ -324,7 +324,6 @@ const CustomerData = ({
]
R.forEach(it => {
- console.log('it', it)
customRequirements.push({
fields: [
{
@@ -336,12 +335,13 @@ const CustomerData = ({
],
title: it.customInfoRequest.customRequest.name,
titleIcon: ,
+ state: R.path(['override'])(it),
authorize: () =>
authorizeCustomRequest({
variables: {
customerId: it.customerId,
infoRequestId: it.customInfoRequest.id,
- isAuthorized: true
+ override: OVERRIDE_AUTHORIZED
}
}),
reject: () =>
@@ -349,7 +349,7 @@ const CustomerData = ({
variables: {
customerId: it.customerId,
infoRequestId: it.customInfoRequest.id,
- isAuthorized: false
+ override: OVERRIDE_REJECTED
}
}),
save: values => {
diff --git a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js
index 91b076ee..b127b5ec 100644
--- a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js
+++ b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js
@@ -95,7 +95,9 @@ const GET_CUSTOMER = gql`
}
customInfoRequests {
customerId
- approved
+ override
+ overrideBy
+ overrideAt
customerData
customInfoRequest {
id
@@ -180,12 +182,12 @@ const SET_AUTHORIZED_REQUEST = gql`
mutation setAuthorizedCustomRequest(
$customerId: ID!
$infoRequestId: ID!
- $isAuthorized: Boolean!
+ $override: String!
) {
setAuthorizedCustomRequest(
customerId: $customerId
infoRequestId: $infoRequestId
- isAuthorized: $isAuthorized
+ override: $override
)
}
`
diff --git a/new-lamassu-admin/src/pages/Customers/components/CustomInfoRequestsData.js b/new-lamassu-admin/src/pages/Customers/components/CustomInfoRequestsData.js
index ced31cef..d8ca647d 100644
--- a/new-lamassu-admin/src/pages/Customers/components/CustomInfoRequestsData.js
+++ b/new-lamassu-admin/src/pages/Customers/components/CustomInfoRequestsData.js
@@ -53,12 +53,12 @@ const SET_AUTHORIZED_REQUEST = gql`
mutation setAuthorizedCustomRequest(
$customerId: ID!
$infoRequestId: ID!
- $isAuthorized: Boolean!
+ $override: String!
) {
setAuthorizedCustomRequest(
customerId: $customerId
infoRequestId: $infoRequestId
- isAuthorized: $isAuthorized
+ override: $override
)
}
`
diff --git a/new-lamassu-admin/src/pages/Triggers/components/AdvancedTriggers.js b/new-lamassu-admin/src/pages/Triggers/components/AdvancedTriggers.js
index cb58bfa2..038a6825 100644
--- a/new-lamassu-admin/src/pages/Triggers/components/AdvancedTriggers.js
+++ b/new-lamassu-admin/src/pages/Triggers/components/AdvancedTriggers.js
@@ -28,13 +28,34 @@ const GET_INFO = gql`
}
`
+const GET_CUSTOM_REQUESTS = gql`
+ query customInfoRequests {
+ customInfoRequests {
+ id
+ customRequest
+ enabled
+ }
+ }
+`
+
const AdvancedTriggersSettings = memo(() => {
const SCREEN_KEY = namespaces.TRIGGERS
const [error, setError] = useState(null)
const [isEditingDefault, setEditingDefault] = useState(false)
const [isEditingOverrides, setEditingOverrides] = useState(false)
- const { data } = useQuery(GET_INFO)
+ const { data, loading: configLoading } = useQuery(GET_INFO)
+ const { data: customInfoReqData, loading: customInfoLoading } = useQuery(
+ GET_CUSTOM_REQUESTS
+ )
+
+ const customInfoRequests =
+ R.path(['customInfoRequests'])(customInfoReqData) ?? []
+ const enabledCustomInfoRequests = R.filter(R.propEq('enabled', true))(
+ customInfoRequests
+ )
+
+ const loading = configLoading || customInfoLoading
const [saveConfig] = useMutation(SAVE_CONFIG, {
refetchQueries: () => ['getData'],
@@ -67,42 +88,47 @@ const AdvancedTriggersSettings = memo(() => {
const onEditingOverrides = (it, editing) => setEditingOverrides(editing)
return (
- <>
-
-
- >
+ !loading && (
+ <>
+
+
+ >
+ )
)
})
diff --git a/new-lamassu-admin/src/pages/Triggers/components/helper.js b/new-lamassu-admin/src/pages/Triggers/components/helper.js
index 0737bca8..e7c660df 100644
--- a/new-lamassu-admin/src/pages/Triggers/components/helper.js
+++ b/new-lamassu-admin/src/pages/Triggers/components/helper.js
@@ -4,18 +4,29 @@ import * as Yup from 'yup'
import Autocomplete from 'src/components/inputs/formik/Autocomplete.js'
import { getView } from 'src/pages/Triggers/helper'
-const advancedRequirementOptions = [
- { display: 'Sanctions', code: 'sanctions' },
- { display: 'ID card image', code: 'idCardPhoto' },
- { display: 'ID data', code: 'idCardData' },
- { display: 'Customer camera', code: 'facephoto' },
- { display: 'US SSN', code: 'usSsn' }
-]
+const buildAdvancedRequirementOptions = customInfoRequests => {
+ const base = [
+ { display: 'Sanctions', code: 'sanctions' },
+ { display: 'ID card image', code: 'idCardPhoto' },
+ { display: 'ID data', code: 'idCardData' },
+ { display: 'Customer camera', code: 'facephoto' },
+ { display: 'US SSN', code: 'usSsn' }
+ ]
-const displayRequirement = code => {
+ const custom = R.map(it => ({
+ display: it.customRequest.name,
+ code: it.id
+ }))(customInfoRequests)
+
+ return R.concat(base, custom)
+}
+
+const displayRequirement = (code, customInfoRequests) => {
return R.prop(
'display',
- R.find(R.propEq('code', code))(advancedRequirementOptions)
+ R.find(R.propEq('code', code))(
+ buildAdvancedRequirementOptions(customInfoRequests)
+ )
)
}
@@ -29,7 +40,7 @@ const defaultSchema = Yup.object().shape({
.required()
})
-const getOverridesSchema = values => {
+const getOverridesSchema = (values, customInfoRequests) => {
return Yup.object().shape({
id: Yup.string()
.label('Requirement')
@@ -40,7 +51,8 @@ const getOverridesSchema = values => {
if (R.find(R.propEq('requirement', requirement))(values)) {
return this.createError({
message: `Requirement ${displayRequirement(
- requirement
+ requirement,
+ customInfoRequests
)} already overriden`
})
}
@@ -84,17 +96,20 @@ const getDefaultSettings = () => {
]
}
-const getOverrides = () => {
+const getOverrides = customInfoRequests => {
return [
{
name: 'requirement',
header: 'Requirement',
width: 196,
size: 'sm',
- view: getView(advancedRequirementOptions, 'display'),
+ view: getView(
+ buildAdvancedRequirementOptions(customInfoRequests),
+ 'display'
+ ),
input: Autocomplete,
inputProps: {
- options: advancedRequirementOptions,
+ options: buildAdvancedRequirementOptions(customInfoRequests),
labelProp: 'display',
valueProp: 'code'
}