From 6323f81db255780d05f330122b3f67873a918e32 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Mon, 11 Sep 2023 21:43:15 -0400 Subject: [PATCH 01/19] Re-enable pending deletion, but not too much Adds a way to prevent early deletion of badges that were registered before a certain date to account for the stoppage we had after prereg. --- uber/tasks/registration.py | 11 ++++++----- .../templates/emails/reg_workflow/pending_badges.html | 9 +++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/uber/tasks/registration.py b/uber/tasks/registration.py index 40fab5aba..6b3c9f071 100644 --- a/uber/tasks/registration.py +++ b/uber/tasks/registration.py @@ -147,17 +147,18 @@ def check_near_cap(): @celery.schedule(timedelta(days=1)) def email_pending_attendees(): - return - already_emailed_accounts = [] with Session() as session: four_days_old = datetime.now(pytz.UTC) - timedelta(hours=96) pending_badges = session.query(Attendee).filter(Attendee.badge_status == c.PENDING_STATUS, - or_(Attendee.registered < datetime.now(pytz.UTC) - timedelta(hours=24)) + Attendee.registered < datetime.now(pytz.UTC) - timedelta(hours=24) ).order_by(Attendee.registered) for badge in pending_badges: - if badge.registered < four_days_old: + # Update `compare_date` to prevent early deletion of badges registered before a certain date + # Implemented for MFF 2023 but let's be honest, we'll probably need it again + compare_date = max(badge.registered, datetime(2023, 9, 12)) + if compare_date < four_days_old: session.delete(badge) session.commit() else: @@ -178,7 +179,7 @@ def email_pending_attendees(): body = render('emails/reg_workflow/pending_badges.html', {'account': badge.managers[0] if badge.managers else None, - 'attendee': badge}, encoding=None) + 'attendee': badge, 'compare_date': compare_date}, encoding=None) send_email.delay( c.REGDESK_EMAIL, email_to, diff --git a/uber/templates/emails/reg_workflow/pending_badges.html b/uber/templates/emails/reg_workflow/pending_badges.html index 7413e3159..b85e0d36c 100644 --- a/uber/templates/emails/reg_workflow/pending_badges.html +++ b/uber/templates/emails/reg_workflow/pending_badges.html @@ -17,6 +17,15 @@ {% endif %}

+ {% if attendee.registered != compare_date %} +

+ We understand that some people encountered a technical issue while attempting to pay for their registration, + and we have now fixed all the issues we're aware of. If you attempted to register and were unable to complete + payment, please try your payment again. If you run into any further issues, please email + registration@furfest.org +

+ {% endif %} +

If this was a mistake, you can From 28bd879dfff571ca8e0ba78f0b8836a9de3cb832 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Mon, 11 Sep 2023 22:00:18 -0400 Subject: [PATCH 02/19] Fix timezone error for pending badge emails --- uber/tasks/registration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uber/tasks/registration.py b/uber/tasks/registration.py index 6b3c9f071..2ba8410db 100644 --- a/uber/tasks/registration.py +++ b/uber/tasks/registration.py @@ -157,7 +157,7 @@ def email_pending_attendees(): for badge in pending_badges: # Update `compare_date` to prevent early deletion of badges registered before a certain date # Implemented for MFF 2023 but let's be honest, we'll probably need it again - compare_date = max(badge.registered, datetime(2023, 9, 12)) + compare_date = max(badge.registered, datetime(2023, 9, 12, tzinfo=pytz.UTC)) if compare_date < four_days_old: session.delete(badge) session.commit() From a862b2caae8c9b8b65d1912f8c05b4f7ca40453c Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Mon, 11 Sep 2023 22:04:08 -0400 Subject: [PATCH 03/19] Stop emailing accounts multiple times for pending badges --- uber/tasks/registration.py | 3 +++ uber/templates/emails/reg_workflow/pending_badges.html | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/uber/tasks/registration.py b/uber/tasks/registration.py index 2ba8410db..b9f5eeed9 100644 --- a/uber/tasks/registration.py +++ b/uber/tasks/registration.py @@ -189,6 +189,9 @@ def email_pending_attendees(): model=badge.managers[0].to_dict() if c.ATTENDEE_ACCOUNTS_ENABLED else badge.to_dict(), ident=email_ident ) + + if c.ATTENDEE_ACCOUNTS_ENABLED: + already_emailed_accounts.append(email_to) diff --git a/uber/templates/emails/reg_workflow/pending_badges.html b/uber/templates/emails/reg_workflow/pending_badges.html index b85e0d36c..c9c9a69f0 100644 --- a/uber/templates/emails/reg_workflow/pending_badges.html +++ b/uber/templates/emails/reg_workflow/pending_badges.html @@ -1,7 +1,7 @@ - You haven't finished registering for {{ c.EVENT_NAME}} ({{ event_dates() }})! +

