def box_terminator_nag(member_number=None, box_label_id=None, nag_type=None): try: box = db_session.query(Box).filter( Box.box_label_id == box_label_id, Member.member_number == member_number).one() except NoResultFound: raise NotFound("Bloop, lådan finns i Lettland") try: template = { "nag-warning": MessageTemplate.BOX_WARNING, "nag-last-warning": MessageTemplate.BOX_FINAL_WARNING, "nag-terminated": MessageTemplate.BOX_TERMINATED, }[nag_type] except KeyError: raise BadRequest(f"Bad nag type {nag_type}") today = date.today() end_date = get_labacess_end_date(box) terminate_date = get_expire_date_from_labaccess_end_date(end_date) send_message( template, box.member, labaccess_end_date=date_to_str(end_date), to_termination_days=(terminate_date - today).days, days_after_expiration=(today - end_date).days, ) box.last_nag_at = datetime.utcnow()
def send_membership_updated_email(member_id, extended_days, end_date): member = db_session.query(Member).get(member_id) send_message(MessageTemplate.ADD_MEMBERSHIP_TIME, member, extended_days=extended_days, end_date=date_to_str(end_date))
def send_key_updated_email(member_id, extended_days, end_date): member = db_session.query(Member).get(member_id) send_message(MessageTemplate.ADD_LABACCESS_TIME, member, extended_days=extended_days, end_date=date_to_str(end_date))
def send_receipt_email(transaction): contents = transaction.contents products = [content.product for content in contents] send_message( MessageTemplate.RECEIPT, transaction.member, cart=list(zip(products, contents)), transaction=transaction, currency="kr", )
def request_password_reset(user_identification): member = get_member_by_user_identification(user_identification) token = generate_token() db_session.add(PasswordResetToken(member_id=member.member_id, token=token)) db_session.flush() send_message( MessageTemplate.PASSWORD_RESET, member, url=config.get_admin_url( f"/password-reset?reset_token={quote_plus(token)}"), )
def membership_reminder(): now = datetime.utcnow().date() members, memberships = get_members_and_membership() members = list(members) end_date_reminder_target = now + timedelta( days=MEMBERSHIP_REMINDER_DAYS_BEFORE) for member, membership in zip(members, memberships): if membership.membership_end is None: # Not a member continue if membership.membership_end < now and not membership.effective_labaccess_active: # Membership already expired # If the member has labaccess active then the member has likely forgot to renew the yearly membership. # Having a yearly membership is a requirement for being allowed to purchase lab membership. continue if membership.membership_end > end_date_reminder_target: # Membership is valid for a long time continue # Don't send a reminder if we sent a reminder the last 28 days. if already_sent_message(MessageTemplate.MEMBERSHIP_REMINDER, member, MEMBERSHIP_REMINDER_GRACE_PERIOD): continue already_purchased = \ pending_action_value_sum(member_id=member.member_id, action_type=ProductAction.ADD_MEMBERSHIP_DAYS) > 0 if already_purchased: # Member has already purchased extra membership continue url = get_login_link(member, "membership reminder", "/shop") send_message( template=MessageTemplate.MEMBERSHIP_REMINDER, member=member, url=url, db_session=db_session, render_template=render_template, expiration_date=membership.membership_end, ) logger.info( f'sending yearly membership reminder to member with id {member.member_id}. Expires ' + str(membership.membership_end))
def labaccess_reminder(render_template): now = datetime.utcnow() end_date_reminder_target = now.date() + timedelta( days=LABACCESS_REMINDER_DAYS_BEFORE) query = db_session.query(Member) query = query.join(Span) query = query.filter( Member.deleted_at.is_(None), Span.type == Span.LABACCESS, Span.deleted_at.is_(None), Span.enddate == end_date_reminder_target, ) for member in query: # We have a candidate, now check if we should send a reminder. # First double check the end date so we don't send reminder if there is another span further in the future. end_date = db_session.query(func.max(Span.enddate)).filter( Span.member == member, Span.type == Span.LABACCESS, Span.deleted_at.is_(None)).scalar() if end_date != end_date_reminder_target: continue # Don't send a reminder if we sent a reminder the last 28 days. if already_sent_message(MessageTemplate.LABACCESS_REMINDER, member, LABACCESS_REMINDER_GRACE_PERIOD): continue already_purchased = \ pending_action_value_sum(member_id=member.member_id, action_type=ProductAction.ADD_LABACCESS_DAYS) > 0 if already_purchased: continue logger.info( f'sending labaccess reminder to member with id {member.member_id}') send_message( template=MessageTemplate.LABACCESS_REMINDER, member=member, db_session=db_session, render_template=render_template, expiration_date=end_date, )
def send_access_token_email(redirect, user_identification, ip, browser): member = get_member_by_user_identification(user_identification) access_token = create_access_token(ip, browser, member.member_id)['access_token'] url = config.get_public_url(f"/member/login/{access_token}?redirect=" + quote_plus(redirect)) logger.info(f"sending login link {url!r} to member_id {member.member_id}") send_message( MessageTemplate.LOGIN_LINK, member, url=url, now=format_datetime(datetime.now()), ) return {"status": "sent"}
def quiz_reminders(): # Assume quiz 1 is the get started quiz quiz_id = 1 quiz_members = quiz_member_answer_stats(quiz_id) now = datetime.utcnow() members, memberships = get_members_and_membership() id_to_member = { member.member_id: (member, membership) for member, membership in zip(members, memberships) } # Get all pending shop actions and check which members have pending purchases of lab access actions = pending_actions() members_with_pending_labaccess = set() for action in actions: if action["action"]["action"] == "add_labaccess_days" and action[ "action"]["value"] > 0: members_with_pending_labaccess.add(action["member_id"]) recently_sent_messages_by_member = set( x[0] for x in db_session.query(Message.member_id).filter( ((Message.template == MessageTemplate.QUIZ_FIRST_NEWMEMBER.value) & (now - timedelta(days=QUIZ_DAYS_FROM_FIRST_EMAIL_TO_REMINDER) < Message.created_at)) | ((Message.template == MessageTemplate.QUIZ_FIRST_OLDMEMBER.value) & (now - timedelta(days=QUIZ_DAYS_FROM_FIRST_EMAIL_TO_REMINDER) < Message.created_at)) | ((Message.template == MessageTemplate.QUIZ_REMINDER.value) & (now - timedelta(days=QUIZ_DAYS_BETWEEN_REMINDERS) < Message.created_at))).group_by(Message.member_id).all()) sent_first_message_by_member = set( x[0] for x in db_session.query(Message.member_id).filter( (Message.template == MessageTemplate.QUIZ_FIRST_NEWMEMBER.value) | (Message.template == MessageTemplate.QUIZ_FIRST_OLDMEMBER.value) ).group_by(Message.member_id).all()) for quiz_member in quiz_members: if quiz_member.remaining_questions > 0: member, membership = id_to_member.get(quiz_member.member_id) # Shouldn't really happen, but best check (db race conditions might cause it I guess) if member is None: continue # We need an email if member.email is None or len(member.email) == 0: continue # Check if the member has any pending purchase of lab access (important to ensure new members get the quiz before the key handout if possible) pending_labaccess = member.member_id in members_with_pending_labaccess # Only send messages to members whose labaccess is active or pending if not (membership.effective_labaccess_active or pending_labaccess): continue # Check if a message has already been sent within given time periods if member.member_id in recently_sent_messages_by_member: continue firstmessage_sent = member.member_id in sent_first_message_by_member template = MessageTemplate.QUIZ_REMINDER if not firstmessage_sent: # An old member has been member for more than 30 days. # The oldmember template was used when the quiz was first introduced to give # existing members a customized message. # It also applies to those who haven't been members for a long time and become members again. is_oldmember = member.created_at < now - timedelta(days=14) if is_oldmember: template = MessageTemplate.QUIZ_FIRST_OLDMEMBER # Ignore old members. We don't send the quiz to them right now continue else: template = MessageTemplate.QUIZ_FIRST_NEWMEMBER url = get_login_link(member, "automatic quiz reminder", "/member/quiz/1") send_message( template=template, member=member, db_session=db_session, render_template=render_template, remaining_questions=quiz_member.remaining_questions, correctly_answered_questions=quiz_member. correctly_answered_questions, url=url, )
def send_new_member_email(member): send_message( MessageTemplate.NEW_MEMBER, member, )