Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix to overnight calendar continous reservation check #329

Merged
merged 1 commit into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion app/shared/overnight-calendar/OvernightCalendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,14 @@ function OvernightCalendar({
}

if ((startDate && !endDate)
&& !isSelectionContinous(startDate, day, filteredReservations, openingHours)) {
&& !isSelectionContinous({
startDate,
endDate: day,
reservations: filteredReservations,
openingHours,
overnightStartTime,
overnightEndTime
})) {
actions.addNotification({
message: t('Notifications.continousFreeDaysError'),
type: 'info',
Expand Down
35 changes: 27 additions & 8 deletions app/shared/overnight-calendar/overnightUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,20 @@ export function getClosedDays(openingHours) {
* Returns reservations modifier for DayPicker
* @param {Date} day
* @param {Object[]} reservations
* @param {string} granularity e.g. 'day' or 'hour' for checking
* is day between reservation start and end. Default is 'day'.
* @param {string} inclusivity e.g. '()' or '[]' for checking
* is day between reservation start and end. Default is '()'.
* @returns {boolean} is day booked
*/
export function reservationsModifier(day, reservations) {
export function reservationsModifier(day, reservations, granularity = 'day', inclusivity = '()') {
if (day && reservations) {
const dayMoment = moment(day);
for (let index = 0; index < reservations.length; index += 1) {
const reservation = reservations[index];
const beginMoment = moment(reservation.begin);
const endMoment = moment(reservation.end);
if (dayMoment.isBetween(beginMoment, endMoment, 'day', '()')) {
if (dayMoment.isBetween(beginMoment, endMoment, granularity, inclusivity)) {
return true;
}
}
Expand Down Expand Up @@ -526,18 +530,33 @@ export function areDatesSameAsInitialDates(startDate, endDate, initialStart, ini

/**
* Returns true if selection is continous i.e. does not contain disabled days
* @param {Date} startDate
* @param {Date} endDate
* @param {Object[]} reservations
* @param {Object[]} openingHours
* @param {Object} params
* @param {Date} params.startDate
* @param {Date} params.endDate
* @param {Object[]} params.reservations
* @param {Object[]} params.openingHours
* @param {string} params.overnightStartTime
* @param {string} params.overnightEndTime
* @returns {boolean} true if selection is continous
*/
export function isSelectionContinous(startDate, endDate, reservations, openingHours) {
export function isSelectionContinous({
startDate, endDate, reservations, openingHours,
overnightStartTime, overnightEndTime
}) {
const dates = createDateArray(startDate, endDate);
if (dates.length < 2) {
return true;
}

dates[0] = setDatesTime(dates[0], overnightStartTime).toDate();
dates[dates.length - 1] = setDatesTime(dates[dates.length - 1], overnightEndTime).toDate();

for (let index = 0; index < dates.length; index += 1) {
const date = dates[index];
if (reservationsModifier(date, reservations) || closedDaysModifier(date, openingHours)) {
const isFirstOrLast = index === 0 || index === dates.length - 1;
const granularity = isFirstOrLast ? 'seconds' : 'days';
if (reservationsModifier(date, reservations, granularity, '[]')
|| closedDaysModifier(date, openingHours)) {
return false;
}
}
Expand Down
106 changes: 101 additions & 5 deletions app/shared/overnight-calendar/tests/overnightUtils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,12 @@ describe('app/shared/overnight-calendar/overnightUtils', () => {
end: '2024-04-29T09:00:00+03:00'
})
];
const reservations2 = [
Reservation.build({
begin: '2024-04-27T13:00:00+03:00',
end: '2024-04-28T09:00:00+03:00'
})
];
const openingHours = [
{ date: '2024-04-19', closes: null, opens: null },
{ date: '2024-04-20', closes: '2024-04-20T20:00:00+03:00', opens: '2024-04-20T06:00:00+03:00' },
Expand All @@ -799,12 +805,41 @@ describe('app/shared/overnight-calendar/overnightUtils', () => {
{ date: '2024-04-29', closes: '2024-04-29T20:00:00+03:00', opens: '2024-04-29T06:00:00+03:00' },
{ date: '2024-04-30', closes: null, opens: null },
];
const overnightStartTime = '13:00:00';
const overnightEndTime = '09:00:00';

test('returns true when no reservations or closed days in selection', () => {
const startDate = moment('2024-04-23').toDate();
const endDate = moment('2024-04-27').toDate();
expect(isSelectionContinous(startDate, endDate, [], openingHours))
const startDate2 = moment('2024-04-26').toDate();
const endDate2 = moment('2024-04-27').toDate();
const startDate3 = moment('2024-04-28').toDate();
const endDate3 = moment('2024-04-29').toDate();
expect(isSelectionContinous({
startDate, endDate, reservations: [], openingHours, overnightStartTime, overnightEndTime
}))
.toBe(true);
expect(isSelectionContinous({
startDate, endDate, reservations, openingHours, overnightStartTime, overnightEndTime
}))
.toBe(true);
expect(isSelectionContinous(startDate, endDate, reservations, openingHours))
expect(isSelectionContinous({
startDate: startDate2,
endDate: endDate2,
reservations: reservations2,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(true);
expect(isSelectionContinous({
startDate: startDate3,
endDate: endDate3,
reservations: reservations2,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(true);
});
test('returns false when reservations or closed days in selection', () => {
Expand All @@ -814,11 +849,72 @@ describe('app/shared/overnight-calendar/overnightUtils', () => {
const endDate2 = moment('2024-04-30').toDate();
const startDate3 = moment('2024-04-19').toDate();
const endDate3 = moment('2024-04-20').toDate();
expect(isSelectionContinous(startDate1, endDate1, reservations, openingHours))
const startDate4 = moment('2024-04-26').toDate();
const endDate4 = moment('2024-04-28').toDate();
const startDate5 = moment('2024-04-26').toDate();
const endDate5 = moment('2024-04-29').toDate();
expect(isSelectionContinous({
startDate: startDate1,
endDate: endDate1,
reservations,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(false);
expect(isSelectionContinous(startDate2, endDate2, reservations, openingHours))
expect(isSelectionContinous({
startDate: startDate1,
endDate: endDate1,
reservations: reservations2,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(false);
expect(isSelectionContinous({
startDate: startDate2,
endDate: endDate2,
reservations,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(false);
expect(isSelectionContinous(startDate3, endDate3, reservations, openingHours))
expect(isSelectionContinous({
startDate: startDate2,
endDate: endDate2,
reservations: reservations2,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(false);
expect(isSelectionContinous({
startDate: startDate3,
endDate: endDate3,
reservations,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(false);
expect(isSelectionContinous({
startDate: startDate4,
endDate: endDate4,
reservations: reservations2,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(false);
expect(isSelectionContinous({
startDate: startDate5,
endDate: endDate5,
reservations: reservations2,
openingHours,
overnightStartTime,
overnightEndTime
}))
.toBe(false);
});
});
Expand Down
Loading