Browse Source

added check for duplicated voting

master
Julio Biason 11 years ago
parent
commit
94d1d61fd2
  1. 97
      luncho/blueprints/voting.py

97
luncho/blueprints/voting.py

@ -86,6 +86,30 @@ class PlaceDoesntBelongToGroupException(LunchoException):
self.json['places'] = self.places
class PlacesVotedMoreThanOnceException(LunchoException):
"""The indicated places were voted more than once. Only a vote
per place is allowed.
.. sourcecode:: http
HTTP/1.1 409 Conflict
Content-Type: text/json
{ "status": "ERROR",
"message": "Places voted more than once",
"places": [<place>, <place>, ...]}
"""
def __init__(self, places):
super(PlacesVotedMoreThanOnceException, self).__init__()
self.status = 409
self.message = 'Places voted more than once'
self.places = places
return
def _json(self):
super(PlacesVotedMoreThanOnceException, self)._json()
self.json['places'] = self.places
# ----------------------------------------------------------------------
# Voting
# ----------------------------------------------------------------------
@ -107,42 +131,77 @@ def cast_vote(group_id):
LOG.debug('User is not member')
raise UserIsNotMemberException()
choices = request.as_json.get('choices')
# check if the user voted today already, for any group
_already_voted(request.user.username)
# check if the user is trying to vote in the same place twice
_check_duplicates(choices)
# check the number of votes the user casted
_check_place_count(choices, group.places)
# check if the places exist and are part of the group
# (don't vote yet, so we can stop the whole thing if there is anything
# wrong)
_check_places(choices, group.places)
# finally, cast the vote
vote = Vote(request.user, group_id)
db.session.add(vote)
db.session.commit() # so vote gets an id
for (pos, place_id) in enumerate(request.as_json.get('choices')):
place = CastedVote(vote, pos, place_id)
db.session.add(place)
db.session.commit()
return jsonify(status='OK')
# ----------------------------------------------------------------------
# Helpers
# ----------------------------------------------------------------------
def _already_voted(username):
"""Check if the user already voted today."""
today = datetime.date.today()
today_vote = Vote.query.filter_by(user=request.user.username,
today_vote = Vote.query.filter_by(user=username,
created_at=today).first()
if today_vote:
LOG.debug('User already voted today')
raise VoteAlreadyCastException()
return
# check the number of votes the user casted
choices = request.as_json.get('choices')
def _check_place_count(choices, group_places):
"""Check if the user voted in the right number of places."""
# maybe the group have less than PLACES_IN_VOTE choices...
max_places = min(current_app.config['PLACES_IN_VOTE'],
len(group.places))
len(group_places))
if len(choices) != max_places:
LOG.debug('Max places = {max_places}, voted for {choices}',
max_places=max_places, choices=len(choices))
raise InvalidNumberOfPlacesCastedException()
return
# check if the places exist and are part of the group
# (don't vote yet, so we can stop the whole thing if there is anything
# wrong)
for place_id in request.as_json.get('choices'):
def _check_places(choices, group_places):
"""Check if the places the user voted exist and belong to the group."""
for place_id in choices:
place = Place.query.get(place_id)
if not place:
raise ElementNotFoundException('Place')
if not place in group.places:
if place not in group_places:
raise PlaceDoesntBelongToGroupException(place_id)
return
# finally, cast the vote
vote = Vote(request.user, group_id)
db.session.add(vote)
db.session.commit() # so vote gets an id
for (pos, place_id) in enumerate(request.as_json.get('choices')):
place = CastedVote(vote, pos, place_id)
db.session.add(place)
db.session.commit()
return jsonify(status='OK')
def _check_duplicates(choices):
"""Check if the places the user voted are listed more than once."""
duplicates = set([x for x in choices if choices.count(x) > 1])
if len(duplicates) > 0:
raise PlacesVotedMoreThanOnceException(duplicates)
return

Loading…
Cancel
Save