Repository: fossasia/open-event-server

Issue:
Implement the Tax API with all it's attributes and proper permissions



Discussion:

Resolving patch:
diff --git a/app/api/__init__.py b/app/api/__init__.py
--- a/app/api/__init__.py
+++ b/app/api/__init__.py
@@ -15,6 +15,7 @@
 from app.api.session_types import SessionTypeList, SessionTypeDetail, SessionTypeRelationship
 from app.api.event_copyright import EventCopyrightList, EventCopyrightDetail, EventCopyrightRelationship
 from app.api.pages import PageList, PageDetail
+from app.api.tax import TaxList, TaxDetail,TaxRelationship
 
 
 api_v1 = Blueprint('v1', __name__, url_prefix='/v1')
@@ -50,7 +51,7 @@
           '/microlocations/<int:microlocation_id>/event', '/social_links/<int:social_link_id>/event',
           '/sponsors/<int:sponsor_id>/event', '/tracks/<int:track_id>/event',
           '/call_for_papers/<int:call_for_paper_id>/event', '/session_types/<int:session_type_id>/event',
-          '/event_copyright/<int:copyright_id>/event')
+          '/event_copyright/<int:copyright_id>/event', '/tax/<int:tax_id>/event')
 api.route(EventRelationship, 'event_ticket', '/events/<int:id>/relationships/ticket')
 api.route(EventRelationship, 'event_microlocation', '/events/<int:id>/relationships/microlocation')
 api.route(EventRelationship, 'event_social_link', '/events/<int:id>/relationships/social_link')
@@ -59,6 +60,8 @@
 api.route(EventRelationship, 'event_call_for_paper', '/events/<int:id>/relationships/call_for_paper')
 api.route(EventRelationship, 'event_session_types', '/events/<int:id>/relationships/session_types')
 api.route(EventRelationship, 'event_copyright', '/events/<int:id>/relationships/event_copyright')
+api.route(EventRelationship, 'event_tax', '/events/<int:id>/relationships/tax')
+
 
 # microlocations
 api.route(MicrolocationList, 'microlocation_list', '/microlocations',
@@ -116,3 +119,9 @@
           '/event_copyright/<int:id>', '/events/<int:event_id>/event_copyright')
 api.route(EventCopyrightRelationship, 'copyright_event',
           '/event_copyright/<int:id>/relationships/event')
+
+
+# tax
+api.route(TaxList, 'tax_list', '/events/<int:id>/tax')
+api.route(TaxDetail, 'tax_detail', '/tax/<int:id>', '/events/<int:event_id>/tax')
+api.route(TaxRelationship, 'tax_event','/tax/<int:id>/relationships/event')
diff --git a/app/api/events.py b/app/api/events.py
--- a/app/api/events.py
+++ b/app/api/events.py
@@ -85,6 +85,13 @@ class Meta:
                                    related_view_kwargs={'event_id': '<id>'},
                                    schema='EventCopyrightSchema',
                                    type_='social_link')
+    tax = Relationship(attribute='tax',
+                       self_view='v1.event_tax',
+                       self_view_kwargs={'id': '<id>'},
+                       related_view='v1.tax_detail',
+                       related_view_kwargs={'event_id': '<id>'},
+                       schema='TaxSchema',
+                       type_='tax')
 
 
 class EventList(ResourceList):
diff --git a/app/api/tax.py b/app/api/tax.py
new file mode 100644
--- /dev/null
+++ b/app/api/tax.py
@@ -0,0 +1,75 @@
+from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
+from marshmallow_jsonapi.flask import Schema, Relationship
+from marshmallow_jsonapi import fields
+from app.models import db
+from app.api.helpers.permissions import jwt_required, is_admin, is_user_itself
+from sqlalchemy.orm.exc import NoResultFound
+from flask_rest_jsonapi.exceptions import ObjectNotFound
+from app.models.event import Event
+from app.models.tax import Tax
+
+class TaxSchema(Schema):
+
+    class Meta:
+        type_ = 'tax'
+        self_view = 'v1.tax_detail'
+        self_view_kwargs = {'id': '<id>'}
+
+    id = fields.Str(dump_only=True)
+    country = fields.Str()
+    tax_name = fields.Str(required=True)
+    tax_rate = fields.Float(required=True)
+    tax_id = fields.Str(required=True)
+    is_invoice_sent = fields.Boolean(default=False)
+    registered_company = fields.Str()
+    address = fields.Str()
+    city = fields.Str()
+    state = fields.Str()
+    zip = fields.Integer()
+    invoice_footer = fields.Str()
+    is_tax_included_in_price = fields.Boolean(default=False)
+    event = Relationship(attribute='event',
+                         self_view='v1.tax_event',
+                         self_view_kwargs={'id': '<id>'},
+                         related_view='v1.event_detail',
+                         related_view_kwargs={'tax_id': '<id>'},
+                         schema='EventSchema',
+                         type_='event')
+
+
+class TaxList(ResourceList):
+
+    def query(self, view_kwargs):
+        query_ = self.session.query(Tax)
+        if view_kwargs.get('id') is not None:
+            query_ = query_.join(Event).filter(Event.id == view_kwargs['id'])
+        return query_
+
+    def before_create_object(self, data, view_kwargs):
+        if view_kwargs.get('id') is not None:
+            event = self.session.query(Event).filter_by(id=view_kwargs['id']).one()
+            data['event_id'] = event.id
+
+    view_kwargs = True
+    decorators = (jwt_required, )
+    schema = TaxSchema
+    data_layer = {'session': db.session,
+                  'model': Tax,
+                  'methods': {
+                      'query': query,
+                      'before_create_object': before_create_object
+                  }}
+
+
+class TaxDetail(ResourceDetail):
+    decorators = (jwt_required, )
+    schema = TaxSchema
+    data_layer = {'session': db.session,
+                  'model': Tax}
+
+
+class TaxRelationship(ResourceRelationship):
+    decorators = (jwt_required, )
+    schema = TaxSchema
+    data_layer = {'session': db.session,
+                  'model': Tax}


Test patch: