include unscheduled use between reservations

This commit is contained in:
Bilal Catic
2019-07-03 14:34:34 +02:00
parent 2b492025fb
commit 23b0924b5a
2 changed files with 143 additions and 10 deletions

View File

@@ -344,8 +344,33 @@ const getLockEntryForReservation = (reservation, nextReservation) => {
});
};
const getEntriesBetween = (reservation, previousReservation) => {
const getEntriesBetween = (fromTimestamp, toTimestamp, resourceId) => {
return new Promise((resolve, reject) => {
if (!fromTimestamp || !toTimestamp || !resourceId){
resolve([]);
}else {
const andTimestampFilters = [];
if (fromTimestamp){
andTimestampFilters.push({[Op.gt]: fromTimestamp});
}
if (toTimestamp){
andTimestampFilters.push({[Op.lt]: toTimestamp});
}
const filters = {
resourceId,
timestamp: {
[Op.and]: andTimestampFilters,
},
};
const order = [['timestamp', 'ASC']];
db.doorLockEvent.findAll({where: filters, order})
.then((results) => resolve(results))
.catch((error) => reject(error));
}
});
};
const getLastEntryForReservation = (reservation) => {

View File

@@ -180,8 +180,7 @@ const analyseReservation = (reservation) => {
.then(([previousReservation, nextReservation]) => {
const getRelatedDoorLockEntriesAsync = [
getUnlockEntryForReservation(reservation, previousReservation),
getLockEntryForReservation(reservation, nextReservation),
getEntriesBetween(reservation, previousReservation)
getLockEntryForReservation(reservation, nextReservation)
];
Promise.all(getRelatedDoorLockEntriesAsync)
@@ -274,6 +273,113 @@ const getIncidentData = (reservation) => {
timeIntervalsToChargeAfter,
} = result;
const incidents = [];
const incidentsAsyncJobs = [];
const { resourceId } = currentReservation;
// 0a. Check for unscheduled use between current and previous reservation
const analysePreviousJob = [];
if (previousReservation && !previousReservationIsBackToBack){
analysePreviousJob.push(analyseReservation(previousReservation));
}else {
analysePreviousJob.push(undefined);
}
incidentsAsyncJobs.push(
Promise.all(analysePreviousJob)
.then(([previousReservationResults]) => {
let fromTimestamp;
let toTimestamp;
if (previousReservationResults){
const previousReservationLockEntry = previousReservationResults.lockEntry;
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;
}
incidentsAsyncJobs.push(
getEntriesBetween(fromTimestamp, toTimestamp, resourceId)
.then((entriesBetween) => {
incidentsAsyncJobs.push(
new Promise((resolve, reject) => {
let pairUnlockEntry = null;
let pairLockEntry = null;
entriesBetween.forEach((entry) => {
if (entry && entry.event){
switch(entry.event){
case doorLockEvents.USER_UNLOCKED:
if (!pairUnlockEntry){
pairUnlockEntry = entry;
}else{
const virtualReservation = {
reservationId: '',
start: pairUnlockEntry.timestamp,
end: pairUnlockEntry.timestamp,
memberId: pairUnlockEntry.memberId,
resourceId,
};
incidents.push({
incidentType: incidentType.UNLOCKED_INCIDENT,
reservation: virtualReservation,
});
pairLockEntry = null;
pairUnlockEntry = entry;
}
break;
case doorLockEvents.USER_LOCKED:
if (pairUnlockEntry && !pairLockEntry){
pairLockEntry = entry;
const virtualReservation = {
reservationId: '',
start: pairUnlockEntry.timestamp,
end: pairLockEntry.timestamp,
memberId: pairUnlockEntry.memberId,
resourceId,
};
const unlockMoment = moment.utc(pairUnlockEntry.timestamp);
const lockMoment = moment.utc(pairLockEntry.timestamp);
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,
reservation: virtualReservation,
doorLockEntry: pairLockEntry,
chargePrice: UNSCHEDULED_CHARGE_PRICE,
timeIntervalsToCharge,
totalChargeFee,
});
}
pairUnlockEntry = null;
pairLockEntry = null;
}else{
if (!pairUnlockEntry){
pairLockEntry = entry;
//Only lock entry, ignore now
}
pairLockEntry = null;
pairUnlockEntry = null;
}
}
}
});
resolve(null);
}));
})
.catch((error) => reject(error)));
})
.catch((error) => reject(error)));
// 1. Check if member entered before reservation start time
if (unlockEntry && chargeBefore && !previousReservationIsBackToBack) {
@@ -306,7 +412,6 @@ const getIncidentData = (reservation) => {
incidentType: incidentType.UNLOCKED_INCIDENT,
reservation,
});
resolve(incidents);
} else {
// No lock entry, no unlock entry and no reservation after this one
// This is either :
@@ -318,6 +423,7 @@ const getIncidentData = (reservation) => {
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
incidentsAsyncJobs.push(
getLastEntryForReservation(reservation)
.then((lastEntry) => {
if (lastEntry && lastEntry.event === doorLockEvents.USER_UNLOCKED){
@@ -326,16 +432,18 @@ const getIncidentData = (reservation) => {
reservation,
});
}
resolve(incidents);
})
.catch((error) => reject(error));
} else {
resolve(incidents);
.catch((error) => reject(error)));
}
}
}else{
resolve(incidents);
}
Promise.all(incidentsAsyncJobs)
.then(() => {
resolve(incidents);
})
.catch((error) => reject(error));
})
.catch((error) => reject(error));
});