diff --git a/lib/customers.js b/lib/customers.js
index 012c042e..371e5634 100644
--- a/lib/customers.js
+++ b/lib/customers.js
@@ -488,7 +488,7 @@ function batch () {
* @returns {array} Array of customers with it's transactions aggregations
*/
-function getCustomersList (phone = null, name = null, address = null, id = null) {
+function getCustomersList (phone = null, name = null, address = null, id = null, email = null) {
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_override,
@@ -529,8 +529,9 @@ function getCustomersList (phone = null, name = null, address = null, id = null)
AND ($5 IS NULL OR CONCAT(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') = $5 OR id_card_data::json->>'firstName' = $5 OR id_card_data::json->>'lastName' = $5)
AND ($6 IS NULL OR id_card_data::json->>'address' = $6)
AND ($7 IS NULL OR id_card_data::json->>'documentNumber' = $7)
+ AND ($8 IS NULL OR email = $8)
limit $3`
- return db.any(sql, [ passableErrorCodes, anonymous.uuid, NUM_RESULTS, phone, name, address, id ])
+ return db.any(sql, [ passableErrorCodes, anonymous.uuid, NUM_RESULTS, phone, name, address, id, email ])
.then(customers => Promise.all(_.map(customer =>
getCustomInfoRequestsData(customer)
.then(camelizeDeep), customers)
diff --git a/lib/new-admin/filters.js b/lib/new-admin/filters.js
index d9b6c32d..89d67434 100644
--- a/lib/new-admin/filters.js
+++ b/lib/new-admin/filters.js
@@ -31,6 +31,7 @@ function transaction () {
function customer () {
const sql = `SELECT DISTINCT * FROM (
SELECT 'phone' AS type, phone AS value FROM customers WHERE phone IS NOT NULL UNION
+ SELECT 'email' AS type, email AS value FROM customers WHERE email IS NOT NULL UNION
SELECT 'name' AS type, id_card_data::json->>'firstName' AS value FROM customers WHERE id_card_data::json->>'firstName' IS NOT NULL AND id_card_data::json->>'lastName' IS NULL UNION
SELECT 'name' AS type, id_card_data::json->>'lastName' AS value FROM customers WHERE id_card_data::json->>'firstName' IS NULL AND id_card_data::json->>'lastName' IS NOT NULL UNION
SELECT 'name' AS type, concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') AS value FROM customers WHERE id_card_data::json->>'firstName' IS NOT NULL AND id_card_data::json->>'lastName' IS NOT NULL UNION
diff --git a/lib/new-admin/graphql/resolvers/customer.resolver.js b/lib/new-admin/graphql/resolvers/customer.resolver.js
index 19b54f79..93695b7e 100644
--- a/lib/new-admin/graphql/resolvers/customer.resolver.js
+++ b/lib/new-admin/graphql/resolvers/customer.resolver.js
@@ -10,7 +10,7 @@ const resolvers = {
isAnonymous: parent => (parent.customerId === anonymous.uuid)
},
Query: {
- customers: (...[, { phone, name, address, id }]) => customers.getCustomersList(phone, name, address, id),
+ customers: (...[, { phone, email, name, address, id }]) => customers.getCustomersList(phone, name, address, id, email),
customer: (...[, { customerId }]) => customers.getCustomerById(customerId),
customerFilters: () => filters.customer()
},
diff --git a/lib/new-admin/graphql/types/customer.type.js b/lib/new-admin/graphql/types/customer.type.js
index 278491ad..d238fda6 100644
--- a/lib/new-admin/graphql/types/customer.type.js
+++ b/lib/new-admin/graphql/types/customer.type.js
@@ -93,7 +93,7 @@ const typeDef = gql`
}
type Query {
- customers(phone: String, name: String, address: String, id: String): [Customer] @auth
+ customers(phone: String, name: String, email: String, address: String, id: String): [Customer] @auth
customer(customerId: ID!): Customer @auth
customerFilters: [Filter] @auth
}
diff --git a/lib/new-admin/graphql/types/transaction.type.js b/lib/new-admin/graphql/types/transaction.type.js
index b66e88cc..8c43f49e 100644
--- a/lib/new-admin/graphql/types/transaction.type.js
+++ b/lib/new-admin/graphql/types/transaction.type.js
@@ -33,6 +33,7 @@ const typeDef = gql`
rawTickerPrice: String
isPaperWallet: Boolean
customerPhone: String
+ customerEmail: String
customerIdCardDataNumber: String
customerIdCardDataExpiration: Date
customerIdCardData: JSONObject
diff --git a/lib/new-admin/services/transactions.js b/lib/new-admin/services/transactions.js
index 4cdd182a..003d7d12 100644
--- a/lib/new-admin/services/transactions.js
+++ b/lib/new-admin/services/transactions.js
@@ -54,6 +54,7 @@ function batch (
const cashInSql = `SELECT 'cashIn' AS tx_class, txs.*,
c.phone AS customer_phone,
+ c.email AS customer_email,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
@@ -86,6 +87,7 @@ function batch (
txs.*,
actions.tx_hash,
c.phone AS customer_phone,
+ c.email AS customer_email,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
@@ -157,7 +159,7 @@ function advancedBatch (data) {
'denomination1', 'denomination2', 'errorCode', 'customerId',
'txVersion', 'publishedAt', 'termsAccepted', 'layer2Address',
'commissionPercentage', 'rawTickerPrice', 'receivedCryptoAtoms',
- 'discount', 'txHash', 'customerPhone', 'customerIdCardDataNumber',
+ 'discount', 'txHash', 'customerPhone', 'customerEmail', 'customerIdCardDataNumber',
'customerIdCardDataExpiration', 'customerIdCardData', 'customerName', 'sendTime',
'customerFrontCameraPath', 'customerIdCardPhotoPath', 'expired', 'machineName', 'walletScore']
@@ -173,7 +175,7 @@ function advancedBatch (data) {
function simplifiedBatch (data) {
const fields = ['txClass', 'id', 'created', 'machineName',
- 'cryptoCode', 'cryptoAtoms', 'fiat', 'fiatCode', 'phone', 'toAddress',
+ 'cryptoCode', 'cryptoAtoms', 'fiat', 'fiatCode', 'phone', 'email', 'toAddress',
'txHash', 'dispense', 'error', 'status', 'fiatProfit', 'cryptoAmount']
const addSimplifiedFields = _.map(it => ({
@@ -234,6 +236,7 @@ function getCustomerTransactionsBatch (ids) {
const cashInSql = `SELECT 'cashIn' AS tx_class, txs.*,
c.phone AS customer_phone,
+ c.email AS customer_email,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
@@ -252,6 +255,7 @@ function getCustomerTransactionsBatch (ids) {
txs.*,
actions.tx_hash,
c.phone AS customer_phone,
+ c.email AS customer_email,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
@@ -280,6 +284,7 @@ function single (txId) {
const cashInSql = `SELECT 'cashIn' AS tx_class, txs.*,
c.phone AS customer_phone,
+ c.email AS customer_email,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
@@ -297,6 +302,7 @@ function single (txId) {
txs.*,
actions.tx_hash,
c.phone AS customer_phone,
+ c.email AS customer_email,
c.id_card_data_number AS customer_id_card_data_number,
c.id_card_data_expiration AS customer_id_card_data_expiration,
c.id_card_data AS customer_id_card_data,
diff --git a/lib/plugins/email/mailgun/mailgun.js b/lib/plugins/email/mailgun/mailgun.js
index 29663da9..2bd32151 100644
--- a/lib/plugins/email/mailgun/mailgun.js
+++ b/lib/plugins/email/mailgun/mailgun.js
@@ -4,7 +4,7 @@ const NAME = 'Mailgun'
function sendMessage ({apiKey, domain, fromEmail, toEmail}, rec) {
const mailgun = Mailgun({apiKey, domain})
- const to = req.email.toEmail ?? toEmail
+ const to = rec.email.toEmail ?? toEmail
const emailData = {
from: `Lamassu Server ${fromEmail}`,
@@ -18,7 +18,7 @@ function sendMessage ({apiKey, domain, fromEmail, toEmail}, rec) {
function sendCustomerMessage ({apiKey, domain, fromEmail}, rec) {
const mailgun = Mailgun({apiKey, domain})
- const to = req.email.toEmail
+ const to = rec.email.toEmail
const emailData = {
from: fromEmail,
diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.js b/new-lamassu-admin/src/pages/Customers/CustomerData.js
index 4029814a..a2aa9a81 100644
--- a/new-lamassu-admin/src/pages/Customers/CustomerData.js
+++ b/new-lamassu-admin/src/pages/Customers/CustomerData.js
@@ -101,6 +101,7 @@ const CustomerData = ({
)
const phone = R.path(['phone'])(customer)
+ const email = R.path(['email'])(customer)
const smsData = R.path(['subscriberInfo'])(customer)
const isEven = elem => elem % 2 === 0
@@ -134,6 +135,9 @@ const CustomerData = ({
idCardPhoto: {
idCardPhoto: null
},
+ email: {
+ email
+ },
smsData: {
phoneNumber: getFormattedPhone(phone, locale.country)
}
@@ -201,6 +205,19 @@ const CustomerData = ({
hasAdditionalData: !R.isNil(smsData) && !R.isEmpty(smsData),
editable: false
},
+ {
+ title: 'Email',
+ fields: customerDataElements.email,
+ titleIcon: ,
+ // state: R.path(['emailOverride'])(customer),
+ // authorize: () => updateCustomer({ emailOverride: OVERRIDE_AUTHORIZED }),
+ // reject: () => updateCustomer({ emailOverride: OVERRIDE_REJECTED }),
+ save: values => editCustomer(values),
+ deleteEditedData: () => deleteEditedData({ email: null }),
+ initialValues: initialValues.email,
+ isAvailable: !R.isNil(customer.email),
+ editable: false
+ },
{
title: 'Name',
titleIcon: ,
diff --git a/new-lamassu-admin/src/pages/Customers/Customers.js b/new-lamassu-admin/src/pages/Customers/Customers.js
index 007cd01e..8a674f4a 100644
--- a/new-lamassu-admin/src/pages/Customers/Customers.js
+++ b/new-lamassu-admin/src/pages/Customers/Customers.js
@@ -31,11 +31,18 @@ const GET_CUSTOMERS = gql`
query configAndCustomers(
$phone: String
$name: String
+ $email: String
$address: String
$id: String
) {
config
- customers(phone: $phone, name: $name, address: $address, id: $id) {
+ customers(
+ phone: $phone
+ email: $email
+ name: $name
+ address: $address
+ id: $id
+ ) {
id
idCardData
phone
@@ -155,6 +162,7 @@ const Customers = () => {
setVariables({
phone: filtersObject.phone,
name: filtersObject.name,
+ email: filtersObject.email,
address: filtersObject.address,
id: filtersObject.id
})
@@ -174,6 +182,7 @@ const Customers = () => {
setVariables({
phone: filtersObject.phone,
name: filtersObject.name,
+ email: filtersObject.email,
address: filtersObject.address,
id: filtersObject.id
})
@@ -188,6 +197,7 @@ const Customers = () => {
setVariables({
phone: filtersObject.phone,
name: filtersObject.name,
+ email: filtersObject.email,
address: filtersObject.address,
id: filtersObject.id
})
diff --git a/new-lamassu-admin/src/pages/Customers/CustomersList.js b/new-lamassu-admin/src/pages/Customers/CustomersList.js
index e9832f89..a7ed2a92 100644
--- a/new-lamassu-admin/src/pages/Customers/CustomersList.js
+++ b/new-lamassu-admin/src/pages/Customers/CustomersList.js
@@ -27,7 +27,8 @@ const CustomersList = ({
{
header: 'Phone/email',
width: 199,
- view: it => `${getFormattedPhone(it.phone, locale.country)} ${it.email}`
+ view: it => `${getFormattedPhone(it.phone, locale.country) || ''}
+ ${it.email || ''}`
},
{
header: 'Name',
diff --git a/new-lamassu-admin/src/pages/Customers/helper.js b/new-lamassu-admin/src/pages/Customers/helper.js
index ee081ef9..50a38bc1 100644
--- a/new-lamassu-admin/src/pages/Customers/helper.js
+++ b/new-lamassu-admin/src/pages/Customers/helper.js
@@ -59,7 +59,7 @@ const ID_CARD_DATA = 'idCardData'
const getAuthorizedStatus = (it, triggers, customRequests) => {
const fields = R.concat(
- ['frontCamera', 'idCardData', 'idCardPhoto', 'usSsn', 'sanctions'],
+ ['frontCamera', 'idCardData', 'idCardPhoto', 'email', 'usSsn', 'sanctions'],
R.map(ite => ite.id, customRequests)
)
const fieldsWithPathSuffix = ['frontCamera', 'idCardPhoto']
@@ -165,6 +165,7 @@ const requirementOptions = [
{ display: 'ID card image', code: 'idCardPhoto' },
{ display: 'ID data', code: 'idCardData' },
{ display: 'US SSN', code: 'usSsn' },
+ { display: 'Email', code: 'email' },
{ display: 'Customer camera', code: 'frontCamera' }
]
@@ -430,6 +431,15 @@ const customerDataElements = {
editable: true
}
],
+ email: [
+ {
+ name: 'email',
+ label: 'Email',
+ component: TextInput,
+ size: 190,
+ editable: false
+ }
+ ],
idCardPhoto: [{ name: 'idCardPhoto' }],
frontCamera: [{ name: 'frontCamera' }]
}
@@ -460,6 +470,9 @@ const customerDataSchemas = {
}),
frontCamera: Yup.object().shape({
frontCamera: Yup.mixed().required()
+ }),
+ email: Yup.object().shape({
+ email: Yup.string().required()
})
}
@@ -486,6 +499,13 @@ const requirementElements = {
initialValues: { usSsn: '' },
saveType: 'customerData'
},
+ email: {
+ schema: customerDataSchemas.email,
+ options: customerDataElements.email,
+ Component: ManualDataEntry,
+ initialValues: { email: '' },
+ saveType: 'customerData'
+ },
idCardPhoto: {
schema: customerDataSchemas.idCardPhoto,
options: customerDataElements.idCardPhoto,
diff --git a/new-lamassu-admin/src/pages/Transactions/Transactions.js b/new-lamassu-admin/src/pages/Transactions/Transactions.js
index 54a95f27..69699f63 100644
--- a/new-lamassu-admin/src/pages/Transactions/Transactions.js
+++ b/new-lamassu-admin/src/pages/Transactions/Transactions.js
@@ -116,6 +116,7 @@ const GET_TRANSACTIONS = gql`
customerFrontCameraPath
txCustomerPhotoPath
customerPhone
+ customerEmail
discount
customerId
isAnonymous
diff --git a/new-lamassu-admin/src/utils/customer.js b/new-lamassu-admin/src/utils/customer.js
index 9056a7a0..3a446e29 100644
--- a/new-lamassu-admin/src/utils/customer.js
+++ b/new-lamassu-admin/src/utils/customer.js
@@ -28,10 +28,13 @@ const displayName = ({
isAnonymous,
customerName,
customerIdCardData,
- customerPhone
+ customerPhone,
+ customerEmail
}) =>
isAnonymous
? 'Anonymous'
- : customerName || R.defaultTo(customerPhone, formatName(customerIdCardData))
+ : customerName ||
+ customerEmail ||
+ R.defaultTo(customerPhone, formatName(customerIdCardData))
export { displayName, formatFullName, formatName }