var DEBUG = false;
var MY_SERVICE_KEY = 'midterm_eval';
// identifies our service within the services_config.json file
// javascript app to connect to firebase and email pdf
// dependencies
require('rconsole');
var Firebase = require("firebase");
var fs = require('fs');
var mustache = require('mustache');
var transactq = require(__dirname + '/transactq');
console.set({
title: 'gradphile.process-midterm-eval'
});
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// load common and secret values for all services
var config = require(__dirname + '/configure_microservice');
config.loadConfiguration(MY_SERVICE_KEY);
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
if (DEBUG) {
config.cc_email = "tom+test@houptlab.org";
config.bcc_email = "tom+test@houptlab.org";
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// set up transactq
transactq.set_firebase_config(MY_SERVICE_KEY,
config.firebase_base_url,
config.firebaseSecret);
transactq.set_mail_server(config.email_account['server'],
config.email_account['from'],
config.email_account['username'],
config.email_account['password']);
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// Load template files
var template_names = [
"instructor_confirmation_email_template",
"student_reminder_email_template",
"student_confirmation_email_template",
"assoc_chair_confirmation_email_template"
];
var templates = {};
for (var i = 0; i < template_names.length; i++) {
templates[template_names[i]] = fs.readFileSync(__dirname + '/email_templates/midterm_eval/' + template_names[i] + '.txt', {
encoding: 'utf-8'
});
mustache.parse(templates[template_names[i]]);
}
//---------------------------------------------------------------------------------------
/**
return a hashmap, eg.
{ "year": "2021", term: "fall"}
Note strings, lowercase.
*/
function current_term(offset_in_terms) {
let curr_date = new Date();
let curr_year = curr_date.getFullYear();
let curr_month = curr_date.getMonth();
const term_map= [
"spring", // jan - april
"spring",
"spring",
"spring",
"summer", //jun - july
"summer",
"summer",
"fall", //aug - dec
"fall",
"fall",
"fall",
"fall"
];
const term_offsets = {
"spring": 0,
"summer": 1,
"fall": 2
};
const term_by_offset = [
"spring","summer","fall"
];
let curr_term = term_map[curr_month];
let curr_term_offset = term_offsets[curr_term];
for (let i=0;i<offset_in_terms;i++) {
curr_term_offset--;
if (curr_term_offset < 0) {
curr_year--;
curr_term_offset = 2;
}
curr_term = term_by_offset[curr_term_offset]
}
return { "year": curr_year.toString(), term: curr_term };
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// var firebaseDB = null;
//
// function connectToFirebase() {
//
// var midtermDataURL = config.firebase_base_url + '/' + config.firebase_directory;
// console.log("config.firebase_directory: " + config.firebase_directory);
// console.log("config.firebase_base_url: " + config.firebase_base_url);
// console.log("midtermDataURL: " + midtermDataURL);
//
// var firebaseDB = new Firebase(midtermDataURL);
//
// firebaseDB.authWithCustomToken(config.firebaseSecret, function(error, authData) {
// if (error) {
// console.error("Error: Login Failed: ", error);
// }
// else {
// console.log("Login Succeeded!");
// auth
//
// } // logged in successfully
//
// });
//
// return midtermData;
//
// }
function monitorFirebase(year,term) {
var midtermDataURL = config.firebase_base_url + '/' + config.firebase_directory + '/' + year + '/' + term + '/';
console.log("config.firebase_directory: " + config.firebase_directory);
console.log("config.firebase_base_url: " + config.firebase_base_url);
console.log("midtermDataURL: " + midtermDataURL);
var midtermData = new Firebase(midtermDataURL);
midtermData.authWithCustomToken(config.firebaseSecret, function(error, authData) {
if (error) {
console.error("Error: Login Failed: ", error);
}
else {
console.log("Login Succeeded for " + year + " " + term + "!", authData);
} // logged in successfully
});
listenForChanges(midtermData);
}
//---------------------------------------------------------------------------------
function listenForChanges(midtermData) {
// listen for additons or changes to idp data
console.log("listen for changes");
midtermData.on('child_added', function(childSnapshot, prevChildKey) {
// console.log(childSnapshot);
console.notice("\n\nChild added at key: " + childSnapshot.key());
processMidtermChild(midtermData,childSnapshot);
});
midtermData.on('child_changed', function(childSnapshot, prevChildKey) {
// console.log(childSnapshot);
console.notice("\n\nChild changed at key: " + childSnapshot.key());
processMidtermChild(midtermData,childSnapshot);
});
}
//---------------------------------------------------------------------------------
function setTimeStampForChildAtKey(firebaseDataRef,childSnapshot,subject_key,timestampKey) {
// utility to save a timestamp into firebase, eg for confirmation email sent
console.log("set timestamp for " + subject_key + " " + timestampKey);
firebaseDataRef.child(childSnapshot.key()).child(subject_key).child(timestampKey).set(Date.now(), function(error) {});
}
//---------------------------------------------------------------------------------
function setCompletedForChild(firebaseDataRef,childSnapshot) {
// utility to save a timestamp into firebase, eg for confirmation email sent
console.log("completed for " + childSnapshot.child('student').child('fsuid') );
firebaseDataRef.child(childSnapshot.key()).child('completed_timestamp').set(Date.now(), function(error) {});
}
//---------------------------------------------------------------------------------
/* logic:
if child has student signature, but has not been sent a confirmation email send confirmation to student.
once student confirmation has been sent, check if chair/cochair needs to sign and send them a reminder
if child has chair signature, but has not been sent a confirmation email, send confirmation to chair.
once chair confirmation has been sent, check if student needs to sign and send them a reminder
*/
//---------------------------------------------------------------------------------
function needs_confirmation(childSnapshot,subject_key) {
console.log("need confirmation " + subject_key + ": " + childSnapshot.child(subject_key).child('signature_timestamp').val());
console.log("confirmation sent " + subject_key + ": " + childSnapshot.child(subject_key).child('sent_conf_email_timestamp').val());
var flag = (
null != childSnapshot.child(subject_key).child('signature_timestamp').val()
&&
null == childSnapshot.child(subject_key).child('sent_conf_email_timestamp').val()
);
console.log(flag );
return (
null != childSnapshot.child(subject_key).child('signature_timestamp').val()
&& null == childSnapshot.child(subject_key).child('sent_conf_email_timestamp').val()
);
}
//---------------------------------------------------------------------------------
function needs_reminder(childSnapshot) {
let keys = [ "chair", "student"];
let needs = {
"chair": { "signed": false, "reminder_sent": false},
"student": { "signed": false, "reminder_sent": false},
}
keys.forEach(function(k) {
needs[k].signed = childSnapshot.child(k).child('sent_conf_email_timestamp').val();
needs[k].reminder_sent = childSnapshot.child(k).child('sent_reminder_email_timestamp').val();
});
if (needs['chair'].signed && !needs['student'].signed && !needs['student'].reminder_sent) {
return 'student';
}
if (needs['student'].signed && !needs['chair'].signed && !needs['chair'].reminder_sent) {
return 'chair';
}
return null;
}
//---------------------------------------------------------------------------------
function needs_completion_timestamp(childSnapshot) {
console.log("need completion student " + childSnapshot.child('student').child('signature_timestamp').val());
console.log("need completion chair " + childSnapshot.child('chair').child('signature_timestamp').val());
let flag = (
null != childSnapshot.child('student').child('signature_timestamp').val()
&&
null != childSnapshot.child('chair').child('signature_timestamp').val()
&&
null == childSnapshot.child('completed_timestamp').val()
);
console.log("need completion flag " + flag);
return (
null != childSnapshot.child('student').child('signature_timestamp').val()
&&
null != childSnapshot.child('chair').child('signature_timestamp').val()
&&
null == childSnapshot.child('completed_timestamp').val()
);
}
//---------------------------------------------------------------------------------
function processMidtermChild(midtermData,childSnapshot) {
console.log("processMidtermChild: " + childSnapshot.key());
if (needs_confirmation(childSnapshot,'student')) {
// confirm with student, email chair and cochair to complete their section
if (DEBUG) console.log('student_signature_timestamp');
student_signed(midtermData,childSnapshot);
}
if (needs_confirmation(childSnapshot,'chair')) {
// confirm with chair and student
if (DEBUG) console.log('chair_signature_timestamp');
chair_signed(midtermData,childSnapshot, 0);
}
if (needs_confirmation(childSnapshot,'cochair')) {
// confirm with cochair and student
if (DEBUG) console.log('cochair_signature_timestamp');
chair_signed(midtermData,childSnapshot, 1);
}
let key = needs_reminder(childSnapshot);
if (key) {
if (DEBUG) console.log(key + ' needs reminder');
if ('student' == key) {
sendStudentReminderEmail(midtermData ,childSnapshot);
}
if ('chair' == key) {
sendChairReminderEmail(midtermData ,childSnapshot);
}
}
if (needs_completion_timestamp(childSnapshot)) {
// confirm with student, email chair and cochair to complete their section
if (DEBUG) console.log('needs completion');
setCompletedForChild(midtermData,childSnapshot);
}
}
//---------------------------------------------------------------------------------------
function sendChairReminderEmail(midtermData,childSnapshot) {
var first_name = childSnapshot.child('student').child('first_name').val().toString();
var last_name = childSnapshot.child('student').child('last_name').val().toString();
var fsuid = childSnapshot.child('student').child('fsuid').val().toString();
var term = childSnapshot.child('term').val().toString();
var year = childSnapshot.child('year').val().toString();
var chair_first_name = childSnapshot.child("chair").child('first_name').val().toString();
var chair_last_name = childSnapshot.child("chair").child('last_name').val().toString();
var chair_email = childSnapshot.child("chair").child('email').val().toString();
var chair_fsuid = chair_last_name
if (null != childSnapshot.child("chair").child('fsuid').val())
var chair_fsuid = childSnapshot.child("chair").child('fsuid').val().toString();
console.notice("chair" + ' Reminder: ' + last_name + ' ' + fsuid);
// var chair_email_message = 'Dear Dr. ' + chair_name + ':\n\n Thank you for submitting the Annual Review form for ' + term + ' ' + year + ' for ' + first_name + ' ' + last_name + '.\n\nThe other members of the student\'s committee will be asked by email to acknowledge the review.\n\nIf you have any questions, feel free to contact ' + config.grad_coordinator + '. \n\n';
var letter_fields = {
"term": term,
"year": year,
"first_name": first_name,
"last_name": last_name,
"chair_first_name": chair_first_name,
"chair_last_name": chair_last_name,
"form_url": (config.gradawan_base_url + '/idp/?id=' + fsuid + '&year=' + year + '&term=' + term),
"grad_coordinator": config.grad_coordinator,
"grad_coordinator_contact": config.grad_coordinator_contact,
"gradphile_name": config.gradphile_name
};
var email_message = mustache.render(templates['chair_reminder_email_template'], letter_fields);
var chair_email_subject = term + ' ' + year + ' IDP to be signed';
if (DEBUG) {
chair_email = "tom+chair@houptlab.org";
}
// send email with reminder
transactq.send_email_with_reminder(fsuid, chair_fsuid, year, term, chair_email, chair_email_subject, email_message);
setTimeStampForChildAtKey(midtermData,childSnapshot,'chair','sent_reminder_email_timestamp');
}
//---------------------------------------------------------------------------------------
function sendStudentReminderEmail(midtermData,childSnapshot) {
var first_name = childSnapshot.child('student').child('first_name').val().toString();
var last_name = childSnapshot.child('student').child('last_name').val().toString();
var fsuid = childSnapshot.child('student').child('fsuid').val().toString();
var student_email = childSnapshot.child('student').child('email').val().toString();
var term = childSnapshot.child('term').val().toString();
var year = childSnapshot.child('year').val().toString();
var chair_first_name = childSnapshot.child('chair').child('first_name').val().toString();
var chair_last_name = childSnapshot.child('chair').child('last_name').val().toString();
console.notice('Student Reminder: ' + last_name + ' ' + fsuid);
var letter_fields = {
"term": term,
"year": year,
"first_name": first_name,
"last_name": last_name,
"chair_first_name": chair_first_name,
"chair_last_name": chair_last_name,
"form_url": (config.gradawan_base_url + '/idp/?id=' + fsuid + '&year=' + year + '&term=' + term),
"grad_coordinator": config.grad_coordinator,
"grad_coordinator_contact": config.grad_coordinator_contact,
"gradphile_name": config.gradphile_name
};
var student_email_message = mustache.render(templates['student_reminder_email_template'], letter_fields);
var student_email_subject = term + ' ' + year + ' IDP to be signed';
if (DEBUG) {
student_email = "tom+student@houptlab.org";
}
// send email without reminder
transactq.send_email(fsuid, fsuid, year, term, student_email, student_email_subject, student_email_message);
setTimeStampForChildAtKey(midtermData,childSnapshot,'student','sent_reminder_email_timestamp');
}
//---------------------------------------------------------------------------------------
function student_signed(midtermData,childSnapshot) {
var first_name = childSnapshot.child('student').child('first_name').val().toString();
var last_name = childSnapshot.child('student').child('last_name').val().toString();
var fsuid = childSnapshot.child('student').child('fsuid').val().toString();
var student_email = childSnapshot.child('student').child('email').val().toString();
var term = childSnapshot.child('term').val().toString();
var year = childSnapshot.child('year').val().toString();
var chair_first_name = childSnapshot.child('chair').child('first_name').val().toString();
var chair_last_name = childSnapshot.child('chair').child('last_name').val().toString();
console.notice('Student Signed: ' + last_name + ' ' + fsuid);
var letter_fields = {
"term": term,
"year": year,
"first_name": first_name,
"last_name": last_name,
"chair_first_name": chair_first_name,
"chair_last_name": chair_last_name,
"form_url": (config.gradawan_base_url + '/idp/?id=' + fsuid + '&year=' + year + '&term=' + term),
"grad_coordinator": config.grad_coordinator,
"grad_coordinator_contact": config.grad_coordinator_contact,
"gradphile_name": config.gradphile_name
};
var student_email_message = mustache.render(templates['student_confirmation_email_template'], letter_fields);
var student_email_subject = term + ' ' + year + ' IDP acknowledgement';
if (DEBUG) {
student_email = "tom+student@houptlab.org";
}
// send email without reminder
transactq.send_email(fsuid, fsuid, year, term, student_email, student_email_subject, student_email_message);
setTimeStampForChildAtKey(midtermData,childSnapshot,'student','sent_conf_email_timestamp');
// if (needs_reminder(childSnapshot,'chair')) {
// sendChairReminderEmail(midtermData,childSnapshot);
// }
}
//---------------------------------------------------------------------------------------
function chair_signed(midtermData,childSnapshot, chair_index) {
// chair_index is 0 for chair, 1 for cochair1, 2 for cochair2
var first_name = childSnapshot.child('student').child('first_name').val().toString();
var last_name = childSnapshot.child('student').child('last_name').val().toString();
var fsuid = childSnapshot.child('student').child('fsuid').val().toString();
var term = childSnapshot.child('term').val().toString();
var year = childSnapshot.child('year').val().toString();
var chair_key = "cochair" + chair_index;
if (chair_index == '0') {
chair_key = 'chair';
}
var chair_conf_key = 'sent_conf_email_timestamp';
var chair_first_name = childSnapshot.child(chair_key).child('first_name').val().toString();
var chair_last_name = childSnapshot.child(chair_key).child('last_name').val().toString();
var chair_email = childSnapshot.child(chair_key).child('email').val().toString();
var chair_fsuid = chair_last_name;
if ( childSnapshot.child(chair_key).hasChild('fsuid') ) {
chair_fsuid = childSnapshot.child(chair_key).child('fsuid').val().toString();
}
console.notice(chair_key + ' Signed: ' + last_name + ' ' + fsuid);
// var chair_email_message = 'Dear Dr. ' + chair_name + ':\n\n Thank you for submitting the Annual Review form for ' + term + ' ' + year + ' for ' + first_name + ' ' + last_name + '.\n\nThe other members of the student\'s committee will be asked by email to acknowledge the review.\n\nIf you have any questions, feel free to contact ' + config.grad_coordinator + '. \n\n';
var letter_fields = {
"term": term,
"year": year,
"first_name": first_name,
"last_name": last_name,
"chair_first_name": chair_first_name,
"chair_last_name": chair_last_name,
"form_url": (config.gradawan_base_url + '/idp/?id=' + fsuid + '&year=' + year + '&term=' + term),
"grad_coordinator": config.grad_coordinator,
"grad_coordinator_contact": config.grad_coordinator_contact,
"gradphile_name": config.gradphile_name
};
var email_message = mustache.render(templates['chair_confirmation_email_template'], letter_fields);
var chair_email_subject = term + ' ' + year + ' IDP acknowledgement';
if (DEBUG) {
chair_email = "tom+chair@houptlab.org";
}
// send email without reminder
transactq.send_email(fsuid, chair_fsuid, year, term, chair_email, chair_email_subject, email_message);
setTimeStampForChildAtKey(midtermData,childSnapshot,'chair',chair_conf_key);
// if (needs_reminder(childSnapshot,'student')) {
// sendStudentReminderEmail(midtermData,childSnapshot)
// }
} // chair signed
//---------------------------------------------------------------------------------------
monitorFirebase("2019","fall");
monitorFirebase("2020","spring");
monitorFirebase("2020","summer");
monitorFirebase("2020","fall");
/*
monitorFirebase("2021","spring");
monitorFirebase("2021","summer");
monitorFirebase("2021","fall");
*/