You haven't finished registering for {{ c.EVENT_NAME}} ({{ event_dates() }})!

{% if c.ATTENDEE_ACCOUNTS_ENABLED and account.pending_attendees|length > 1 %} @@ -22,7 +22,7 @@ We understand that some people encountered a technical issue while attempting to pay for their registration, and we have now fixed all the issues we're aware of. If you attempted to register and were unable to complete payment, please try your payment again. If you run into any further issues, please email - registration@furfest.org + registration@furfest.org.

{% endif %} From 82623801de4828dbf88fd1d31a8262da74390a79 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Mon, 11 Sep 2023 22:07:20 -0400 Subject: [PATCH 04/19] Update pending badge email text Yes I'm a perfectionist. --- uber/templates/emails/reg_workflow/pending_badges.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/uber/templates/emails/reg_workflow/pending_badges.html b/uber/templates/emails/reg_workflow/pending_badges.html index c9c9a69f0..3636f83d1 100644 --- a/uber/templates/emails/reg_workflow/pending_badges.html +++ b/uber/templates/emails/reg_workflow/pending_badges.html @@ -24,10 +24,11 @@ payment, please try your payment again. If you run into any further issues, please email registration@furfest.org.

- {% endif %} - +

If these issues affected you, you can + {% else %}

If this was a mistake, you can + {% endif %} finish registering and pay here. Incomplete badges are deleted after three days so please do not delay. From 7cd167763a1b906356007c3bc5f977e9929a8ee1 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Mon, 11 Sep 2023 22:21:49 -0400 Subject: [PATCH 05/19] Tweak pending badge email wording Requested via Slack --- uber/templates/emails/reg_workflow/pending_badges.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uber/templates/emails/reg_workflow/pending_badges.html b/uber/templates/emails/reg_workflow/pending_badges.html index 3636f83d1..8b88bcecd 100644 --- a/uber/templates/emails/reg_workflow/pending_badges.html +++ b/uber/templates/emails/reg_workflow/pending_badges.html @@ -24,7 +24,7 @@ payment, please try your payment again. If you run into any further issues, please email registration@furfest.org.

-

If these issues affected you, you can +

If these issues affected your registration or you wish to pay for your pending registration, you can {% else %}

