Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send email notifications #43

Merged
merged 3 commits into from
May 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"presets": ["@babel/preset-env"],
"plugins": ["@babel/transform-runtime"]
"plugins": ["@babel/transform-runtime"],
"env": {
"test": {
"plugins": [ "istanbul" ]
}
}
}
4 changes: 2 additions & 2 deletions UI/js/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const id = 1;
const bucket = 'quick-credit';
const folder = 'profile_photos';
const endpoint = 's3.eu-west-2.amazonaws.com';
// const base_url = 'https://qcredit.herokuapp.com';
const base_url = 'http://localhost:3000';
const base_url = 'https://qcredit.herokuapp.com';
// const base_url = 'http://localhost:3000';

// const reload_pix = () => {
// const container = document.getElementById('photo_window');
Expand Down
4 changes: 3 additions & 1 deletion controllers/AuthController.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import
check_user_exists,
get_existing_user,
add_user_to_db,
check_password
check_password,
sendSignUpMessage
} from './helpers/AuthController';

const users_model = new Model('users');
Expand All @@ -25,6 +26,7 @@ const AuthController = {
const clause = `WHERE id=${id}`;
const err_msg = `User with id ${id} does not exist.`;
const user = await get_existing_user(users_model, res, clause, err_msg);
sendSignUpMessage(user, req);
return res.status(201).json({ data: { ...user, token: req.token } });
},

Expand Down
44 changes: 29 additions & 15 deletions controllers/LoansController.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import
loan_repayment_history,
check_loan_existence,
add_repayment_to_db,
get_repayment_by_id,
return_repay_or_error,
update_loan_status,
update_loan_balance
update_loan_balance,
sendFollowUpMessage,
sendNewApplicationMessage
} from './helpers/LoansController';

