648 lines
28 KiB
JavaScript
648 lines
28 KiB
JavaScript
'use strict';
|
|
|
|
const moment = require('moment-timezone');
|
|
|
|
const db = require('../../models/index');
|
|
const Op = require('sequelize').Op;
|
|
|
|
const workbookCreator = require('excel4node');
|
|
|
|
const { incidentType, UI_TIMEZONE, DEFAULT_DATE_FORMAT, integrationServiceErrors } = require('../../constants/constants');
|
|
|
|
const { getAllBookingsForMembersInDateRange } = require('./bookings');
|
|
const { fetchAllMembers } = require('../officeRnD/members');
|
|
const { fetchOffices, fetchResources } = require('../officeRnD/resources');
|
|
const { getChargedCanceledReservations } = require('../integration/bookingChangeCharges');
|
|
|
|
const getUnlockedIncidents = (startDate, endDate, memberIds) => {
|
|
const attributes = ['id', 'reservationId', 'memberId', 'resourceId', 'bookingStart', 'bookingEnd', 'unlockTimestamp', 'incidentLevel', 'incidentLevelPrice'];
|
|
|
|
const filters = {
|
|
deleted: false
|
|
};
|
|
|
|
if (startDate && endDate) {
|
|
const bookingStartCondition = {
|
|
bookingStart: {
|
|
[Op.and]: {
|
|
[Op.gte]: startDate.toISOString(),
|
|
[Op.lte]: endDate.toISOString(),
|
|
}
|
|
}
|
|
};
|
|
|
|
const unlockTimestampCondition = {
|
|
unlockTimestamp: {
|
|
[Op.and]: {
|
|
[Op.gte]: startDate.toISOString(),
|
|
[Op.lte]: endDate.toISOString(),
|
|
}
|
|
}
|
|
};
|
|
|
|
const bookingStartOrUnlockTimestamp = {
|
|
[Op.or]: [bookingStartCondition, unlockTimestampCondition]
|
|
};
|
|
|
|
Object.assign(filters, bookingStartOrUnlockTimestamp);
|
|
}
|
|
|
|
if (memberIds.length > 0){
|
|
filters.memberId = {
|
|
[Op.in]: memberIds
|
|
};
|
|
}
|
|
|
|
return db.unlockedIncident.findAll({
|
|
attributes,
|
|
where: filters,
|
|
sort: [
|
|
['bookingStart', 'ASC']
|
|
]
|
|
});
|
|
};
|
|
|
|
const getUnscheduledIncidents = (startDate, endDate, memberIds) => {
|
|
const attributes = [
|
|
'id',
|
|
'reservationId',
|
|
'memberId',
|
|
'resourceId',
|
|
'bookingStart',
|
|
'bookingEnd',
|
|
'unlockTimestamp',
|
|
'lockTimestamp',
|
|
'timeIntervalsToCharge',
|
|
'chargePrice',
|
|
'totalChargeFee'
|
|
];
|
|
|
|
const filters = {
|
|
deleted: false
|
|
};
|
|
|
|
if (startDate && endDate) {
|
|
const bookingStartCondition = {
|
|
bookingStart: {
|
|
[Op.and]: {
|
|
[Op.gte]: startDate.toISOString(),
|
|
[Op.lte]: endDate.toISOString(),
|
|
}
|
|
}
|
|
};
|
|
|
|
const unlockTimestampCondition = {
|
|
unlockTimestamp: {
|
|
[Op.and]: {
|
|
[Op.gte]: startDate.toISOString(),
|
|
[Op.lte]: endDate.toISOString(),
|
|
}
|
|
}
|
|
};
|
|
|
|
const bookingStartOrUnlockTimestamp = {
|
|
[Op.or]: [bookingStartCondition, unlockTimestampCondition]
|
|
};
|
|
|
|
Object.assign(filters, bookingStartOrUnlockTimestamp);
|
|
}
|
|
|
|
|
|
if (memberIds.length > 0){
|
|
filters.memberId = {
|
|
[Op.in]: memberIds
|
|
};
|
|
}
|
|
|
|
return db.unscheduledIncident.findAll({
|
|
attributes,
|
|
where: filters,
|
|
sort: [
|
|
['bookingStart', 'ASC']
|
|
]
|
|
});
|
|
};
|
|
|
|
const getBookingChangeIncidents = (startDate, endDate, memberIds) => {
|
|
const attributes = [
|
|
'id',
|
|
'reservationId',
|
|
'memberId',
|
|
'oldResourceId',
|
|
'newResourceId',
|
|
'oldBookingStart',
|
|
'oldBookingEnd',
|
|
'newBookingStart',
|
|
'newBookingEnd',
|
|
'incidentType',
|
|
'chargeFee',
|
|
'createdAt'
|
|
];
|
|
|
|
const filters = {
|
|
deleted: false,
|
|
};
|
|
|
|
if (startDate && endDate) {
|
|
filters.createdAt = {
|
|
[Op.and]: {
|
|
[Op.gte]: startDate.toISOString(),
|
|
[Op.lte]: endDate.toISOString(),
|
|
}
|
|
}
|
|
}
|
|
|
|
if (memberIds.length > 0){
|
|
filters.memberId = {
|
|
[Op.in]: memberIds
|
|
};
|
|
}
|
|
|
|
return db.bookingChangeIncident.findAll({
|
|
attributes,
|
|
where: filters,
|
|
sort: [
|
|
['createdAt', 'ASC']
|
|
]
|
|
});
|
|
};
|
|
|
|
const formatTime = (timestamp) => {
|
|
const momentObject = moment.tz(timestamp, UI_TIMEZONE);
|
|
if (momentObject.isValid()){
|
|
return momentObject.format('MM/DD/YYYY hh:mm a');
|
|
}else{
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const getAllIncidents = (dateRange, memberIds) => {
|
|
return new Promise ((resolve, reject) => {
|
|
let startDate, endDate;
|
|
|
|
if (dateRange.startDate && dateRange.endDate){
|
|
startDate = moment.tz(dateRange.startDate, DEFAULT_DATE_FORMAT, UI_TIMEZONE).startOf('day');
|
|
endDate = moment.tz(dateRange.endDate, DEFAULT_DATE_FORMAT, UI_TIMEZONE).endOf('day');
|
|
|
|
if (!startDate.isValid() || !endDate.isValid() || endDate.isBefore(startDate)){
|
|
reject(integrationServiceErrors.INVALID_DATE_RANGE);
|
|
return;
|
|
}
|
|
}
|
|
|
|
const dataFetchJobs = [
|
|
fetchAllMembers(),
|
|
fetchOffices(),
|
|
fetchResources(),
|
|
getUnlockedIncidents(startDate, endDate, memberIds),
|
|
getUnscheduledIncidents(startDate, endDate, memberIds),
|
|
getBookingChangeIncidents(startDate, endDate, memberIds)
|
|
];
|
|
|
|
Promise.all(dataFetchJobs)
|
|
.then((data) => {
|
|
const members = data[0];
|
|
const offices = data[1];
|
|
const resources = data[2];
|
|
const unlockedIncidents = data[3];
|
|
const unscheduledIncidents = data[4];
|
|
const bookingChangeIncidents = data[5];
|
|
|
|
const membersMap = {};
|
|
const officesMap = {};
|
|
const resourcesMap = {};
|
|
|
|
members.forEach((member) => membersMap[member.memberId] = member);
|
|
offices.forEach((office) => officesMap[office.officeId] = office);
|
|
resources.forEach((resource) => resourcesMap[resource.resourceId] = resource);
|
|
|
|
const allIncidents = [];
|
|
|
|
unlockedIncidents.forEach((unlockedIncident) => {
|
|
const incidentTypeNumber = unlockedIncident.reservationId ?
|
|
incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION : incidentType.UNLOCKED_INCIDENT_STANDALONE;
|
|
|
|
const resourceObject = resourcesMap[unlockedIncident.resourceId];
|
|
const officeObject = resourceObject ? officesMap[resourceObject.officeId] : null;
|
|
|
|
const memberName = membersMap[unlockedIncident.memberId] ? membersMap[unlockedIncident.memberId].name : 'Unknown member';
|
|
const resourceName = resourceObject ? resourceObject.resourceName : 'Unknown room';
|
|
const officeId = resourceObject ? resourceObject.officeId : '';
|
|
const officeName = officeObject ? officeObject.officeName : 'Unknown office';
|
|
const officeSlug = officeObject ? officeObject.officeSlug : '-';
|
|
|
|
allIncidents.push({
|
|
incidentId: unlockedIncident.id,
|
|
memberId: unlockedIncident.memberId,
|
|
memberName,
|
|
resourceName,
|
|
officeId,
|
|
officeName,
|
|
officeSlug,
|
|
bookingStart: formatTime(unlockedIncident.bookingStart) || '-',
|
|
bookingEnd: formatTime(unlockedIncident.bookingEnd) || '-',
|
|
bookingStartRaw: unlockedIncident.bookingStart,
|
|
bookingEndRaw: unlockedIncident.bookingEnd,
|
|
unlockTimestamp: formatTime(unlockedIncident.unlockTimestamp) || '-',
|
|
unlockTimestampRaw: unlockedIncident.unlockTimestamp,
|
|
incidentType: incidentTypeNumber,
|
|
incidentLevel: unlockedIncident.incidentLevel,
|
|
incidentPrice: unlockedIncident.incidentLevelPrice,
|
|
});
|
|
});
|
|
|
|
unscheduledIncidents.forEach((unscheduledIncident) => {
|
|
let incidentTypeNumber;
|
|
if (unscheduledIncident.reservationId){
|
|
if (unscheduledIncident.unlockTimestamp && !unscheduledIncident.lockTimestamp){
|
|
incidentTypeNumber = incidentType.UNSCHEDULED_INCIDENT_BEFORE_RESERVATION;
|
|
}else{
|
|
incidentTypeNumber = incidentType.UNSCHEDULED_INCIDENT_AFTER_RESERVATION;
|
|
}
|
|
}else{
|
|
incidentTypeNumber = incidentType.UNSCHEDULED_INCIDENT_STANDALONE;
|
|
}
|
|
|
|
const resourceObject = resourcesMap[unscheduledIncident.resourceId];
|
|
const officeObject = resourceObject ? officesMap[resourceObject.officeId] : null;
|
|
|
|
const memberName = membersMap[unscheduledIncident.memberId] ? membersMap[unscheduledIncident.memberId].name : 'Unknown member';
|
|
const resourceName = resourceObject ? resourceObject.resourceName : 'Unknown room';
|
|
const officeId = resourceObject ? resourceObject.officeId : '';
|
|
const officeName = officeObject ? officeObject.officeName : 'Unknown office';
|
|
const officeSlug = officeObject ? officeObject.officeSlug : '-';
|
|
|
|
allIncidents.push({
|
|
incidentId: unscheduledIncident.id,
|
|
memberId: unscheduledIncident.memberId,
|
|
memberName,
|
|
resourceName,
|
|
officeId,
|
|
officeName,
|
|
officeSlug,
|
|
bookingStart: formatTime(unscheduledIncident.bookingStart) || '-',
|
|
bookingEnd: formatTime(unscheduledIncident.bookingEnd) || '-',
|
|
bookingStartRaw: unscheduledIncident.bookingStart,
|
|
bookingEndRaw: unscheduledIncident.bookingEnd,
|
|
unlockTimestamp: formatTime(unscheduledIncident.unlockTimestamp) || '-',
|
|
lockTimestamp: formatTime(unscheduledIncident.lockTimestamp) || '-',
|
|
unlockTimestampRaw: unscheduledIncident.unlockTimestamp,
|
|
lockTimestampRaw: unscheduledIncident.lockTimestamp,
|
|
incidentType: incidentTypeNumber,
|
|
timeIntervalsToCharge: unscheduledIncident.timeIntervalsToCharge,
|
|
chargePrice: unscheduledIncident.chargePrice,
|
|
totalChargeFee: unscheduledIncident.totalChargeFee,
|
|
});
|
|
});
|
|
|
|
bookingChangeIncidents.forEach((bookingChangeIncident) => {
|
|
const {
|
|
id,
|
|
memberId,
|
|
oldResourceId,
|
|
newResourceId,
|
|
oldBookingStart,
|
|
oldBookingEnd,
|
|
newBookingStart,
|
|
newBookingEnd,
|
|
incidentType,
|
|
chargeFee,
|
|
deleted,
|
|
createdAt,
|
|
} = bookingChangeIncident;
|
|
const memberName = membersMap[memberId] ? membersMap[memberId].name : 'Unknown member';
|
|
const oldResource = resourcesMap[oldResourceId];
|
|
const newResource = newResourceId ? resourcesMap[newResourceId] : null;
|
|
const oldResourceName = oldResource ? oldResource.resourceName : 'Unknown room';
|
|
const newResourceName = newResource ? newResource.resourceName : null;
|
|
const officeId = oldResource ? oldResource.officeId : '';
|
|
const officeName = officesMap[officeId] ? officesMap[officeId].officeName : 'Unknown office';
|
|
const officeSlug = officesMap[officeId] ? officesMap[officeId].officeSlug : '-';
|
|
allIncidents.push({
|
|
incidentId: id,
|
|
memberId,
|
|
memberName,
|
|
oldResourceName,
|
|
newResourceName,
|
|
officeId,
|
|
officeName,
|
|
officeSlug,
|
|
oldBookingStart: formatTime(oldBookingStart) || '-',
|
|
oldBookingEnd: formatTime(oldBookingEnd) || '-',
|
|
newBookingStart: formatTime(newBookingStart) || '-',
|
|
newBookingEnd: formatTime(newBookingEnd) || '-',
|
|
oldBookingStartRaw: oldBookingStart,
|
|
oldBookingEndRaw: oldBookingEnd,
|
|
newBookingStartRaw: newBookingStart,
|
|
newBookingEndRaw: newBookingEnd,
|
|
incidentType,
|
|
totalChargeFee: chargeFee,
|
|
deleted,
|
|
incidentTimestamp: formatTime(createdAt) || '-',
|
|
incidentTimestampRaw: createdAt,
|
|
});
|
|
});
|
|
|
|
resolve(allIncidents);
|
|
})
|
|
.catch((error) => reject(error));
|
|
});
|
|
};
|
|
|
|
const getMemberPracticeSummaryReport = (year) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const startDate = moment.tz(year, 'YYYY', UI_TIMEZONE).startOf('year').format(DEFAULT_DATE_FORMAT);
|
|
const endDate = moment.tz(year, 'YYYY', UI_TIMEZONE).endOf('year').format(DEFAULT_DATE_FORMAT);
|
|
const dateRange = {
|
|
startDate,
|
|
endDate,
|
|
};
|
|
|
|
const asyncJobs = [getAllBookingsForMembersInDateRange(dateRange), fetchAllMembers()];
|
|
|
|
Promise.all(asyncJobs)
|
|
.then((results) => {
|
|
const allBookings = results[0];
|
|
const allMembers = results[1];
|
|
|
|
const membersMap = {};
|
|
|
|
allMembers.forEach((member) => {
|
|
membersMap[member.memberId] = member;
|
|
});
|
|
|
|
const reportMap = {};
|
|
|
|
const oneMonthObject = {
|
|
totalBookedHours: 0,
|
|
totalChargedHours: 0,
|
|
cancellationPercentage: 0,
|
|
growthRate: 0,
|
|
};
|
|
|
|
const oneMemberObject = [];
|
|
for (let i = 0; i < 12; i++) {
|
|
oneMemberObject.push(Object.assign({}, oneMonthObject));
|
|
}
|
|
|
|
const reservationIdsForAdditionalData = [];
|
|
|
|
allBookings.forEach((booking) => {
|
|
const {reservationId, memberId, start, end, timezone, canceled} = booking.get();
|
|
const startMoment = moment.tz(start, timezone);
|
|
const endMoment = moment.tz(end, timezone);
|
|
|
|
if (startMoment.isValid() && endMoment.isValid()) {
|
|
const bookingMonth = startMoment.month();
|
|
const bookingLength = endMoment.diff(startMoment, 'hours', true);
|
|
|
|
if (!reportMap[memberId]) {
|
|
reportMap[memberId] = JSON.parse(JSON.stringify(oneMemberObject));
|
|
}
|
|
|
|
reportMap[memberId][bookingMonth].totalBookedHours += bookingLength;
|
|
|
|
if (canceled) {
|
|
reservationIdsForAdditionalData.push(reservationId);
|
|
} else {
|
|
reportMap[memberId][bookingMonth].totalChargedHours += bookingLength;
|
|
}
|
|
}
|
|
});
|
|
|
|
getChargedCanceledReservations(reservationIdsForAdditionalData)
|
|
.then((incidents) => {
|
|
console.log('Charged canceled reservations ...');
|
|
incidents.forEach((incident) => {
|
|
const {memberId, oldBookingStart, oldBookingEnd} = incident.get();
|
|
|
|
const startMoment = moment.tz(oldBookingStart, UI_TIMEZONE);
|
|
const endMoment = moment.tz(oldBookingEnd, UI_TIMEZONE);
|
|
|
|
if (startMoment.isValid() && endMoment.isValid()) {
|
|
const bookingMonth = startMoment.month();
|
|
const bookingLength = endMoment.diff(startMoment, 'hours', true);
|
|
|
|
reportMap[memberId][bookingMonth].totalChargedHours += bookingLength;
|
|
}
|
|
|
|
});
|
|
|
|
// Generate report sheet
|
|
|
|
const reportWorkbook = new workbookCreator.Workbook({});
|
|
const reportWorksheet = reportWorkbook.addWorksheet('Sheet 1');
|
|
|
|
const titleStyle = reportWorkbook.createStyle({
|
|
font: {
|
|
size: 18
|
|
}
|
|
});
|
|
const centeredStyle = reportWorkbook.createStyle({
|
|
alignment: {
|
|
horizontal: 'center',
|
|
}
|
|
});
|
|
const headerStyle = reportWorkbook.createStyle({
|
|
font: {
|
|
bold: true,
|
|
},
|
|
fill: {
|
|
type: 'pattern',
|
|
patternType: 'solid',
|
|
fgColor: '48cdd4',
|
|
}
|
|
});
|
|
const solidBlackBorder = {
|
|
left: {
|
|
style: 'thin',
|
|
color: '000000',
|
|
},
|
|
right: {
|
|
style: 'thin',
|
|
color: '000000',
|
|
},
|
|
top: {
|
|
style: 'thin',
|
|
color: '000000',
|
|
},
|
|
bottom: {
|
|
style: 'thin',
|
|
color: '000000',
|
|
}
|
|
};
|
|
const yellowCellStyle = reportWorkbook.createStyle({
|
|
fill: {
|
|
type: 'pattern',
|
|
patternType: 'solid',
|
|
fgColor: 'eaed37',
|
|
},
|
|
border: solidBlackBorder,
|
|
});
|
|
const redCellStyle = reportWorkbook.createStyle({
|
|
fill: {
|
|
type: 'pattern',
|
|
patternType: 'solid',
|
|
fgColor: 'e81717',
|
|
},
|
|
border: solidBlackBorder,
|
|
});
|
|
const greenCellStyle = reportWorkbook.createStyle({
|
|
fill: {
|
|
type: 'pattern',
|
|
patternType: 'solid',
|
|
fgColor: '329932',
|
|
},
|
|
border: solidBlackBorder,
|
|
});
|
|
const decimalPointStyle = reportWorkbook.createStyle({
|
|
numberFormat: '#,##0.00; -#,##0.00; -'
|
|
});
|
|
|
|
reportWorksheet.cell(2, 6, 2, 8, true).string('Member Practice Summary Report').style(titleStyle);
|
|
reportWorksheet.row(2).setHeight(20); // 20 is good height for font 18
|
|
|
|
reportWorksheet.cell(4, 6).string(`Year : ${year}`);
|
|
|
|
reportWorksheet.cell(7, 1).string('Member name');
|
|
reportWorksheet.column(1).setWidth(35);
|
|
|
|
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
for (let i = 0; i < 12; i++) {
|
|
reportWorksheet.cell(6, 3 + i * 5, 6, 6 + i * 5, true).string(monthNames[i]).style(centeredStyle);
|
|
|
|
reportWorksheet.cell(7, 3 + i * 5).string('Total Booked [h]');
|
|
reportWorksheet.cell(7, 4 + i * 5).string('Total Charged [h]');
|
|
reportWorksheet.cell(7, 5 + i * 5).string('Cancellation [%]');
|
|
reportWorksheet.cell(7, 6 + i * 5).string('Growth [%]');
|
|
|
|
reportWorksheet.column(3 + i * 5).setWidth(20);
|
|
reportWorksheet.column(4 + i * 5).setWidth(20);
|
|
reportWorksheet.column(5 + i * 5).setWidth(20);
|
|
reportWorksheet.column(6 + i * 5).setWidth(20);
|
|
}
|
|
|
|
reportWorksheet.cell(7, 1, 7, 61).style(headerStyle);
|
|
|
|
const memberIdsListFromReportMap = Object.keys(reportMap);
|
|
|
|
const activeMemberIdsList = [];
|
|
const inactiveMemberIdsList = [];
|
|
|
|
memberIdsListFromReportMap.forEach((memberId) => {
|
|
if (memberId){
|
|
if (membersMap[memberId] && membersMap[memberId].active){
|
|
activeMemberIdsList.push(memberId);
|
|
}else{
|
|
console.log('[Get Member Practice Summary Report] Unknown member ');
|
|
console.log('\tmemberId : ', memberId);
|
|
console.log('\tmembersMap[memberId] : ', membersMap[memberId]);
|
|
inactiveMemberIdsList.push(memberId);
|
|
}
|
|
}else{
|
|
console.log('[Get Member Practice Summary Report] memberId is wrong : ', memberId);
|
|
}
|
|
});
|
|
|
|
const sortMemberIdsListByName = (memberId1, memberId2) => {
|
|
const name1 = membersMap[memberId1] ? membersMap[memberId1].name || 'Unknown member' : null;
|
|
const name2 = membersMap[memberId2] ? membersMap[memberId2].name || 'Unknown member' : null;
|
|
|
|
if (!name1 || !name2){
|
|
return 0;
|
|
}
|
|
|
|
if (name1 > name2){
|
|
return 1;
|
|
}else{
|
|
return -1;
|
|
}
|
|
};
|
|
activeMemberIdsList.sort(sortMemberIdsListByName);
|
|
inactiveMemberIdsList.sort(sortMemberIdsListByName);
|
|
|
|
const populateReportForMember = (startRow, memberId, index) => {
|
|
|
|
const memberName = membersMap[memberId] ? membersMap[memberId].name : 'Unknown member';
|
|
reportWorksheet.cell(startRow + index, 1).string(memberName);
|
|
|
|
const memberReport = reportMap[memberId];
|
|
for (let i = 0; i< 12; i++){
|
|
const totalBookedHours = memberReport[i].totalBookedHours;
|
|
const totalChargedHoursCurrentMonth = memberReport[i].totalChargedHours;
|
|
let totalChargedHoursPreviousMonth = totalChargedHoursCurrentMonth;
|
|
if (i > 0){
|
|
totalChargedHoursPreviousMonth = memberReport[i-1].totalChargedHours;
|
|
}
|
|
|
|
let cancellationPercentage = ((totalBookedHours - totalChargedHoursCurrentMonth) / totalBookedHours)*100;
|
|
let growthRate = ((totalChargedHoursCurrentMonth - totalChargedHoursPreviousMonth) / totalChargedHoursPreviousMonth)*100;
|
|
if (isNaN(cancellationPercentage) || !cancellationPercentage){
|
|
cancellationPercentage = 0;
|
|
}
|
|
if (isNaN(growthRate) || growthRate > 100){
|
|
growthRate = 0;
|
|
}
|
|
|
|
const totalBookedHoursCell = reportWorksheet.cell(startRow + index, 3 + i*5);
|
|
const totalChargedHoursCell = reportWorksheet.cell(startRow + index, 4 + i*5);
|
|
const cancellationRateCell = reportWorksheet.cell(startRow + index, 5 + i*5);
|
|
const growthRateCell = reportWorksheet.cell(startRow + index, 6 + i*5);
|
|
|
|
totalBookedHoursCell.number(totalBookedHours).style(decimalPointStyle);
|
|
totalChargedHoursCell.number(totalChargedHoursCurrentMonth).style(decimalPointStyle);
|
|
cancellationRateCell.number(cancellationPercentage).style(decimalPointStyle);
|
|
growthRateCell.number(growthRate).style(decimalPointStyle);
|
|
|
|
if (cancellationPercentage > 30){
|
|
cancellationRateCell.style(yellowCellStyle);
|
|
}
|
|
|
|
if (growthRate > 30){
|
|
growthRateCell.style(greenCellStyle);
|
|
}
|
|
if (growthRate < -30){
|
|
growthRateCell.style(redCellStyle);
|
|
}
|
|
}
|
|
};
|
|
|
|
const startRowForActiveMembers = 8;
|
|
activeMemberIdsList.forEach((memberId, index) => populateReportForMember(startRowForActiveMembers, memberId, index));
|
|
|
|
const inactiveMembersHeaderRow = startRowForActiveMembers + activeMemberIdsList.length + 1;
|
|
const startRowForInactiveMembers = inactiveMembersHeaderRow + 2;
|
|
reportWorksheet.cell(inactiveMembersHeaderRow, 1).string('Deactivated members').style(headerStyle);
|
|
|
|
inactiveMemberIdsList.forEach((memberId, index) => populateReportForMember(startRowForInactiveMembers, memberId, index));
|
|
|
|
reportWorksheet.cell(1, 1).string('Generated at : ');
|
|
reportWorksheet.cell(2, 1).string(moment.tz(UI_TIMEZONE).format('MMM DD, YYYY HH:mm a'));
|
|
|
|
const reportName = `${moment.tz(UI_TIMEZONE).format('DDMMYYYYHHmmss')}.xlsx`;
|
|
const reportPath = `report_sheets/${reportName}`;
|
|
reportWorkbook.write(reportPath, (error) => {
|
|
if (error){
|
|
reject(error);
|
|
}
|
|
resolve({reportPath});
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
console.log('Error : ', error);
|
|
resolve({
|
|
report: reportMap,
|
|
error: integrationServiceErrors.ERRORS_IN_MEMBER_PRACTICE_SUMMARY_REPORT
|
|
});
|
|
});
|
|
})
|
|
.catch((error) => reject(error));
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
getAllIncidents,
|
|
getMemberPracticeSummaryReport,
|
|
};
|