Repository: fossasia/open-event-server

Issue:
Implementation of a route to serve Event Invoices
**Is your feature request related to a problem? Please describe.**
An event invoice should be served over a route which allows only the organizer to access their respective event invoices. 

**Describe the solution you'd like**
Similar to tickets & order invoice serving.

**Additional context**
Working on it.


Discussion:
@shreyanshdwivedi As soon as I've implemented this, you can test your basic layout for the event invoice PDF template written in Jinja :)

Resolving patch:
diff --git a/app/api/auth.py b/app/api/auth.py
--- a/app/api/auth.py
+++ b/app/api/auth.py
@@ -10,6 +10,7 @@
 from flask_jwt import current_identity as current_user, jwt_required
 from flask_limiter.util import get_remote_address
 from healthcheck import EnvironmentDump
+from flask_rest_jsonapi.exceptions import ObjectNotFound
 from sqlalchemy.orm.exc import NoResultFound
 
 from app import get_settings
@@ -32,6 +33,8 @@
 from app.models.notification import PASSWORD_CHANGE as PASSWORD_CHANGE_NOTIF
 from app.models.order import Order
 from app.models.user import User
+from app.models.event_invoice import EventInvoice
+
 
 logger = logging.getLogger(__name__)
 authorised_blueprint = Blueprint('authorised_blueprint', __name__, url_prefix='/')
@@ -295,9 +298,9 @@ def change_password():
     })
 
 
-def return_file(file_name_prefix, file_path, order_identifier):
+def return_file(file_name_prefix, file_path, identifier):
     response = make_response(send_file(file_path))
-    response.headers['Content-Disposition'] = 'attachment; filename=%s-%s.pdf' % (file_name_prefix, order_identifier)
+    response.headers['Content-Disposition'] = 'attachment; filename=%s-%s.pdf' % (file_name_prefix, identifier)
     return response
 
 
@@ -345,6 +348,28 @@ def order_invoices(order_identifier):
         return ForbiddenError({'source': ''}, 'Authentication Required to access Invoice').respond()
 
 
+@ticket_blueprint.route('/events/invoices/<string:invoice_identifier>')
+@jwt_required()
+def event_invoices(invoice_identifier):
+    if not current_user:
+        return ForbiddenError({'source': ''}, 'Authentication Required to access Invoice').respond()
+    try:
+        event_invoice = EventInvoice.query.filter_by(identifier=invoice_identifier).first()
+        event_id = event_invoice.event_id
+    except NoResultFound:
+        return NotFoundError({'source': ''}, 'Event Invoice not found').respond()
+    if not current_user.is_organizer(event_id) and not current_user.is_staff:
+        return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()
+    key = UPLOAD_PATHS['pdf']['event_invoices'].format(identifier=invoice_identifier)
+    file_path = '../generated/invoices/{}/{}/'.format(key, generate_hash(key)) + invoice_identifier + '.pdf'
+    try:
+        return return_file('event-invoice', file_path, invoice_identifier)
+    except FileNotFoundError:
+        raise ObjectNotFound({'source': ''},
+                             "The Event Invoice isn't available at the moment. \
+                             Invoices are usually issued on the 1st of every month")
+
+
 # Access for Environment details & Basic Auth Support
 def requires_basic_auth(f):
     @wraps(f)


Test patch: