Repository: fossasia/open-event-server

Issue:
Rating field of feedback should be float
**I'm submitting a ...**  
- [x] bug report
- [ ] feature request
- [ ] support request => Please do not submit support requests here, instead ask your query in out Gitter channel at https://gitter.im/fossasia/open-event-server

**Current behavior:**
The `rating` field of `feedback` is set to `String` 

**Expected behavior:**
`Rating` field should be `float`

<img width="634" alt="screen shot 2018-05-10 at 11 45 49 am" src="https://user-images.githubusercontent.com/16715499/39855731-b6a7ebe6-544a-11e8-8cf5-40e41ea9f0af.png">



Discussion:
Will you be working on this issue? Or can I undertake it? Please let me know :)
@schedutron please go ahead

Resolving patch:
diff --git a/app/api/schema/feedbacks.py b/app/api/schema/feedbacks.py
--- 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
--- 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/migrations/versions/194a5a2a44ef_.py b/migrations/versions/194a5a2a44ef_.py
new file mode 100644
--- /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 ###


Test patch: