diff --git a/app/api/schema/feedbacks.py b/app/api/schema/feedbacks.py index e76250482c..9c5bd51f45 100644 --- a/app/api/schema/feedbacks.py +++ b/app/api/schema/feedbacks.py @@ -1,3 +1,6 @@ +"""Schema class for Feedbacks""" + +from marshmallow.validate import Range from marshmallow_jsonapi import fields from marshmallow_jsonapi.flask import Schema, Relationship @@ -18,7 +21,7 @@ class Meta: inflect = dasherize id = fields.Str(dump_only=True) - rating = fields.Str(required=True) + rating = fields.Float(required=True, validate=Range(min=0, max=5)) comment = fields.Str(required=False) event = Relationship(attribute='event', self_view='v1.feedback_event', diff --git a/app/models/feedback.py b/app/models/feedback.py index 15da144aa7..194c7f04d1 100644 --- a/app/models/feedback.py +++ b/app/models/feedback.py @@ -5,7 +5,7 @@ class Feedback(db.Model): """Feedback model class""" __tablename__ = 'feedback' id = db.Column(db.Integer, primary_key=True) - rating = db.Column(db.String, nullable=False) + rating = db.Column(db.Float, nullable=False) comment = db.Column(db.String, nullable=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE')) @@ -13,7 +13,9 @@ class Feedback(db.Model): db.ForeignKey('events.id', ondelete='CASCADE')) def __init__(self, rating=None, comment=None, event_id=None, user_id=None): - self.rating = rating + rating = float(rating) + self.rating = round(rating*2, 0) / 2 # Rounds to nearest 0.5 + self.comment = comment self.event_id = event_id self.user_id = user_id diff --git a/docs/api/api_blueprint.apib b/docs/api/api_blueprint.apib index f61e363c13..25f440b52a 100644 --- a/docs/api/api_blueprint.apib +++ b/docs/api/api_blueprint.apib @@ -201,7 +201,7 @@ Create a new user using an email, password and an optional name. { "attributes": { - "email": "example@example.com", + "email": "email@example.com", "password": "password", "avatar_url": "http://example.com/example.png", "first-name": "John", @@ -18923,7 +18923,7 @@ feedbacks related to the events. | Parameter | Description | Type | Required | |:----------|-------------|------|----------| -| `rating` | Rating for the overall event | string | **yes** | +| `rating` | Rating for the overall event | float | **yes** | | `comment` | Comments and suggestions about the event | string | - | diff --git a/migrations/versions/194a5a2a44ef_.py b/migrations/versions/194a5a2a44ef_.py new file mode 100644 index 0000000000..2fb4ae24ed --- /dev/null +++ b/migrations/versions/194a5a2a44ef_.py @@ -0,0 +1,62 @@ +"""empty message + +Revision ID: 194a5a2a44ef +Revises: caf96244e10b +Create Date: 2018-05-21 01:54:54.296053 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '194a5a2a44ef' +down_revision = 'caf96244e10b' + +class ReplaceableObject(object): + def __init__(self, name, sqltext): + self.name = name + self.sqltext = sqltext + +update_rating_func = ReplaceableObject( + "update_rating(rating text)", + """ + RETURNS text AS $$ + DECLARE + r NUMERIC; + BEGIN + r = cast(rating as NUMERIC); + IF r < 0 OR r > 5 THEN + RETURN '0'; + END IF; + r = round(r*2) / 2; + RETURN cast(r as VARCHAR); + EXCEPTION WHEN invalid_text_representation THEN + RETURN '0'; + END; + $$ + STRICT + LANGUAGE plpgsql IMMUTABLE; + """) + + +def upgrade(): + op.create_or_replace_sp(update_rating_func) + op.execute("UPDATE feedback SET rating=update_rating(rating)") + op.execute("DROP FUNCTION update_rating(text)") + + op.alter_column('feedback', 'rating', + existing_type=sa.VARCHAR(), + type_=sa.Float(), + existing_nullable=False, + postgresql_using='rating::double precision') + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('feedback', 'rating', + existing_type=sa.Float(), + type_=sa.VARCHAR(), + existing_nullable=False) + # ### end Alembic commands ###