diff --git a/services/doorLock/doorLock.js b/services/doorLock/doorLock.js index 08c7fb6..1171261 100644 --- a/services/doorLock/doorLock.js +++ b/services/doorLock/doorLock.js @@ -238,7 +238,25 @@ const getUnlockEntryForReservation = (reservation, previousReservation) => { const entriesBeforeReservationStart = entries.filter((entry) => moment.utc(entry.timestamp).isBefore(reservation.start)); + // if (memberId === '5ce785af422bdd00967fb781') { + // console.log('Start : ', moment.tz(reservation.start, UI_TIMEZONE).format('DD.MM HH:mm')); + // console.log('End : ', moment.tz(reservation.end, UI_TIMEZONE).format('DD.MM HH:mm')); + // console.log('\tPrevious reservation '); + // console.log('\tStart : ', previousReservation ? moment.tz(previousReservation.start, UI_TIMEZONE).format('DD.MM HH:mm') : '-'); + // console.log('\tEnd : ', previousReservation ? moment.tz(previousReservation.end, UI_TIMEZONE).format('DD.MM HH:mm') : '-'); + // console.log('\t---------------------------'); + // console.log('\tSearch for entries : '); + // console.log('\tFrom : ', fromTimestamp ? moment.tz(fromTimestamp, UI_TIMEZONE).format('DD.MM HH:mm') : '-'); + // console.log('\tTo : ', toTimestamp ? moment.tz(toTimestamp, UI_TIMEZONE).format('DD.MM HH:mm') : '-'); + // console.log('\t---------------------------'); + // console.log('\tEntries before reservation start : '); + // } + entriesBeforeReservationStart.forEach((entry) => { + // if (memberId === '5ce785af422bdd00967fb781') { + // console.log('\t', entry.event, '\t', moment.tz(entry.timestamp, UI_TIMEZONE).format('DD.MM HH:mm')); + // } + if (!eventFound) { if (entry.event === doorLockEvents.USER_UNLOCKED) { if (pairedLockEntry) { @@ -256,13 +274,25 @@ const getUnlockEntryForReservation = (reservation, previousReservation) => { }); if (eventFound){ + // if (memberId === '5ce785af422bdd00967fb781') { + // console.log('\t=> FOUND UNLOCK ENTRY - NO NEED TO LOOK AFTER <='); + // } resolve(candidateUnlockEntry); } else { candidateUnlockEntry = null; const numberOfEntriesLeft = entries.length - entriesBeforeReservationStart.length; const entriesAfterReservationStart = entries.slice(0, numberOfEntriesLeft); + const invertedEntriesAfterReservationStart = entriesAfterReservationStart.reverse(); + + // if (memberId === '5ce785af422bdd00967fb781') { + // console.log('\t-----------------------------'); + // console.log('\tEntries after reservation start : '); + // } + invertedEntriesAfterReservationStart.forEach((entry) => { + // if (memberId === '5ce785af422bdd00967fb781') { + // console.log('\t', entry.event, '\t', moment.tz(entry.timestamp, UI_TIMEZONE).format('DD.MM HH:mm')); + // } - entriesAfterReservationStart.forEach((entry) => { if (!eventFound) { if (entry.event === doorLockEvents.USER_UNLOCKED) { eventFound = true; @@ -303,7 +333,7 @@ const getLockEntryForReservation = (reservation, nextReservation) => { resourceId, }; - const order = [['timestamp', 'ASC']]; + const order = [['timestamp', 'DESC']]; db.doorLockEvent.findAll({ attributes, @@ -311,47 +341,31 @@ const getLockEntryForReservation = (reservation, nextReservation) => { order, }) .then((entries) => { - let candidateLockEntry = null; - let pairedUnlockEntry = null; - let eventFound = false; - const entriesAfterReservationEnd = entries.filter((entry) => moment.utc(entry.timestamp).isAfter(reservation.end)); + const entriesBeforeReservationEnd = entries.filter(entry => moment.utc(entry.timestamp).isBefore(reservation.end)); - entriesAfterReservationEnd.forEach((entry) => { - if (!eventFound) { - if (entry.event === doorLockEvents.USER_LOCKED) { - if (pairedUnlockEntry) { - pairedUnlockEntry = null; - candidateLockEntry = null; - } else { - candidateLockEntry = entry; - eventFound = true; - } - } - if (entry.event === doorLockEvents.USER_UNLOCKED){ - pairedUnlockEntry = entry; - } + if (entriesBeforeReservationEnd.length > 0){ + const lastEntryInReservationTime = entriesBeforeReservationEnd[0]; + if (lastEntryInReservationTime.event === doorLockEvents.USER_LOCKED){ + resolve(lastEntryInReservationTime); + return; } - }); - - if (eventFound){ - resolve(candidateLockEntry); - } else { - candidateLockEntry = null; - const numberOfEntriesLeft = entries.length - entriesAfterReservationEnd.length; - const entriesBeforeReservationEnd = entries.slice(0, numberOfEntriesLeft); - - entriesBeforeReservationEnd.reverse().forEach((entry) => { - if (!eventFound) { - if (entry.event === doorLockEvents.USER_LOCKED) { - eventFound = true; - candidateLockEntry = entry; - } - } - }); - - resolve(candidateLockEntry); } + + + + // Phase 2 + const numberOfEntriesLeft = entries.length - entriesBeforeReservationEnd.length; + const entriesAfterReservationEnd = entries.slice(0, numberOfEntriesLeft).reverse(); + if (entriesAfterReservationEnd.length > 0){ + const firstEntryAfterReservation = entriesAfterReservationEnd[0]; + if (firstEntryAfterReservation.event === doorLockEvents.USER_LOCKED){ + resolve(firstEntryAfterReservation); + return; + } + } + + resolve(null); }) .catch((error) => reject(error)); }); diff --git a/services/integration/doorLockCharges.js b/services/integration/doorLockCharges.js index e3cc7e7..cdefd66 100644 --- a/services/integration/doorLockCharges.js +++ b/services/integration/doorLockCharges.js @@ -255,9 +255,8 @@ const analyseReservation = (reservation) => { } let timeIntervalsToChargeBefore = Math.floor(timeDifferenceFromUnlockEntry / UNSCHEDULED_TIME_RESOLUTION); - if (timeDifferenceFromUnlockEntry < UNSCHEDULED_USE_INITIAL_TIME_SEGMENT_LENGTH){ - timeIntervalsToChargeBefore = 0; - } + timeIntervalsToChargeBefore -= 1; // Remove first N minutes, N = UNSCHEDULED_TIME_RESOLUTION + const totalChargeFeeBefore = timeIntervalsToChargeBefore * UNSCHEDULED_CHARGE_PRICE; const chargeBefore = totalChargeFeeBefore > 0; @@ -267,9 +266,8 @@ const analyseReservation = (reservation) => { timeDifferenceFromLockEntry = lockTime.diff(currentReservationEnd, 'minutes'); } let timeIntervalsToChargeAfter = Math.floor(timeDifferenceFromLockEntry / UNSCHEDULED_TIME_RESOLUTION); - if (timeDifferenceFromLockEntry < UNSCHEDULED_USE_INITIAL_TIME_SEGMENT_LENGTH){ - timeIntervalsToChargeAfter = 0; - } + timeIntervalsToChargeAfter -= 1; // Remove first N minutes, N = UNSCHEDULED_TIME_RESOLUTION + const totalChargeFeeAfter = timeIntervalsToChargeAfter * UNSCHEDULED_CHARGE_PRICE; const chargeAfter = totalChargeFeeAfter > 0; @@ -587,37 +585,13 @@ const getIncidentData = (reservation) => { //Skip }else{ getEntriesAsyncCheck = getEntriesBetween(fromTimestamp, toTimestamp, resourceId); - getEntriesAsyncCheck - .then((entriesBetween) => { - // 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--------------------'); - // - // console.log('\tFrom timestamp : ', fromTimestamp ? moment.tz(fromTimestamp, UI_TIMEZONE).format('DD.MM, HH:mm') : '-'); - // console.log('\tTo timestamp : ', toTimestamp ? moment.tz(toTimestamp, UI_TIMEZONE).format('DD.MM, HH:mm') : '-'); - // console.log('\t--------------------'); - // } + } + //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; @@ -650,7 +624,18 @@ const getIncidentData = (reservation) => { const unlockMoment = moment.utc(pairUnlockEntry.timestamp); const lockMoment = moment.utc(pairLockEntry.timestamp); - if (lockMoment.tz(UI_TIMEZONE).isSame(unlockMoment.tz(UI_TIMEZONE), 'day')){ + 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; @@ -667,23 +652,10 @@ const getIncidentData = (reservation) => { totalChargeFee, }); } - }else{ - incidents.push({ - incidentType: incidentType.UNLOCKED_INCIDENT_STANDALONE, - reservation: emptyReservation, - unlockTimestamp: pairUnlockEntry.timestamp, - memberId: pairUnlockEntry.memberId, - resourceId, - }); } - pairUnlockEntry = null; pairLockEntry = null; }else{ - if (!pairUnlockEntry){ - pairLockEntry = entry; - //Only lock entry, ignore now - } pairLockEntry = null; pairUnlockEntry = null; } @@ -703,21 +675,7 @@ const getIncidentData = (reservation) => { pairLockEntry = null; pairUnlockEntry = null; } - - - //Now wait also for "forgotToLockAsyncCheck" to finish - // Promise.all([forgotToLockAsyncCheck]) - // .then(() => { - // resolve(incidents); - // }) - // .catch(error => reject(error)); - }) - .catch((error) => reject(error)) - } - - //Now wait for "forgotToLockAsyncCheck", and possible "getEntriesBetween" to finish - Promise.all([forgotToLockAsyncCheck, getEntriesAsyncCheck]) - .then(() => { + } resolve(incidents); }) .catch(error => reject(error)); diff --git a/services/integration/invoiceIntegration.js b/services/integration/invoiceIntegration.js index 468b968..8ddf483 100644 --- a/services/integration/invoiceIntegration.js +++ b/services/integration/invoiceIntegration.js @@ -46,6 +46,8 @@ const createFeeFromIncident = (incident) => { let bookingTimeExplanation = ''; let incidentTimeExplanation = ''; + let additionalDateTimeExplanation = ''; + let spacing = ''; let roomExplanation = ''; @@ -140,6 +142,7 @@ const createFeeFromIncident = (incident) => { // dateExplanation = `${oldBookingStartMoment.clone().format('ddd, MMM DD')} -> ${newBookingStartMoment.clone().format('ddd, MMM DD')}`; dateExplanation = `${oldBookingStartMoment.clone().format('MMM DD')}`; bookingTimeExplanation = `[${oldBookingStartMoment.clone().format('HH:mm')} to ${oldBookingEndMoment.clone().format('HH:mm')}]`; + additionalDateTimeExplanation = ` -> ${newBookingStartMoment.clone().format('MMM DD')} [${newBookingStartMoment.clone().format('HH:mm')} to ${newBookingEndMoment.clone().format('HH:mm')}]`; incidentTimeExplanation = `moved on : ${incidentTimestampMoment.clone().format('MMM DD, HH:mm')}`; incidentExplanation += `, ${incidentTimeExplanation}`; @@ -186,7 +189,7 @@ const createFeeFromIncident = (incident) => { break; } - const formattedName = `${officeSlug}, ${dateExplanation} ${bookingTimeExplanation}${spacing}${roomExplanation}, ${incidentExplanation}`; + const formattedName = `${officeSlug}, ${dateExplanation} ${bookingTimeExplanation}${additionalDateTimeExplanation}${spacing}${roomExplanation}, ${incidentExplanation}`; return { name: formattedName,