Skip to content

Commit

Permalink
sending email
Browse files Browse the repository at this point in the history
  • Loading branch information
mbayopanda committed Jul 1, 2019
1 parent 54fc906 commit af4b449
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 56 deletions.
4 changes: 2 additions & 2 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ DEBUG=app,errors
UPLOAD_DIR='client/upload'

# Mailgun Creds
MAILGUN_API_KEY="key-XXX"
MAILGUN_DOMAIN="sandbox3ffc48c87d5e4c1c9fa257342faf6f75.mailgun.org"
MAILGUN_API_KEY="key-bb7f9b72800a8d0a7a4daf58da05324f_REMOVE_"
MAILGUN_DOMAIN="bhi.ma_REMOVE_"
MAILGUN_SERVER_ADDRESS="notifications@bhi.ma"
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
"angular-ui-bootstrap": "^2.5.6",
"angular-ui-grid": "^4.8.0",
"angular-ui-router": "angular-ui/angular-ui-router-bower#1.0.0-rc.1",
"axios": "^0.19.0",
"body-parser": "^1.18.3",
"bootstrap": "^3.3.0",
"chai-spies": "^1.0.0",
Expand Down
76 changes: 68 additions & 8 deletions server/controllers/admin/cronEmailReport/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
* HTTP END POINT
* API controller for the table cron_email_report
*/
const axios = require('axios');
const debug = require('debug')('app');

const db = require('../../../lib/db');
const CronJob = require('../../../lib/cronjob');
const Moment = require('../../../lib/moment');
const FilterParser = require('../../../lib/filter');

const mailer = require('../../../lib/mailer');
const auth = require('../../auth');
const dbReports = require('../../report.handlers');

function find(options = {}) {
const filters = new FilterParser(options, { tableAlias : 'cer' });
const sql = `
Expand Down Expand Up @@ -101,7 +104,7 @@ async function create(req, res, next) {

const result = await db.exec(query, [cron]);
const created = await lookup(result.insertId);
await createEmailReportJob(created, sendEmailReport.call(this, created));
await createEmailReportJob(created, sendEmailReportDocument.call(this, created));

res.status(201).json({ id : result.insertId });
} catch (error) {
Expand Down Expand Up @@ -130,7 +133,7 @@ function launchCronEmailReportJobs() {
find()
.then(rows => {
if (!rows.length) { return null; }
const jobs = rows.map(row => createEmailReportJob(row, sendEmailReport.call(this, row)));
const jobs = rows.map(row => createEmailReportJob(row, sendEmailReportDocument.call(this, row)));
return Promise.all(jobs);
})
.then(() => debug('Reports scanned successfully'));
Expand All @@ -147,16 +150,73 @@ function createEmailReportJob(record, cb) {
}

/**
* @function createReportDocument
* @function sendEmailReportDocument
* @param {object} record A row of cron email report
* @param {object} options The report options
*/
function createReportDocument(record, options) {
console.log(record, options);
async function sendEmailReportDocument(record) {
try {
const options = JSON.parse(record.params);
const fn = dbReports[record.report_key];
const contacts = await loadContacts(record.entity_group_uuid);
const session = await loadSession();
const document = await fn(options, session);
const filename = replaceSlash(document.headers.filename);

if (contacts.length) {
const attachments = [
{ filename, stream : document.report },
];
const content = `
Hi,
We have attached to this email the ${filename} file
Thank you,
`;
const mails = contacts.map(c => {
return mailer.email(c, record.label, content, {
attachments,
});
});

await Promise.all(mails);
debug(`(${record.label}) report sent by email to ${contacts.length} contacts`);
}
} catch (e) {
throw e;
}
}

function sendEmailReport(params) {
console.log('>>> send report by mail <<< with params :', params);
function replaceSlash(name = '', value = '_') {
const regex = /\//gi;
return name.replace(regex, value);
}

function loadContacts(entityGroupUuid) {
const query = `
SELECT e.email FROM entity e
JOIN entity_group_entity ege ON ege.entity_uuid = e.uuid
JOIN entity_group eg ON eg.uuid = ege.entity_group_uuid
WHERE eg.uuid = ?;
`;
return db.exec(query, [entityGroupUuid])
.then(contacts => contacts.map(c => c.email));
}

function loadSession() {
const query = `
SELECT
user.id, user.username, user.display_name, user.email, user.deactivated,
project.enterprise_id , project.id AS project_id
FROM user
JOIN project_permission
JOIN project ON user.id = project_permission.user_id
AND project.id = project_permission.project_id
LIMIT 1`;

return db.one(query)
.then(user => auth.loadSessionInformation(user));
}

function addDynamicDatesOptions(cronId, hasDynamicDates, options) {
Expand Down
3 changes: 3 additions & 0 deletions server/controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ exports.logout = logout;
// POST /auth/reload
exports.reload = reload;

// expose session locally
exports.loadSessionInformation = loadSessionInformation;


function loginRoute(req, res, next) {
const { username, password, project } = req.body;
Expand Down
80 changes: 42 additions & 38 deletions server/controllers/finance/reports/balance/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const TEMPLATE = './server/controllers/finance/reports/balance/report.handlebars

// expose to the API
exports.document = document;
exports.reporting = reporting;

// default report parameters
const DEFAULT_PARAMS = {
Expand All @@ -32,6 +33,46 @@ const DEFAULT_PARAMS = {

const TITLE_ID = 6;

/**
* @description this function helps to get html document of the report in server side
* so that we can use it with others modules on the server side
* @param {*} options the report options
* @param {*} session the session
*/
async function reporting(options, session) {
try {
const params = options;
const context = {};

_.defaults(params, DEFAULT_PARAMS);

context.useSeparateDebitsAndCredits = Number.parseInt(params.useSeparateDebitsAndCredits, 10);
context.shouldPruneEmptyRows = Number.parseInt(params.shouldPruneEmptyRows, 10);
context.shouldHideTitleAccounts = Number.parseInt(params.shouldHideTitleAccounts, 10);
context.includeClosingBalances = Number.parseInt(params.includeClosingBalances, 10);

const currencyId = session.enterprise.currency_id;

const period = await getPeriodFromParams(params.fiscal_id, params.period_id, context.includeClosingBalances);
_.merge(context, { period });

const { accounts, totals } = await getBalanceForFiscalYear(period, currencyId);
_.merge(context, { accounts, totals });

const tree = await computeBalanceTree(accounts, totals, context, context.shouldPruneEmptyRows);
_.merge(context, { accounts : tree.accounts, totals : tree.totals });

if (context.shouldHideTitleAccounts) {
context.accounts = accounts.filter(account => account.isTitleAccount === 0);
}

const report = new ReportManager(TEMPLATE, session, params);
return report.render(context);
} catch (error) {
throw error;
}
}

/**
* @function document
*
Expand All @@ -44,44 +85,7 @@ const TITLE_ID = 6;
* NOTE(@jniles): This file corresponds to the "Balance Report" on the client.
*/
function document(req, res, next) {
const params = req.query;
const context = {};
let report;

_.defaults(params, DEFAULT_PARAMS);

context.useSeparateDebitsAndCredits = Number.parseInt(params.useSeparateDebitsAndCredits, 10);
context.shouldPruneEmptyRows = Number.parseInt(params.shouldPruneEmptyRows, 10);
context.shouldHideTitleAccounts = Number.parseInt(params.shouldHideTitleAccounts, 10);
context.includeClosingBalances = Number.parseInt(params.includeClosingBalances, 10);

try {
report = new ReportManager(TEMPLATE, req.session, params);
} catch (e) {
next(e);
return;
}

const currencyId = req.session.enterprise.currency_id;

getPeriodFromParams(params.fiscal_id, params.period_id, context.includeClosingBalances)
.then(period => {
_.merge(context, { period });
return getBalanceForFiscalYear(period, currencyId);
})
.then(({ accounts, totals }) => {
_.merge(context, { accounts, totals });
return computeBalanceTree(accounts, totals, context, context.shouldPruneEmptyRows);
})
.then(({ accounts, totals }) => {
_.merge(context, { accounts, totals });

if (context.shouldHideTitleAccounts) {
context.accounts = accounts.filter(account => account.isTitleAccount === 0);
}

return report.render(context);
})
reporting(req.query, req.session)
.then(result => {
res.set(result.headers).send(result.report);
})
Expand Down
5 changes: 5 additions & 0 deletions server/controllers/report.handlers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const financeReports = require('./finance/reports');

module.exports = {
balance_report : financeReports.balance.reporting,
};
25 changes: 18 additions & 7 deletions server/lib/mailer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,26 @@ function processAttachments(attachments = []) {
// default to the name of the file if the name has not been specified
attach.filename = attach.filename || path.parse(attach.path).base;

debug(`#processAttachments() loading ${attach.path}`);
if (!attach.stream) {
debug(`#processAttachments() loading ${attach.path}`);

// asynchronously load the file and add it as as an attachment
return fs.readFile(attach.path)
.then(file =>
new mailgun.Attachment({
filename : attach.filename,
data : file,
}));
}

debug(`#processAttachments() attach stream ${attach.filename}`);

// asynchronously load the file and add it as as an attachment
return fs.readFile(attach.path)
.then(file =>
new mailgun.Attachment({
filename : attach.filename,
data : file,
}));
return new mailgun.Attachment({
filename : attach.filename,
data : attach.stream,
});

}));
}

Expand Down

0 comments on commit af4b449

Please sign in to comment.