Skip to content

Commit

Permalink
Merge pull request #1 from alphagov/add-pay-specific-event-format
Browse files Browse the repository at this point in the history
Add pay specific event format
  • Loading branch information
sfount authored Apr 23, 2020
2 parents 6bfa658 + 313b8ec commit a7e15c8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/process.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import S3Provider from './providers/S3Provider'
import SQSConsumer from './consumers/SQSConsumer'
import GovUkPayPaymentEventMessage from './transformers/GovUKPayPaymentEventMessage'
const { PROVIDER_S3_BUCKET_NAME, PROVIDER_S3_SOURCE_FILE, CONSUMER_SQS_QUEUE_URL } = process.env

const s3Provider = new S3Provider(PROVIDER_S3_BUCKET_NAME, PROVIDER_S3_SOURCE_FILE)
const sqs = new SQSConsumer(CONSUMER_SQS_QUEUE_URL).writer()
const sqs = new SQSConsumer(CONSUMER_SQS_QUEUE_URL, new GovUkPayPaymentEventMessage()).writer()

s3Provider
.stream()
Expand Down
41 changes: 41 additions & 0 deletions src/transformers/GovUKPayPaymentEventMessage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import GovUKPayPaymentEventMessage from './GovUKPayPaymentEventMessage'
describe('message formatter', () => {
const messageFromS3Csv = {
'transaction_id': 'some-transaction-id',
'event_date': 'some-event-date',
'parent_transaction_id': 'some-parent-transaction-id',
'event_name': 'some-event-type',
'transaction_type': 'some-resource-type',
'reference': 'some-reference',
'amount': 'some-amount'
}
const messageBuilder = new GovUKPayPaymentEventMessage()

test('correctly transforms known reserved columns', () => {
const formatted = messageBuilder.transform(messageFromS3Csv)
const body = JSON.parse(formatted.MessageBody)

expect(body).toHaveProperty('resource_external_id')
expect(body).toHaveProperty('parent_resource_external_id')
expect(body).toHaveProperty('resource_type')
expect(body).toHaveProperty('timestamp')
expect(body).toHaveProperty('event_details')
expect(body).toHaveProperty('event_type')
})

test('ignores reserved properties if not needed on transaction', () => {
const formatted = messageBuilder.transform({ 'transaction_id': 'some-transaction-id' })
const body = JSON.parse(formatted.MessageBody)

expect(body).toHaveProperty('resource_external_id')
expect(body).not.toHaveProperty('parent_resource_external_id')
})

test('correctly formats well formatted flat message', () => {
const formatted = messageBuilder.transform(messageFromS3Csv)
const body = JSON.parse(formatted.MessageBody)

expect(body.event_details.reference).toBe('some-reference')
expect(body.event_details.amount).toBe('some-amount')
})
})
55 changes: 55 additions & 0 deletions src/transformers/GovUKPayPaymentEventMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* eslint-disable @typescript-eslint/camelcase */
import crypto from 'crypto'
import SQS = require("aws-sdk/clients/sqs")
import Transformer from './Transformer'
import { Message } from './../providers/Provider'

interface PaymentEventMessage {
event_details: { [key: string]: string };
resource_type?: string;
resource_external_id?: string;
event_date?: string;
event_type?: string;
parent_resource_external_id?: string;
[key: string]: string | { [key: string]: string };
}

// we can gaurantee the existence of required fields as anything with permissions
// to this resource will be validating data entry
function formatPaymentEventMessage(message: Message): PaymentEventMessage {
const reservedKeys = [
{ key: 'transaction_id', target: 'resource_external_id' },
{ key: 'parent_transaction_id', target: 'parent_resource_external_id' },
{ key: 'transaction_type', target: 'resource_type' },
{ key: 'event_date', target: 'timestamp' },
{ key: 'event_name', target: 'event_type' }
]
const formatted: PaymentEventMessage = { event_details: {} }

// initially extract the reserved properties
for (const reserved of reservedKeys) {
const reservedEntry = message[reserved.key]
if (reservedEntry) {
formatted[reserved.target] = reservedEntry
delete message[reserved.key]
}
}

// any remaining properties will override attributes of the transaction itself
// put these in `event_data`
for (const paymentEventMessageKey in message) {
formatted.event_details[paymentEventMessageKey] = message[paymentEventMessageKey]
}
return formatted
}

export default class GovUkPayPaymentEventMessage implements Transformer {
transform(message: Message): SQS.SendMessageBatchRequestEntry {
return {
Id: crypto.randomBytes(16).toString('hex'),
MessageBody: JSON.stringify(
formatPaymentEventMessage(message)
)
}
}
}

0 comments on commit a7e15c8

Please sign in to comment.