diff --git a/services/doorLock/doorLock.js b/services/doorLock/doorLock.js index 2d96318..ea45109 100644 --- a/services/doorLock/doorLock.js +++ b/services/doorLock/doorLock.js @@ -18,6 +18,7 @@ const { const { fetchAllMembers } = require('../officeRnD/members'); const { getMappingsFromDatabase } = require('../officeRnD/resources'); +const { getFirstReservationInBlock } = require('../officeRnD/bookings'); const extractMappingFromFileName = (fileName) => { const contentBetweenBracketsRegex = /\[(.*?)\]/; @@ -360,9 +361,48 @@ const getLockEntryForReservation = (reservation, nextReservation) => { }); }; +const getLastEntryForReservation = (reservation) => { + return new Promise ((resolve, reject) => { + getFirstReservationInBlock(reservation) + .then((firstReservationInBlock) => { + const { memberId, resourceId } = reservation; + let fromTimestamp = reservation.start; + const toTimestamp = reservation.end; + if (firstReservationInBlock){ + fromTimestamp = firstReservationInBlock.start; + } + + const filters = { + memberId, + resourceId, + timestamp: { + [Op.and]: [ + {[Op.gte]: fromTimestamp}, + {[Op.lte]: toTimestamp} + ] + }, + }; + + const order = [['timestamp', 'DESC']]; + + db.doorLockEvent.findAll({where: filters, order}) + .then((entries) => { + if (entries && entries.length > 0){ + resolve(entries[0]); + } else { + resolve (undefined); + } + }) + .catch((error) => reject(error)); + }) + .catch((error) => reject(error)); + }); +}; + module.exports = { parseDoorLockDataFile, writeDoorLockEvent, getUnlockEntryForReservation, getLockEntryForReservation, + getLastEntryForReservation, }; diff --git a/services/integration/doorLockCharges.js b/services/integration/doorLockCharges.js index 8ead2f0..7cc5029 100644 --- a/services/integration/doorLockCharges.js +++ b/services/integration/doorLockCharges.js @@ -3,9 +3,9 @@ const moment = require('moment-timezone'); const db = require('../../models/index'); -const { incidentType, unlockedIncidentLevelsPrices, UNSCHEDULED_CHARGE_PRICE, MAX_BACK_TO_BACK_DIFFERENCE, UNSCHEDULED_TIME_RESOLUTION } = require('../../constants/constants'); -const { getUnlockEntryForReservation, getLockEntryForReservation } = require('../doorLock/doorLock'); -const { getAllFinishedBookings, getFirstReservationInBlock, getFirstPreviousBooking, getFirstNextBooking } = require('../officeRnD/bookings'); +const { doorLockEvents, incidentType, unlockedIncidentLevelsPrices, UNSCHEDULED_CHARGE_PRICE, MAX_BACK_TO_BACK_DIFFERENCE, UNSCHEDULED_TIME_RESOLUTION } = require('../../constants/constants'); +const { getUnlockEntryForReservation, getLockEntryForReservation, getLastEntryForReservation } = require('../doorLock/doorLock'); +const { getAllFinishedBookings, getFirstPreviousBooking, getFirstNextBooking } = require('../officeRnD/bookings'); const getSortedIncidentsForMember = (memberId) => { const attributes = ['bookingStart', 'incidentLevel', 'incidentLevelPrice']; @@ -169,45 +169,6 @@ const setUnlockedIncidentsLevel = (incidentReservations) => { }); }; -const getUnlockEntryForBlockReservations = (lastReservation, firstReservation) => { - return new Promise ((resolve, reject) => { - analyseReservation(firstReservation) - .then((result) => { - const reservationBeforeFirstReservationInBlock = result.previousReservation; - const unlockEntryForFirstReservation = result.unlockEntry; - - if (unlockEntryForFirstReservation){ - resolve(unlockEntryForFirstReservation); - }else{ - const fromTimestamp = reservationBeforeFirstReservationInBlock ? - reservationBeforeFirstReservationInBlock.end : - moment.utc(firstReservation.start).tz(UI_TIMEZONE).startOf('Day').toISOString(); - const toTimestamp = lastReservation.end; - const { memberId, reservationId } = lastReservation; - - const filters = { - memberId, - reservationId, - event: doorLockEvents.USER_UNLOCKED, - timestamp: { - [Op.and]: [ - {[Op.gt]: fromTimestamp}, - {[Op.lte]: toTimestamp} - ] - }, - }; - - db.doorLockEvent.findOne({where: filters}) - .then((anyUnlockEntryInBlock) => { - resolve(anyUnlockEntryInBlock); - }) - .catch((error) => reject(error)); - } - }) - .catch((error) => reject(error)); - }); -}; - const analyseReservation = (reservation) => { return new Promise ((resolve, reject) => { const getNearBookingsAsync = [ @@ -288,20 +249,6 @@ const analyseReservation = (reservation) => { }); }; -const checkIfMemberEverEntered = (reservation) => { - return new Promise ((resolve, reject) => { - getFirstReservationInBlock(reservation) - .then((firstReservationInBlock) => { - getUnlockEntryForBlockReservations(reservation, firstReservationInBlock) - .then((unlockEntry) => { - resolve(!!unlockEntry); - }) - .catch((error) => reject(error)); - }) - .catch((error) => reject(error)); - }); -}; - const getIncidentData = (reservation) => { return new Promise ((resolve, reject) => { analyseReservation(reservation) @@ -351,15 +298,43 @@ const getIncidentData = (reservation) => { }); } - // 3. Check if member forgot to lock door - if (unlockEntry && !lockEntry && !nextReservationIsBackToBack){ - incidents.push({ - incidentType: incidentType.UNLOCKED_INCIDENT, - reservation, - }); - } + // 3. Check if member forgot to lock the door + if (!lockEntry && !nextReservationIsBackToBack){ + if (unlockEntry){ + incidents.push({ + incidentType: incidentType.UNLOCKED_INCIDENT, + reservation, + }); + resolve(incidents); + } 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 - resolve(incidents); + 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 + getLastEntryForReservation(reservation) + .then((lastEntry) => { + if (lastEntry && lastEntry.event === doorLockEvents.USER_UNLOCKED){ + incidents.push({ + incidentType: incidentType.UNLOCKED_INCIDENT, + reservation, + }); + } + resolve(incidents); + }) + .catch((error) => reject(error)); + } else { + resolve(incidents); + } + } + }else{ + resolve(incidents); + } }) .catch((error) => reject(error)); }); diff --git a/services/officeRnD/bookings.js b/services/officeRnD/bookings.js index 51607cb..c31da33 100644 --- a/services/officeRnD/bookings.js +++ b/services/officeRnD/bookings.js @@ -116,10 +116,10 @@ const getFirstPreviousBooking = (reservation) => { const getFirstReservationInBlock = (reservation) => { return new Promise ((resolve, reject) => { - const {resourceId, memberId, start} = reservation; + const { resourceId, memberId, start } = reservation; const fromTimestamp = moment.utc(start).subtract(MAX_BACK_TO_BACK_DIFFERENCE).toISOString(); - const toTimestamp = reservation.end; + const toTimestamp = start; const filters = { resourceId,