If this was a mistake, you can From 40c23643e12cc1a679cc5163202f5b6bbc4eea8b Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Wed, 13 Sep 2023 22:54:48 -0400 Subject: [PATCH 06/19] Add support for running the hotel lottery in the plugin --- uber/models/attendee.py | 2 +- uber/site_sections/preregistration.py | 11 +++- .../preregistration/attendee_card.html | 7 +-- uber/templates/preregistration/homepage.html | 55 +++++++++++++++++++ 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/uber/models/attendee.py b/uber/models/attendee.py index 71f46b000..ab2fdede3 100644 --- a/uber/models/attendee.py +++ b/uber/models/attendee.py @@ -2153,7 +2153,7 @@ class AttendeeAccount(MagModel): hashed = Column(UnicodeText, private=True) password_reset = relationship('PasswordReset', backref='attendee_account', uselist=False) attendees = relationship( - 'Attendee', backref='managers', cascade='save-update,merge,refresh-expire,expunge', + 'Attendee', backref='managers', order_by='Attendee.registered', cascade='save-update,merge,refresh-expire,expunge', secondary='attendee_attendee_account') imported = Column(Boolean, default=False) diff --git a/uber/site_sections/preregistration.py b/uber/site_sections/preregistration.py index 8388a6de1..3e12908cd 100644 --- a/uber/site_sections/preregistration.py +++ b/uber/site_sections/preregistration.py @@ -24,7 +24,7 @@ from uber.models import Attendee, AttendeeAccount, Attraction, Email, Group, ModelReceipt, PromoCode, PromoCodeGroup, \ ReceiptTransaction, SignedDocument, Tracking from uber.tasks.email import send_email -from uber.utils import add_opt, check, check_pii_consent, localized_now, normalize_email, genpasswd, valid_email, \ +from uber.utils import add_opt, check, check_pii_consent, localized_now, normalize_email, normalize_email_legacy, genpasswd, valid_email, \ valid_password, SignNowDocument, validate_model from uber.payments import PreregCart, TransactionRequest, ReceiptManager import uber.validations as validations @@ -1404,12 +1404,21 @@ def homepage(self, session, message=''): if receipt and receipt.current_amount_owed and attendee.is_valid: attendees_who_owe_money[attendee.full_name] = receipt.current_amount_owed + account_attendee = None + account_attendees = session.valid_attendees().filter(~Attendee.badge_status.in_([c.REFUNDED_STATUS, c.NOT_ATTENDING]) + ).filter(Attendee.normalized_email == normalize_email_legacy(account.email)) + if account_attendees.count() == 1: + account_attendee = account_attendees.first() + if account_attendee not in account.attendees: + account_attendee = None + if not account: raise HTTPRedirect('../landing/index') return { 'message': message, 'homepage_account': account, + 'account_attendee': account_attendee, 'attendees_who_owe_money': attendees_who_owe_money, } diff --git a/uber/templates/preregistration/attendee_card.html b/uber/templates/preregistration/attendee_card.html index c77a20bb4..6c5c88719 100644 --- a/uber/templates/preregistration/attendee_card.html +++ b/uber/templates/preregistration/attendee_card.html @@ -59,7 +59,6 @@ {% include 'attendee_card_extra.html' %} - {% if attendee.group %}

@@ -100,10 +99,8 @@
{% elif attendee.is_valid %} - {% set multiple_buttons = c.ART_SHOW_OPEN or c.AFTER_MARKETPLACE_REG_START and c.BEFORE_MARKETPLACE_DEADLINE or attendee.art_show_applications or attendee.marketplace_applications %} - {% if multiple_buttons %}
- {% endif %} + {% include 'preregistration/card_buttons.html' %} Edit Details @@ -129,9 +126,7 @@ {% endif %} {% endif %} - {% if multiple_buttons %}
- {% endif %} {% endif %} diff --git a/uber/templates/preregistration/homepage.html b/uber/templates/preregistration/homepage.html index cfd285e20..925c39619 100644 --- a/uber/templates/preregistration/homepage.html +++ b/uber/templates/preregistration/homepage.html @@ -176,4 +176,59 @@

