Repository: fossasia/open-event-server

Issue:
Generate ical, xcal, pentabarf xml files on event published
**Is your feature request related to a problem? Please describe.**
When the event is published, the ical, xcal and pentabarf xml files need to be created and the url should be updated.

**Describe the solution you'd like**
In after create method of event patch, start the celery tasks for the same.

**Describe alternatives you've considered**
\-

**Additional context**
Blocker #4775 


Discussion:

Resolving patch:
diff --git a/app/api/events.py b/app/api/events.py
--- a/app/api/events.py
+++ b/app/api/events.py
@@ -18,6 +18,7 @@
 from app.api.helpers.permission_manager import has_access
 from app.api.helpers.utilities import dasherize
 from app.api.schema.events import EventSchemaPublic, EventSchema
+from app.api.helpers.export_helpers import create_export_job
 # models
 from app.models import db
 from app.models.access_code import AccessCode
@@ -132,6 +133,9 @@ def after_create_object(self, event, data, view_kwargs):
         role_invite = RoleInvite(user.email, role.title_name, event.id, role.id, datetime.now(pytz.utc),
                                  status='accepted')
         save_to_db(role_invite, 'Organiser Role Invite Added')
+        if event.state == 'published' and event.schedule_published_on:
+            start_export_tasks(event)
+
         if data.get('original_image_url'):
             try:
                 uploaded_images = create_save_image_sizes(data['original_image_url'], 'event', event.id)
@@ -435,13 +439,20 @@ def before_update_object(self, event, data, view_kwargs):
             data['thumbnail_image_url'] = uploaded_images['thumbnail_image_url']
             data['icon_image_url'] = uploaded_images['icon_image_url']
 
+    def after_update_object(self, event, data, view_kwargs):
+        if event.state == 'published' and event.schedule_published_on:
+            start_export_tasks(event)
+        else:
+            clear_export_urls(event)
+
     decorators = (api.has_permission('is_coorganizer', methods="PATCH,DELETE", fetch="id", fetch_as="event_id",
                                      model=Event),)
     schema = EventSchema
     data_layer = {'session': db.session,
                   'model': Event,
                   'methods': {
-                      'before_update_object': before_update_object
+                      'before_update_object': before_update_object,
+                      'after_update_object': after_update_object
                   }}
 
 
@@ -490,3 +501,28 @@ class EventCopyResource(ResourceList):
     methods = ['POST', ]
     data_layer = {'class': EventCopyLayer,
                   'session': db.Session}
+
+
+def start_export_tasks(event):
+    event_id = str(event.id)
+    # XCAL
+    from .helpers.tasks import export_xcal_task
+    task_xcal = export_xcal_task.delay(event_id, temp=False)
+    create_export_job(task_xcal.id, event_id)
+
+    # ICAL
+    from .helpers.tasks import export_ical_task
+    task_ical = export_ical_task.delay(event_id, temp=False)
+    create_export_job(task_ical.id, event_id)
+
+    # PENTABARF XML
+    from .helpers.tasks import export_pentabarf_task
+    task_pentabarf = export_pentabarf_task.delay(event_id, temp=False)
+    create_export_job(task_pentabarf.id, event_id)
+
+
+def clear_export_urls(event):
+    event.ical_url = None
+    event.xcal_url = None
+    event.pentabarf_url = None
+    save_to_db(event)
diff --git a/app/api/helpers/storage.py b/app/api/helpers/storage.py
--- a/app/api/helpers/storage.py
+++ b/app/api/helpers/storage.py
@@ -59,6 +59,12 @@
         'ical': 'exports/{event_id}/ical',
         'xcal': 'exports/{event_id}/xcal'
     },
