From aff1a3bec305de0b73a495eb45155a6b430627cf Mon Sep 17 00:00:00 2001 From: xxcxy Date: Thu, 30 Dec 2021 14:49:16 +0800 Subject: [PATCH] support customer payment event --- README.md | 1 + config/default.js | 1 + config/test.js | 1 + migrations/elasticsearch_sync.js | 57 ++++++++++++ src/constants.js | 15 +++ src/services/ProcessorService.js | 2 + .../ProcessorServiceCustomerPayment.js | 92 +++++++++++++++++++ 7 files changed, 169 insertions(+) create mode 100644 src/services/ProcessorServiceCustomerPayment.js diff --git a/README.md b/README.md index 835bb44..fb3cb5a 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ While running tests, the index names could be overwritten using environment vari export ES_PROJECT_INDEX=projects_test export ES_TIMELINE_INDEX=timelines_test export ES_METADATA_INDEX=metadata_test +export ES_CUSTOMER_PAYMENT_INDEX=customer_payments_test ``` #### Running integration tests and coverage diff --git a/config/default.js b/config/default.js index cc9b67e..0ae67f0 100644 --- a/config/default.js +++ b/config/default.js @@ -33,6 +33,7 @@ module.exports = { ES_PROJECT_INDEX: process.env.ES_PROJECT_INDEX || 'projects', ES_TIMELINE_INDEX: process.env.ES_TIMELINE_INDEX || 'timelines', ES_METADATA_INDEX: process.env.ES_METADATA_INDEX || 'metadata', + ES_CUSTOMER_PAYMENT_INDEX: process.env.ES_CUSTOMER_PAYMENT_INDEX || 'customer_payments', ES_TYPE: process.env.ES_TYPE || 'doc', // ES 6.x accepts only 1 Type per index and it's mandatory to define it ES_METADATA_DEFAULT_ID: process.env.ES_METADATA_DEFAULT_ID || 1 // use for setting default id of metadata }, diff --git a/config/test.js b/config/test.js index 2ce4c38..120b445 100644 --- a/config/test.js +++ b/config/test.js @@ -6,6 +6,7 @@ module.exports = { esConfig: { ES_PROJECT_INDEX: process.env.ES_PROJECT_INDEX || 'projects_test', ES_TIMELINE_INDEX: process.env.ES_TIMELINE_INDEX || 'timelines_test', + ES_CUSTOMER_PAYMENT_INDEX: process.env.ES_CUSTOMER_PAYMENT_INDEX || 'customer_payments_test', ES_METADATA_INDEX: process.env.ES_METADATA_INDEX || 'metadata_test' } } diff --git a/migrations/elasticsearch_sync.js b/migrations/elasticsearch_sync.js index 3db1741..9e19c2f 100644 --- a/migrations/elasticsearch_sync.js +++ b/migrations/elasticsearch_sync.js @@ -16,6 +16,7 @@ const helper = require('../src/common/helper') const ES_PROJECT_INDEX = config.get('esConfig.ES_PROJECT_INDEX') const ES_TIMELINE_INDEX = config.get('esConfig.ES_TIMELINE_INDEX') const ES_METADATA_INDEX = config.get('esConfig.ES_METADATA_INDEX') +const ES_CUSTOMER_PAYMENT_INDEX = config.get('esConfig.ES_CUSTOMER_PAYMENT_INDEX') const ES_TYPE = config.get('esConfig.ES_TYPE') // create new elasticsearch client @@ -839,6 +840,56 @@ function getRequestBody (indexName) { } } + const customerPaymentMapping = { + properties: { + id: { + type: 'long' + }, + amount: { + type: 'long' + }, + currency: { + type: 'string' + }, + reference: { + type: 'string' + }, + referenceId: { + type: 'string' + }, + paymentIntentId: { + type: 'string' + }, + clientSecret: { + type: 'string' + }, + status: { + type: 'string' + }, + createdAt: { + type: 'date', + format: 'strict_date_optional_time||epoch_millis' + }, + createdBy: { + type: 'integer' + }, + updatedAt: { + type: 'date', + format: 'strict_date_optional_time||epoch_millis' + }, + updatedBy: { + type: 'integer' + }, + deletedAt: { + type: 'date', + format: 'strict_date_optional_time||epoch_millis' + }, + deletedBy: { + type: 'integer' + } + } + } + const result = { index: indexName, include_type_name: true, @@ -859,6 +910,9 @@ function getRequestBody (indexName) { case ES_TIMELINE_INDEX: result.body.mappings[ES_TYPE] = timelineMapping break + case ES_CUSTOMER_PAYMENT_INDEX: + result.body.mappings[ES_TYPE] = customerPaymentMapping + break default: throw new Error(`Invalid index name '${indexName}'`) } @@ -878,6 +932,9 @@ esClient.indices.delete({ // Re-create metadata index .then(() => esClient.indices.delete({ index: ES_METADATA_INDEX, ignore: [404] })) .then(() => esClient.indices.create(getRequestBody(ES_METADATA_INDEX))) + // Re-create customerPayment index + .then(() => esClient.indices.delete({ index: ES_CUSTOMER_PAYMENT_INDEX, ignore: [404] })) + .then(() => esClient.indices.create(getRequestBody(ES_CUSTOMER_PAYMENT_INDEX))) .then(() => { logger.info('elasticsearch indices synced successfully') process.exit() diff --git a/src/constants.js b/src/constants.js index 142919b..0d49424 100644 --- a/src/constants.js +++ b/src/constants.js @@ -32,6 +32,7 @@ const RESOURCES = { TIMELINE: 'timeline', MILESTONE: 'milestone', MILESTONE_TEMPLATE: 'milestone.template', + CUSTOMER_PAYMENT: 'customer-payment', ATTACHMENT: 'attachment' } @@ -72,6 +73,19 @@ const ATTACHMENT_TYPES = { 'LINK': 'link' } +const CUSTOMER_PAYMENT_STATUS = { + CANCELED: 'canceled', + PROCESSING: 'processing', + REQUIRES_ACTION: 'requires_action', + REQUIRES_CAPTURE: 'requires_capture', + REQUIRES_CONFIRMATION: 'requires_confirmation', + REQUIRES_PAYMENT_METHOD: 'requires_payment_method', + SUCCEEDED: 'succeeded', + REFUNDED: 'refunded', + REFUND_FAILED: 'refund_failed', + REFUND_PENDING: 'refund_pending' +} + module.exports = { RESOURCES, REGEX, @@ -80,5 +94,6 @@ module.exports = { INVITE_STATUS, PROJECT_MEMBER_ROLE, MILESTONE_TEMPLATE_REFERENCES, + CUSTOMER_PAYMENT_STATUS, ATTACHMENT_TYPES } diff --git a/src/services/ProcessorService.js b/src/services/ProcessorService.js index 423e57b..fef7e3f 100644 --- a/src/services/ProcessorService.js +++ b/src/services/ProcessorService.js @@ -26,6 +26,7 @@ const ProcessorServiceTimeline = require('./ProcessorServiceTimeline') const ProcessorServiceMilestone = require('./ProcessorServiceMilestone') const ProcessorServiceMilestoneTemplate = require('./ProcessorServiceMilestoneTemplate') const ProcessorServiceProjectMemberInvite = require('./ProcessorServiceProjectMemberInvite') +const ProcessorServiceCustomerPayment = require('./ProcessorServiceCustomerPayment') /** * Create schema. @@ -63,6 +64,7 @@ const MappingResourceFunction = { [RESOURCES.TIMELINE]: ProcessorServiceTimeline, [RESOURCES.MILESTONE]: ProcessorServiceMilestone, [RESOURCES.MILESTONE_TEMPLATE]: ProcessorServiceMilestoneTemplate, + [RESOURCES.CUSTOMER_PAYMENT]: ProcessorServiceCustomerPayment, [RESOURCES.PROJECT_MEMBER_INVITE]: ProcessorServiceProjectMemberInvite } diff --git a/src/services/ProcessorServiceCustomerPayment.js b/src/services/ProcessorServiceCustomerPayment.js new file mode 100644 index 0000000..2caf973 --- /dev/null +++ b/src/services/ProcessorServiceCustomerPayment.js @@ -0,0 +1,92 @@ +/** + * Service for customer payment Elasticsearch processor. + */ + +const Joi = require('joi') +const config = require('config') +const _ = require('lodash') + +const logger = require('../common/logger') +const helper = require('../common/helper') +const { CUSTOMER_PAYMENT_STATUS } = require('../constants') + +const client = helper.getESClient() + +/** + * create schema + * @return {Object} the schema + */ +function createIdSchema () { + return Joi.object().keys({ + id: Joi.number().integer().positive().required() + }).unknown(true).required() +} + +/** + * create schema + * @return {Object} the schema + */ +function createSchema () { + return createIdSchema().keys({ + amount: Joi.number().integer().min(1).required(), + currency: Joi.string().required(), + paymentIntentId: Joi.string().required(), + status: Joi.string().valid(_.values(CUSTOMER_PAYMENT_STATUS)).required(), + reference: Joi.string().optional(), + referenceId: Joi.string().optional(), + createdAt: Joi.any(), + updatedAt: Joi.any(), + deletedAt: Joi.any(), + createdBy: Joi.any(), + updatedBy: Joi.any(), + deletedBy: Joi.any() + }).unknown(true).required() +} + +/** + * Create message in Elasticsearch. + * @param {Object} message the customer payment created message + * @return {Promise} promise result + */ +async function create (message) { + await client.create({ + index: config.get('esConfig.ES_CUSTOMER_PAYMENT_INDEX'), + type: config.get('esConfig.ES_TYPE'), + id: message.id, + body: message + }) + logger.debug(`CustomerPayment created successfully in elasticsearch index, (customerPayment: ${JSON.stringify(message)})`) +} + +create.schema = { + message: createSchema() +} + +/** + * Update message in Elasticsearch. + * @param {Object} message the customer payment updated message + * @return {Promise} promise result + */ +async function update (message) { + await client.update({ + index: config.get('esConfig.ES_CUSTOMER_PAYMENT_INDEX'), + type: config.get('esConfig.ES_TYPE'), + id: message.id, + body: { + doc: message + } + }) + logger.debug(`CustomerPayment updated successfully in elasticsearch index, (customerPayment: ${message.id})`) +} + +update.schema = { + message: createSchema() +} + +// Exports +module.exports = { + create, + update +} + +logger.buildService(module.exports)