Cancelled Registrations

}); }); + +{# TODO: move this to a script file #} + {% endblock %} From b02f0c2a09905ce9306ff46dbb625f927db5e2ff Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Thu, 14 Sep 2023 19:34:00 -0400 Subject: [PATCH 07/19] Update attendee login Part 1 of 2 of a fix for attendee login --- uber/site_sections/preregistration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uber/site_sections/preregistration.py b/uber/site_sections/preregistration.py index 3e12908cd..48a00ff2d 100644 --- a/uber/site_sections/preregistration.py +++ b/uber/site_sections/preregistration.py @@ -1366,7 +1366,7 @@ def validate_account_email(self, account_email, **params): def login(self, session, **params): email = params.get('account_email') # This email has already been validated password = params.get('account_password') - account = session.query(AttendeeAccount).filter_by(email=normalize_email(email)).first() + account = session.query(AttendeeAccount).filter(AttendeeAccount.normalized_email=normalize_email_legacy(email)).first() if account and not account.hashed: return {'success': False, 'message': "We had an issue logging you into your account. Please contact an administrator."} elif not account or not bcrypt.hashpw(password, account.hashed) == account.hashed: From 2b8795c33c599c066f32ff97e16426e9bbd5ba92 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Thu, 14 Sep 2023 19:36:29 -0400 Subject: [PATCH 08/19] Add normalized email for DB account queries Part 2 of fixing attendee account login --- uber/models/attendee.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/uber/models/attendee.py b/uber/models/attendee.py index ab2fdede3..abee635b1 100644 --- a/uber/models/attendee.py +++ b/uber/models/attendee.py @@ -2167,6 +2167,14 @@ def strip_email(self): def normalize_email(self): self.email = normalize_email(self.email) + @hybrid_property + def normalized_email(self): + return normalize_email_legacy(self.email) + + @normalized_email.expression + def normalized_email(cls): + return func.replace(func.lower(func.trim(cls.email)), '.', '') + @property def has_only_one_badge(self): return len(self.attendees) == 1 From 1a9ed3207e5030556b7bf483a254721f1bd3ba79 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Thu, 14 Sep 2023 19:41:04 -0400 Subject: [PATCH 09/19] Fix server-breaking error whoops --- uber/site_sections/preregistration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uber/site_sections/preregistration.py b/uber/site_sections/preregistration.py index 48a00ff2d..4cc84587c 100644 --- a/uber/site_sections/preregistration.py +++ b/uber/site_sections/preregistration.py @@ -1366,7 +1366,7 @@ def validate_account_email(self, account_email, **params): def login(self, session, **params): email = params.get('account_email') # This email has already been validated password = params.get('account_password') - account = session.query(AttendeeAccount).filter(AttendeeAccount.normalized_email=normalize_email_legacy(email)).first() + account = session.query(AttendeeAccount).filter(AttendeeAccount.normalized_email == normalize_email_legacy(email)).first() if account and not account.hashed: return {'success': False, 'message': "We had an issue logging you into your account. Please contact an administrator."} elif not account or not bcrypt.hashpw(password, account.hashed) == account.hashed: From 88977dbee1f950ebcb4cd99948b018d9ad6b1668 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Tue, 19 Sep 2023 20:57:58 -0400 Subject: [PATCH 10/19] Add old normalization back into attendee accounts Whatever I did before caused way too many problems, so now we are using the old normalized emails for attendee accounts again. This should hopefully stop creating multiple accounts with different cases. --- uber/models/__init__.py | 20 ++++++++++---------- uber/models/group.py | 8 ++++++++ uber/site_sections/preregistration.py | 21 ++++++++++++--------- uber/site_sections/reg_admin.py | 8 ++++---- uber/utils.py | 6 +++--- 5 files changed, 37 insertions(+), 26 deletions(-) diff --git a/uber/models/__init__.py b/uber/models/__init__.py index 3dc083776..ad60bd668 100644 --- a/uber/models/__init__.py +++ b/uber/models/__init__.py @@ -34,7 +34,7 @@ from uber.errors import HTTPRedirect from uber.decorators import cost_property, department_id_adapter, presave_adjustment, suffix_property from uber.models.types import Choice, DefaultColumn as Column, MultiChoice -from uber.utils import check_csrf, normalize_email, normalize_phone, DeptChecklistConf, report_critical_exception, \ +from uber.utils import check_csrf, normalize_email_legacy, normalize_phone, DeptChecklistConf, report_critical_exception, \ valid_email, valid_password from uber.payments import ReceiptManager @@ -970,7 +970,7 @@ def guess_watchentry_attendees(self, entry): Attendee.watchlist_id == None).all() def get_attendee_account_by_email(self, email): - return self.query(AttendeeAccount).filter_by(email=normalize_email(email)).one() + return self.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(email)).one() def get_admin_account_by_email(self, email): from uber.utils import normalize_email_legacy @@ -985,7 +985,7 @@ def lookup_attendee(self, first_name, last_name, email, zip_code): last_name=last_name, zip_code=zip_code ).filter( - Attendee.normalized_email == normalize_email(email), + Attendee.normalized_email == normalize_email_legacy(email), Attendee.is_valid == True ).limit(10).all() @@ -1061,10 +1061,7 @@ def create_attendee_account(self, email=None, normalized_email=None, password=No from uber.models import Attendee, AttendeeAccount from uber.utils import normalize_email_legacy - if email: - normalized_email = uber.utils.normalize_email(email) - - new_account = AttendeeAccount(email=normalized_email, hashed=bcrypt.hashpw(password, bcrypt.gensalt()) if password else '') + new_account = AttendeeAccount(normalized_email=normalize_email_legacy(email), hashed=bcrypt.hashpw(password, bcrypt.gensalt()) if password else '') self.add(new_account) return new_account @@ -1076,7 +1073,7 @@ def add_attendee_to_account(self, attendee, account): account.attendees.append(attendee) def match_attendee_to_account(self, attendee): - existing_account = self.query(AttendeeAccount).filter_by(email=normalize_email(attendee.email)).first() + existing_account = self.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(attendee.email)).first() if existing_account: self.add_attendee_to_account(attendee, existing_account) @@ -1622,6 +1619,7 @@ def search(self, text, *filters): attendees = self.query(Attendee) \ .outerjoin(Attendee.group) \ .outerjoin(Attendee.promo_code) \ + .outerjoin(Attendee.managers) \ .outerjoin(aliased_pcg, PromoCode.group) \ .options( joinedload(Attendee.group), @@ -1700,9 +1698,11 @@ def check_text_fields(search_text): target, term, search_term, op = self.parse_attr_search_terms(search_text) if target == 'email': - attr_search_filter = Attendee.normalized_email.icontains(normalize_email(search_term)) + attr_search_filter = Attendee.normalized_email.contains(normalize_email_legacy(search_term)) + elif target == 'account_email': + attr_search_filter = AttendeeAccount.normalized_email.contains(normalize_email_legacy(search_term)) elif target == 'group': - attr_search_filter = Group.name.icontains(search_term.strip()) + attr_search_filter = Group.normalized_name.contains(search_term.strip().lower()) elif target == 'has_ribbon': attr_search_filter = Attendee.ribbon == Attendee.ribbon.type.convert_if_labels(search_term.title()) elif target in Attendee.searchable_bools: diff --git a/uber/models/group.py b/uber/models/group.py index 7d1d3195b..6fd2e37e9 100644 --- a/uber/models/group.py +++ b/uber/models/group.py @@ -175,6 +175,14 @@ def floating(self): badges. """ return [a for a in self.attendees if a.is_unassigned and a.paid == c.PAID_BY_GROUP] + + @hybrid_property + def normalized_name(self): + return self.name.strip().lower() + + @normalized_name.expression + def normalized_name(cls): + return func.lower(func.trim(cls.name)) @hybrid_property def is_valid(self): diff --git a/uber/site_sections/preregistration.py b/uber/site_sections/preregistration.py index 4cc84587c..933c33dc0 100644 --- a/uber/site_sections/preregistration.py +++ b/uber/site_sections/preregistration.py @@ -101,12 +101,15 @@ def check_account(session, email, password, confirm_password, skip_if_logged_in= if email and valid_email(email): return valid_email(email) + + super_normalized_old_email = normalize_email_legacy(normalize_email(old_email)) - existing_account = session.query(AttendeeAccount).filter_by(email=normalize_email(email)).first() - if existing_account and (old_email and existing_account.email != normalize_email(old_email) - or logged_in_account and logged_in_account.email != existing_account.email + existing_account = session.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(email)).first() + if existing_account and (old_email and normalize_email_legacy(normalize_email(existing_account.email)) != super_normalized_old_email or not old_email and not logged_in_account): return "There's already an account with that email address." + elif logged_in_account and logged_in_account.normalized_email != existing_account.normalized_email: + return "You cannot reset someone's password while logged in as someone else." if update_password: if password and password != confirm_password: @@ -117,7 +120,7 @@ def check_account(session, email, password, confirm_password, skip_if_logged_in= def set_up_new_account(session, attendee, email=None): email = email or attendee.email token = genpasswd(short=True) - account = session.query(AttendeeAccount).filter_by(email=normalize_email(email)).first() + account = session.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(email)).first() if account: if account.password_reset: session.delete(account.password_reset) @@ -1378,7 +1381,7 @@ def login(self, session, **params): @ajax def create_account(self, session, **params): email = params.get('account_email') # This email has already been validated - account = session.query(AttendeeAccount).filter_by(email=normalize_email(email)).first() + account = session.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(email)).first() if account: return {'success': False, 'message': "You already have an account. Please use the 'forgot your password' link. \ Keep in mind your account may be from a prior year."} @@ -1430,7 +1433,7 @@ def grant_account(self, session, id, message=''): message = "Something went wrong. Please try again." if not attendee.email: message = "This attendee needs an email address to set up a new account." - if session.current_attendee_account() and normalize_email(attendee.email) == session.current_attendee_account().email: + if session.current_attendee_account() and normalize_email_legacy(attendee.email) == session.current_attendee_account().normalized_email: message = "You cannot grant an account to someone with the same email address as your account." if not message: set_up_new_account(session, attendee) @@ -1803,7 +1806,7 @@ def update_account(self, session, id, **params): def reset_password(self, session, **params): if 'account_email' in params: account_email = params['account_email'] - account = session.query(AttendeeAccount).filter_by(email=normalize_email(account_email)).first() + account = session.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(account_email)).first() if 'admin_url' in params: success_url = "../{}message=Password reset email sent.".format(params['admin_url']) else: @@ -1835,7 +1838,7 @@ def new_password_setup(self, session, account_email, token, message='', **params if 'id' in params: account = session.attendee_account(params['id']) else: - account = session.query(AttendeeAccount).filter_by(email=normalize_email(account_email)).first() + account = session.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(account_email)).first() if not account or not account.password_reset: message = 'Invalid link. This link may have already been used or replaced.' elif account.password_reset.is_expired: @@ -1852,7 +1855,7 @@ def new_password_setup(self, session, account_email, token, message='', **params params.get('confirm_password'), False, True, account.email) if not message: - account.email = account_email + account.email = normalize_email(account_email) account.hashed = bcrypt.hashpw(account_password, bcrypt.gensalt()) session.delete(account.password_reset) for attendee in account.attendees: diff --git a/uber/site_sections/reg_admin.py b/uber/site_sections/reg_admin.py index 59f1999f6..7147e7f7b 100644 --- a/uber/site_sections/reg_admin.py +++ b/uber/site_sections/reg_admin.py @@ -65,7 +65,7 @@ def comped_receipt_item(item): def assign_account_by_email(session, attendee, account_email): from uber.site_sections.preregistration import set_up_new_account - account = session.query(AttendeeAccount).filter_by(email=normalize_email(account_email)).first() + account = session.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(account_email)).first() if not account: if c.ONE_MANAGER_PER_BADGE and attendee.managers: # It's too confusing for an admin to move someone to a new account and still see them on their old account @@ -513,7 +513,7 @@ def add_all_accounts(self, session, show_all='', email_contains='', **params): if not show_all: attendees = attendees.filter_by(is_valid=True, is_unassigned=False) if email_contains: - attendees = attendees.filter(Attendee.normalized_email.contains(normalize_email(email_contains))) + attendees = attendees.filter(Attendee.normalized_email.contains(normalize_email_legacy(email_contains))) new_account = 0 assigned = 0 @@ -584,10 +584,10 @@ def attendee_account_form(self, session, id, message='', **params): new_email = params.get('new_account_email', '') if cherrypy.request.method == 'POST' and new_email: - if normalize_email(new_email) == normalize_email(account.email): + if normalize_email(normalize_email_legacy(new_email)) == normalize_email(account.normalized_email): message = "That is already the email address for this account!" else: - existing_account = session.query(AttendeeAccount).filter_by(email=normalize_email(new_email)).first() + existing_account = session.query(AttendeeAccount).filter_by(normalized_email=normalize_email_legacy(new_email)).first() if existing_account: message = "That account already exists. You can instead reassign this account's attendees." else: diff --git a/uber/utils.py b/uber/utils.py index f6eb8dc7b..b895c0f16 100644 --- a/uber/utils.py +++ b/uber/utils.py @@ -1324,7 +1324,7 @@ def attendee_import(import_job): except Exception as ex: import_job.errors += "; {}".format("; ".join(str(ex))) if import_job.errors else "; ".join(str(ex)) - account = session.query(AttendeeAccount).filter(AttendeeAccount.email == normalize_email(account_to_import['email'])).first() + account = session.query(AttendeeAccount).filter(AttendeeAccount.normalized_email == normalize_email_legacy(account_to_import['email'])).first() if not account: del account_to_import['id'] account = AttendeeAccount().apply(account_to_import, restricted=False) @@ -1416,7 +1416,7 @@ def attendee_account_import(import_job): import_job.completed = datetime.now() return - account = session.query(AttendeeAccount).filter(AttendeeAccount.email == normalize_email(account_to_import['email'])).first() + account = session.query(AttendeeAccount).filter(AttendeeAccount.normalized_email == normalize_email_legacy(account_to_import['email'])).first() if not account: del account_to_import['id'] account = AttendeeAccount().apply(account_to_import, restricted=False) @@ -1546,7 +1546,7 @@ def group_import(import_job): except Exception as ex: import_job.errors += "; {}".format("; ".join(str(ex))) if import_job.errors else "; ".join(str(ex)) - account = session.query(AttendeeAccount).filter(AttendeeAccount.email == normalize_email(account_to_import['email'])).first() + account = session.query(AttendeeAccount).filter(AttendeeAccount.normalized_email == normalize_email_legacy(account_to_import['email'])).first() if not account: del account_to_import['id'] account = AttendeeAccount().apply(account_to_import, restricted=False) From b63a253c8e66249c5d128f68389f353e11c747d9 Mon Sep 17 00:00:00 2001 From: Victoria Earl Date: Wed, 20 Sep 2023 19:01:47 -0400 Subject: [PATCH 11/19] Get art show applications working This mostly involves making all the shared pages compatible with bootstrap 3. I had also accidentally removed all the fields for creating a new badge. Also includes unapproved dealers in the attendee search. --- uber/payments.py | 1 + uber/receipt_items.py | 10 +++++----- uber/site_sections/art_show_applications.py | 5 ++++- uber/site_sections/registration.py | 3 ++- uber/templates/art_show_applications/confirmation.html | 5 ++--- uber/templates/art_show_applications/edit.html | 6 ++---- uber/templates/art_show_applications/index.html | 9 ++++++--- uber/templates/base.html | 4 +++- uber/templates/confirm_tabs.html | 2 +- uber/templates/marketplace/edit.html | 1 - uber/templates/marketplace/index.html | 4 ---- uber/templates/preregistration/preregbase.html | 4 +++- uber/templates/preregistration/stripeForm.html | 2 +- 13 files changed, 30 insertions(+), 26 deletions(-) diff --git a/uber/payments.py b/uber/payments.py index 7f2dc3c0b..b32de227c 100644 --- a/uber/payments.py +++ b/uber/payments.py @@ -803,6 +803,7 @@ def create_new_receipt(cls, model, create_model=False, items=None): for calculation in i[model.__class__.__name__].values(): item = calculation(model) if item: + log.debug(item) try: desc, cost, col_name, count = item except ValueError: diff --git a/uber/receipt_items.py b/uber/receipt_items.py index 2d2a16335..02b922662 100644 --- a/uber/receipt_items.py +++ b/uber/receipt_items.py @@ -32,19 +32,19 @@ def overridden_app_cost(app): @cost_calculation.ArtShowApplication def panel_cost(app): - return ("General Panel", c.COST_PER_PANEL * 100, app.panels, None) if app.panels else None + return ("General Panel", c.COST_PER_PANEL * 100, 'panels', app.panels) if app.panels else None @cost_calculation.ArtShowApplication def table_cost(app): - return ("General Table", c.COST_PER_TABLE * 100, app.tables, None) if app.tables else None + return ("General Table", c.COST_PER_TABLE * 100, 'tables', app.tables) if app.tables else None @cost_calculation.ArtShowApplication def mature_panel_cost(app): - return ("Mature Panel", c.COST_PER_PANEL * 100, app.panels_ad, None) if app.panels_ad else None + return ("Mature Panel", c.COST_PER_PANEL * 100, 'panels_ad', app.panels_ad) if app.panels_ad else None @cost_calculation.ArtShowApplication def mature_table_cost(app): - return ("Mature Table", c.COST_PER_TABLE * 100, app.tables_ad, None) if app.tables_ad else None + return ("Mature Table", c.COST_PER_TABLE * 100, 'tables_ad', app.tables_ad) if app.tables_ad else None @cost_calculation.ArtShowApplication def mailing_fee_cost(app): @@ -151,7 +151,7 @@ def badge_cost(group): @cost_calculation.Group def set_cost(group): if not group.auto_recalc: - return ("Custom fee for group {}".format(group.name), group.cost * 100, None) + return ("Custom fee for group {}".format(group.name), group.cost * 100, 'cost') @cost_calculation.Attendee diff --git a/uber/site_sections/art_show_applications.py b/uber/site_sections/art_show_applications.py index dc293f926..54276747b 100644 --- a/uber/site_sections/art_show_applications.py +++ b/uber/site_sections/art_show_applications.py @@ -180,7 +180,10 @@ def confirm_pieces(self, session, id, **params): 'Confirmation email sent') def confirmation(self, session, id): - return {'app': session.art_show_application(id)} + return { + 'app': session.art_show_application(id), + 'logged_in_account': session.current_attendee_account(), + } def mailing_address(self, session, message='', **params): app = session.art_show_application(params) diff --git a/uber/site_sections/registration.py b/uber/site_sections/registration.py index 684f31061..2babb326e 100644 --- a/uber/site_sections/registration.py +++ b/uber/site_sections/registration.py @@ -72,7 +72,8 @@ def index(self, session, message='', page='0', search_text='', uploaded_id='', o if c.DEV_BOX and not int(page): page = 1 - filter = Attendee.badge_status.in_([c.NEW_STATUS, c.COMPLETED_STATUS, c.WATCHED_STATUS]) if not invalid else None + filter = Attendee.badge_status.in_([c.NEW_STATUS, c.COMPLETED_STATUS, c.WATCHED_STATUS, c.UNAPPROVED_DEALER_STATUS] + ) if not invalid else None attendees = session.query(Attendee) if invalid else session.query(Attendee).filter(filter) total_count = attendees.count() count = 0 diff --git a/uber/templates/art_show_applications/confirmation.html b/uber/templates/art_show_applications/confirmation.html index 3caf20c37..e380a0ae2 100644 --- a/uber/templates/art_show_applications/confirmation.html +++ b/uber/templates/art_show_applications/confirmation.html @@ -1,9 +1,8 @@ {% extends "./preregistration/preregbase.html" %} {% block title %}Art Show Application Received{% endblock %} -{% block backlink %}{% endblock %} {% block content %} -
-

{% if c.AFTER_ART_SHOW_WAITLIST %}You've been added to our waitlist! +
+

{% if c.AFTER_ART_SHOW_WAITLIST %}You've been added to our waitlist! {% else %}Thanks for applying for the Art Show!{% endif %}

We've received your application for the {{ c.EVENT_NAME }} Art Show. You applied for {{ app.panels }} diff --git a/uber/templates/art_show_applications/edit.html b/uber/templates/art_show_applications/edit.html index 718648208..1b34d6e95 100644 --- a/uber/templates/art_show_applications/edit.html +++ b/uber/templates/art_show_applications/edit.html @@ -1,12 +1,10 @@ {% extends "preregistration/preregbase.html" %} {% block title %}Art Show Application{% endblock %} -{% block backlink %}{% endblock %} {% block content %} {% include "region_opts.html" %} -{% include "prereg_masthead.html" %} {% set attendee = app.attendee %} -
-
+
+
Art Show Application Information
diff --git a/uber/templates/art_show_applications/index.html b/uber/templates/art_show_applications/index.html index 96b6371a0..d8277ce12 100644 --- a/uber/templates/art_show_applications/index.html +++ b/uber/templates/art_show_applications/index.html @@ -1,6 +1,5 @@ {% extends "preregistration/preregbase.html" %} {% block title %}Art Show Application{% endblock %} -{% block backlink %}{% endblock %} {% block content %} -
+
-

{{ c.EVENT_NAME }} Art Show Application

+

{{ c.EVENT_NAME }} Art Show Application

{% if c.AFTER_ART_SHOW_DEADLINE and not c.HAS_ART_SHOW_ACCESS %} Unfortunately, the deadline for art show applications has passed and we are no longer accepting applications. {% else %} @@ -66,6 +65,10 @@

Your Information

The confirmation number you received when you registered.

+
+ {% include 'art_show_applications/new_attendee_fields.html' %} +
+

Art Information

{% include 'art_show_applications/art_show_form.html' %} diff --git a/uber/templates/base.html b/uber/templates/base.html index 727048eb6..6007c4985 100644 --- a/uber/templates/base.html +++ b/uber/templates/base.html @@ -519,7 +519,9 @@ {% endif %} {% endblock %} {% block header %}{% endblock %} - {% block alert %}{% endblock %} + {% block alert %} + + {% endblock %} {% block masthead %}{% endblock %} {% if title_text %}

{{ title_text }}

{% endif %} {% block content %}{% endblock %} diff --git a/uber/templates/confirm_tabs.html b/uber/templates/confirm_tabs.html index 1106423de..4c44523f8 100644 --- a/uber/templates/confirm_tabs.html +++ b/uber/templates/confirm_tabs.html @@ -45,7 +45,7 @@ {% endfor %} {% for art_show_app in attendee.art_show_applications %} -