@ionaai/rtnapi
Version:
common api collection for RTN
1,306 lines (1,160 loc) • 69.8 kB
JavaScript
'use strict';
var _ = require("underscore");
var lodash = require("lodash-node");
var moment = require('moment');
var path = require('path')
var Cache = require('memory-cache');
var request = require('request');
var DBModel = require('@ionaai/rtndbmodel');
var SMSLog = DBModel.smsLog;
var LifeCycle = DBModel.applicationLifeCycle;
var MailLog = DBModel.mailLog;
var User = DBModel.user;
var fs = require('fs');
var Interviews = DBModel.interviews;
var Job = DBModel.job;
var AppliedJobData = DBModel.appliedJobData;
var mongoose = require("mongoose");
var ejs = require('ejs');
var stageDetail = require("./stageDetails.json");
var stageFunnelMap = require("./stageFunnelMap.json");
var exotel = require('./exotel');
var Match = require('./match');
var PrepServices = require('./prepservices');
function generateUUID() {
var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
var count = function (ary, classifier) {
return ary.reduce(function (counter, item) {
var p = (classifier || String)(item);
counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
return counter;
}, {})
}
var searchJobsByUser = function (Job, params, colString, next) {
Date.prototype.toLocaleDateString = function (d) {
var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sept", "Oct", "Nov", "Dec"
];
return (d.getDate() + "-" + monthNames[d.getMonth()] + "-" + (d.getYear() - 100));
};
var query = Job.find();
if (params.industry) {
query.in('industry', params.industry);
}
if (params.sector) {
query.in('sector', params.sector);
}
if (params.function) {
query.in('function', params.function);
}
Job.find(query).exec(function (err, jobs) {
if (!err) {
var data = _.map(jobs, function (item) {
return {
id: item.id,
name: item.name,
cutOffText: item.cutOffText,
eligibility: item.eligibility,
eligibilityTags: item.eligibilityTags,
salaryRange: item.salaryRange,
minSalary: item.minSalary,
excitingStuff: item.excitingStuff,
employer: item.employer,
workLocation: _.pluck(item.workLocation, "area").join(" ,"),
logoUrl: item.logoUrl,
urlSlug: item.urlSlug,
hotJobFactor: item.hotJobFactor,
incentiveAvailable: item.incentiveAvailable,
gender: item.gender,
badges: item.badges,
localCandidateOnly: item.localCandidateOnly
};
});
next(null, data);
} else {
next(err, 'Something went wrong while executing query.');
}
})
};
var similarJobsByJobName = function (Job, params, next) {
Date.prototype.toLocaleDateString = function (d) {
var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sept", "Oct", "Nov", "Dec"
];
return (d.getDate() + "-" + monthNames[d.getMonth()] + "-" + (d.getYear() - 100));
};
var query = Job.find();
query.ne("_id", params.id);
var queryArray = [];
if (params.state) {
query.elemMatch("workLocation", {
state: params.state
});
}
if (params.function) {
queryArray.push({
function: params.function
});
}
if (params.roleName) {
queryArray.push({
roleName: params.roleName
});
}
if (params.titleName) {
queryArray.push({
titleName: params.titleName
});
}
query.where({
'isApplicable': true,
'applicationType': 'application'
});
query.or(queryArray);
Job.find(query).limit(3).exec(function (err, jobs) {
console.log("Found Jobs " + (jobs ? jobs.length : 0));
if (!err && jobs) {
var data = _.map(jobs, function (item) {
return {
id: item.id,
name: item.name,
cutOffText: item.cutOffText,
eligibility: item.eligibility,
eligibilityTags: item.eligibilityTags,
salaryRange: item.salaryRange,
minSalary: item.minSalary,
excitingStuff: item.excitingStuff,
orgDisplayName: item.orgDisplayName,
workLocation: _.pluck(item.workLocation, "area").join(" ,"),
logoUrl: item.logoUrl,
urlSlug: item.urlSlug,
hotJobFactor: item.hotJobFactor,
incentiveAvailable: item.incentiveAvailable,
gender: item.gender,
badges: item.badges,
localCandidateOnly: item.localCandidateOnly
};
});
next(null, data);
} else if (!jobs) {
next(null, jobs);
} else {
console.log(err);
next(err, 'Something went wrong while executing query.');
}
})
};
var searchUsersByJobParams = function (AppliedJobData, params, next) {
Date.prototype.toLocaleDateString = function (d) {
var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sept", "Oct", "Nov", "Dec"
];
return (d.getDate() + "-" + monthNames[d.getMonth()] + "-" + (d.getYear() - 100));
};
var query = AppliedJobData.find({
isMasterApplication: true
});
if (params.degreeTypes) {
query.in('educationInfo.degreeType', params.degreeTypes);
}
if (params.fresherFlag) {
if (params.fresherFlag == "yes") {
query.where('isFresher').eq(true);
} else {
query.where('isFresher').eq(false);
}
}
if (params.notDegreeTypes) {
query.nin('educationInfo.degreeType', params.notDegreeTypes);
}
if (params.degrees) {
query.in('educationInfo.degree', params.degrees);
}
if (params.cities) {
var receivedCities = [];
for (var i = 0; i < params.cities.length; i++) {
if (receivedCities.indexOf(params.cities[i].city) === -1) {
receivedCities.push(params.cities[i].city)
}
}
query.in('location.city', receivedCities);
}
if (params.states) {
query.in('location.state', params.states);
}
if (params.mobiles) {
query.in('mobile', params.mobiles);
}
if (params.emails) {
query.in('email', params.emails);
}
if (params.names) {
query.in('seeker_profile.first_name', params.names);
}
if (params.appliedJobs) {
query.in('appliedJobs.jobId', params.appliedJobs);
}
if (params.assessments) {
query.in('assessments.quizTypeName', params.assessments);
}
if (params.creationDateStart) {
var dateString = params.creationDateStart;
var cutoff = new Date(dateString);
var cutOffNext = cutoff;
if (params.creationDateEnd) {
dateString = params.creationDateEnd;
var cutoff2 = new Date(dateString);
cutOffNext = cutoff2;
}
query.where('creationDate').gt(cutoff).lt(cutOffNext);
}
AppliedJobData.find(query, 'email isFresher mobile enrolledCourses assessments applicationDate educationInfo userId seeker_profile.first_name seeker_profile.last_name location').exec(function (err, users) {
console.log("Found Users " + users.length);
if (!err) {
var data = _.map(users, function (item) {
return {
id: item.userId,
name: item.seeker_profile.first_name + ' ' + (item.seeker_profile.last_name ? item.seeker_profile.last_name : ''),
email: item.email,
phone: item.mobile,
addressLine1: item.location ? item.location.addressLine1 : '',
addressLine2: item.location ? item.location.addressLine2 : '',
state: item.location ? item.location.state : '',
addressCity: item.location ? item.location.city : '',
educationInfo: item.educationInfo ? _.map(item.educationInfo, function (i) {
return i.degreeType;
}).join(", ") : '',
creationDate: item.applicationDate.toLocaleDateString(item.applicationDate),
enrolledCourses: item.enrolledCourses ? item.enrolledCourses.length : 0,
assessments: item.assessments ? item.assessments.length : 0,
isFresher: item.isFresher
};
});
next(null, data);
} else {
next(err, 'Something went wrong while executing query.');
}
})
};
//-------START------------
// Creating queue data structure for Breadth First Search of tree
var Queue = function () {
this.first = null;
};
var qNode = function (data) {
this.data = data;
this.next = null;
};
Queue.prototype.enqueue = function (data) {
var node = new qNode(data);
if (!this.first) {
this.first = node;
} else {
var n = this.first;
while (n.next) {
n = n.next;
}
n.next = node;
}
return node;
};
Queue.prototype.dequeue = function () {
var temp = this.first;
this.first = this.first.next;
return temp;
};
//-------END------------
//Creating tree data structure
function Node(stageName, count) {
this.stageName = stageName;
this.children = [];
}
function Tree(stageName) {
var node = new Node(stageName);
this._root = node;
}
//returing a node and its children from tree by doing the Depth First Search
Tree.prototype.traverseDF = function (node) {
var temp = [];
(function recurse(currentNode) {
lodash.each(currentNode.children, function (value, index) {
recurse(currentNode.children[index]);
})
temp.push(currentNode.stageName);
})(node);
return temp;
};
//based on a stage returing a node and its children from tree by doing the Depth First Search
Tree.prototype.traverseDFStage = function (stage) {
var that = this,
childStages = null;
(function recurse(currentNode) {
lodash.each(currentNode.children, function (value, index) {
if (currentNode.children[index].stageName != stage) {
recurse(currentNode.children[index]);
} else {
var node = currentNode.children[index];
childStages = that.traverseDF(node);
return false;
}
})
})(this._root);
return childStages;
}
//Now if the stages array parameter is equal to ["Interview Selected","Interview Rejected","Interview Invited","On Hold"]
//then the final result should be ["Interview Invited","Interview Selected","Interview Rejected","Not Attended",
//"Offer Rejected","Offer Given","Offer Accepted","Joined","On Hold"]
//that means extract the stage first from stages array whose children covers the maximum stages from stages array
//for example in above example extarct "Interview Invited" first because its children contain most of the other elements
//of the stages array like "Interview Selected","Interview Rejected". After this find the children of the left element
//of the stages array i.e. "On Hold"
//If stages array contains any of the below exceptional stages value then they will always be included in the final result as
//they donot fall under funnel mode
//exceptionalStages=["Filtered Out","Dormant","Not Qualified","In Queue","Cancelled By User"]
Tree.prototype.getStageAndChildren = function (stages) {
console.log(stages);
var exceptionalStages = ["Filtered Out", "Dormant", "Not Qualified", "In Queue", "Cancelled By User"];
var node = null;
var childStages = [];
childStages.push(lodash.intersection(stages, exceptionalStages));
stages = lodash.difference(stages, exceptionalStages);
if (stages.indexOf(this._root.stageName) >= 0) {
childStages.push(this.traverseDFStage(this._root.stageName));
} else {
var that = this;
var queue = new Queue();
queue.enqueue(this._root);
var currentTree = queue.dequeue();
while (currentTree) {
for (var i = 0, length = currentTree.data.children.length; i < length; i++) {
queue.enqueue(currentTree.data.children[i]);
}
if (stages.indexOf(currentTree.data.stageName) >= 0) {
var childnodes = that.traverseDFStage(currentTree.data.stageName),
isarrayOfChildnodesSupersetsetOfStages;
stages.splice(stages.indexOf(currentTree.data.stageName), 1);
isarrayOfChildnodesSupersetsetOfStages = stages.every(function (val) {
return childnodes.indexOf(val) >= 0;
});
childStages.push(childnodes);
if (isarrayOfChildnodesSupersetsetOfStages) {
break;
} else {
for (var i = 0; i < stages.length; i++) {
if (childnodes.indexOf(stages[i]) >= 0) {
stages.splice(stages.indexOf(stages[i]), 1);
}
}
currentTree = queue.dequeue();
}
} else {
if (queue.first) {
currentTree = queue.dequeue();
} else {
break;
}
}
}
}
return childStages.join(",").split(",");
};
//Saves the stage funnel structure in tree data structure. Then uses the getStageAndChildren(stages) function to get
//the stage names of the stages array and their children.
var GetStageAndChildren = function (stageNames) {
var stageTree = new Tree('Started');
stageTree._root.children.push(new Node('Qualified'));
stageTree._root.children[0].children.push(new Node('Recommended'));
stageTree._root.children[0].children.push(new Node('RTN Rejected'));
stageTree._root.children[0].children.push(new Node('Assessment Invited'));
stageTree._root.children[0].children.push(new Node('Assessment Rejected'));
stageTree._root.children[0].children.push(new Node('Assessment Not Attended'));
stageTree._root.children[0].children[0].children.push(new Node('On Hold'));
stageTree._root.children[0].children[0].children.push(new Node('Recommended Rejected'));
stageTree._root.children[0].children[0].children.push(new Node('Interview Invited'));
stageTree._root.children[0].children[0].children[2].children.push(new Node('Interview Selected'));
stageTree._root.children[0].children[0].children[2].children.push(new Node('Interview Rejected'));
stageTree._root.children[0].children[0].children[2].children.push(new Node('Not Attended'));
stageTree._root.children[0].children[0].children[2].children[0].children.push(new Node('Offer Rejected'));
stageTree._root.children[0].children[0].children[2].children[0].children.push(new Node('Offer Given'));
stageTree._root.children[0].children[0].children[2].children[0].children.push(new Node('Offer Accepted'));
stageTree._root.children[0].children[0].children[2].children[0].children.push(new Node('Joined'));
var stageAndChildrenStages = stageTree.getStageAndChildren(stageNames);
console.log("stageAndChildren " + stageAndChildrenStages);
return stageAndChildrenStages;
}
var GetStagesInFunnel = function (stages, lifeCycle) {
var finalStageList = [];
if (stages.constructor === Array) {
_.each(stages, function (stage) {
console.log("Find Funneled stage of " + stage);
var thisStage = _.find(lifeCycle.stages, function (s) {
return (s.name == stage);
});
console.log(thisStage.funnelStages);
finalStageList = [].concat(finalStageList, thisStage.funnelStages);
});
finalStageList = _.uniq(finalStageList);
console.log(finalStageList);
return finalStageList;
} else {
var finalStageList = _.find(lifeCycle.stages, function (s) {
return (s.name == stages);
})
console.log(finalStageList);
return finalStageList.funnelStages;
}
}
var findApplicants = function (AppliedJobData, params, next) {
let skip = params.skip;
let limit = params.limit;
//Search Query Magicwords parsing
if (params.appInterviewDate) {
if (params.appInterviewDate === 'TODAY') {
params.appInterviewDate = moment().startOf('day').format("DD/MM/YYYY");
} else if (params.appInterviewDate === 'TOMORROW') {
params.appInterviewDate = moment().add(1, 'days').startOf('day').format("DD/MM/YYYY");
} else if (params.appInterviewDate === 'TOMORROW+1') {
params.appInterviewDate = moment().add(2, 'days').startOf('day').format("DD/MM/YYYY");
}
}
Date.prototype.toLocaleDateString = function (d) {
var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sept", "Oct", "Nov", "Dec"
];
return (d.getDate() + "-" + monthNames[d.getMonth()] + "-" + (d.getYear() - 100));
};
var query = undefined;
if (params.userSearch) {
query = AppliedJobData.find({
isMasterApplication: true,
isArchived: false
});
} else {
query = AppliedJobData.find({
isMasterApplication: false,
isArchived: false
});
}
if (params.keyword) {
var keyword = params.keyword.replace("@gmail.com", "");
query = query.where({
$text: {
$search: keyword
},
isMasterApplication: false
});
}
if (params.appId) {
var appId = params.appId;
query = query.where({
applicationId: appId
});
}
if (params.bulkSearchDataType && params.bulkSearchData) {
console.log("bulk search for ", params.bulkSearchDataType);
var givenString = params.bulkSearchData.replace("[", "").replace("]", "");
var splitStrings = givenString.split(/["\s,;]/);
console.log("Split data ", splitStrings.length, " > ", splitStrings);
if (params.bulkSearchDataType === 'Mobile Numbers') {
query.in('mobile', splitStrings);
} else if (params.bulkSearchDataType === 'Email Ids') {
query.in('email', splitStrings);
} else if (params.bulkSearchDataType === 'External / Oracle Ids') {
query.in('client.applicationId', splitStrings);
} else if (params.bulkSearchDataType === 'Passport Numbers') {
query.in('passport.number', splitStrings);
} else if (params.bulkSearchDataType === 'ApplicationId') {
query.in('applicationId', splitStrings);
}
}
if (params.agencies && params.agencies.length) {
query.elemMatch('agencies', {
associatedOrgId: params.orgId,
orgId: {
$in: params.agencies
}
});
}
if (params.vendorLock) {
query.where('vendorLock.status', {
$in: ['requested', 'open']
});
}
if (params.countryCodes && params.countryCodes.length) {
query.where('countryCode', {
$in: params.countryCodes
});
}
if (params.nationalities && params.nationalities.length) {
query.where('passport.nationality', {
$in: params.nationalities
});
}
if (params.clients && params.clients.length) {
query.where('client.orgId', {
$in: params.clients
});
}
if (params.orgType === 'employer') {
query.where('client.orgId', params.orgId);
} else if (params.orgIds && params.orgIds.length && (!params.agencies)) {
var agencyOption = {
orgId: params.orgId
}
query.elemMatch('agencies', agencyOption);
} else if (params.orgId) {
var agencyOption = {
orgId: params.orgId
}
query.elemMatch('agencies', agencyOption);
}
if (params.applicationType) {
var applicationType = params.applicationType;
query = query.where('applicationType', applicationType);
}
if (params.isVisited === 'yes') {
query.where('isVisited', true);
} else if (params.isVisited === 'no') {
query.where('isVisited', false);
}
if (params.abbyStatus) {
query.where('abbyStatus', params.abbyStatus);
}
if (params.tags && params.tags.length) {
query.in('tags.title', params.tags);
}
if (params.gender) {
query.in('gender', params.gender);
}
//sourcingOrgIds will be always overwritten by basicPlutoOrgId
if (params.basicPlutoOrgId) {
query.in('basicPAOrgId', params.basicPlutoOrgId);
}
if (params.jobAdvisorByUserId && params.jobAdvisorByUserId === "Not Assigned") {
query.where('jobAdvisor', {
$exists: false
});
} else if (params.jobAdvisorByUserId) {
query.in('jobAdvisor.userId', params.jobAdvisorByUserId);
}
if (params.stages) {
if (params.stages.indexOf(",") > 0) {
params.stages = params.stages.split(",");
}
if (!params.isFunnel) {
query.in('currentStage', params.stages);
} else {
var stageAndChildren = GetStagesInFunnel(params.stages, params.lifeCycle);
query.in('currentStage', stageAndChildren);
}
}
if (params.jobIds) {
query.in('jobId', params.jobIds);
}
if (params.onlyJobRoles) {
query.where({
entityType: 'jobRole'
});
}
if (params.bulkStageSessionId) {
query.in('stageHistory.sessionId', params.bulkStageSessionId);
}
//Supporting Advanced Search Options
var advancedOptions = {};
var isAdvancedSearchTriggered = false;
var isAdvancedSearchCvTemplateTriggered = false;
//query.elemMatch('stageHistory',{})
if (params.historySelectedStage) {
isAdvancedSearchTriggered = true;
advancedOptions.nextStage = params.historySelectedStage;
}
if (params.cvTemplate) {
isAdvancedSearchCvTemplateTriggered = true;
advancedOptions.urlSlug = params.cvTemplate
console.log(params.cvTemplate)
}
if (params.startDateCvTemplate && params.endDateCvTemplate) {
isAdvancedSearchCvTemplateTriggered = true;
var from = moment.utc(params.startDateCvTemplate, "DD/MM/YYYY").startOf('day').toDate();
var to = moment.utc(params.endDateCvTemplate, "DD/MM/YYYY").startOf('day').toDate();
console.log("cv template Dates:", from, to);
advancedOptions.createdOn = {
$gte: from,
$lt: to
};
} else if (params.startDateCvTemplate) {
isAdvancedSearchCvTemplateTriggered = true;
var from = moment.utc(params.startDateCvTemplate, "DD/MM/YYYY").startOf('day').toDate();
console.log("cv template Dates (after):", from);
advancedOptions.createdOn = {
$gte: from
};
} else if (params.endDateCvTemplate) {
isAdvancedSearchCvTemplateTriggered = true;
var to = moment.utc(params.endDateCvTemplate, "DD/MM/YYYY").startOf('day').toDate();
console.log("cv template Dates (before):", to);
advancedOptions.createdOn = {
$lt: to
};
}
if (params.stageFromDate && params.stageToDate) {
isAdvancedSearchTriggered = true;
var from = moment.utc(params.stageFromDate, "DD/MM/YYYY").startOf('day').toDate();
var to = moment.utc(params.stageToDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("stage Dates:", from, to);
advancedOptions.stageDate = {
$gte: from,
$lt: to
};
} else if (params.stageFromDate) {
isAdvancedSearchTriggered = true;
var from = moment.utc(params.stageFromDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("stageFrom Date Dates (after):", from);
advancedOptions.stageDate = {
$gte: from
};
} else if (params.stageToDate) {
isAdvancedSearchTriggered = true;
var to = moment.utc(params.stageToDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("stageToDate Dates (before):", to);
advancedOptions.stageDate = {
$lt: to
};
}
if (params.processingFromDate && params.processingToDate) {
isAdvancedSearchTriggered = true;
var from = moment.utc(params.processingFromDate, "DD/MM/YYYY").startOf('day').toDate();
var to = moment.utc(params.processingToDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("processing Dates:", from, to);
query.gte('processingDate', from);
query.lte('processingDate', to);
} else if (params.processingFromDate) {
isAdvancedSearchTriggered = true;
var from = moment.utc(params.processingFromDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("processingFromDate Dates (after):", from);
query.gte('processingDate', from);
} else if (params.processingToDate) {
isAdvancedSearchTriggered = true;
var to = moment.utc(params.processingToDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("processingToDate Dates (before):", to);
query.lte('processingDate', to);
}
if (params.historyFromDate && params.historyToDate) {
isAdvancedSearchTriggered = true;
var from = moment.utc(params.historyFromDate, "DD/MM/YYYY").startOf('day').toDate();
var to = moment.utc(params.historyToDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("history Dates:", from, to);
advancedOptions.updatedOn = {
$gte: from,
$lt: to
};
} else if (params.historyFromDate) {
isAdvancedSearchTriggered = true;
var from = moment.utc(params.historyFromDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("history Dates (after):", from);
advancedOptions.updatedOn = {
$gte: from
};
} else if (params.historyToDate) {
isAdvancedSearchTriggered = true;
var to = moment.utc(params.historyToDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("history Dates (before):", to);
advancedOptions.updatedOn = {
$lt: to
};
}
if (params.updatedByUserId) {
isAdvancedSearchTriggered = true;
advancedOptions.updatedByUserId = params.updatedByUserId;
}
if (params.interviewSlotFromDate && params.interviewSlotToDate) {
var from = moment.utc(params.interviewSlotFromDate, "DD/MM/YYYY").startOf('day').toDate();
var to = moment.utc(params.interviewSlotToDate, "DD/MM/YYYY").startOf('day').toDate();
query.gte('interviewSlot.date', from)
query.lte('interviewSlot.date', to)
} else if (params.interviewSlotFromDate) {
var from = moment.utc(params.interviewSlotFromDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("interview Dates (after):", from);
query.gte('interviewSlot.date', from)
} else if (params.interviewSlotToDate) {
var to = moment.utc(params.interviewSlotToDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("interview slot Dates (before):", to);
query.lte('interviewSlot.date', to)
}
if (params.appInterviewDate) {
var appInterviewDate = moment.utc(params.appInterviewDate, "DD/MM/YYYY").startOf('day').toDate();
console.log("interview slot Date:", appInterviewDate);
query.where('interviewSlot.startDate', appInterviewDate)
}
if (isAdvancedSearchTriggered) {
console.log("Advanced Search option (history) : " + JSON.stringify(advancedOptions));
query.elemMatch('stageHistory', advancedOptions);
}
if (isAdvancedSearchCvTemplateTriggered) {
console.log("Advanced Search option (cvTemplate) : " + JSON.stringify(advancedOptions));
query.elemMatch('cvTemplates', advancedOptions);
}
//must be deprecated soon
if (params.jobUrlSlug && params.jobUrlSlug.length) {
query.in('jobUrlSlug', params.jobUrlSlug);
}
if (params.jobRoleUrl && params.jobRoleUrl.length) {
query.in('jobRoleUrl', params.jobRoleUrl);
}
if (params.jobUrlSlugs) {
query.in('jobUrlSlug', params.jobUrlSlugs);
}
if (params.location && params.location.length) {
query.in('location.area', params.location);
}
if (params.assessmentScore && params.assessmentScore >= 0) {
query.gte('assessments.report.dataUnit.obtainedPercentage', params.assessmentScore);
}
if (params.assessmentScore && params.assessmentScore < 0) {
query.lt('assessments.report.dataUnit.obtainedPercentage', (params.assessmentScore) * (-1));
}
if (params.interviewDate) {
var interviewFrom = moment(params.interviewDate).utc().startOf('day').toDate();
var interviewTo = moment(params.interviewDate).utc().add(1, 'days').startOf('day').toDate();
query.gte('interviewSlot.date', interviewFrom)
query.lt('interviewSlot.date', interviewTo)
console.log(interviewFrom, interviewTo);
}
if (params.isFresher) {
query.where('isFresher', params.isFresher);
}
if (params.qualification && params.qualification.length) {
var processedQualification = []
for (var i = 0; i < params.qualification.length; i++) {
var thisQualification = params.qualification[i]
if (thisQualification.degreeType && thisQualification.degree && thisQualification.passingYear) {
var cookedQualification = {
'educationInfo.degreeType': thisQualification.degreeType,
'educationInfo.degree': thisQualification.degree,
'educationInfo.passingYear': thisQualification.passingYear
}
} else if (thisQualification.degreeType && thisQualification.degree) {
var cookedQualification = {
'educationInfo.degreeType': thisQualification.degreeType,
'educationInfo.degree': thisQualification.degree,
}
} else if (thisQualification.degreeType && thisQualification.passingYear) {
var cookedQualification = {
'educationInfo.degreeType': thisQualification.degreeType,
'educationInfo.passingYear': thisQualification.passingYear
}
} else {
var cookedQualification = {
'educationInfo.degreeType': thisQualification.degreeType,
}
}
processedQualification.push(cookedQualification)
if (i === params.qualification.length - 1) {
query.or(processedQualification)
}
}
}
console.log(query._conditions);
AppliedJobData.find(query.sort({
applicationDate: -1
})).skip(skip).limit(limit).exec(function (err, ajds) {
var totalApplicants = (ajds ? ajds.length : 0);
console.log("Found Applicants " + totalApplicants);
if (!err) {
ajds = _.first(ajds, 5000);
var refinedAjds = _.map(ajds, function (item) {
var associatedOrgId = undefined;
if (params.orgType !== 'employer') {
associatedOrgId = params.orgId;
}
var thisVendor = _.find(item.agencies, function (a) {
if (!associatedOrgId) {
return !a.associatedOrgId;
} else {
return a.associatedOrgId === associatedOrgId;
}
});
return {
id: item.userId,
name: item.seeker_profile.first_name + (item.seeker_profile.last_name ? (' ' + item.seeker_profile.last_name) : ''),
seeker_profile: item.seeker_profile,
FBUserId: item.FBUserId,
email: item.email ? item.email : '',
jobUrlSlug: item.jobUrlSlug,
jobId: item.jobId,
jobRoleUrl: item.jobRoleUrl,
passport: item.passport,
personalAttributes: item.personalAttributes,
attachmentsLength: item.attachments ? item.attachments.length : 0,
phone: item.mobile,
city: item.location ? item.location.city : '',
zip: item.location ? item.location.zip : '',
state: item.location ? item.location.state : '',
authSourceUtm: item.authSourceUtm ? item.authSourceUtm : '',
isFresher: item.isFresher ? item.isFresher : '',
abbyStatus: item.abbyStatus ? item.abbyStatus : '',
localUserId: item.localUserId ? item.localUserId : '',
isVisited: item.isVisited ? item.isVisited : '',
currentStage: item.currentStage ? item.currentStage : '',
educationInfo: item.educationInfo ? _.map(item.educationInfo, function (i) {
return i.degreeType;
}).join(", ") : '',
applicationId: item.applicationId ? item.applicationId : '',
applicationDate: item.applicationDate ? item.applicationDate : '',
qnaSet: item.qnaSet,
displayPic: item.displayPic,
vendor: thisVendor ? thisVendor : undefined,
client: item.client,
vendorLock: item.vendorLock,
trainingSlot: item.trainingSlot,
interviewSlot: item.interviewSlot,
skills: _.filter(item.skills, function (s) {
return s.type === 'English';
}),
workLocation: _.map(item.workLocation, function (w) {
return w.area;
}).join(", "),
jobName: item.jobName ? item.jobName : '',
screeningId: item.screeningId ? item.screeningId : '',
tags: item.tags ? item.tags : undefined,
qnaSetLength: item.qnaSet ? item.qnaSet.length : 0,
interviewDate: item.interviewSlot ? item.interviewSlot.date : '',
interviewVenue: item.interviewSlot ? item.interviewSlot.venue : '',
jobAdvisor: (item.jobAdvisor) ? (item.jobAdvisor.seeker_profile.first_name + (item.jobAdvisor.seeker_profile.last_name ? (' ' + item.jobAdvisor.seeker_profile.last_name) : '')) : '',
stageHistory: params.isStageHistoryNeeded ? item.stageHistory : [],
userSourceOrgId: (item.userSource) ? item.userSource.orgId : '',
userSourceOrgName: (item.userSource) ? item.userSource.orgName : '',
matchScore: (item.matchScore) ? item.matchScore : '',
countryCode: (item.countryCode) ? item.countryCode : '',
currentPosition: (item.currentPosition) ? item.currentPosition : '',
profileSummary: (item.profileSummary) ? item.profileSummary : '',
keyskills: (item.keyskills) ? item.keyskills : ''
};
});
//post search params - turbo mode
var turbo = {
};
if (params.turbo) {
var stageData = [];
var stages = _.pluck(refinedAjds, "currentStage");
stages = count(stages);
for (var property in stages) {
if (stages.hasOwnProperty(property)) {
stageData.push([property, stages[property]])
}
};
var jobData = [];
var jobs = _.pluck(refinedAjds, "jobName");
jobs = count(jobs);
for (var property in jobs) {
if (jobs.hasOwnProperty(property)) {
jobData.push([property, jobs[property]])
}
};
var authSourceData = [];
var authSourceUtms = _.pluck(refinedAjds, "authSourceUtm");
authSourceUtms = count(authSourceUtms);
for (var property in authSourceUtms) {
if (authSourceUtms.hasOwnProperty(property)) {
authSourceData.push([property, authSourceUtms[property]])
}
};
var vendorData = [];
// console.log(refinedAjds);
var vendors = _.pluck(refinedAjds, "vendor");
vendors = _.map(vendors, function (i) {
if (i) {
return i.orgName;
}
});
vendors = count(vendors);
for (var property in vendors) {
if (vendors.hasOwnProperty(property)) {
vendorData.push([property, vendors[property]])
}
};
turbo = {
stages: stageData,
jobs: jobData,
authSourceData: authSourceData,
vendorData: vendorData,
totalApplicants: totalApplicants
}
}
var payLoad = {
applicants: refinedAjds,
turbo: turbo,
userSearch: params.userSearch
};
console.log(refinedAjds.length);
next(null, payLoad);
} else {
next(err, 'Something went wrong while executing query.');
}
})
};
var findStageHistoryChangeTrend = function (AppliedJobData, startDate, endDate, next) {
//endDate is not included
console.log("========================= Changes b/w: ", startDate, " - ", endDate, " =========================");
AppliedJobData.find({
stageHistory: {
$elemMatch: {
updatedOn: {
$gte: startDate,
$lt: endDate
}
}
}
}).exec(function (err, applications) {
console.log("Impacted applications: " + (applications ? applications.length : 0));
if (!err && applications && applications.length) {
//Stage History changes
var StageHistories = [];
_.each(applications, function (item) {
var todaySHs = _.filter(item.stageHistory, function (sh) {
if ((sh.updatedOn >= startDate) && (sh.updatedOn < endDate) && (sh.updatedByRole !== 'abby')) {
return true;
}
});
var todaySHss = _.map(todaySHs, function (sh) {
return {
updatedByRole: sh.updatedByRole,
updatedByUserId: sh.updatedByUserId,
previousStage: sh.previousStage,
stageDate: sh.stageDate,
nextStage: sh.nextStage,
updatedBy: sh.updatedBy,
orgId: sh.orgId,
orgAccessLifeCycleLabel: sh.orgAccessLifeCycleLabel,
updatedOn: sh.updatedOn,
mobile: item.mobile
}
})
StageHistories = StageHistories.concat(todaySHss);
});
var PlutoPremiumStageHistories = _.filter(StageHistories, function (sh) {
if (sh.updatedByRole === "plutoPremium") {
return true;
}
});
var PlutoPremiumProcessings = _.filter(StageHistories, function (sh) {
if (sh.updatedByRole === "plutoPremium" && sh.nextStage === "Processed") {
return true;
}
});
var UniquePlutoPremiumProcessings = _.uniq(PlutoPremiumProcessings, function (item) {
return item.mobile;
})
var UniquePlutoPremiumProcessingsGrouped = _.groupBy(UniquePlutoPremiumProcessings, function (item) {
return item.updatedBy.first_name
})
var processingData = _.map(UniquePlutoPremiumProcessingsGrouped, function (group) {
return {
processings: group.length,
jobAdvisor: group[0].updatedBy
}
});
processingData = _.sortBy(processingData, function (item) {
return -1 * item.processings
});
console.log(processingData);
var ElpisStageHistories = _.filter(StageHistories, function (sh) {
if (sh.updatedByRole === "elpis") {
return true;
}
});
var groups = _.groupBy(StageHistories, function (value) {
return value.updatedBy + '#' + value.nextStage +
'#' + value.previousStage + '#' + value.updatedByRole;
});
var data = _.map(groups, function (group) {
return {
updatedBy: group[0].updatedBy.first_name + ' ' + group[0].updatedBy.last_name,
updatedByUserId: group[0].updatedByUserId,
orgAccessLifeCycleLabel: group[0].orgAccessLifeCycleLabel,
updatedByRole: group[0].updatedByRole,
previousStage: group[0].previousStage,
nextStage: group[0].nextStage,
history: group.length
}
});
data = _.sortBy(data, function (o) {
return o.updatedByRole + '_' + o.updatedBy + '_' + o.previousStage + '_' + o.nextStage;
});
var finalSummary = {
startDate: startDate.format('DD/MM/YYYY'),
endDate: endDate.format('DD/MM/YYYY'),
impactedApplicants: applications.length,
stageHistories: StageHistories.length,
premiumPlutoChanges: PlutoPremiumStageHistories.length,
processingData: processingData,
UniquePlutoPremiumProcessings: UniquePlutoPremiumProcessings,
elpisChanges: ElpisStageHistories.length,
history: data
};
next(null, finalSummary);
} else {
next(err, null);
}
})
};
var findStageHistoryTrendByDate = function (AppliedJobData, startDate, endDate, userId, next) {
//endDate is not included
console.log("========================= Changes b/w: ", startDate, " - ", endDate, " =========================");
var query;
if (userId) {
query = {
entityType: 'jobRole',
stageHistory: {
$elemMatch: {
updatedOn: {
$gte: startDate,
$lt: endDate
},
nextStage: "Processed"
}
},
'jobAdvisor.userId': userId
};
} else {
query = {
entityType: 'jobRole',
stageHistory: {
$elemMatch: {
updatedOn: {
$gte: startDate,
$lt: endDate
},
nextStage: "Processed"
}
}
};
}
AppliedJobData.find(query).exec(function (err, applications) {
console.log("Impacted applications: " + (applications ? applications.length : 0));
if (!err && applications) {
next(null, applications);
} else {
next(err, null);
}
})
};
var lifeCycleBuilderApplicantSearch = function (ajd, orgId, next) {
var orgId = orgId ? orgId : ajd.client.orgId;
var cacheName = 'elpis' + orgId + 'RTNALC';
console.log('cacheName: ' + cacheName);
var name = 'Recruiter';
if (Cache.get(cacheName)) {
console.log('Got cached ' + cacheName);
next(JSON.parse(Cache.get(cacheName)));
} else {
var query = LifeCycle.findOne({
'name': name,
role: 'elpis'
});
if (orgId) {
query = LifeCycle.findOne({
'name': name,
role: 'elpis',
orgId: orgId
});
}
query.exec(function (err, lifeCycle) {
if (!err && lifeCycle) {
console.log('Got lifeCycle:' + lifeCycle.name);
Cache.put(cacheName, JSON.stringify(lifeCycle));
next(lifeCycle);
} else {
console.log(err);
next(null, err);
}
});
}
};
var sendStageChangeSMSToUser = function (ajd, interviewSlot, orgId, thisStage, lifeCycleSettings, reqBody) {
if (reqBody && reqBody.smsText) {
var template = parseKeywordFromMessage(reqBody.smsText, ajd);
saveSmsToSmsLog(ajd, template, lifeCycleSettings);
} else if (thisStage && thisStage.smsText) {
var template = parseKeywordFromMessage(thisStage.smsText, ajd);
saveSmsToSmsLog(ajd, template, lifeCycleSettings);
}
};
var parseKeywordFromMessage = function (body, ajd) {
if (body) {
var tempBody = body;
if (ajd.seeker_profile) {
tempBody = body.replace("<name - autofill|30>", (ajd.seeker_profile.first_name + ' ' + ajd.seeker_profile.last_name));
tempBody = tempBody.replace("*USERNAME*", (ajd.seeker_profile.first_name + ' ' + ajd.seeker_profile.last_name));
tempBody = tempBody.replace("*USERFNAME*", ajd.seeker_profile.first_name);
tempBody = tempBody.replace("*USERLNAME*", ajd.seeker_profile.last_name);
}
//*JOBNAME*
tempBody = tempBody.replace("*JOBNAME*", ajd.jobName ? ajd.jobName : 'job');
//CLIENTNAME
tempBody = tempBody.replace("*CLIENTNAME*", ajd.client ? ajd.client.orgName : 'company');
//JOBBOTLINK
tempBody = tempBody.replace("*JOBBOTLINK*", ajd.jobUrlSlug ? ('http://iona.ai/job/' + ajd.jobId) : 'http://iona.ai');
//INTERVIEWVENUE
tempBody = tempBody.replace("*INTERVIEWVENUE*", ajd.interviewSlot ? ajd.interviewSlot.venue : '');
tempBody = tempBody.replace("*INTERVIEWDATE*", ajd.interviewSlot ? moment(ajd.interviewSlot.startDate).format("DD/MM/YYYY") : '');
tempBody = tempBody.replace("*INTERVIEWTIME*", (ajd.interviewSlot && ajd.interviewSlot.time) ? ajd.interviewSlot.time : '');
tempBody = tempBody.replace("*INTERVIEWINSTRUCTION*", (ajd.interviewSlot && ajd.interviewSlot.instruction) ? ajd.interviewSlot.instructions : '');
tempBody = tempBody.replace("*INTERVIEWMAPLINK*", (ajd.interviewSlot && ajd.interviewSlot.maplink) ? ajd.interviewSlot.maplink : '');
return tempBody;
} else {
return body;
}
};
var saveSmsToSmsLog = function (ajd, template, settings) {
var smsLog = new SMSLog({
sid: 'textLocal',
txnId: ajd.applicationId,
userId: ajd.userId,
senderId: settings ? settings.smsSenderId : '',
mobile: ajd.mobile,
smsBody: template,
countryCode: ajd.countryCode,
deliveryStatus: "inQueue",
isTransactional: true,
priority: 0
});
smsLog.save(function (err, saved) {
if (!err && saved) {
console.log("Queued SMS for service status change : " + ajd.currentStage)
} else {
console.log(JSON.stringify(err))
}
})
};
var sendStageChangeEmailToUser = function (ajd, interviewSlot, orgId, thisStage, lifeCycleSettings, reqBody) {
var mailTemplates = path.join(path.dirname(fs.realpathSync(__filename)), './mailTemplates')
var templatePath = mailTemplates + '/filler.ejs';
var template = '';
var subject = '';
if (reqBody && reqBody.emailText) {
template = parseKeywordFromMessage(reqBody.emailText, ajd);
subject = parseKeywordFromMessage(reqBody.emailSubject, ajd);
} else if (thisStage && thisStage.emailText) {
template = parseKeywordFromMessage(thisStage.emailText, ajd);
subject = parseKeywordFromMessage(thisStage.emailSubject, ajd);
}
if (subject && template) {
var mailLog = new MailLog({
_id: mongoose.Types.ObjectId(),
txnId: ajd.id,
userId: ajd.userId,
email: ajd.email,
subject: subject,
deliveryStatus: "InQueue",
isOpened: false,
source: lifeCycleSettings ? lifeCycleSettings.sourceEmail : "help@hireira.com",
replyToAddresses: lifeCycleSettings ? lifeCycleSettings.sourceEmail : "help@hireira.com",
retu