263 lines
12 KiB
JavaScript
263 lines
12 KiB
JavaScript
'use strict';
|
|
|
|
const moment = require('moment-timezone');
|
|
|
|
const { getAllIncidents } = require('./reports');
|
|
const { getActiveBookingsForMembersInDateRange } = require('./bookings');
|
|
|
|
const { DEFAULT_DATE_FORMAT, UI_TIMEZONE, incidentTypeExplanations, incidentType, unlockedIncidentLevelsPrices } = require('../../constants/constants');
|
|
const { getResourceMappings } = require('../officeRnD/resources');
|
|
const { fetchAllMembers } = require('../officeRnD/members');
|
|
|
|
const createFeeFromIncident = (incident) => {
|
|
const {
|
|
memberId,
|
|
officeId,
|
|
officeName,
|
|
resourceName,
|
|
oldResourceName,
|
|
newResourceName,
|
|
bookingStartRaw,
|
|
bookingEndRaw,
|
|
oldBookingStartRaw,
|
|
oldBookingEndRaw,
|
|
newBookingStartRaw,
|
|
newBookingEndRaw,
|
|
unlockTimestampRaw,
|
|
lockTimestampRaw,
|
|
incidentLevel,
|
|
timeIntervalsToCharge,
|
|
incidentPrice,
|
|
chargePrice,
|
|
totalChargeFee,
|
|
incidentTimestampRaw
|
|
} = incident;
|
|
const incidentTypeNumber = incident.incidentType;
|
|
|
|
const incidentExplanation = incidentTypeExplanations[incidentTypeNumber];
|
|
|
|
let date = '';
|
|
let price = 0;
|
|
let quantity = 0;
|
|
// let priceExplanation = '';
|
|
let bookingTimeExplanation = '';
|
|
let incidentTimeExplanation = '';
|
|
let incidentTypeExplanation = '';
|
|
let additionalIncidentExplanation = '';
|
|
|
|
let roomExplanation = '';
|
|
let dateExplanation = '';
|
|
|
|
const bookingStartMoment = moment.tz(bookingStartRaw, UI_TIMEZONE);
|
|
const bookingEndMoment = moment.tz(bookingEndRaw, UI_TIMEZONE);
|
|
const unlockMoment = moment.tz(unlockTimestampRaw, UI_TIMEZONE);
|
|
const lockMoment = moment.tz(lockTimestampRaw, UI_TIMEZONE);
|
|
|
|
const oldBookingStartMoment = moment.tz(oldBookingStartRaw, UI_TIMEZONE);
|
|
const oldBookingEndMoment = moment.tz(oldBookingEndRaw, UI_TIMEZONE);
|
|
const newBookingStartMoment = moment.tz(newBookingStartRaw, UI_TIMEZONE);
|
|
const newBookingEndMoment = moment.tz(newBookingEndRaw, UI_TIMEZONE);
|
|
|
|
const incidentTimestampMoment = moment.tz(incidentTimestampRaw, UI_TIMEZONE);
|
|
|
|
switch (incidentTypeNumber){
|
|
case incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION:
|
|
roomExplanation = resourceName;
|
|
dateExplanation = bookingStartMoment.clone().startOf('day').format('MMM DD');
|
|
bookingTimeExplanation = `${bookingStartMoment.clone().format('HH:mm a')} - ${bookingEndMoment.clone().format('HH:mm a')}`;
|
|
incidentTimeExplanation = ''; // `UNLOCK : ${unlockMoment.clone().format('HH:mm a')}`;
|
|
additionalIncidentExplanation = ` ${unlockedIncidentLevelsPrices[incidentLevel].description},`;
|
|
incidentTypeExplanation = '';
|
|
|
|
date = bookingStartMoment.clone().startOf('day').format();
|
|
|
|
price = +incidentPrice.toFixed(2);
|
|
quantity = 1.00;
|
|
// priceExplanation = `$${price}, 1 x $${price.toFixed(2)}`;
|
|
break;
|
|
case incidentType.UNSCHEDULED_INCIDENT_BEFORE_RESERVATION:
|
|
roomExplanation = resourceName;
|
|
dateExplanation = bookingStartMoment.clone().startOf('day').format('MMM DD');
|
|
bookingTimeExplanation = `${bookingStartMoment.clone().format('HH:mm a')} - ${bookingEndMoment.clone().format('HH:mm a')}`;
|
|
incidentTimeExplanation = ` Unlock : ${unlockMoment.clone().format('HH:mm a')},`;
|
|
incidentTypeExplanation = '';
|
|
|
|
date = bookingStartMoment.clone().startOf('day').format();
|
|
|
|
price = +chargePrice.toFixed(2);
|
|
quantity = +timeIntervalsToCharge.toFixed(2);
|
|
// priceExplanation = `$${totalChargeFee.toFixed(2)}, ${quantity} x $${price.toFixed(2)}`;
|
|
break;
|
|
case incidentType.UNSCHEDULED_INCIDENT_AFTER_RESERVATION:
|
|
roomExplanation = resourceName;
|
|
dateExplanation = bookingStartMoment.clone().startOf('day').format('MMM DD');
|
|
bookingTimeExplanation = `${bookingStartMoment.clone().format('HH:mm a')} - ${bookingEndMoment.clone().format('HH:mm a')}`;
|
|
incidentTimeExplanation = ` Lock : ${lockMoment.clone().format('HH:mm a')},`;
|
|
incidentTypeExplanation = '';
|
|
|
|
date = bookingStartMoment.clone().startOf('day').format();
|
|
|
|
price = +chargePrice.toFixed(2);
|
|
quantity = +timeIntervalsToCharge.toFixed(2);
|
|
// priceExplanation = `$${totalChargeFee.toFixed(2)}, ${quantity} x $${price.toFixed(2)}`;
|
|
break;
|
|
case incidentType.UNLOCKED_INCIDENT_STANDALONE:
|
|
roomExplanation = resourceName;
|
|
dateExplanation = unlockMoment.clone().startOf('day').format('MMM DD');
|
|
bookingTimeExplanation = `No reservation`;
|
|
incidentTimeExplanation = ''; // `UNLOCK : ${unlockMoment.clone().format('HH:mm a')}`;
|
|
additionalIncidentExplanation = ` ${unlockedIncidentLevelsPrices[incidentLevel].description},`;
|
|
incidentTypeExplanation = '';
|
|
|
|
date = unlockMoment.clone().startOf('day').format();
|
|
|
|
price = +incidentPrice.toFixed(2);
|
|
quantity = 1.00;
|
|
// priceExplanation = `$${price.toFixed(2)}, 1 x $${price.toFixed(2)}`;
|
|
break;
|
|
case incidentType.UNSCHEDULED_INCIDENT_STANDALONE:
|
|
roomExplanation = resourceName;
|
|
dateExplanation = unlockMoment.clone().startOf('day').format('MMM DD');
|
|
bookingTimeExplanation = `No reservation`;
|
|
incidentTimeExplanation = ` Unlock : ${unlockMoment.clone().format('HH:mm a')} Lock : ${lockMoment.clone().format('HH:mm a')},`;
|
|
incidentTypeExplanation = '';
|
|
|
|
date = unlockMoment.clone().startOf('day').format();
|
|
|
|
price = +chargePrice.toFixed(2);
|
|
quantity = +timeIntervalsToCharge.toFixed(2);
|
|
// priceExplanation = `$${totalChargeFee.toFixed(2)}, ${quantity} x $${price.toFixed(2)}`;
|
|
break;
|
|
case incidentType.BOOKING_MOVED_TO_ANOTHER_DAY:
|
|
if (oldResourceName !== newResourceName){
|
|
roomExplanation = `${oldResourceName} -> ${newResourceName}`;
|
|
}else{
|
|
roomExplanation = oldResourceName;
|
|
}
|
|
|
|
dateExplanation = `${oldBookingStartMoment.clone().format('MMM DD')} -> ${newBookingStartMoment.clone().format('MMM DD')}`;
|
|
bookingTimeExplanation = `(${oldBookingStartMoment.clone().format('HH:mm a')} - ${oldBookingEndMoment.clone().format('HH:mm a')}) -> (${newBookingStartMoment.clone().format('HH:mm a')} - ${newBookingEndMoment.clone().format('HH:mm a')})`;
|
|
incidentTimeExplanation = ` Moved on : ${incidentTimestampMoment.clone().format('MMM DD, HH:mm a')},`;
|
|
incidentTypeExplanation = '[Cancellation]';
|
|
|
|
date = incidentTimestampMoment.clone().startOf('day').format();
|
|
|
|
price = +totalChargeFee.toFixed(2);
|
|
quantity = 1.00;
|
|
// priceExplanation = `$${totalChargeFee.toFixed(2)}, 1 x $${price.toFixed(2)}`;
|
|
break;
|
|
case incidentType.BOOKING_SHORTENED:
|
|
if (oldResourceName !== newResourceName){
|
|
roomExplanation = `${oldResourceName} -> ${newResourceName}`;
|
|
}else{
|
|
roomExplanation = oldResourceName;
|
|
}
|
|
|
|
dateExplanation = `${oldBookingStartMoment.clone().format('MMM DD')}`;
|
|
bookingTimeExplanation = `(${oldBookingStartMoment.clone().format('HH:mm a')} - ${oldBookingEndMoment.clone().format('HH:mm a')}) -> (${newBookingStartMoment.clone().format('HH:mm a')} - ${newBookingEndMoment.clone().format('HH:mm a')})`;
|
|
incidentTimeExplanation = ` Shortened on : ${incidentTimestampMoment.clone().format('MMM DD, HH:mm a')},`;
|
|
incidentTypeExplanation = '[Cancellation]';
|
|
|
|
date = incidentTimestampMoment.clone().startOf('day').format();
|
|
|
|
price = +totalChargeFee.toFixed(2);
|
|
quantity = 1.00;
|
|
// priceExplanation = `$${totalChargeFee.toFixed(2)}, 1 x $${price.toFixed(2)}`;
|
|
break;
|
|
case incidentType.BOOKING_CANCELED_LATE:
|
|
roomExplanation = oldResourceName;
|
|
dateExplanation = `${oldBookingStartMoment.clone().format('MMM DD')}`;
|
|
bookingTimeExplanation = `${oldBookingStartMoment.clone().format('HH:mm a')} - ${oldBookingEndMoment.clone().format('HH:mm a')}`;
|
|
incidentTimeExplanation = ` Canceled on : ${incidentTimestampMoment.clone().format('MMM DD, HH:mm a')},`;
|
|
incidentTypeExplanation = '[Cancellation]';
|
|
|
|
date = incidentTimestampMoment.clone().startOf('day').format();
|
|
|
|
price = +totalChargeFee.toFixed(2);
|
|
quantity = 1.00;
|
|
// priceExplanation = `$${totalChargeFee.toFixed(2)}, 1 x $${price.toFixed(2)}`;
|
|
break;
|
|
}
|
|
|
|
const formattedName = `${incidentTypeExplanation} ${incidentExplanation},${additionalIncidentExplanation}${incidentTimeExplanation} ${officeName}, ${roomExplanation}, ${dateExplanation}, ${bookingTimeExplanation}`;
|
|
|
|
return {
|
|
name: formattedName,
|
|
price,
|
|
quantity,
|
|
date,
|
|
member: memberId,
|
|
team: null,
|
|
office: officeId,
|
|
isPersonal: false,
|
|
}
|
|
};
|
|
|
|
const createFeeFromBooking = (booking, resourceMappings) => {
|
|
const { officeId, resourceId, memberId, start, end, timezone, hourlyRate } = booking;
|
|
const { officesMap, resourcesMap } = resourceMappings;
|
|
|
|
const startMoment = moment.tz(start, DEFAULT_DATE_FORMAT, timezone);
|
|
const endMoment = moment.tz(end, DEFAULT_DATE_FORMAT, timezone);
|
|
const reservationLength = endMoment.diff(startMoment, 'hours', true);
|
|
|
|
const officeName = officesMap[officeId].officeName || 'Unknown';
|
|
const resourceName = resourcesMap[resourceId].resourceName || 'Unknown';
|
|
|
|
const formattedDate = startMoment.clone().startOf('day').format('MMM DD');
|
|
const formattedStartTime = startMoment.format('HH:mm a');
|
|
const formattedEndTime = endMoment.format('HH:mm a');
|
|
|
|
const formattedName = `${officeName}, ${resourceName}, ${formattedDate} [${formattedStartTime} - ${formattedEndTime}]`;
|
|
|
|
return {
|
|
name: formattedName,
|
|
price: +hourlyRate.toFixed(2),
|
|
quantity: +reservationLength.toFixed(2),
|
|
date: startMoment.startOf('day').toISOString(),
|
|
member: memberId,
|
|
team: null,
|
|
office: officeId,
|
|
isPersonal: false,
|
|
}
|
|
};
|
|
|
|
const getMembersFeesForDateRange = (dateRange, memberIds) => {
|
|
return new Promise((resolve, reject) => {
|
|
const collectData = [getAllIncidents(dateRange, memberIds), getActiveBookingsForMembersInDateRange(dateRange, memberIds), getResourceMappings(), fetchAllMembers()];
|
|
|
|
|
|
Promise.all(collectData)
|
|
.then((result) => {
|
|
const allIncidents = result[0];
|
|
const allActiveBookings = result[1];
|
|
const resourceMappings = result[2];
|
|
const membersList = result[3];
|
|
|
|
const memberIdTeamMappings = {};
|
|
membersList.forEach((member) => {
|
|
memberIdTeamMappings[member.memberId] = member.teamId;
|
|
});
|
|
|
|
const allFees = [];
|
|
|
|
allIncidents.forEach((incident) => allFees.push(createFeeFromIncident(incident)));
|
|
allActiveBookings.forEach((booking) => allFees.push(createFeeFromBooking(booking, resourceMappings)));
|
|
|
|
allFees.forEach((fee) => {
|
|
fee.team = memberIdTeamMappings[fee.member] || null;
|
|
});
|
|
|
|
resolve(allFees);
|
|
})
|
|
.catch((error) => {
|
|
console.log(error);
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
getMembersFeesForDateRange,
|
|
};
|