149 lines
7.3 KiB
JavaScript
149 lines
7.3 KiB
JavaScript
'use strict';
|
|
|
|
const moment = require('moment-timezone');
|
|
const db = require('../../models/index');
|
|
const Op = require('sequelize').Op;
|
|
|
|
const { UI_TIMEZONE, BOOKING_CHANGE_PERCENTAGE_CHARGE, ALLOWED_BOOKING_CANCELLATION_TIME, incidentType } = require('../../constants/constants');
|
|
|
|
const bulkWriteBookingChangeIncidents = (incidents) => {
|
|
return new Promise((resolve, reject) => {
|
|
const asyncJobs = [];
|
|
incidents.forEach((incident) => {
|
|
asyncJobs.push(db.bookingChangeIncident.findOrCreate({where: incident, defaults: incident}));
|
|
});
|
|
|
|
Promise.all(asyncJobs)
|
|
.then(() => {
|
|
resolve();
|
|
})
|
|
.catch((error) => reject(error));
|
|
});
|
|
};
|
|
|
|
const chargeBookingChanges = (changes) => {
|
|
return new Promise((resolve, reject) => {
|
|
if (Array.isArray(changes)){
|
|
const incidents = [];
|
|
changes.forEach((change) => {
|
|
const { oldReservation, newReservation } = change;
|
|
if (oldReservation && newReservation){
|
|
const oldResourceId = oldReservation.resourceId;
|
|
const oldStart = oldReservation.start ? moment.utc(oldReservation.start) : null;
|
|
const oldEnd = oldReservation.end ? moment.utc(oldReservation.end) : null;
|
|
|
|
const newStart = newReservation.start ? moment.utc(newReservation.start) : null;
|
|
const newEnd = newReservation.end ? moment.utc(newReservation.end) : null;
|
|
const reservationCreationTimestamp = newReservation.createdAt ? moment.utc(newReservation.createdAt) : null;
|
|
|
|
const reservationTimezone = newReservation.timezone ? newReservation.timezone : UI_TIMEZONE;
|
|
const reservationHourlyRate = oldReservation.hourlyRate ? oldReservation.hourlyRate : newReservation.hourlyRate;
|
|
const canceled = newReservation.canceled;
|
|
|
|
if (oldStart && oldEnd && newStart && newEnd && reservationHourlyRate){
|
|
const oldReservationLength = oldEnd.diff(oldStart, 'hours', true);
|
|
const newReservationLength = newEnd.diff(newStart, 'hours', true);
|
|
|
|
const differenceFromNow = oldStart.diff(moment.utc(), 'hours');
|
|
|
|
if (differenceFromNow < 24){
|
|
// Changed reservation that was within 24hrs from now
|
|
const { reservationId, memberId, resourceId } = newReservation;
|
|
|
|
if (!canceled) {
|
|
// Check if new reservation is on same day
|
|
const sameDay = oldStart.tz(reservationTimezone).isSame(newStart.tz(reservationTimezone), 'day');
|
|
|
|
if (sameDay) {
|
|
// Reservation moved in same day
|
|
// Check if member shortened the reservation
|
|
|
|
if (newReservationLength < oldReservationLength) {
|
|
const differenceInLength = oldReservationLength - newReservationLength;
|
|
const chargeFee = differenceInLength * reservationHourlyRate * BOOKING_CHANGE_PERCENTAGE_CHARGE / 100;
|
|
|
|
const incident = {
|
|
reservationId,
|
|
memberId,
|
|
oldResourceId: oldResourceId || resourceId,
|
|
newResourceId: resourceId,
|
|
oldBookingStart: oldReservation.start,
|
|
oldBookingEnd: oldReservation.end,
|
|
newBookingStart: newReservation.start,
|
|
newBookingEnd: newReservation.end,
|
|
incidentType: incidentType.BOOKING_SHORTENED,
|
|
chargeFee,
|
|
};
|
|
|
|
incidents.push(incident);
|
|
}
|
|
} else {
|
|
// Reservation moved to another day
|
|
// Add cancellation charge
|
|
const chargeFee = oldReservationLength * reservationHourlyRate * BOOKING_CHANGE_PERCENTAGE_CHARGE / 100;
|
|
|
|
const incident = {
|
|
reservationId,
|
|
memberId,
|
|
oldResourceId: oldResourceId || resourceId,
|
|
newResourceId: resourceId,
|
|
oldBookingStart: oldReservation.start,
|
|
oldBookingEnd: oldReservation.end,
|
|
newBookingStart: newReservation.start,
|
|
newBookingEnd: newReservation.end,
|
|
incidentType: incidentType.BOOKING_MOVED_TO_ANOTHER_DAY,
|
|
chargeFee,
|
|
};
|
|
|
|
incidents.push(incident);
|
|
}
|
|
}else{
|
|
const differenceFromCreation = moment.utc().diff(reservationCreationTimestamp, 'minutes');
|
|
|
|
if (differenceFromCreation > ALLOWED_BOOKING_CANCELLATION_TIME){
|
|
const chargeFee = 2 * reservationHourlyRate * oldReservationLength * BOOKING_CHANGE_PERCENTAGE_CHARGE / 100;
|
|
const incident = {
|
|
reservationId,
|
|
memberId,
|
|
oldResourceId: oldResourceId || resourceId,
|
|
newResourceId: null,
|
|
oldBookingStart: oldReservation.start,
|
|
oldBookingEnd: oldReservation.end,
|
|
newBookingStart: null,
|
|
newBookingEnd: null,
|
|
incidentType: incidentType.BOOKING_CANCELED_LATE,
|
|
chargeFee,
|
|
};
|
|
|
|
incidents.push(incident);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
resolve(bulkWriteBookingChangeIncidents(incidents));
|
|
}else{
|
|
reject('Input argument is not an array !');
|
|
}
|
|
});
|
|
};
|
|
|
|
const getChargedCanceledReservations = (reservationIds) => {
|
|
const filters = {
|
|
reservationId: {
|
|
[Op.in]: reservationIds,
|
|
},
|
|
incidentType: incidentType.BOOKING_CANCELED_LATE,
|
|
};
|
|
|
|
const attributes = ['memberId', 'oldBookingStart', 'oldBookingEnd'];
|
|
|
|
return db.bookingChangeIncident.findAll({attributes, where: filters});
|
|
};
|
|
|
|
module.exports = {
|
|
chargeBookingChanges,
|
|
getChargedCanceledReservations,
|
|
};
|