Repository: fossasia/open-event-server

Issue:
API to download check in data in a CSV
Allow organiser to download check in data in a CSV from event dashboard

Possible filters include

- Date
- Track Type
- Session
- Type (registration, daily, check in, check out, check in & check out)

Data to return
- ticket id
- date time
- session details (track name, session name and speaker name)
- type


Discussion:
hey I would like to work on this, can you assign me this task.
We don't assign issues to external contributors. Please comment that you're working on the issue after checking that no one else is, and then send a pull request for it. Thank You!
I am working on it

@avinashyadav0027 there's nothing to work on. The database is not even setup for this
oh okay, : ) sorry i am a newbie.

Resolving patch:
diff --git a/app/api/custom/users_check_in.py b/app/api/custom/users_check_in.py
new file mode 100644
--- /dev/null
+++ b/app/api/custom/users_check_in.py
@@ -0,0 +1,15 @@
+from flask import Blueprint, request
+from flask.helpers import send_from_directory
+
+from app.api.helpers.permissions import jwt_required
+from app.api.helpers.user_check_in import export_csv
+
+users_check_in_routes = Blueprint('users_check_in_routes', __name__, url_prefix='/v1')
+
+
+@users_check_in_routes.route('/export/user-check-in/csv', methods=['POST'])
+@jwt_required
+def export_user_check_in_csv():
+    """Export user check-in data as CSV."""
+    file_path = export_csv(request.json)
+    return send_from_directory('../', file_path, as_attachment=True)
diff --git a/app/api/helpers/user_check_in.py b/app/api/helpers/user_check_in.py
--- a/app/api/helpers/user_check_in.py
+++ b/app/api/helpers/user_check_in.py
@@ -1,10 +1,102 @@
-from app.api.helpers.errors import UnprocessableEntityError
+import csv
+import os
+import uuid
+from datetime import datetime, timedelta
+
+from flask import current_app
+
+from app.api.helpers.errors import BadRequestError, UnprocessableEntityError
 from app.api.helpers.static import STATION_TYPE
+from app.api.helpers.storage import UPLOAD_PATHS, UploadedFile, generate_hash, upload
 from app.models.session import Session
 from app.models.station import Station
 from app.models.user_check_in import UserCheckIn
 
 
+def export_csv(data):
+    if data is None:
+        raise BadRequestError({'source': data}, 'Bad Request Error')
+
+    query_ = UserCheckIn.query.join(Station)
+    if 'session_id' in data and data['session_id']:
+        query_ = query_.filter(UserCheckIn.session_id == data['session_id'])
+    if 'date' in data and data['date']:
+        dt = datetime.strptime(data['date'], '%Y-%m-%d')
+        start = dt - timedelta(0)
+        end = start + timedelta(days=1)
+        query_ = query_.filter(UserCheckIn.created_at >= start).filter(
+            UserCheckIn.created_at < end
+        )
+    if 'track_type' in data and data['track_type']:
+        query_ = query_.filter(UserCheckIn.track_name == data['track_type'])
+    if 'type' in data and data['type']:
+        if '&' in data['type']:
+            query_ = query_.filter(
+                Station.station_type.in_(x.strip() for x in data['type'].split('&'))
+            )
+        else:
+            query_ = query_.filter(Station.station_type == data['type'])
+    userCheckIns = query_.order_by(UserCheckIn.created_at.desc()).all()
+
+    try:
+        filedir = os.path.join(current_app.config.get('BASE_DIR'), 'static/uploads/temp/')
+        if not os.path.isdir(filedir):
+            os.makedirs(filedir)
+
+        identifier = uuid.uuid1().hex
+        filename = f"user-check-in-{identifier}.csv"
+        file_path = os.path.join(filedir, filename)
+
+        with open(file_path, "w") as temp_file:
+            writer = csv.writer(temp_file)
+            content = create_file_csv(userCheckIns)
+            for row in content:
+                writer.writerow(row)
+        csv_file = UploadedFile(file_path=file_path, filename=filename)
+        uploadPath = UPLOAD_PATHS['exports-temp']['csv'].format(
+            event_id='admin', identifier=identifier
+        )
+        upload(csv_file, uploadPath)
+        os.remove(filedir + filename)
+        return f'static/media/{uploadPath}/{generate_hash(uploadPath)}/{filename}'
+    except Exception as e:
+        raise BadRequestError({'source': e}, 'Bad Request Error')
+
+
+def create_file_csv(userCheckIns):
+    headers = [
+        'Ticket Id',
+        'Date Time',
+        'Track Name',
+        'Session Name',
+        'Speaker Name',
+        'Type',
+    ]
+
+    columns = [
+        'ticket_holder_id',
+        'created_at',
+        'track_name',
+        'session_name',
+        'speaker_name',
+        'type',
+    ]
+    rows = [headers]
+    for userCheckIn in userCheckIns:
+        data = []
+        for column in columns:
+            if column == 'type':
+                data.append(userCheckIn.station.station_type)
+                continue
+            if column == 'created_at':
+                data.append(userCheckIn.created_at.strftime('%Y-%m-%d %H:%M:%S'))
+                continue
+            data.append(getattr(userCheckIn, column))
+        rows.append(data)
+
+    return rows
+
+
 def validate_microlocation(station: Station, session: Session):
     """
     validate if microlocation matches
diff --git a/app/instance.py b/app/instance.py
--- a/app/instance.py
+++ b/app/instance.py
@@ -172,6 +172,7 @@ def create_app():
         from app.api.custom.badge_forms import badge_forms_routes
         from app.api.custom.tickets import ticket_routes
         from app.api.custom.users import users_routes
+        from app.api.custom.users_check_in import users_check_in_routes
 
         app.register_blueprint(api_v1)
         app.register_blueprint(event_copy)
@@ -208,6 +209,7 @@ def create_app():
         app.register_blueprint(badge_forms_routes)
         app.register_blueprint(ticket_routes)
         app.register_blueprint(users_routes)
+        app.register_blueprint(users_check_in_routes)
 
         add_engine_pidguard(db.engine)
 


Test patch: