|
'use strict' |
|
|
|
// Built-in |
|
const { log } = console |
|
|
|
// common |
|
const Responses = require('./API_Responses'); |
|
const Dynamo = require('./Dynamo'); |
|
|
|
// AWS resources |
|
const aws = require('aws-sdk') |
|
const ses = new aws.SES({region: 'us-east-1'}); |
|
|
|
// libraries |
|
const fs = require('fs'); |
|
const { promisify } = require('util') |
|
const readFile = promisify(fs.readFile) |
|
const Handlebars = require('handlebars'); |
|
|
|
// environment variables |
|
const { ENTERPRISE_TABLE, PROJECT_TABLE, TREE_TABLE } = process.env |
|
|
|
exports.handler = async event => { |
|
// Input data for organisation and which month |
|
let body = JSON.parse(event.body); // parse JSON object |
|
|
|
// need to update this to loop on active enterprises |
|
const enterpriseId = body.enterpriseId // get from the event input JSON |
|
let projectId = ""; |
|
let monthDate = ""; |
|
|
|
// if monthDate (YYYY-MM) is passed in, use that value |
|
if (body.monthDate !== "") { |
|
monthDate = body.monthDate; |
|
} else { // report to be run 1st of following month, so we want last month |
|
let today = new Date(); |
|
today.setMonth(today.getMonth() - 1); |
|
let month = today.getMonth() + 1; // +1 for human readable month |
|
month = month < 10 ? `0${month}` : `${month}`; // deal with padding 0 |
|
monthDate = `${today.getFullYear()}-${month}`; // format YYYY-MM |
|
} |
|
|
|
// do some validation of enterprise ID and monthDate |
|
if (!enterpriseId.match(/^[0-9a-f]{8}$/)) { |
|
let error = `The "enterpriseId" must be 8 hex digit string. Got "${enterpriseId}" instead.` |
|
log(error); |
|
return Responses._400({message: error}); |
|
} else if (!monthDate.match(/^\d{4}-\d{2}$/)) { |
|
let error = `Required "month date" format is YYYY-MM. Got "${monthDate}" instead.` |
|
log(error); |
|
return Responses._400({message: error}); |
|
} |
|
|
|
// Start getting data for the email |
|
const TableName = TREE_TABLE |
|
const IndexName = 'myGSI' |
|
const query = { |
|
enterpriseId, |
|
} |
|
const KeyConditionExpression = |
|
Object.keys(query).map(x => `#${x[0]} = :${x[0]}`).join() |
|
+ ' and begins_with(created, :dt)' |
|
// { "#n": "name" } |
|
const ExpressionAttributeNames = Object |
|
.keys(query) |
|
.map(x => ({ [`#${x[0]}`] : x })) |
|
.reduce((x, acc) => Object.assign(acc, x), {}) |
|
// { ":n": "John" } |
|
const ExpressionAttributeValues = Object |
|
.keys(query) |
|
.map(x => ({ [`:${x[0]}`] : query[x] })) |
|
.concat({':dt': monthDate}) // Ex. '2018-11' |
|
.reduce((x, acc) => Object.assign(acc, x), {}) |
|
|
|
let treeResult = await Dynamo.query({ |
|
TableName, |
|
IndexName, |
|
KeyConditionExpression, |
|
ExpressionAttributeNames, |
|
ExpressionAttributeValues, |
|
}).catch(err => { |
|
log('Error in Dynamo Query', err) |
|
return null |
|
}) |
|
|
|
if (!treeResult){ |
|
return Responses._400({message: `There was an error fetching the data for enterprise of ${enterpriseId} and monthDate of ${monthDate} from ${TableName}`}) |
|
} |
|
|
|
// calculate tree count per project from result |
|
let report = {}; |
|
let treeCount = ""; |
|
|
|
// sum the tree count for each projectId |
|
treeResult |
|
.forEach(val => { |
|
report[val.projectId] = (report[val.projectId] > 0 ? report[val.projectId] : 0 ) + val.treeCount; |
|
}) |
|
|
|
// get the just project IDs in an array |
|
let projectIds = Object.keys(report); |
|
|
|
if (projectIds.length === 1) { // only purchased with 1 project (this is the norm) |
|
projectId = projectIds.join(); // get the single projectId |
|
treeCount = report[projectId]; // get the treeCount for that project |
|
} else { |
|
let error = `Trees planted with multiple projects for Enterprise id ${enterpriseId} and monthDate ${monthDate}, email must be generated manually at this time`; |
|
log(error); |
|
return Responses._400({message: error}); |
|
} |
|
|
|
// get project details |
|
let projectDetails = await Dynamo.get( |
|
{ |
|
TableName: PROJECT_TABLE, |
|
Key: { id: projectId } |
|
} |
|
).catch(err => { |
|
log('Error in Dynamo Get', err) |
|
return null |
|
}) |
|
|
|
if (!projectDetails) { |
|
error = "Could not retrieve project data for project: " + projectId |
|
log(error) |
|
return Responses._400({ error }) |
|
} |
|
|
|
// get enterprise details |
|
let enterpriseDetails = await Dynamo.get( |
|
{ |
|
TableName: ENTERPRISE_TABLE, |
|
Key: { id: enterpriseId } |
|
} |
|
).catch(err => { |
|
log('Error in Dynamo Get', err) |
|
return null |
|
}) |
|
|
|
if (!enterpriseDetails) { |
|
let error = "Count not retrieve enterprise data for enterprise: " + enterpriseId |
|
log(error) |
|
return Responses._400({ error }) |
|
} |
|
|
|
// prepare the email |
|
let emailHtmlTemplate = await readFile(__dirname + "/emailTemplates/monthlyTreeReportEmail.html").then((result) => { |
|
if (!result) { |
|
log('Unable to load HTML template'); |
|
throw 'Unable to load HTML template' |
|
} |
|
return result |
|
}).catch(err => { |
|
log('Unable to load HTML template', err) |
|
}) |
|
|
|
// Prepare data for template placeholders |
|
let emailData = { |
|
"enterpriseName": enterpriseDetails.name, |
|
"monthDate": monthDate, |
|
"treeCount": treeCount, |
|
"projectName": projectDetails.reforestationProjectCountry_en, |
|
"organisationName": projectDetails.reforestationCompanyName_en, |
|
"contactName": enterpriseDetails.contact.name, |
|
"contactEmail": enterpriseDetails.contact["email address"], |
|
"year": monthDate.slice(0,4), |
|
}; |
|
|
|
// Inject data into the template |
|
let templateHtml = Handlebars.compile(emailHtmlTemplate.toString()); |
|
let bodyHtml = templateHtml(emailData); |
|
|
|
// Prepare SES Parameters |
|
let params = { |
|
Destination: { |
|
ToAddresses: [emailData.contactEmail] |
|
}, |
|
Message: { |
|
Body: { |
|
Text: { Data: `Enterprise Name: ${emailData.enterpriseName}, Trees: ${treeCount}` |
|
}, |
|
Html: { |
|
Data: bodyHtml |
|
} |
|
}, |
|
Subject: { |
|
Data: `Monthly Report Email for ${emailData.enterpriseName} Trees: ${treeCount}` |
|
} |
|
}, |
|
Source: "info@DigitalHumani.com" |
|
}; |
|
|
|
try { |
|
await ses.sendEmail(params).promise(); |
|
return Responses._200({message: 'email sent'}) |
|
} catch (error) { |
|
console.log('error', error); |
|
return Responses._400({message: 'failed to send email'}) |
|
} |
|
} |