Skip to content

Commit

Permalink
Reservations added to the same session may not be duplicated anymore
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Krienbühl committed Apr 27, 2016
1 parent a36cad3 commit 9d3cd38
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 8 deletions.
3 changes: 3 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Changelog
---------

- Reservations added to the same session may not be duplicated anymore.
[href]

- Errors raised during reservation now have a 'reservation' attribute.
[href]

Expand Down
13 changes: 13 additions & 0 deletions libres/db/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,19 @@ def new_reservations_by_dates(dates):
if not reservations:
raise errors.InvalidReservationError

# have a very simple overlap check for reservations, it's not important
# that this catches *all* possible problems - that's being handled
# by the reservation slots - but it should stop us from adding the same
# reservation twice on a single session
if session_id:
found = self.queries.reservations_by_session(session_id)
found = found.with_entities(Reservation.target, Reservation.start)
found = set(found.all())

for reservation in reservations:
if (reservation.target, reservation.start) in found:
raise errors.OverlappingReservationError

for reservation in reservations:
self.session.add(reservation)

Expand Down
4 changes: 4 additions & 0 deletions libres/modules/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def __init__(self, start, end, existing):
self.existing = existing


class OverlappingReservationError(LibresError):
pass


class AffectedReservationError(LibresError):

def __init__(self, existing):
Expand Down
35 changes: 35 additions & 0 deletions libres/tests/test_reservation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

from datetime import datetime, timedelta
from libres.db.models import Reservation
from libres.modules.errors import OverlappingReservationError
from sedate import standardize_date
from uuid import uuid4


def test_reservation_title():
Expand Down Expand Up @@ -53,3 +55,36 @@ def test_group_reservation_timespans(scheduler):
assert timespans[1].start == standardize_date(dates[1][0], 'Europe/Zurich')
assert timespans[1].end == standardize_date(dates[1][1], 'Europe/Zurich')\
- timedelta(microseconds=1)


def test_overlapping_reservations(scheduler):
start = datetime(2015, 2, 5, 15)
end = datetime(2015, 2, 5, 16)

scheduler.allocate(dates=(start, end))

# overlapping reservations are only prohibited on a per-session base
scheduler.reserve(
email='test@example.org',
dates=(start, end),
session_id=uuid4()
)
scheduler.reserve(
email='test@example.org',
dates=(start, end),
session_id=uuid4()
)

session_id = uuid4()
scheduler.reserve(
email='test@example.org',
dates=(start, end),
session_id=session_id
)

with pytest.raises(OverlappingReservationError):
scheduler.reserve(
email='test@example.org',
dates=(start, end),
session_id=session_id
)
19 changes: 11 additions & 8 deletions libres/tests/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,21 +366,24 @@ def test_reserve_single_token_per_session(scheduler):

session_id = new_uuid()

start = datetime(2011, 1, 1, 15)
end = datetime(2011, 1, 1, 16)

scheduler.allocate((start, end), quota=3)
a1, a2 = scheduler.allocate(
dates=(
datetime(2011, 1, 1, 15), datetime(2011, 1, 1, 16),
datetime(2011, 1, 2, 15), datetime(2011, 1, 2, 16)
),
quota=1
)

token1 = scheduler.reserve(
email=u'test@example.org',
dates=(start, end),
dates=(a1.start, a1.end),
session_id=session_id,
single_token_per_session=True
)

token2 = scheduler.reserve(
email=u'test@example.org',
dates=(start, end),
dates=(a2.start, a2.end),
session_id=session_id,
single_token_per_session=True
)
Expand All @@ -391,14 +394,14 @@ def test_reserve_single_token_per_session(scheduler):

token3 = scheduler.reserve(
email=u'test@example.org',
dates=(start, end),
dates=(a1.start, a1.end),
session_id=session_id,
single_token_per_session=True
)

token4 = scheduler.reserve(
email=u'test@example.org',
dates=(start, end),
dates=(a2.start, a2.end),
session_id=session_id,
single_token_per_session=True
)
Expand Down

0 comments on commit 9d3cd38

Please sign in to comment.