+    'exports-temp': {
+        'zip': 'exports/{event_id}/temp/zip',
+        'pentabarf': 'exports/{event_id}/temp/pentabarf',
+        'ical': 'exports/{event_id}/temp/ical',
+        'xcal': 'exports/{event_id}/temp/xcal'
+    },
     'custom-placeholders': {
         'original': 'custom-placeholders/{identifier}/original',
         'thumbnail': 'custom-placeholders/{identifier}/thumbnail',
diff --git a/app/api/helpers/tasks.py b/app/api/helpers/tasks.py
--- a/app/api/helpers/tasks.py
+++ b/app/api/helpers/tasks.py
@@ -115,11 +115,15 @@ def import_event_task(self, email, file, source_type, creator_id):
 
 
 @celery.task(base=RequestContextTask, name='export.ical', bind=True)
-def export_ical_task(self, event_id):
+def export_ical_task(self, event_id, temp=True):
     event = safe_query(db, Event, 'id', event_id, 'event_id')
 
     try:
-        filedir = current_app.config.get('BASE_DIR') + '/static/uploads/temp/' + event_id + '/'
+        if temp:
+            filedir = current_app.config.get('BASE_DIR') + '/static/uploads/temp/' + event_id + '/'
+        else:
+            filedir = current_app.config.get('BASE_DIR') + '/static/uploads/' + event_id + '/'
+
         if not os.path.isdir(filedir):
             os.makedirs(filedir)
         filename = "ical.ics"
@@ -127,11 +131,16 @@ def export_ical_task(self, event_id):
         with open(file_path, "w") as temp_file:
             temp_file.write(str(ICalExporter.export(event_id), 'utf-8'))
         ical_file = UploadedFile(file_path=file_path, filename=filename)
-        event.ical_url = upload(ical_file, UPLOAD_PATHS['exports']['ical'].format(event_id=event_id))
-        save_to_db(event)
+        if temp:
+            ical_url = upload(ical_file, UPLOAD_PATHS['exports-temp']['ical'].format(event_id=event_id))
+        else:
+            ical_url = upload(ical_file, UPLOAD_PATHS['exports']['ical'].format(event_id=event_id))
         result = {
-            'download_url': event.ical_url
+            'download_url': ical_url
         }
+        if not temp:
+            event.ical_url = ical_url
+            save_to_db(event)
 
     except Exception as e:
         print(traceback.format_exc())
@@ -141,11 +150,15 @@ def export_ical_task(self, event_id):
 
 
 @celery.task(base=RequestContextTask, name='export.xcal', bind=True)
-def export_xcal_task(self, event_id):
+def export_xcal_task(self, event_id, temp=True):
     event = safe_query(db, Event, 'id', event_id, 'event_id')
 
     try:
-        filedir = current_app.config.get('BASE_DIR') + '/static/uploads/temp/' + event_id + '/'
+        if temp:
+            filedir = current_app.config.get('BASE_DIR') + '/static/uploads/temp/' + event_id + '/'
+        else:
+            filedir = current_app.config.get('BASE_DIR') + '/static/uploads/' + event_id + '/'
+
         if not os.path.isdir(filedir):
             os.makedirs(filedir)
         filename = "xcal.xcs"
@@ -153,11 +166,17 @@ def export_xcal_task(self, event_id):
         with open(file_path, "w") as temp_file:
             temp_file.write(str(XCalExporter.export(event_id), 'utf-8'))
         xcal_file = UploadedFile(file_path=file_path, filename=filename)
-        event.xcal_url = upload(xcal_file, UPLOAD_PATHS['exports']['xcal'].format(event_id=event_id))
-        save_to_db(event)
+        if temp:
+            xcal_url = upload(xcal_file, UPLOAD_PATHS['exports-temp']['xcal'].format(event_id=event_id))
+        else:
+            xcal_url = upload(xcal_file, UPLOAD_PATHS['exports']['xcal'].format(event_id=event_id))
         result = {
-            'download_url': event.xcal_url
+            'download_url': xcal_url
         }
+        if not temp:
+            event.xcal_url = xcal_url
+            save_to_db(event)
+
     except Exception as e:
         print(traceback.format_exc())
         result = {'__error': True, 'result': str(e)}
@@ -166,11 +185,15 @@ def export_xcal_task(self, event_id):
 
 
 @celery.task(base=RequestContextTask, name='export.pentabarf', bind=True)
-def export_pentabarf_task(self, event_id):
+def export_pentabarf_task(self, event_id, temp=True):
     event = safe_query(db, Event, 'id', event_id, 'event_id')
 
     try:
-        filedir = current_app.config.get('BASE_DIR') + '/static/uploads/temp/' + event_id + '/'
+        if temp:
+            filedir = current_app.config.get('BASE_DIR') + '/static/uploads/temp/' + event_id + '/'
+        else:
+            filedir = current_app.config.get('BASE_DIR') + '/static/uploads/' + event_id + '/'
+
         if not os.path.isdir(filedir):
             os.makedirs(filedir)
         filename = "pentabarf.xml"
@@ -178,11 +201,17 @@ def export_pentabarf_task(self, event_id):
         with open(file_path, "w") as temp_file:
             temp_file.write(str(PentabarfExporter.export(event_id), 'utf-8'))
         pentabarf_file = UploadedFile(file_path=file_path, filename=filename)
-        event.pentabarf_url = upload(pentabarf_file, UPLOAD_PATHS['exports']['pentabarf'].format(event_id=event_id))
-        save_to_db(event)
+        if temp:
+            pentabarf_url = upload(pentabarf_file, UPLOAD_PATHS['exports-temp']['pentabarf'].format(event_id=event_id))
+        else:
+            pentabarf_url = upload(pentabarf_file, UPLOAD_PATHS['exports']['pentabarf'].format(event_id=event_id))
         result = {
-            'download_url': event.pentabarf_url
+            'download_url': pentabarf_url
         }
+        if not temp:
+            event.pentabarf_url = pentabarf_url
+            save_to_db(event)
+
     except Exception as e:
         print(traceback.format_exc())
         result = {'__error': True, 'result': str(e)}


Test patch: