include unscheduled use between reservations
This commit is contained in:
@@ -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) => {
|
const getLastEntryForReservation = (reservation) => {
|
||||||
|
|||||||
@@ -180,8 +180,7 @@ const analyseReservation = (reservation) => {
|
|||||||
.then(([previousReservation, nextReservation]) => {
|
.then(([previousReservation, nextReservation]) => {
|
||||||
const getRelatedDoorLockEntriesAsync = [
|
const getRelatedDoorLockEntriesAsync = [
|
||||||
getUnlockEntryForReservation(reservation, previousReservation),
|
getUnlockEntryForReservation(reservation, previousReservation),
|
||||||
getLockEntryForReservation(reservation, nextReservation),
|
getLockEntryForReservation(reservation, nextReservation)
|
||||||
getEntriesBetween(reservation, previousReservation)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
Promise.all(getRelatedDoorLockEntriesAsync)
|
Promise.all(getRelatedDoorLockEntriesAsync)
|
||||||
@@ -274,6 +273,113 @@ const getIncidentData = (reservation) => {
|
|||||||
timeIntervalsToChargeAfter,
|
timeIntervalsToChargeAfter,
|
||||||
} = result;
|
} = result;
|
||||||
const incidents = [];
|
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
|
// 1. Check if member entered before reservation start time
|
||||||
if (unlockEntry && chargeBefore && !previousReservationIsBackToBack) {
|
if (unlockEntry && chargeBefore && !previousReservationIsBackToBack) {
|
||||||
@@ -306,7 +412,6 @@ const getIncidentData = (reservation) => {
|
|||||||
incidentType: incidentType.UNLOCKED_INCIDENT,
|
incidentType: incidentType.UNLOCKED_INCIDENT,
|
||||||
reservation,
|
reservation,
|
||||||
});
|
});
|
||||||
resolve(incidents);
|
|
||||||
} else {
|
} else {
|
||||||
// No lock entry, no unlock entry and no reservation after this one
|
// No lock entry, no unlock entry and no reservation after this one
|
||||||
// This is either :
|
// This is either :
|
||||||
@@ -318,6 +423,7 @@ const getIncidentData = (reservation) => {
|
|||||||
if (previousReservationIsBackToBack){
|
if (previousReservationIsBackToBack){
|
||||||
// To ensure that this is last reservation in block (there is previous but no next reservation back to back)
|
// 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
|
// Now, just check if member actually locked before in the reservation time
|
||||||
|
incidentsAsyncJobs.push(
|
||||||
getLastEntryForReservation(reservation)
|
getLastEntryForReservation(reservation)
|
||||||
.then((lastEntry) => {
|
.then((lastEntry) => {
|
||||||
if (lastEntry && lastEntry.event === doorLockEvents.USER_UNLOCKED){
|
if (lastEntry && lastEntry.event === doorLockEvents.USER_UNLOCKED){
|
||||||
@@ -326,16 +432,18 @@ const getIncidentData = (reservation) => {
|
|||||||
reservation,
|
reservation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
resolve(incidents);
|
|
||||||
})
|
})
|
||||||
.catch((error) => reject(error));
|
.catch((error) => reject(error)));
|
||||||
} else {
|
|
||||||
resolve(incidents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
resolve(incidents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Promise.all(incidentsAsyncJobs)
|
||||||
|
.then(() => {
|
||||||
|
resolve(incidents);
|
||||||
|
})
|
||||||
|
.catch((error) => reject(error));
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch((error) => reject(error));
|
.catch((error) => reject(error));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user