'use strict'; const moment = require('moment-timezone'); const db = require('../../models/index'); const Op = require('sequelize').Op; const { UI_TIMEZONE, BOOKING_CHANGE_PERCENTAGE_CHARGE, CHARGE_BOOKING_CHANGE_UNDER_TIME, ALLOWED_BOOKING_CANCELLATION_TIME, incidentType } = require('../../constants/constants'); const bulkWriteBookingChangeIncidents = (incidents) => { //TODO: Check if this complete method can be replaced with // return db.bookingChangeIncident.bulkCreate(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 getIncidentsFromChanges = (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(), 'minutes'); console.log('Change detected : '); console.log('\tOld reservation :'); console.log('\t\tResource : ', oldResourceId); console.log('\t\tStart : ', oldStart.format()); console.log('\t\tEnd : ', oldEnd.format()); console.log('\t\tLength : ', oldReservationLength); console.log('\tNew Reservation :'); console.log('\t\tResource : ', newReservation.resourceId); console.log('\t\tStart : ', newStart.format()); console.log('\t\tEnd : ', newEnd.format()); console.log('\t\tLength : ', newReservationLength); console.log('\t\tCanceled : ', canceled); console.log('\t---------------------------------'); console.log('\tDifference : ', differenceFromNow, 'minutes'); console.log(''); console.log('\tIs booking changed too late ? ', differenceFromNow, ' < ', CHARGE_BOOKING_CHANGE_UNDER_TIME); if (differenceFromNow < CHARGE_BOOKING_CHANGE_UNDER_TIME){ const { reservationId, memberId, resourceId } = newReservation; console.log('\t\tYes'); console.log('\tIs booking canceled ?'); if (!canceled) { console.log('\t\tNo'); // Check if new reservation is on same day const sameDay = oldStart.tz(reservationTimezone).isSame(newStart.tz(reservationTimezone), 'day'); console.log('\tIs new reservation on the same day ?'); if (sameDay) { console.log('\t\tYes'); // Reservation moved in same day // Check if member shortened the reservation console.log('\tIs reservation shortened ? ', newReservationLength, ' < ', oldReservationLength); if (newReservationLength < oldReservationLength) { console.log('\t\tYes'); const differenceInLength = oldReservationLength - newReservationLength; const chargeFee = differenceInLength * reservationHourlyRate * BOOKING_CHANGE_PERCENTAGE_CHARGE / 100; console.log('\t\t\tThis is [shortened] incident ! Charge fee : ', chargeFee); 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{ console.log('\t\tNo'); } } else { console.log('\t\tNo'); // Reservation moved to another day // Add cancellation charge const chargeFee = oldReservationLength * reservationHourlyRate * BOOKING_CHANGE_PERCENTAGE_CHARGE / 100; console.log('\t\t\tThis is incident ! Charge fee : ', chargeFee); 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{ console.log('\t\tYes'); const differenceFromCreation = moment.utc().diff(reservationCreationTimestamp, 'minutes'); console.log('\tIs booking created in past ', ALLOWED_BOOKING_CANCELLATION_TIME, ' minutes ?', differenceFromCreation, ' > ', ALLOWED_BOOKING_CANCELLATION_TIME); if (differenceFromCreation > ALLOWED_BOOKING_CANCELLATION_TIME){ console.log('\t\tYes'); const chargeFee = reservationHourlyRate * oldReservationLength * BOOKING_CHANGE_PERCENTAGE_CHARGE / 100; console.log('\t\t\tThis is [cancellation] incident ! charge fee : ', chargeFee); 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); } } } else{ console.log('\t\tNo'); } } } }); resolve(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', 'chargeFee']; return db.bookingChangeIncident.findAll({attributes, where: filters}); }; module.exports = { getChargedCanceledReservations, getIncidentsFromChanges, bulkWriteBookingChangeIncidents, };