const loans_model = new Model('loans');
Expand All @@ -21,21 +23,18 @@ const repayments_model = new Model('repayments');
const LoansController = {
get_all_loans: async (req, res) => {
const { status, repaid } = req.query;
const rows = `id, userid, createdon, status, repaid, useremail,
amount, tenor, interest, balance, paymentinstallment`;
dev_logger(`rep ${repaid}, ${typeof repaid}`);
try {
let data;
if (status && repaid) {
data = await loans_model.select(
`id, userid, createdon, status, repaid,
amount, tenor, interest, balance, paymentinstallment`,
data = await loans_model.select(rows,
`WHERE status='${status}' AND repaid='${repaid}'`
);
}
else {
data = await loans_model.select(
`id, userid, createdon, status, repaid,
amount, tenor, interest, balance, paymentinstallment`,
);
data = await loans_model.select(rows);
}
return res.status(200).json({ data: data.rows });
}
Expand All @@ -45,7 +44,12 @@ const LoansController = {
get_loan: async (req, res) => {
const { id } = req.params;
try {
return get_loan_by_id(loans_model, id, res, 200);
const loan = await get_loan_by_id(loans_model, id, res);
if (loan) {
return res.status(200).json({ data: loan });
}
return res.status(404)
.json({ error: `Loan with id ${id} does not exist` });
}
catch (e) { return; }
},
Expand All @@ -54,7 +58,9 @@ const LoansController = {
try {
const { rows } = await add_loan_to_db(loans_model, req, res);
const [ { id }, ] = rows;
return get_loan_by_id(loans_model, id, res, 201);
const loan = await get_loan_by_id(loans_model, id, res, 201);
sendNewApplicationMessage(loan);
return res.status(201).json({ data: loan });
}
catch (e) { return; }
},
Expand All @@ -67,8 +73,15 @@ const LoansController = {

req.status = status;
try {
await update_loan_status(loans_model, req, res);
return get_loan_by_id(loans_model, id, res, 200);
const loan = await check_loan_existence(loans_model, req, res);
if (loan) {
await update_loan_status(loans_model, req, res);
const loan = await get_loan_by_id(loans_model, id, res);
sendFollowUpMessage(status, loan);
return res.status(200).json({ data: loan });
}
return res.status(404)
.json({ error: `Loan with id ${id} does not exist.` });
}
catch (e) { throw InternalServerError(res, e); }
},
Expand All @@ -90,15 +103,15 @@ const LoansController = {
);
const [ { id }, ] = rows;
await update_loan_balance(loans_model, req, res);
return await get_repayment_by_id(repayments_model, id, res, 201);
return return_repay_or_error(repayments_model, id, res, 201);
}
catch (e) { return; }
},

get_repayment: async (req, res) => {
const { id } = req.params;
try {
return get_repayment_by_id(repayments_model, id, res, 200);
return return_repay_or_error(repayments_model, id, res, 200);
}
catch (e) { return; }
},
Expand All @@ -114,4 +127,5 @@ const LoansController = {
},
};


export default LoansController;
33 changes: 18 additions & 15 deletions controllers/UsersController.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import Model from '../models/Model';
import { InternalServerError } from '../utils/errorHandlers';
import {
get_existing_user, check_user_exists
get_existing_user, check_user_exists, update_if_exists
} from './helpers/AuthController';
import { aws_signed_url, } from './helpers/UsersController';

const users_model = new Model('users');

const UsersController = {
confirm_account: async (req, res) => {
try {

const { id } = req.params;
const clause = `WHERE id=${req.params.id}`;
const column = 'mailverified=true';
update_if_exists(users_model, id, column, clause, res);
}
catch (e) { return; }
},

get_user: async (req, res) => {
const { id } = req.params;
const clause = `WHERE id=${id}`;
Expand All @@ -26,34 +37,26 @@ const UsersController = {
verify_user: async (req, res) => {
const { id } = req.params;
const clause = `WHERE id=${id}`;
const column = 'status=\'verified\'';
try {

const exists = await check_user_exists(users_model, clause, res);
if (exists) {
await users_model.update('status=\'verified\'', clause);
const user = await get_existing_user(users_model, res, clause);
return res.status(200).json({ data: user });
}
return res.status(404)
.json({ error: `User with id ${id} not found` });
update_if_exists(users_model, id, column, clause, res);
}
catch (e) { return; }
},

get_users: async (req, res) => {
const { status } = req.query;
const rows = `id, email, firstname, lastname,
phone, status, address, mailverified`;
try {
let data;
if (status) {
data = await users_model.select(
'id, email, firstname, lastname, phone, status, address',
`WHERE status='${status}'`
rows, `WHERE status='${status}'`
);
}
else {
data = await users_model.select(
'id, email, firstname, lastname, phone, status, address',
);
data = await users_model.select(rows);
}
return res.status(200).json({ data: data.rows });
}
Expand Down
40 changes: 39 additions & 1 deletion controllers/helpers/AuthController.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
import bcrypt from 'bcrypt';
import titlecase from 'titlecase';

import { InternalServerError } from '../../utils/errorHandlers';
import sendEmail from '../../utils/sendEmail';
import { async } from 'rxjs/internal/scheduler/async';

export const sendSignUpMessage = (user, req) => {
const path = `/users/${user.id}/account-confirmation`;
const url = `${req.protocol}://${req.hostname}${path}`;

const template_data = {
firstname: titlecase(user.firstname),
lastname: titlecase(user.lastname),
confirm_account_link: url,
};
const data = {
email: user.email,
template_name: 'confirm_account',
};
sendEmail(data, template_data);
return;
};

export const check_user_exists = async (model_instance, clause, res) => {
try {
Expand Down Expand Up @@ -39,12 +59,30 @@ export const add_user_to_db = async (model_instance, req, res) => {
};

export const get_existing_user = async (model_instance, res, clause) => {
const select_rows = `id, email, firstname, mailverified,
photo, lastname, phone, status, address`;
try {
const { rows } = await model_instance.select(
'id, email, firstname, photo, lastname, phone, status, address',
select_rows,
clause
);
return rows[0];
}
catch (e) { throw InternalServerError(res, e); }
};

export const update_if_exists = async (model_instance,
id, column, clause, res) => {

try {
const exists = await check_user_exists(model_instance, clause, res);
if (exists) {
await model_instance.update(column, clause);
const user = await get_existing_user(model_instance, res, clause);
return res.status(200).json({ data: user });
}
return res.status(404)
.json({ error: `User with id ${id} not found` });
}
catch (e) { return; }
};
82 changes: 60 additions & 22 deletions controllers/helpers/LoansController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
import titlecase from 'titlecase';

import { InternalServerError } from '../../utils/errorHandlers';
import { dev_logger } from '../../utils/loggers';
import sendEmail from '../../utils/sendEmail';
// import { dev_logger } from '../../utils/loggers';

export const sendNewApplicationMessage = loan => {
const template_data = {
amount: loan.amount,
interest: loan.interest,
tenor: loan.tenor,
paymentinstallment: loan.paymentinstallment
};
const data = {
email: loan.useremail,
template_name: 'new_loan_application',
};
sendEmail(data, template_data);
return;
};

export const sendFollowUpMessage = (status, loan) => {
let message;
if (status === 'approved') {
message = 'Congratulations, your loan application was approved.';
}
else {
message = 'Sorry, your loan application was rejected.';
}
const template_data = {
status: titlecase(status),
message
};
const data = {
email: loan.useremail,
template_name: 'loan_status',
};
sendEmail(data, template_data);
return;
};

export const check_loan_existence = async (model_instance, req, res) => {
const { id } = req.params;
Expand All @@ -13,16 +51,18 @@ export const check_loan_existence = async (model_instance, req, res) => {
};

export const add_loan_to_db = async (model_instance, req, res) => {
const { userid, amount, tenor } = req.body;
const { userid, useremail, amount, tenor } = req.body;
const interest = 0.05 * amount;
const paymentinstallment = (amount + interest) / tenor;
const balance = amount - 0;

try {
return await model_instance.insert_with_return(
'(userid, amount, tenor, interest, balance, paymentinstallment)',
`'${userid}', '${amount}', '${tenor}', '${interest}', '${balance}',
'${paymentinstallment}'`);
`(userid, useremail, amount, tenor, interest,
balance, paymentinstallment)`,

`'${userid}', '${useremail}', '${amount}', '${tenor}',
'${interest}', '${balance}', '${paymentinstallment}'`);
}
catch (e) { throw InternalServerError(res, e);}
};
Expand All @@ -46,21 +86,17 @@ export const update_loan_balance = async (model_instance, req, res) => {
catch (e) { throw InternalServerError(res, e); }
};

export const get_loan_by_id = async (model_instance, id, res, code) => {
export const get_loan_by_id = async (model_instance, id, res) => {
try {
const { rows } = await model_instance.select(
`id, userid, createdon, status, repaid, amount,
`id, userid, useremail, createdon, status, repaid, amount,
tenor, interest, balance, paymentinstallment`,
`WHERE id=${id}`
);
if (rows.length === 0) return res.status(404).json({
error: `Loan with id ${id} does not exist`
});

return res.status(code).json({ data: rows[0] });
return rows[0];
}
catch (e) {
throw InternalServerError(null, res, e);
throw InternalServerError(res, e);
}
};

Expand Down Expand Up @@ -88,19 +124,21 @@ export const add_repayment_to_db = async (model_instance, req, res) => {
catch (e) { throw InternalServerError(res, e);}
};

export const get_repayment_by_id = async (model_instance, id, res, code) => {
export const get_repayment_from_db = async (model_instance, id, res) => {
try {
const { rows } = await model_instance.select(
'id, loanid, adminid, createdon, amount', `WHERE id=${id}`
);
if (rows.length === 0) {
return res.status(404).json({
error: `Repayment with id ${id} not found`
});
}
return res.status(code).json({ data: rows[0] });
return rows[0];
}
catch (e) {
throw InternalServerError(null, res, e);
catch (e) { throw InternalServerError(res, e); }
};

export const return_repay_or_error = async (model_instance, id, res, code) => {
const repay = await get_repayment_from_db(model_instance, id, res);
if (repay) {
return res.status(code).json({ data: repay });
}
return res.status(404)
.json({ error: `Repayment with id ${id} not found` });
};
Loading