Files
old-psihologija/services/integration/doorLockCharges.js

769 lines
42 KiB
JavaScript

'use strict';
const moment = require('moment-timezone');
const db = require('../../models/index');
const Op = require('sequelize').Op;
const {
doorLockEvents,
incidentType,
unlockedIncidentLevelsPrices,
UNSCHEDULED_CHARGE_PRICE,
MAX_BACK_TO_BACK_DIFFERENCE,
UNSCHEDULED_USE_INITIAL_TIME_SEGMENT_LENGTH,
UNSCHEDULED_TIME_RESOLUTION,
UI_TIMEZONE
} = require('../../constants/constants');
const { getUnlockEntryForReservation, getLockEntryForReservation, getEntriesBetween, getLastEntryForReservation } = require('../doorLock/doorLock');
const { getAllFinishedBookings, getFirstPreviousBooking, getFirstNextBooking } = require('../officeRnD/bookings');
const getSortedIncidentsForMember = (memberId) => {
const attributes = ['bookingStart', 'incidentLevel', 'incidentLevelPrice', 'unlockTimestamp'];
const filters = {
memberId,
deleted: false
};
const order = [['unlockTimestamp', 'DESC']];
return db.unlockedIncident.findAll({
attributes,
where: filters,
order,
})
};
const insertUnscheduledIncidents = (incidents) => {
const asyncJobs = [];
incidents.forEach((incident) => {
const { reservation, unlockTimestamp, lockTimestamp, memberId, resourceId, chargePrice, timeIntervalsToCharge, totalChargeFee } = incident;
const { reservationId, start, end } = reservation;
const incidentForDB = {
reservationId,
memberId,
resourceId,
bookingStart: start,
bookingEnd: end,
doorLockEventTimestamp: null,
doorLockEventType: null,
chargePrice,
timeIntervalsToCharge,
totalChargeFee,
unlockTimestamp,
lockTimestamp,
deleted: false
};
asyncJobs.push(db.unscheduledIncident.findOrCreate({
where: {
reservationId,
memberId,
resourceId,
bookingStart: start,
bookingEnd: end,
unlockTimestamp,
lockTimestamp,
},
defaults: {...incidentForDB},
}));
});
return Promise.all(asyncJobs);
};
const deleteUnscheduledIncidentsById = (incidentIds) => {
const filters = {
id: {
[Op.in]: incidentIds
}
};
return db.unscheduledIncident.update({deleted: true},{where: filters});
};
const insertUnlockedIncidents = (incidents) => {
const asyncJobs = [];
incidents.forEach((incident) => {
const { reservation, memberId, resourceId, unlockTimestamp, incidentLevel, incidentLevelPrice } = incident;
const { reservationId, start, end} = reservation;
const incidentForDB = {
reservationId,
memberId,
resourceId,
bookingStart: start,
bookingEnd: end,
unlockTimestamp,
incidentLevel,
incidentLevelPrice,
deleted: false
};
asyncJobs.push(db.unlockedIncident.findOrCreate({
where: {
reservationId,
memberId,
resourceId,
bookingStart: start,
bookingEnd: end,
unlockTimestamp,
incidentLevel,
},
defaults: {...incidentForDB},
}));
});
return Promise.all(asyncJobs);
};
const deleteUnlockedIncidentsById = (incidentIds) => {
const filters = {
id: {
[Op.in]: incidentIds
}
};
return db.unlockedIncident.update({deleted: true},{where: filters});
};
const setUnlockedIncidentsLevel = (incidents) => {
return new Promise ((resolve, reject) => {
const sortingFunction = (incidentA, incidentB) => {
const sortCondition = moment.utc(incidentA.unlockTimestamp).isBefore(moment.utc(incidentB.unlockTimestamp));
return sortCondition ? -1 : 1;
};
incidents.sort(sortingFunction);
const membersLastIncident = {};
incidents.forEach((incident) => {
membersLastIncident[incident.memberId] = {
incidentLevel: null,
incidentTimestamp: null,
};
});
const asyncJobs = [];
Object.keys(membersLastIncident).forEach((memberId) => {
asyncJobs.push(getSortedIncidentsForMember(memberId));
});
Promise.all(asyncJobs)
.then((results) => {
results.forEach((result) => {
const lastIncident = result && result[0] ? result[0] : null;
if (lastIncident) {
membersLastIncident[lastIncident.memberId] = {
incidentLevel: lastIncident.incidentLevel,
incidentTimestamp: lastIncident.unlockTimestamp,
}
}
});
const incidentsWithLevel = [];
incidents.forEach((incident) => {
const memberLastIncident = membersLastIncident[incident.memberId];
const formattedIncident = {
reservation: incident.reservation,
memberId: incident.memberId,
resourceId: incident.resourceId,
incidentLevel: undefined,
incidentLevelPrice: undefined,
unlockTimestamp: incident.unlockTimestamp,
};
if (!memberLastIncident.incidentLevel) {
formattedIncident.incidentLevel = unlockedIncidentLevelsPrices.UNLOCKED_0.title;
formattedIncident.incidentLevelPrice = unlockedIncidentLevelsPrices.UNLOCKED_0.price;
} else {
const lastIncidentTime = moment.tz(memberLastIncident.incidentTimestamp, UI_TIMEZONE).startOf('month');
const currentIncidentTime = moment.tz(incident.unlockTimestamp, UI_TIMEZONE).startOf('month');
const timeDiff = Math.abs(lastIncidentTime.diff(currentIncidentTime, 'months'));
if (timeDiff >= (parseInt(process.env.UNLOCK_STREAK_REPAIR_AFTER) || 6)){
formattedIncident.incidentLevel = unlockedIncidentLevelsPrices.UNLOCKED_0.title;
formattedIncident.incidentLevelPrice = unlockedIncidentLevelsPrices.UNLOCKED_0.price;
} else {
const lastIncidentLevelId = unlockedIncidentLevelsPrices[memberLastIncident.incidentLevel].id;
const maxId = 5;
if ((lastIncidentLevelId && (lastIncidentLevelId >= maxId)) || (timeDiff === 0)){
formattedIncident.incidentLevel = memberLastIncident.incidentLevel;
formattedIncident.incidentLevelPrice = unlockedIncidentLevelsPrices[formattedIncident.incidentLevel].price;
} else {
const nextId = lastIncidentLevelId + 1;
Object.keys(unlockedIncidentLevelsPrices).forEach((key) => {
if (unlockedIncidentLevelsPrices[key].id === nextId){
formattedIncident.incidentLevel = unlockedIncidentLevelsPrices[key].title;
formattedIncident.incidentLevelPrice = unlockedIncidentLevelsPrices[key].price
}
});
}
}
}
memberLastIncident.incidentLevel = formattedIncident.incidentLevel;
memberLastIncident.incidentTimestamp = formattedIncident.unlockTimestamp;
incidentsWithLevel.push(formattedIncident);
});
resolve(incidentsWithLevel);
})
.catch((error) => reject(error));
});
};
const analyseReservation = (reservation) => {
return new Promise ((resolve, reject) => {
const getNearBookingsAsync = [
getFirstPreviousBooking(reservation),
getFirstNextBooking(reservation)
];
Promise.all(getNearBookingsAsync)
.then(([previousReservation, nextReservation]) => {
const getRelatedDoorLockEntriesAsync = [
getUnlockEntryForReservation(reservation, previousReservation),
getLockEntryForReservation(reservation, nextReservation)
];
Promise.all(getRelatedDoorLockEntriesAsync)
.then(([unlockEntry, lockEntry, entriesBetween]) => {
const currentReservationStart = moment.utc(reservation.start);
const currentReservationEnd = moment.utc(reservation.end);
let timeDifferenceFromPreviousReservation = MAX_BACK_TO_BACK_DIFFERENCE + 100;
if (previousReservation) {
const previousReservationEnd = moment.utc(previousReservation.end);
timeDifferenceFromPreviousReservation = currentReservationStart.diff(previousReservationEnd, 'minutes');
}
const previousReservationIsBackToBack = timeDifferenceFromPreviousReservation <= MAX_BACK_TO_BACK_DIFFERENCE;
let timeDifferenceBeforeNextReservation = MAX_BACK_TO_BACK_DIFFERENCE + 100;
if (nextReservation) {
const nextReservationStart = moment.utc(nextReservation.start);
timeDifferenceBeforeNextReservation = nextReservationStart.diff(currentReservationEnd, 'minutes');
}
const nextReservationIsBackToBack = timeDifferenceBeforeNextReservation <= MAX_BACK_TO_BACK_DIFFERENCE;
let timeDifferenceFromUnlockEntry = 0;
if (unlockEntry) {
const unlockTime = moment.utc(unlockEntry.timestamp);
timeDifferenceFromUnlockEntry = currentReservationStart.diff(unlockTime, 'minutes');
}
let timeIntervalsToChargeBefore = Math.floor(timeDifferenceFromUnlockEntry / UNSCHEDULED_TIME_RESOLUTION);
timeIntervalsToChargeBefore -= 1; // Remove first N minutes, N = UNSCHEDULED_TIME_RESOLUTION
const totalChargeFeeBefore = timeIntervalsToChargeBefore * UNSCHEDULED_CHARGE_PRICE;
const chargeBefore = totalChargeFeeBefore > 0;
let timeDifferenceFromLockEntry = 0;
if (lockEntry) {
const lockTime = moment.utc(lockEntry.timestamp);
timeDifferenceFromLockEntry = lockTime.diff(currentReservationEnd, 'minutes');
}
let timeIntervalsToChargeAfter = Math.floor(timeDifferenceFromLockEntry / UNSCHEDULED_TIME_RESOLUTION);
timeIntervalsToChargeAfter -= 1; // Remove first N minutes, N = UNSCHEDULED_TIME_RESOLUTION
const totalChargeFeeAfter = timeIntervalsToChargeAfter * UNSCHEDULED_CHARGE_PRICE;
const chargeAfter = totalChargeFeeAfter > 0;
// const reservationMoment = moment.tz(reservation.start, reservation.timezone);
// if (reservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-11-21 00:00:16+00')) {
// console.log('\r\n\r\n==== ANALYSE RESERVATION ==== ');
// console.log('\tStart : ', reservationMoment.format('DD.MM, HH:mm'));
// console.log('\tEnd : ', moment.tz(reservation.end, reservation.timezone).format('DD.MM, HH:mm'));
// console.log('\t----------------------------------');
// console.log('\tFirst previous reservation : ');
// if (previousReservation) {
// console.log('\t\tStart : ', moment.tz(previousReservation.start, previousReservation.timezone).format('DD.MM, HH:mm'));
// console.log('\t\tEnd : ', moment.tz(previousReservation.end, previousReservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\t\tNO PREVIOUS RESERVATION');
// }
//
// console.log('\tFirst next reservation : ');
// if (nextReservation) {
// console.log('\t\tStart : ', moment.tz(nextReservation.start, nextReservation.timezone).format('DD.MM, HH:mm'));
// console.log('\t\tEnd : ', moment.tz(nextReservation.end, nextReservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\t\tNO NEXT RESERVATION');
// }
// console.log('\t----------------------------------');
// if (unlockEntry) {
// console.log('\tUnlock entry : ', moment.tz(unlockEntry.timestamp, reservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\tUnlock entry : NO UNLOCK ENTRY');
// }
// if (lockEntry) {
// console.log('\tLock entry : ', moment.tz(lockEntry.timestamp, reservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\tLock entry : NO LOCK ENTRY');
// }
//
// console.log('\t----------------------------------');
// console.log('\tTime before : ');
// console.log('\t\tOriginal : ', timeDifferenceFromUnlockEntry);
// console.log('\t\tModified : ', timeIntervalsToChargeBefore);
// console.log('\tTime after : ');
// console.log('\t\tOriginal : ', timeDifferenceFromLockEntry);
// console.log('\t\tModified : ', timeIntervalsToChargeAfter);
// }
const result = {
currentReservation: reservation,
previousReservation,
nextReservation,
unlockEntry,
lockEntry,
previousReservationIsBackToBack,
nextReservationIsBackToBack,
timeDifferenceFromPreviousReservation,
timeDifferenceBeforeNextReservation,
timeDifferenceFromUnlockEntry,
timeDifferenceFromLockEntry,
chargeBefore,
chargeAfter,
totalChargeFeeBefore,
totalChargeFeeAfter,
timeIntervalsToChargeBefore,
timeIntervalsToChargeAfter,
};
resolve(result);
})
.catch((error) => reject(error));
})
.catch((error) => reject(error));
});
};
const getIncidentData = (reservation) => {
return new Promise ((resolve, reject) => {
analyseReservation(reservation)
.then((result) => {
const {
currentReservation,
previousReservation,
nextReservation,
unlockEntry,
lockEntry,
previousReservationIsBackToBack,
nextReservationIsBackToBack,
timeDifferenceFromPreviousReservation,
timeDifferenceBeforeNextReservation,
timeDifferenceFromUnlockEntry,
timeDifferenceFromLockEntry,
chargeBefore,
chargeAfter,
totalChargeFeeBefore,
totalChargeFeeAfter,
timeIntervalsToChargeBefore,
timeIntervalsToChargeAfter,
} = result;
const incidents = [];
const { resourceId } = currentReservation;
// const reservationMoment = moment.tz(currentReservation.start, currentReservation.timezone);
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-11-23 00:00:16+00')) {
// console.log('\r\n\r\n==== ANALYSE RESERVATION [GET INCIDENT DATA] ==== ');
// console.log('\tStart : ', reservationMoment.format('DD.MM, HH:mm'));
// console.log('\tEnd : ', moment.tz(currentReservation.end, currentReservation.timezone).format('DD.MM, HH:mm'));
// console.log('\t----------------------------------');
// console.log('\tFirst previous reservation : is back to back [', previousReservationIsBackToBack ? 'T' : 'F' , ']');
// if (previousReservation) {
// console.log('\t\tStart : ', moment.tz(previousReservation.start, previousReservation.timezone).format('DD.MM, HH:mm'));
// console.log('\t\tEnd : ', moment.tz(previousReservation.end, previousReservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\t\tNO PREVIOUS RESERVATION');
// }
//
// console.log('\tFirst next reservation : is back to back [', nextReservationIsBackToBack ? 'T' : 'F', ']');
// if (nextReservation) {
// console.log('\t\tStart : ', moment.tz(nextReservation.start, nextReservation.timezone).format('DD.MM, HH:mm'));
// console.log('\t\tEnd : ', moment.tz(nextReservation.end, nextReservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\t\tNO NEXT RESERVATION');
// }
// console.log('\t----------------------------------');
// if (unlockEntry) {
// console.log('\tUnlock entry : ', moment.tz(unlockEntry.timestamp, reservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\tUnlock entry : NO UNLOCK ENTRY');
// }
// if (lockEntry) {
// console.log('\tLock entry : ', moment.tz(lockEntry.timestamp, reservation.timezone).format('DD.MM, HH:mm'));
// } else {
// console.log('\tLock entry : NO LOCK ENTRY');
// }
// }
//**********************
const emptyReservation = {
reservationId: null,
start: null,
end: null,
};
// 1. Check if member entered before reservation start time
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\r\n\r\nChecking if member entered before reservation start time :');
// console.log('\tunlockEntry : ', unlockEntry && unlockEntry.timestamp ? unlockEntry.timestamp : 'NO UNLOCK ENTRY');
// console.log('\tCharge before : ', chargeBefore);
// console.log('\tThere is prev. res : ', previousReservationIsBackToBack);
// }
if (unlockEntry && chargeBefore && !previousReservationIsBackToBack) {
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\tIncident : YES');
// }
incidents.push({
incidentType: incidentType.UNSCHEDULED_INCIDENT_BEFORE_RESERVATION,
reservation,
unlockTimestamp: unlockEntry.timestamp,
lockTimestamp: null,
memberId: reservation.memberId,
resourceId: reservation.resourceId,
chargePrice: UNSCHEDULED_CHARGE_PRICE,
timeIntervalsToCharge: timeIntervalsToChargeBefore,
totalChargeFee: totalChargeFeeBefore,
});
}else{
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\tIncident : NO');
// }
}
// 2. Check if member left after reservation end time
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\r\n\r\nChecking if member left after reservation end time :');
// console.log('\tlockEntry : ', lockEntry && lockEntry.timestamp ? lockEntry.timestamp : 'NO LOCK ENTRY');
// console.log('\tCharge after : ', chargeAfter);
// console.log('\tThere is res after : ', nextReservationIsBackToBack);
// }
if (lockEntry && chargeAfter && !nextReservationIsBackToBack) {
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\tIncident : YES');
// }
incidents.push({
incidentType: incidentType.UNSCHEDULED_INCIDENT_AFTER_RESERVATION,
reservation,
unlockTimestamp: null,
lockTimestamp: lockEntry.timestamp,
memberId: reservation.memberId,
resourceId: reservation.resourceId,
chargePrice: UNSCHEDULED_CHARGE_PRICE,
timeIntervalsToCharge: timeIntervalsToChargeAfter,
totalChargeFee: totalChargeFeeAfter,
});
}else{
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\tIncident : NO');
// }
}
// 3. Check if member forgot to lock the door
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\r\n\r\nChecking if member left unlocked door :');
// console.log('\tunlockEntry : ', unlockEntry && unlockEntry.timestamp ? unlockEntry.timestamp : 'NO UNLOCK ENTRY');
// console.log('\tlockEntry : ', lockEntry && lockEntry.timestamp ? lockEntry.timestamp : 'NO LOCK ENTRY');
// console.log('\tThere is res before: ', previousReservationIsBackToBack);
// console.log('\tThere is res after : ', nextReservationIsBackToBack);
// }
let forgotToLockAsyncCheck;
if (!lockEntry && !nextReservationIsBackToBack){
if (unlockEntry){
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\tIncident : YES [#1]');
// }
incidents.push({
incidentType: incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION,
unlockTimestamp: unlockEntry.timestamp,
memberId: reservation.memberId,
resourceId: unlockEntry.resourceId,
reservation: reservation && reservation.dataValues ? reservation.dataValues : emptyReservation,
});
} else {
// No lock entry, no unlock entry and no reservation after this one
// This is either :
// 1. Last reservation in block of N reservations
// 1a. Member locked before entering this reservation
// 1b. Member forgot to lock the door <<< Only this is real incident
// 2. One reservation, but member never entered
if (previousReservationIsBackToBack){
// To ensure that this is last reservation in block (there is previous but no next reservation back to back)
// Now, just check if member actually locked before in the reservation time
forgotToLockAsyncCheck = getLastEntryForReservation(reservation);
forgotToLockAsyncCheck
.then((lastEntry) => {
if (lastEntry && lastEntry.event === doorLockEvents.USER_UNLOCKED){
// if (currentReservation.memberId === '5ce785af422bdd00967fb781' && reservationMoment.isAfter('2019-12-01 00:00:16+00')) {
// console.log('\tIncident : YES [#2]');
// }
incidents.push({
incidentType: incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION,
unlockTimestamp: lastEntry.timestamp,
memberId: lastEntry.memberId,
resourceId: lastEntry.resourceId,
reservation: reservation && reservation.dataValues ? reservation.dataValues : emptyReservation,
});
}
})
.catch((error) => reject(error));
}
}
}
// 4. Check for unscheduled use between current and previous reservation
const analysePreviousJob = [];
if (previousReservation && !previousReservationIsBackToBack){
analysePreviousJob.push(analyseReservation(previousReservation));
}else {
analysePreviousJob.push(undefined);
}
Promise.all(analysePreviousJob)
.then(([previousReservationResults]) => {
let fromTimestamp;
let toTimestamp;
if (previousReservationResults){
const previousReservationLockEntry = previousReservationResults.lockEntry;
const previousReservationUnlockEntry = previousReservationResults.unlockEntry;
//Special check for bookings with break between
if (previousReservation &&
!previousReservationIsBackToBack &&
previousReservation.memberId === currentReservation.memberId &&
previousReservationUnlockEntry && !previousReservationLockEntry &&
!unlockEntry && lockEntry //current reservation unlock / lock entries
) {
const unlockMoment = previousReservation.end ? moment.utc(previousReservation.end) : null;
const lockMoment = currentReservation.start ? moment.utc(currentReservation.start) : null;
if (unlockMoment && lockMoment){
const timeDifference = lockMoment.diff(unlockMoment, 'minutes');
const timeIntervalsToCharge = Math.floor(timeDifference / UNSCHEDULED_TIME_RESOLUTION);
const totalChargeFee = timeIntervalsToCharge * UNSCHEDULED_CHARGE_PRICE;
if (timeIntervalsToCharge > 0) {
incidents.push({
incidentType: incidentType.UNSCHEDULED_INCIDENT_STANDALONE,
reservation: emptyReservation,
unlockTimestamp: previousReservation.end,
lockTimestamp: currentReservation.start,
memberId: currentReservation.memberId,
resourceId,
chargePrice: UNSCHEDULED_CHARGE_PRICE,
timeIntervalsToCharge,
totalChargeFee,
});
}
}
}
fromTimestamp = previousReservationLockEntry && previousReservationLockEntry.timestamp ?
previousReservationLockEntry.timestamp : previousReservation.end;
toTimestamp = unlockEntry && unlockEntry.timestamp ?
unlockEntry.timestamp : reservation.start;
}else{
fromTimestamp = undefined;
toTimestamp = unlockEntry && unlockEntry.timestamp ?
unlockEntry.timestamp : reservation.start;
}
// Let's skip this if previous reservation is back-to-back
let getEntriesAsyncCheck;
if (previousReservation && previousReservationIsBackToBack){
//Skip
}else{
getEntriesAsyncCheck = getEntriesBetween(fromTimestamp, toTimestamp, resourceId);
}
//Now wait for "forgotToLockAsyncCheck", and possible "getEntriesBetween" to finish
Promise.all([forgotToLockAsyncCheck, getEntriesAsyncCheck])
.then((asyncActionResults) => {
const entriesBetween = asyncActionResults[1];
if (Array.isArray(entriesBetween)){
let pairUnlockEntry = null;
let pairLockEntry = null;
//Inspect all entries and insert detected incidents
entriesBetween.forEach((entry) => {
// console.log('\tEvent : ', entry.event);
// console.log('\tEvent : ', entry.timestamp ? moment.tz(entry.timestamp, UI_TIMEZONE).format('DD.MM, HH:mm') : '-');
if (entry && entry.event){
switch(entry.event){
case doorLockEvents.USER_UNLOCKED:
if (!pairUnlockEntry){
pairUnlockEntry = entry;
}else{
incidents.push({
incidentType: incidentType.UNLOCKED_INCIDENT_STANDALONE,
reservation: emptyReservation,
unlockTimestamp: pairUnlockEntry.timestamp,
memberId: pairUnlockEntry.memberId,
resourceId,
});
pairLockEntry = null;
pairUnlockEntry = entry;
}
break;
case doorLockEvents.USER_LOCKED:
if (pairUnlockEntry && !pairLockEntry){
pairLockEntry = entry;
const unlockMoment = moment.utc(pairUnlockEntry.timestamp);
const lockMoment = moment.utc(pairLockEntry.timestamp);
const entriesOnSameDay = lockMoment.tz(UI_TIMEZONE).isSame(unlockMoment.tz(UI_TIMEZONE), 'day');
const sameMember = pairUnlockEntry.memberId === pairLockEntry.memberId;
if ((entriesOnSameDay && !sameMember) || (!entriesOnSameDay)){
incidents.push({
incidentType: incidentType.UNLOCKED_INCIDENT_STANDALONE,
reservation: emptyReservation,
unlockTimestamp: pairUnlockEntry.timestamp,
memberId: pairUnlockEntry.memberId,
resourceId,
});
}else if (entriesOnSameDay && sameMember){
const timeDifference = lockMoment.diff(unlockMoment, 'minutes');
const timeIntervalsToCharge = Math.floor(timeDifference / UNSCHEDULED_TIME_RESOLUTION);
const totalChargeFee = timeIntervalsToCharge * UNSCHEDULED_CHARGE_PRICE;
if (timeIntervalsToCharge > 0){
incidents.push({
incidentType: incidentType.UNSCHEDULED_INCIDENT_STANDALONE,
reservation: emptyReservation,
unlockTimestamp: pairUnlockEntry.timestamp,
lockTimestamp: pairLockEntry.timestamp,
memberId: pairUnlockEntry.memberId,
resourceId,
chargePrice: UNSCHEDULED_CHARGE_PRICE,
timeIntervalsToCharge,
totalChargeFee,
});
}
}
pairUnlockEntry = null;
pairLockEntry = null;
}else{
pairLockEntry = null;
pairUnlockEntry = null;
}
}
}
});
if (pairUnlockEntry){
incidents.push({
incidentType: incidentType.UNLOCKED_INCIDENT_STANDALONE,
reservation: emptyReservation,
unlockTimestamp: pairUnlockEntry.timestamp,
memberId: pairUnlockEntry.memberId,
resourceId,
});
pairLockEntry = null;
pairUnlockEntry = null;
}
}
resolve(incidents);
})
.catch(error => reject(error));
})
.catch(error => reject(error));
//
// Promise.all(incidentsAsyncJobs)
// .then(() => {
// // console.log('\tDone with Async jobs for reservation ');
// // console.log('\t\tStart : ', reservationMoment.format('DD.MM, HH:mm'));
// // console.log('\t\tEnd : ', moment.tz(currentReservation.end, currentReservation.timezone).format('DD.MM, HH:mm'));
//
// setTimeout(() => {resolve(incidents)}, 10000);
// // resolve(incidents);
// })
// .catch((error) => reject(error));
})
.catch((error) => reject(error));
});
};
const calculateDoorLockCharges = () => {
return new Promise((resolve, reject) => {
getAllFinishedBookings()
.then((reservations) => {
const unlockedIncidents = [];
const unscheduledIncidents = [];
const asyncCheckForIncidents = [];
reservations.forEach((reservation) => {
asyncCheckForIncidents.push(getIncidentData(reservation));
});
Promise.all(asyncCheckForIncidents)
.then((allReservationsIncidents) => {
allReservationsIncidents.forEach((reservationIncidents) => {
reservationIncidents.forEach((incident) => {
if (incident.error) {
console.log('Error checking incident : ', incident.error);
} else if (incident.incidentType) {
switch (incident.incidentType) {
case incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION:
case incidentType.UNLOCKED_INCIDENT_STANDALONE:
unlockedIncidents.push(incident);
break;
case incidentType.UNSCHEDULED_INCIDENT_BEFORE_RESERVATION:
case incidentType.UNSCHEDULED_INCIDENT_AFTER_RESERVATION:
case incidentType.UNSCHEDULED_INCIDENT_STANDALONE:
unscheduledIncidents.push(incident);
break;
}
}
});
});
setUnlockedIncidentsLevel(unlockedIncidents)
.then((completedUnlockedIncidents) => {
const insertIncidentsJobs = [insertUnscheduledIncidents(unscheduledIncidents), insertUnlockedIncidents(completedUnlockedIncidents)];
Promise.all(insertIncidentsJobs)
.then(() => {
resolve(true);
})
.catch((error) => {
reject(error);
});
/*
insertUnscheduledIncidents(unscheduledIncidents)
.catch((error) => console.log(error));
insertUnlockedIncidents(completedUnlockedIncidents)
.catch((error) => console.log(error));
*/
})
.catch((error) => reject(error));
})
.catch((error) => reject(error));
})
.catch((error) => reject(error));
});
};
module.exports = {
calculateDoorLockCharges,
deleteUnlockedIncidentsById,
deleteUnscheduledIncidentsById
};