From 5afcdea1b1f59e14997c648cfcaff10c73e50c32 Mon Sep 17 00:00:00 2001 From: lthanhhieu Date: Mon, 16 Oct 2023 14:18:01 +0700 Subject: [PATCH 1/8] feature-9077: Missing stats for daily check in scanning returning from API --- app/api/custom/check_in_stats.py | 108 ++++++++++++++---- .../rev-2023-08-17-15:38:43-bce7acfe5a4f_.py | 4 +- 2 files changed, 87 insertions(+), 25 deletions(-) diff --git a/app/api/custom/check_in_stats.py b/app/api/custom/check_in_stats.py index 27e84b1149..1ac5046e72 100644 --- a/app/api/custom/check_in_stats.py +++ b/app/api/custom/check_in_stats.py @@ -1,7 +1,7 @@ import datetime from flask import Blueprint, request -from sqlalchemy import desc +from sqlalchemy import asc, desc, func from app.api.helpers.permissions import jwt_required from app.api.helpers.static import STATION_TYPE @@ -30,11 +30,10 @@ def get_registration_stats(event_id): """ # check if event is existed event = Event.query.filter(Event.id == event_id).first() - current_time = datetime.datetime.utcnow().date() + total_attendee = TicketHolder.query.filter(TicketHolder.event_id == event_id).count() if event is None: return {"message": "Event can not be found."}, 404 stations = Station.query.filter(Station.event_id == event_id).all() - total_attendee = TicketHolder.query.filter(TicketHolder.event_id == event_id).count() registration_stations = [ station.id for station in stations @@ -50,24 +49,82 @@ def get_registration_stats(event_id): for station in stations if station.station_type == STATION_TYPE.get('check out') ] + data = { + "total_attendee": total_attendee, + "registration_stations": registration_stations, + "check_in_stations": check_in_stations, + "check_out_stations": check_out_stations, + } + + if request.args.get('today_only'): + results = {} + date = datetime.date.today().strftime("%Y-%m-%d") + data["date"] = date + results[date] = get_data_by_date(data) + else: + stationIds = [] + for station in stations: + stationIds.append(station.id) + date_list = list( + zip( + *db.session.query(func.date(UserCheckIn.created_at)) + .distinct() + .filter( + UserCheckIn.station_id.in_(stationIds), + ) + .order_by(asc(func.date(UserCheckIn.created_at))) + .all() + ) + ) + dates = list( + map( + str, + date_list[0] if date_list else [], + ) + ) + + if len(dates) == 0: + return { + "total_attendee": total_attendee, + "total_registered": 0, + "total_not_checked_in": total_attendee - 0, + "total_track_checked_in": 0, + "total_track_checked_out": 0, + "total_session_checked_in": 0, + "total_session_checked_out": 0, + }, 200 + + results = {} + for date in dates: + data["date"] = date + results[date] = get_data_by_date(data) + return results, 200 + + +def get_data_by_date(data): + """ + Get data by date + @param data + @return: result + """ registered_attendee = ( UserCheckIn.query.with_entities(UserCheckIn.ticket_holder_id) .filter( - UserCheckIn.station_id.in_(registration_stations), - UserCheckIn.created_at >= current_time, + UserCheckIn.station_id.in_(data['registration_stations']), + func.date(UserCheckIn.created_at) == data['date'], ) .group_by(UserCheckIn.ticket_holder_id) .count() ) check_in_attendee = UserCheckIn.query.filter( - UserCheckIn.station_id.in_(check_in_stations), - UserCheckIn.created_at >= current_time, + UserCheckIn.station_id.in_(data['check_in_stations']), + func.date(UserCheckIn.created_at) == data['date'], ) check_out_attendee = UserCheckIn.query.filter( - UserCheckIn.station_id.in_(check_out_stations), - UserCheckIn.created_at >= current_time, + UserCheckIn.station_id.in_(data['check_out_stations']), + func.date(UserCheckIn.created_at) == data['date'], ) session_checked_in = check_in_attendee.with_entities( @@ -86,9 +143,9 @@ def get_registration_stats(event_id): Session.id.in_( [user_check_in.session_id for user_check_in in session_checked_in] ), - UserCheckIn.station_id.in_(check_in_stations), + UserCheckIn.station_id.in_(data['check_in_stations']), Session.id == UserCheckIn.session_id, - UserCheckIn.created_at >= current_time, + func.date(UserCheckIn.created_at) == data['date'], ) track_checked_in_count = ( @@ -101,9 +158,9 @@ def get_registration_stats(event_id): Session.id.in_( [user_check_in.session_id for user_check_in in session_checked_out] ), - UserCheckIn.station_id.in_(check_out_stations), + UserCheckIn.station_id.in_(data['check_out_stations']), UserCheckIn.session_id == Session.id, - UserCheckIn.created_at >= current_time, + func.date(UserCheckIn.created_at) == data['date'], ) track_checked_out_count = ( @@ -115,30 +172,32 @@ def get_registration_stats(event_id): track_stat = [] if request.args.get('session_ids'): session_stat = get_session_stats( - request.args.get('session_ids'), session_checked_in, session_checked_out + request.args.get('session_ids'), + session_checked_in, + session_checked_out, + data['date'], ) if request.args.get('track_ids'): track_stat = get_track_stats( request.args.get('track_ids'), check_in_attendee, check_out_attendee, - current_time, + data['date'], ) - return { - "total_attendee": total_attendee, + "total_attendee": data['total_attendee'], "total_registered": registered_attendee, - "total_not_checked_in": total_attendee - registered_attendee, + "total_not_checked_in": data['total_attendee'] - registered_attendee, "total_track_checked_in": track_checked_in_count, "total_track_checked_out": track_checked_out_count, "total_session_checked_in": session_checked_in_count, "total_session_checked_out": session_checked_out_count, "session_stats": session_stat, "track_stats": track_stat, - }, 200 + } -def get_session_stats(session_ids, session_checked_in, session_checked_out): +def get_session_stats(session_ids, session_checked_in, session_checked_out, date): """ Get session stats @param session_ids: session id to get @@ -181,7 +240,10 @@ def get_session_stats(session_ids, session_checked_in, session_checked_out): stationStorePaxs = ( db.session.query(StationStorePax) - .filter(StationStorePax.session_id == session_id) + .filter( + StationStorePax.session_id == session_id, + func.date(StationStorePax.created_at) == date, + ) .order_by(desc("created_at")) .all() ) @@ -231,7 +293,7 @@ def get_track_stats(track_ids, check_in_attendee, check_out_attendee, current_ti ), UserCheckIn.id.in_([user_check_in.id for user_check_in in check_in_attendee]), Session.id == UserCheckIn.session_id, - UserCheckIn.created_at >= current_time, + func.date(UserCheckIn.created_at) == current_time, Session.track_id == track_id, ) @@ -249,7 +311,7 @@ def get_track_stats(track_ids, check_in_attendee, check_out_attendee, current_ti [user_check_in.id for user_check_in in check_out_attendee] ), UserCheckIn.session_id == Session.id, - UserCheckIn.created_at >= current_time, + func.date(UserCheckIn.created_at) == current_time, Session.track_id == track_id, ) diff --git a/migrations/versions/rev-2023-08-17-15:38:43-bce7acfe5a4f_.py b/migrations/versions/rev-2023-08-17-15:38:43-bce7acfe5a4f_.py index 8538fd9873..39e79ef46d 100644 --- a/migrations/versions/rev-2023-08-17-15:38:43-bce7acfe5a4f_.py +++ b/migrations/versions/rev-2023-08-17-15:38:43-bce7acfe5a4f_.py @@ -1,7 +1,7 @@ """empty message Revision ID: bce7acfe5a4f -Revises: 24271525a263 +Revises: 1af4cc4f7cd5 Create Date: 2023-08-17 15:38:43.387065 """ @@ -12,7 +12,7 @@ # revision identifiers, used by Alembic. revision = 'bce7acfe5a4f' -down_revision = '24271525a263' +down_revision = '1af4cc4f7cd5' def upgrade(): From 84a28543b72911f33ef678c56439eed858a6ef6e Mon Sep 17 00:00:00 2001 From: lthanhhieu Date: Mon, 16 Oct 2023 14:34:50 +0700 Subject: [PATCH 2/8] feature-9077: Missing stats for daily check in scanning returning from API --- app/api/custom/check_in_stats.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/api/custom/check_in_stats.py b/app/api/custom/check_in_stats.py index 1ac5046e72..cc2cb63425 100644 --- a/app/api/custom/check_in_stats.py +++ b/app/api/custom/check_in_stats.py @@ -92,6 +92,16 @@ def get_registration_stats(event_id): "total_track_checked_out": 0, "total_session_checked_in": 0, "total_session_checked_out": 0, + "track_stats": [], + "session_stats": { + "check_in": 0, + "check_out": 0, + "manual_count": {}, + "session_id": request.args.get('session_ids'), + "session_name": "", + "speakers": [], + "track_name": "", + }, }, 200 results = {} From 4c21f71dbb0599438e32304a9a32c5d0faf876f0 Mon Sep 17 00:00:00 2001 From: lthanhhieu Date: Mon, 16 Oct 2023 14:57:52 +0700 Subject: [PATCH 3/8] feature-9077: Missing stats for daily check in scanning returning from API --- docs/api/blueprint/user_check_in.apib | 4 ++-- .../all/integration/api/users_check_in/test_users_check_in.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/api/blueprint/user_check_in.apib b/docs/api/blueprint/user_check_in.apib index b98d8d59f7..0eead151f7 100644 --- a/docs/api/blueprint/user_check_in.apib +++ b/docs/api/blueprint/user_check_in.apib @@ -29,9 +29,9 @@ Get registration stats. "check_out": 0, "manual_count": {}, "session_id": "1", - "session_name": "example", + "session_name": "", "speakers": [], - "track_name": "example" + "track_name": "" } ], "total_attendee": 0, diff --git a/tests/all/integration/api/users_check_in/test_users_check_in.py b/tests/all/integration/api/users_check_in/test_users_check_in.py index 9db818db59..8953f42532 100644 --- a/tests/all/integration/api/users_check_in/test_users_check_in.py +++ b/tests/all/integration/api/users_check_in/test_users_check_in.py @@ -21,9 +21,9 @@ def test_get_registration_stats(db, client, jwt): "check_out": 0, "manual_count": {}, "session_id": "1", - "session_name": "example", + "session_name": "", "speakers": [], - "track_name": "example", + "track_name": "", } ], "total_attendee": 0, From e4e1c3f1db681bc25dbb85a46cc0bba167bab089 Mon Sep 17 00:00:00 2001 From: lthanhhieu Date: Mon, 16 Oct 2023 15:07:10 +0700 Subject: [PATCH 4/8] feature-9077: Missing stats for daily check in scanning returning from API --- app/api/custom/check_in_stats.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/api/custom/check_in_stats.py b/app/api/custom/check_in_stats.py index cc2cb63425..39e037014e 100644 --- a/app/api/custom/check_in_stats.py +++ b/app/api/custom/check_in_stats.py @@ -93,15 +93,17 @@ def get_registration_stats(event_id): "total_session_checked_in": 0, "total_session_checked_out": 0, "track_stats": [], - "session_stats": { - "check_in": 0, - "check_out": 0, - "manual_count": {}, - "session_id": request.args.get('session_ids'), - "session_name": "", - "speakers": [], - "track_name": "", - }, + "session_stats": [ + { + "check_in": 0, + "check_out": 0, + "manual_count": {}, + "session_id": request.args.get('session_ids'), + "session_name": "", + "speakers": [], + "track_name": "", + } + ], }, 200 results = {} From b42a000ba414a2b3ebb116580076bfb475aae67e Mon Sep 17 00:00:00 2001 From: lthanhhieu Date: Mon, 16 Oct 2023 15:30:55 +0700 Subject: [PATCH 5/8] feature-9077: Missing stats for daily check in scanning returning from API --- .../api/helpers/test_csv_jobs_util.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/all/integration/api/helpers/test_csv_jobs_util.py b/tests/all/integration/api/helpers/test_csv_jobs_util.py index e7f9f734e8..1ead138972 100644 --- a/tests/all/integration/api/helpers/test_csv_jobs_util.py +++ b/tests/all/integration/api/helpers/test_csv_jobs_util.py @@ -1,17 +1,25 @@ import unittest from datetime import datetime -from app.api.helpers.csv_jobs_util import * +import pytz + +from app.api.helpers.csv_jobs_util import ( + export_attendees_csv, + export_orders_csv, + export_sessions_csv, + export_speakers_csv, +) from app.models import db +from app.models.custom_form import ATTENDEE_CUSTOM_FORM from tests.all.integration.auth_helper import create_user from tests.all.integration.utils import OpenEventTestCase from tests.factories import common from tests.factories.attendee import AttendeeFactory from tests.factories.custom_form import CustomFormFactory +from tests.factories.event import EventFactoryBasic from tests.factories.order import OrderFactory from tests.factories.session import SessionSubFactory from tests.factories.speaker import SpeakerFactory -from app.models.custom_form import ATTENDEE_CUSTOM_FORM class TestExportCSV(OpenEventTestCase): @@ -19,7 +27,8 @@ def test_export_orders_csv(self): """Method to check the orders data export""" with self.app.test_request_context(): - test_order = OrderFactory(created_at=datetime.now()) + event = EventFactoryBasic() + test_order = OrderFactory(created_at=datetime.now(), event_id=event.id) test_order.amount = 2 field_data = export_orders_csv([test_order]) assert field_data[1][2] == 'initializing' @@ -34,7 +43,8 @@ def test_export_attendees_csv(self): test_attendee.order = test_order custom_forms = CustomFormFactory() field_data = export_attendees_csv( - [test_attendee], [custom_forms], ATTENDEE_CUSTOM_FORM) + [test_attendee], [custom_forms], ATTENDEE_CUSTOM_FORM + ) # new export_attendees_csv will return list of dictionary for csv_writer assert field_data[0].get("Tax ID") == "tax id" From f1b893e0f006790c5d236df207ac9bba5717f9a7 Mon Sep 17 00:00:00 2001 From: Hieu Lam Date: Tue, 17 Oct 2023 16:50:15 +0700 Subject: [PATCH 6/8] feature-9077: Add document --- app/api/custom/check_in_stats.py | 4 ++-- docs/api/blueprint/user_check_in.apib | 4 ++-- .../all/integration/api/users_check_in/test_users_check_in.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/api/custom/check_in_stats.py b/app/api/custom/check_in_stats.py index 39e037014e..a6ea0f0ec0 100644 --- a/app/api/custom/check_in_stats.py +++ b/app/api/custom/check_in_stats.py @@ -84,7 +84,7 @@ def get_registration_stats(event_id): ) if len(dates) == 0: - return { + return { "2023-10-17": { "total_attendee": total_attendee, "total_registered": 0, "total_not_checked_in": total_attendee - 0, @@ -104,7 +104,7 @@ def get_registration_stats(event_id): "track_name": "", } ], - }, 200 + }}, 200 results = {} for date in dates: diff --git a/docs/api/blueprint/user_check_in.apib b/docs/api/blueprint/user_check_in.apib index 0eead151f7..ca0ce7eb71 100644 --- a/docs/api/blueprint/user_check_in.apib +++ b/docs/api/blueprint/user_check_in.apib @@ -22,7 +22,7 @@ Get registration stats. + Response 200 (application/json) - { + { "2023-10-17": { "session_stats": [ { "check_in": 0, @@ -42,7 +42,7 @@ Get registration stats. "total_track_checked_in": 0, "total_track_checked_out": 0, "track_stats": [] - } + }} ## Create User Check In [/v1/user-check-in] diff --git a/tests/all/integration/api/users_check_in/test_users_check_in.py b/tests/all/integration/api/users_check_in/test_users_check_in.py index 8953f42532..4d95d21277 100644 --- a/tests/all/integration/api/users_check_in/test_users_check_in.py +++ b/tests/all/integration/api/users_check_in/test_users_check_in.py @@ -14,7 +14,7 @@ def test_get_registration_stats(db, client, jwt): headers=jwt, ) - result = { + result = { "2023-10-17": { "session_stats": [ { "check_in": 0, @@ -34,7 +34,7 @@ def test_get_registration_stats(db, client, jwt): "total_track_checked_in": 0, "total_track_checked_out": 0, "track_stats": [], - } + }} assert response.status_code == 200 assert json.loads(response.data) == result From 6e315fa1c32c7de2618eeed8ae9f9d39350536db Mon Sep 17 00:00:00 2001 From: Hieu Lam Date: Tue, 17 Oct 2023 16:52:16 +0700 Subject: [PATCH 7/8] feature-9077: Add document --- app/api/custom/check_in_stats.py | 44 ++++++++++--------- docs/api/blueprint/user_check_in.apib | 44 ++++++++++--------- .../api/users_check_in/test_users_check_in.py | 44 ++++++++++--------- 3 files changed, 69 insertions(+), 63 deletions(-) diff --git a/app/api/custom/check_in_stats.py b/app/api/custom/check_in_stats.py index a6ea0f0ec0..a27d9786dd 100644 --- a/app/api/custom/check_in_stats.py +++ b/app/api/custom/check_in_stats.py @@ -84,27 +84,29 @@ def get_registration_stats(event_id): ) if len(dates) == 0: - return { "2023-10-17": { - "total_attendee": total_attendee, - "total_registered": 0, - "total_not_checked_in": total_attendee - 0, - "total_track_checked_in": 0, - "total_track_checked_out": 0, - "total_session_checked_in": 0, - "total_session_checked_out": 0, - "track_stats": [], - "session_stats": [ - { - "check_in": 0, - "check_out": 0, - "manual_count": {}, - "session_id": request.args.get('session_ids'), - "session_name": "", - "speakers": [], - "track_name": "", - } - ], - }}, 200 + return { + "2023-10-17": { + "total_attendee": total_attendee, + "total_registered": 0, + "total_not_checked_in": total_attendee - 0, + "total_track_checked_in": 0, + "total_track_checked_out": 0, + "total_session_checked_in": 0, + "total_session_checked_out": 0, + "track_stats": [], + "session_stats": [ + { + "check_in": 0, + "check_out": 0, + "manual_count": {}, + "session_id": request.args.get('session_ids'), + "session_name": "", + "speakers": [], + "track_name": "", + } + ], + } + }, 200 results = {} for date in dates: diff --git a/docs/api/blueprint/user_check_in.apib b/docs/api/blueprint/user_check_in.apib index ca0ce7eb71..ef6156fa7c 100644 --- a/docs/api/blueprint/user_check_in.apib +++ b/docs/api/blueprint/user_check_in.apib @@ -22,27 +22,29 @@ Get registration stats. + Response 200 (application/json) - { "2023-10-17": { - "session_stats": [ - { - "check_in": 0, - "check_out": 0, - "manual_count": {}, - "session_id": "1", - "session_name": "", - "speakers": [], - "track_name": "" - } - ], - "total_attendee": 0, - "total_not_checked_in": 0, - "total_registered": 0, - "total_session_checked_in": 0, - "total_session_checked_out": 0, - "total_track_checked_in": 0, - "total_track_checked_out": 0, - "track_stats": [] - }} + { + "2023-10-17": { + "session_stats": [ + { + "check_in": 0, + "check_out": 0, + "manual_count": {}, + "session_id": "1", + "session_name": "", + "speakers": [], + "track_name": "" + } + ], + "total_attendee": 0, + "total_not_checked_in": 0, + "total_registered": 0, + "total_session_checked_in": 0, + "total_session_checked_out": 0, + "total_track_checked_in": 0, + "total_track_checked_out": 0, + "track_stats": [] + } + } ## Create User Check In [/v1/user-check-in] diff --git a/tests/all/integration/api/users_check_in/test_users_check_in.py b/tests/all/integration/api/users_check_in/test_users_check_in.py index 4d95d21277..168a126fbf 100644 --- a/tests/all/integration/api/users_check_in/test_users_check_in.py +++ b/tests/all/integration/api/users_check_in/test_users_check_in.py @@ -14,27 +14,29 @@ def test_get_registration_stats(db, client, jwt): headers=jwt, ) - result = { "2023-10-17": { - "session_stats": [ - { - "check_in": 0, - "check_out": 0, - "manual_count": {}, - "session_id": "1", - "session_name": "", - "speakers": [], - "track_name": "", - } - ], - "total_attendee": 0, - "total_not_checked_in": 0, - "total_registered": 0, - "total_session_checked_in": 0, - "total_session_checked_out": 0, - "total_track_checked_in": 0, - "total_track_checked_out": 0, - "track_stats": [], - }} + result = { + "2023-10-17": { + "session_stats": [ + { + "check_in": 0, + "check_out": 0, + "manual_count": {}, + "session_id": "1", + "session_name": "", + "speakers": [], + "track_name": "", + } + ], + "total_attendee": 0, + "total_not_checked_in": 0, + "total_registered": 0, + "total_session_checked_in": 0, + "total_session_checked_out": 0, + "total_track_checked_in": 0, + "total_track_checked_out": 0, + "track_stats": [], + } + } assert response.status_code == 200 assert json.loads(response.data) == result From 2028f22992a59c490d1c55ec7a236b05da118bc4 Mon Sep 17 00:00:00 2001 From: Hieu Lam Date: Tue, 17 Oct 2023 17:08:33 +0700 Subject: [PATCH 8/8] feature-9077: remove space --- tests/all/integration/api/users_check_in/test_users_check_in.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/all/integration/api/users_check_in/test_users_check_in.py b/tests/all/integration/api/users_check_in/test_users_check_in.py index 168a126fbf..395e73d457 100644 --- a/tests/all/integration/api/users_check_in/test_users_check_in.py +++ b/tests/all/integration/api/users_check_in/test_users_check_in.py @@ -14,7 +14,7 @@ def test_get_registration_stats(db, client, jwt): headers=jwt, ) - result = { + result = { "2023-10-17": { "session_stats": [ {