'use strict'; const moment = require('moment-timezone'); const db = require('../../models/index'); const Op = require('sequelize').Op; const { incidentType, UI_TIMEZONE, DEFAULT_DATE_FORMAT, integrationServiceErrors } = require('../../constants/constants'); const { fetchAllMembers } = require('../officeRnD/members'); const { fetchOffices, fetchResources } = require('../officeRnD/resources'); const getUnlockedIncidents = (startDate, endDate, memberId) => { const attributes = ['id', 'reservationId', 'memberId', 'resourceId', 'bookingStart', 'bookingEnd', 'unlockTimestamp', 'incidentLevel', 'incidentLevelPrice']; const filters = {}; 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 (memberId){ filters.memberId = memberId; } return db.unlockedIncident.findAll({ attributes, where: filters, sort: [ ['bookingStart', 'ASC'] ] }); }; const getUnscheduledIncidents = (startDate, endDate, memberId) => { const attributes = [ 'id', 'reservationId', 'memberId', 'resourceId', 'bookingStart', 'bookingEnd', 'unlockTimestamp', 'lockTimestamp', 'timeIntervalsToCharge', 'chargePrice', 'totalChargeFee' ]; const filters = {}; 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 (memberId){ filters.memberId = memberId; } return db.unscheduledIncident.findAll({ attributes, where: filters, sort: [ ['bookingStart', 'ASC'] ] }); }; const getBookingChangeIncidents = (startDate, endDate, memberId) => { const attributes = [ 'id', 'reservationId', 'memberId', 'oldResourceId', 'newResourceId', 'oldBookingStart', 'oldBookingEnd', 'newBookingStart', 'newBookingEnd', 'incidentType', 'chargeFee', 'createdAt' ]; const filters = {}; if (startDate && endDate) { filters.createdAt = { [Op.and]: { [Op.gte]: startDate.toISOString(), [Op.lte]: endDate.toISOString(), } } } if (memberId){ filters.memberId = memberId; } 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, memberId) => { 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, memberId), getUnscheduledIncidents(startDate, endDate, memberId), getBookingChangeIncidents(startDate, endDate, memberId) ]; 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; allIncidents.push({ incidentId: unlockedIncident.id, memberId: unlockedIncident.memberId, memberName: membersMap[unlockedIncident.memberId].name, resourceName: resourcesMap[unlockedIncident.resourceId].resourceName, officeName: officesMap[resourcesMap[unlockedIncident.resourceId].officeId].officeName, bookingStart: formatTime(unlockedIncident.bookingStart), bookingEnd: formatTime(unlockedIncident.bookingEnd), unlockTimestamp: formatTime(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; } allIncidents.push({ incidentId: unscheduledIncident.id, memberId: unscheduledIncident.memberId, memberName: membersMap[unscheduledIncident.memberId].name, resourceName: resourcesMap[unscheduledIncident.resourceId].resourceName, officeName: officesMap[resourcesMap[unscheduledIncident.resourceId].officeId].officeName, bookingStart: formatTime(unscheduledIncident.bookingStart), bookingEnd: formatTime(unscheduledIncident.bookingEnd), unlockTimestamp: formatTime(unscheduledIncident.unlockTimestamp), lockTimestamp: formatTime(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, createdAt, } = bookingChangeIncident; const memberName = membersMap[memberId].name; const oldResource = resourcesMap[oldResourceId]; const newResource = newResourceId ? resourcesMap[newResourceId] : null; const oldResourceName = oldResource.resourceName; const newResourceName = newResource ? newResource.resourceName : null; const officeName = officesMap[oldResource.officeId].officeName; allIncidents.push({ incidentId: id, memberId, memberName, oldResourceName, newResourceName, officeName, oldBookingStart: formatTime(oldBookingStart), oldBookingEnd: formatTime(oldBookingEnd), newBookingStart: formatTime(newBookingStart), newBookingEnd: formatTime(newBookingEnd), incidentType, totalChargeFee: chargeFee, incidentTimestamp: formatTime(createdAt), }); }); resolve(allIncidents); }) .catch((error) => reject(error)); }); }; module.exports = { getUnlockedIncidents, getUnscheduledIncidents, getAllIncidents, };