diff --git a/lib/customers.js b/lib/customers.js index 159b62b0..6e5a70d5 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -7,6 +7,7 @@ const NUM_RESULTS = 20 const camelize = require('camelize') const Pgp = require('pg-promise')() const complianceOverrides = require('./compliance_overrides') +const users = require('./users') function add (customer) { const sql = 'insert into customers (id, phone, phone_at) values ($1, $2, now()) returning *' @@ -38,18 +39,20 @@ function get (phone) { */ function update (id, data, userToken) { const formattedData = _.omit(['id'], _.mapKeys(_.snakeCase, data)) - const updateData = addOverrideUser(formattedData, userToken) - addComplianceOverrides(id, updateData, userToken) + const updateData = enhanceOverrideFields(formattedData, userToken) const sql = Pgp.helpers.update(updateData, _.keys(updateData), 'customers') + ' where id=$1 returning *' return db.one(sql, [id]) - .then(customer => customer ? format(customer) : null) + .then(addComplianceOverrides(id, updateData, userToken)) + .then(populateOverrideUsernames) + .then(format) } -function getById (id) { +function getById (id, userToken) { const sql = 'select * from customers where id=$1' return db.oneOrNone(sql, [id]) - .then(customer => customer ? format(customer) : null) + .then(populateOverrideUsernames) + .then(format) } function getDailyVolume (id) { @@ -66,29 +69,45 @@ function getDailyVolume (id) { } /** - * Add *override_by fields with acting user's token + * Get all available complianceTypes + * that can be overriden (excluding hard_limit) * - * @name addOverrideUser + * @name getComplianceTypes * @function * - * @param {object} customer Customer's object to add the fields - * @param {string} userToken Acting user's token - * @returns {object} Customer populated with *_by fields + * @returns {array} Array of compliance types' names */ -function addOverrideUser (customer, userToken) { - if (!userToken) return customer - // Overrode fields - const overrideFields = [ - 'sms_override', - 'id_card_data_override', - 'id_card_photo_override', - 'front_facing_cam_override', - 'sanctions_check_override', - 'authorized_override' ] - overrideFields.forEach(field => { - if (customer[field]) customer[field + '_by'] = userToken - }) - return customer +function getComplianceTypes () { + return [ + 'sms', + 'id_card_data', + 'id_card_photo', + 'front_facing_cam', + 'sanctions_check', + 'authorized' ] +} + +/** + * Add *override_by and *override_at fields with acting user's token + * and date of override respectively before saving to db. + * + * @name enhanceOverrideFields + * @function + * + * @param {object} fields Override fields to be enhanced + * @param {string} userToken Acting user's token + * @returns {object} fields enhanced with *_by and *_at fields + */ +function enhanceOverrideFields (fields, userToken) { + if (!userToken) return fields + // Populate with computedFields (user who overrode and overriden timestamps date) + _.each(field => { + if (fields[field + '_override']) { + fields[field + '_override_by'] = userToken + fields[field + '_override_at'] = new Date().toISOString() + } + }, getComplianceTypes()) + return fields } /** @@ -107,52 +126,33 @@ function addOverrideUser (customer, userToken) { * @returns {promise} Result from compliance_overrides creation */ function addComplianceOverrides (id, customer, userToken) { - // Compliance override field mappings - const overrideFields = [{ - name: 'sms_override', - complianceType: 'sms' - }, { - name: 'id_card_data_override', - complianceType: 'id_card_data' - }, { - name: 'id_card_photo_override', - complianceType: 'id_card_photo' - }, { - name: 'front_facing_cam_override', - complianceType: 'front_camera' - }, { - name: 'sanctions_check_override', - complianceType: 'sanctions' - }, { - name: 'authorized_override', - complianceType: 'authorized' - }] - // Prepare compliance overrides to save const overrides = _.map(field => { - return (customer[field.name]) ? { + const complianceName = field + '_override' + return (customer[complianceName]) ? { customerId: id, - complianceType: field.complianceType, + complianceType: field, overrideBy: userToken, - verification: customer[field.name] + verification: customer[complianceName] } : null - }, overrideFields) + }, getComplianceTypes()) - // Save all the updated compliance override fields - return Promise.all(_.compact(overrides) - .map(override => complianceOverrides.add(override))) + // Save all the updated override fields + return Promise.all(_.map(complianceOverrides.add, _.compact(overrides))) } /** * Format and populate fields * for customer record * - * @function format + * @name format + * @function * * @param {object} Customer object * @returns {object} Customer camelized & populated with computed fields */ function format (customer) { + if (!customer) return null /** * Populate with status field * @@ -174,6 +174,31 @@ function format (customer) { return camelize(customer) } +/** + * Populate the customer object with user names + * only for those override fields that contain + * *override_by values (user token references) + * + * @name populateOverrideUsernames + * @function + * + * @param {object} customer Customer object to populate + * @returns {promise} Customer with populated *by_name fields + */ +function populateOverrideUsernames (customer) { + return Promise.all(_.map(field => { + if (customer[field + '_override_by']) { + return users.get(customer[field + '_override_by']) + .then(user => { + // just add the name to the customer object + customer[field + '_override_by_name'] = user.name + return null + }) + } else return null + }, getComplianceTypes())) + .then(() => customer) +} + /** * Query all customers * @@ -191,4 +216,4 @@ function batch () { .then(_.map(format)) } -module.exports = { add, get, batch, getById, update} +module.exports = { add, get, batch, getById, update } diff --git a/migrations/1505296896905-manual-override.js b/migrations/1505296896905-manual-override.js index aa73da80..4b172d48 100644 --- a/migrations/1505296896905-manual-override.js +++ b/migrations/1505296896905-manual-override.js @@ -13,7 +13,7 @@ exports.up = function (next) { * @see {@link http://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/} */ `create type compliance_type as enum - ('authorized', 'sms', 'id_card_data', 'id_card_photo', 'sanctions', 'cross_ref', 'front_camera', 'hard_limit')`, + ('authorized', 'sms', 'id_card_data', 'id_card_photo', 'sanctions_check', 'front_facing_cam', 'hard_limit')`, 'alter table compliance_authorizations alter column compliance_type set data type compliance_type using compliance_type::text::compliance_type', 'drop type compliance_types', @@ -21,17 +21,23 @@ exports.up = function (next) { 'alter table customers drop column manually_verified ', "alter table customers add column sms_override verification_type not null default 'automatic'", - 'alter table customers add column sms_override_by references user_tokens (token)', + 'alter table customers add column sms_override_by text references user_tokens (token)', + 'alter table customers add column sms_override_at timestamptz', "alter table customers add column id_card_data_override verification_type not null default 'automatic'", - 'alter table customers add column id_card_data_override_by references user_tokens (token)', + 'alter table customers add column id_card_data_override_by text references user_tokens (token)', + 'alter table customers add column id_card_data_override_at timestamptz', "alter table customers add column id_card_photo_override verification_type not null default 'automatic'", - 'alter table customers add column id_card_photo_override_by references user_tokens (token)', + 'alter table customers add column id_card_photo_override_by text references user_tokens (token)', + 'alter table customers add column id_card_photo_override_at timestamptz', "alter table customers add column front_facing_cam_override verification_type not null default 'automatic'", - 'alter table customers add column front_facing_cam_override_by references user_tokens (token)', + 'alter table customers add column front_facing_cam_override_by text references user_tokens (token)', + 'alter table customers add column front_facing_cam_override_at timestamptz', "alter table customers add column sanctions_check_override verification_type not null default 'automatic'", - 'alter table customers add column sanctions_check_override_by references user_tokens (token)', + 'alter table customers add column sanctions_check_override_by text references user_tokens (token)', + 'alter table customers add column sanctions_check_override_at timestamptz', "alter table customers add column authorized_override verification_type not null default 'automatic'", - 'alter table customers add column authorized_override_by references user_tokens (token)', + 'alter table customers add column authorized_override_by text references user_tokens (token)', + 'alter table customers add column authorized_override_at timestamptz', 'alter table customers add column authorized_at timestamptz', 'alter table customers add column sanctions_check_at timestamptz', diff --git a/public/elm.js b/public/elm.js index 5cf1d40d..331d9d35 100644 --- a/public/elm.js +++ b/public/elm.js @@ -38298,12 +38298,12 @@ var _user$project$Customer_View$customerActions = F2( { ctor: '::', _0: _elm_lang$html$Html_Events$onClick( - A3(_user$project$Customer_Types$PatchCustomer, id, 'authorizedOverride', 'automatic')), + A3(_user$project$Customer_Types$PatchCustomer, id, 'authorizedOverride', 'blocked')), _1: {ctor: '[]'} }, { ctor: '::', - _0: _elm_lang$html$Html$text('Unblock'), + _0: _elm_lang$html$Html$text('Block'), _1: {ctor: '[]'} }); }