From cbca673f33c892053c873d252de7d69ed5dbc9ad Mon Sep 17 00:00:00 2001 From: Hieu Lam Date: Fri, 13 Oct 2023 11:54:23 +0700 Subject: [PATCH 1/8] fix-9075: Remove empty line, add - in format jinja2 to remove empty line if do not have data --- app/templates/cvf/badge_qr_template.cvf | 163 ++++++++++-------------- 1 file changed, 64 insertions(+), 99 deletions(-) diff --git a/app/templates/cvf/badge_qr_template.cvf b/app/templates/cvf/badge_qr_template.cvf index ffae605e98..095a16c405 100644 --- a/app/templates/cvf/badge_qr_template.cvf +++ b/app/templates/cvf/badge_qr_template.cvf @@ -1,133 +1,98 @@ BEGIN:VCARD - VERSION:3.0 - -X-SOCIALPROFILE;TYPE=EVENTYAY:{{ ticket_id }} - +EVENTYAY:{{ ticket_id }} EMAIL:{{ email }} -{% if firstname or lastname %} +{%- if firstname or lastname %} FN:{{ firstname|default('') }} {{ lastname|default('') }} - N:{{ lastname|default('') }};{{ firstname|default('') }};;; -{% endif %} - -{% if phone %} +{%- endif %} +{%- if phone %} TEL;TYPE=HOME:{{ phone }} -{% endif %} - -{% if workPhone %} +{%- endif %} +{%- if workPhone %} TEL;TYPE=WORK:{{ workPhone }} -{% endif %} - -{% if address or city or state or country %} +{%- endif %} +{%- if address or city or state or country %} ADR;TYPE=ADDRESS:;;{{ address }};{{city|default('')}};{{state|default('')}};;{{country|default('')}} -{% endif %} - -{% if billingAddress %} +{%- endif %} +{%- if billingAddress %} ADR;TYPE=BILLING:;;{{billingAddress}};;;; -{% endif %} - -{% if homeAddress %} +{%- endif %} +{%- if homeAddress %} ADR;TYPE=HOME:;;{{homeAddress}};;;; -{% endif %} - -{% if shippingAddress %} +{%- endif %} +{%- if shippingAddress %} ADR;TYPE=SHIPPING:;;{{shippingAddress}};;;; -{% endif %} - -{% if workAddress %} +{%- endif %} +{%- if workAddress %} ADR;TYPE=WORK:;;{{workAddress}};;;; -{% endif %} - -{% if company %} +{%- endif %} +{%- if company %} ORG:{{company}} -{% endif %} - -{% if jobTitle %} +{%- endif %} +{%- if jobTitle %} ORG:{{jobTitle}} -{% endif %} - -{% if website %} +{%- endif %} +{%- if website %} URL;TYPE=WEBSITE:{{website}} -{% endif %} - -{% if blog %} +{%- endif %} +{%- if blog %} URL;TYPE=BLOG:{{blog}} -{% endif %} - -{% if twitter %} +{%- endif %} +{%- if twitter %} URL;TYPE=TWITTER:{{twitter}} -{% endif %} - -{% if facebook %} +{%- endif %} +{%- if facebook %} URL;TYPE=FACEBOK:{{facebook}} -{% endif %} - -{% if github %} +{%- endif %} +{%- if github %} URL;TYPE=GITHUB:{{github}} -{% endif %} - -{% if linkedin %} +{%- endif %} +{%- if linkedin %} URL;TYPE=LINIKENDIN:{{linkedin}} -{% endif %} - -{% if instagram %} +{%- endif %} +{%- if instagram %} URL;TYPE=INSTAGRAM:{{instagram}} -{% endif %} - -{% if gender %} +{%- endif %} +{%- if gender %} X-SOCIALPROFILE;TYPE=GENDER:{{gender}} -{% endif %} - -{% if ageGroup %} +{%- endif %} +{%- if ageGroup %} X-SOCIALPROFILE;TYPE=AGEGROUP:{{ageGroup}} -{% endif %} - -{% if acceptVideoRecording %} +{%- endif %} +{%- if acceptVideoRecording %} X-SOCIALPROFILE;TYPE=ACCEPTVIDEORECORDING:{{acceptVideoRecording}} -{% endif %} - -{% if acceptShareDetails %} +{%- endif %} +{%- if acceptShareDetails %} X-SOCIALPROFILE;TYPE=ACCEPTSHAREDETAILS:{{acceptShareDetails}} -{% endif %} - -{% if acceptReceiveEmails %} +{%- endif %} +{%- if acceptReceiveEmails %} X-SOCIALPROFILE;TYPE=ACCEPTRECEIVEEMAILS:{{acceptReceiveEmails}} -{% endif %} - -{% if is_consent_form_field %} +{%- endif %} +{%- if is_consent_form_field %} X-SOCIALPROFILE;TYPE=ConsentFormField:{{is_consent_form_field}} -{% endif %} - -{% if is_consent_form_field_photo %} +{%- endif %} +{%- if is_consent_form_field_photo %} X-SOCIALPROFILE;TYPE=ConsentFormFieldPhoto:{{is_consent_form_field_photo}} -{% endif %} - -{% if is_consent_of_refund_policy %} +{%- endif %} +{%- if is_consent_of_refund_policy %} X-SOCIALPROFILE;TYPE=ConsentOfRefundPolicy:{{is_consent_of_refund_policy}} -{% endif %} - -{% if native_language %} +{%- endif %} +{%- if native_language %} X-SOCIALPROFILE;TYPE=NativeLanguage:{{native_language}} -{% endif %} - -{% if fluent_language %} +{%- endif %} +{%- if fluent_language %} X-SOCIALPROFILE;TYPE=FluentLanguage:{{fluent_language}} -{% endif %} - -{% if home_wiki %} +{%- endif %} +{%- if home_wiki %} X-SOCIALPROFILE;TYPE=HomeWiki:{{home_wiki}} -{% endif %} - -{% if wiki_scholarship %} +{%- endif %} +{%- if wiki_scholarship %} X-SOCIALPROFILE;TYPE=WikiScholarship:{{wiki_scholarship}} -{% endif %} - -{% for custom_field in custom_fields %} -{% for key, value in custom_field.items() %} +{%- endif %} +{%- for custom_field in custom_fields %} +{%- for key, value in custom_field.items() %} X-SOCIALPROFILE;TYPE={{key}}:{{value}} -{% endfor %} -{% endfor %} - -END:VCARD - +{%- endfor %} +{%- endfor %} +END:VCARD \ No newline at end of file From 5afcdea1b1f59e14997c648cfcaff10c73e50c32 Mon Sep 17 00:00:00 2001 From: lthanhhieu Date: Mon, 16 Oct 2023 14:18:01 +0700 Subject: [PATCH 2/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 3/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 4/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 5/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 6/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 0fc3e0a52d36090e52b46af9c64e3c41f0b0fbcf Mon Sep 17 00:00:00 2001 From: Hieu Lam Date: Tue, 17 Oct 2023 16:33:28 +0700 Subject: [PATCH 7/8] fix-9075: Fix 2heads --- app/api/helpers/tasks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/api/helpers/tasks.py b/app/api/helpers/tasks.py index d5bacd2b21..d0068f8803 100644 --- a/app/api/helpers/tasks.py +++ b/app/api/helpers/tasks.py @@ -960,3 +960,4 @@ def validate_badge_print(attendee_id): .all() ) return ticket_holder, badge_form, badge_field_forms + From 8ae57a3e499582d4f878ab737807d4ebdf86eb34 Mon Sep 17 00:00:00 2001 From: lthanhhieu Date: Wed, 18 Oct 2023 10:14:10 +0700 Subject: [PATCH 8/8] fix-9075: Fix image --- app/api/helpers/tasks.py | 2 +- app/templates/pdf/badge_forms.html | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/api/helpers/tasks.py b/app/api/helpers/tasks.py index d0068f8803..84237ca800 100644 --- a/app/api/helpers/tasks.py +++ b/app/api/helpers/tasks.py @@ -917,6 +917,7 @@ def create_print_badge_pdf(self, attendee_id, list_field_show): ), UPLOAD_PATHS['pdf']['badge_forms_pdf'].format(identifier=badge_form.badge_id), identifier=badge_form.badge_id, + new_renderer=True, ) result = {'download_url': badge_url} ticket_holder.is_badge_printed = True @@ -960,4 +961,3 @@ def validate_badge_print(attendee_id): .all() ) return ticket_holder, badge_form, badge_field_forms - diff --git a/app/templates/pdf/badge_forms.html b/app/templates/pdf/badge_forms.html index 6dcb5ce44b..6c0eb35a10 100644 --- a/app/templates/pdf/badge_forms.html +++ b/app/templates/pdf/badge_forms.html @@ -4,7 +4,7 @@ @@ -20,7 +20,7 @@ {% else %}