示例#1
0
    def test_email(self,
                   session,
                   subject=None,
                   body=None,
                   from_address=None,
                   to_address=None,
                   **params):
        """
        Testing only: send a test email as a system user
        """

        output_msg = ""

        if subject and body and from_address and to_address:
            send_email(from_address, to_address, subject, body)
            output_msg = "RAMS has attempted to send your email."

        right_now = str(datetime.now())

        return {
            'from_address':
            from_address or c.STAFF_EMAIL,
            'to_address': (to_address
                           or ("*****@*****.**" if c.DEV_BOX
                               else AdminAccount.admin_email()) or ""),
            'subject':
            c.EVENT_NAME_AND_YEAR + " test email " + right_now,
            'body':
            body or
            "ignore this email, <b>it is a test</b> of the <u>RAMS email system</u> "
            + right_now,
            'message':
            output_msg,
        }
示例#2
0
    def update(self, session, password='', message='', **params):
        account = session.admin_account(params, checkgroups=['access'])
        if account.is_new:
            if c.AT_OR_POST_CON and not password:
                message = 'You must enter a password'
            else:
                password = password if c.AT_OR_POST_CON else genpasswd()
                account.hashed = bcrypt.hashpw(password, bcrypt.gensalt())

        message = message or check(account)
        if not message:
            message = 'Account settings uploaded'
            account.attendee = session.attendee(
                account.attendee_id
            )  # dumb temporary hack, will fix later with tests
            session.add(account)
            if account.is_new and not c.AT_OR_POST_CON:
                body = render(
                    'emails/accounts/new_account.txt', {
                        'account': account,
                        'password': password,
                        'creator': AdminAccount.admin_name()
                    })
                send_email(c.ADMIN_EMAIL,
                           session.attendee(account.attendee_id).email,
                           'New ' + c.EVENT_NAME + ' Ubersystem Account', body)
        else:
            session.rollback()

        raise HTTPRedirect('index?message={}', message)
示例#3
0
    def really_send(self, model_instance, raise_errors=False):
        """
        Actually send an email to a particular model instance (i.e. a particular attendee).

        Doesn't perform any kind of checks at all if we should be sending this, just immediately sends the email
        no matter what.

        NOTE: use send_if_should() instead of calling this method unless you 100% know what you're doing.
        NOTE: send_email() fails if c.SEND_EMAILS is False
        """
        try:
            subject = self.computed_subject(model_instance)
            format = 'text' if self.template.endswith('.txt') else 'html'
            send_email(self.sender,
                       model_instance.email,
                       subject,
                       self.render(model_instance),
                       format,
                       model=model_instance,
                       cc=self.cc,
                       ident=self.ident)
        except Exception:
            log.error('error sending {!r} email to {}',
                      self.subject,
                      model_instance.email,
                      exc_info=True)
            if raise_errors:
                raise
示例#4
0
    def pay_for_extra_members(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [group] = charge.groups
        badges_to_add = charge.dollar_amount // c.GROUP_PRICE
        if charge.dollar_amount % c.GROUP_PRICE:
            message = 'Our preregistration price has gone up since you tried to add the badges; please try again'
        else:
            message = charge.charge_cc(session, stripeToken)

        if message:
            raise HTTPRedirect('group_members?id={}&message={}', group.id,
                               message)
        else:
            session.assign_badges(group, group.badges + badges_to_add)
            group.amount_paid += charge.dollar_amount
            session.merge(group)
            if group.is_dealer:
                send_email(c.MARKETPLACE_EMAIL,
                           c.MARKETPLACE_EMAIL,
                           'Dealer Paid for Extra Members',
                           render('emails/dealers/payment_notification.txt',
                                  {'group': group}),
                           model=group)
            raise HTTPRedirect(
                'group_members?id={}&message={}', group.id,
                'You payment has been accepted and the badges have been added to your group'
            )
示例#5
0
    def process_group_payment(self, session, payment_id, stripeToken):
        charge = Charge.get(payment_id)
        [group] = charge.groups
        message = charge.charge_cc(session, stripeToken)
        if message:
            raise HTTPRedirect('group_members?id={}&message={}', group.id,
                               message)
        else:
            group.amount_paid += charge.dollar_amount

            session.merge(group)
            if group.is_dealer:
                try:
                    send_email(c.MARKETPLACE_EMAIL,
                               c.MARKETPLACE_EMAIL,
                               'Dealer Payment Completed',
                               render(
                                   'emails/dealers/payment_notification.txt',
                                   {'group': group}),
                               model=group)
                except Exception:
                    log.error(
                        'unable to send dealer payment confirmation email',
                        exc_info=True)
            raise HTTPRedirect('group_members?id={}&message={}', group.id,
                               'Your payment has been accepted!')
示例#6
0
    def reset(self, session, message='', email=None):
        if email is not None:
            try:
                account = session.get_account_by_email(email)
            except NoResultFound:
                message = 'No account exists for email address {!r}'.format(
                    email)
            else:
                password = genpasswd()
                if account.password_reset:
                    session.delete(account.password_reset)
                    session.commit()
                session.add(
                    PasswordReset(admin_account=account,
                                  hashed=bcrypt.hashpw(password,
                                                       bcrypt.gensalt())))
                body = render('emails/accounts/password_reset.txt', {
                    'name': account.attendee.full_name,
                    'password': password
                })

                send_email(c.ADMIN_EMAIL, account.attendee.email,
                           c.EVENT_NAME + ' Admin Password Reset', body)
                raise HTTPRedirect(
                    'login?message={}',
                    'Your new password has been emailed to you')

        return {'email': email, 'message': message}
示例#7
0
    def transfer_badge(self, session, message='', **params):
        old = session.attendee(params['id'])

        assert old.is_transferable, 'This badge is not transferrable.'
        session.expunge(old)
        attendee = session.attendee(params, restricted=True)

        if 'first_name' in params:
            message = check(attendee, prereg=True)
            if (old.first_name == attendee.first_name and old.last_name == attendee.last_name) \
                    or (old.legal_name and old.legal_name == attendee.legal_name):
                message = 'You cannot transfer your badge to yourself.'
            elif not message and (not params['first_name']
                                  and not params['last_name']):
                message = check(attendee, prereg=True)
            if not message and (not params['first_name']
                                and not params['last_name']):
                message = 'First and Last names are required.'

            if not message:
                subject = c.EVENT_NAME + ' Registration Transferred'
                body = render('emails/reg_workflow/badge_transfer.txt', {
                    'new': attendee,
                    'old': old
                })

                try:
                    send_email(c.REGDESK_EMAIL,
                               [old.email, attendee.email, c.REGDESK_EMAIL],
                               subject,
                               body,
                               model=attendee)
                except Exception:
                    log.error('unable to send badge change email',
                              exc_info=True)

                if attendee.amount_unpaid:
                    raise HTTPRedirect('attendee_donation_form?id={}',
                                       attendee.id)
                else:
                    raise HTTPRedirect(
                        'badge_updated?id={}&message={}', attendee.id,
                        'Your registration has been transferred')
        else:
            for attr in c.UNTRANSFERABLE_ATTRS:
                setattr(attendee, attr, getattr(Attendee(), attr))

        return {
            'old': old,
            'attendee': attendee,
            'message': message,
            'affiliates': session.affiliates()
        }
示例#8
0
def send_pending_email_report(pending_email_categories, sender):
    rendering_data = {
        'pending_email_categories': pending_email_categories,
        'primary_sender': sender,
    }
    subject = c.EVENT_NAME + ' Pending Emails Report for ' + localized_now(
    ).strftime('%Y-%m-%d')
    body = render('emails/daily_checks/pending_emails.html', rendering_data)
    send_email(c.STAFF_EMAIL,
               sender,
               subject,
               body,
               format='html',
               model='n/a')
示例#9
0
 def reset_problems(self, session, game_id):
     game = session.indie_game(game_id)
     for review in game.reviews:
         if review.has_video_issues:
             body = render('emails/video_fixed.txt', {'review': review})
             send_email(c.MIVS_EMAIL, review.judge.email,
                        'MIVS: Video Problems Resolved for {}'.format(review.game.title), body)
             review.video_status = c.PENDING
         if review.has_game_issues:
             body = render('emails/game_fixed.txt', {'review': review})
             send_email(c.MIVS_EMAIL, review.judge.email,
                        'MIVS: Game Problems Resolved for {}'.format(review.game.title), body)
             review.game_status = c.PENDING
     raise HTTPRedirect(
         'index?message={}{}', review.game.title, ' has been marked as having its judging issues fixed')
示例#10
0
    def create_judge(self, session, message='', first_name='', last_name='', email='', **params):
        judge = session.indie_judge(params, checkgroups=['genres', 'platforms'])
        if cherrypy.request.method == 'POST':
            message = check(judge)
            if not message and not first_name or not last_name or not email:
                message = 'First name, last name, and email address are all required to add a judge'

            if not message:
                # only match on last name and email, to prevent nickname issues; this could cause
                # problems if we had two judges with the same last name AND the same email address
                attendee = session.query(Attendee).filter_by(last_name=last_name, email=email).first()
                if attendee and attendee.admin_account:
                    if attendee.admin_account.judge:
                        raise HTTPRedirect(
                            'index?message={}{}', attendee.full_name, ' is already registered as a judge')
                    else:
                        attendee.admin_account.judge = judge
                        attendee.admin_account.access = ','.join(map(str, set(
                            attendee.admin_account.access_ints + [c.INDIE_JUDGE])))

                        raise HTTPRedirect('index?message={}{}', attendee.full_name, ' has been granted judge access')

                if not attendee:
                    attendee = Attendee(first_name=first_name, last_name=last_name, email=email,
                                        placeholder=True, badge_type=c.ATTENDEE_BADGE, paid=c.NEED_NOT_PAY)
                    session.add(attendee)

                password = genpasswd()
                attendee.admin_account = AdminAccount(
                    judge=judge,
                    access=str(c.INDIE_JUDGE),
                    hashed=bcrypt.hashpw(password, bcrypt.gensalt())
                )
                email_body = render('emails/accounts/new_account.txt', {
                    'password': password,
                    'account': attendee.admin_account
                })
                send_email(c.MIVS_EMAIL, attendee.email, 'New ' + c.EVENT_NAME + ' Ubersystem Account', email_body)
                raise HTTPRedirect(
                    'index?message={}{}', attendee.full_name, ' has been given an admin account as an Indie Judge')

        return {
            'message': message,
            'judge': judge,
            'first_name': first_name,
            'last_name': last_name,
            'email': email
        }
示例#11
0
def check_unassigned():
    if c.PRE_CON and (c.DEV_BOX or c.SEND_EMAILS):
        with Session() as session:
            unassigned = session.query(Attendee).filter(
                Attendee.staffing == True,
                not_(Attendee.dept_memberships.any())).order_by(
                    Attendee.full_name).all()  # noqa: E712
            subject = c.EVENT_NAME + ' Unassigned Volunteer Report for ' + localized_now(
            ).strftime('%Y-%m-%d')
            if unassigned and session.no_email(subject):
                body = render('emails/daily_checks/unassigned.html',
                              {'unassigned': unassigned})
                send_email(c.STAFF_EMAIL,
                           c.STAFF_EMAIL,
                           subject,
                           body,
                           format='html',
                           model='n/a')
示例#12
0
 def unapprove(self, session, id, action, email, convert=None, message=''):
     assert action in ['waitlisted', 'declined']
     group = session.group(id)
     subject = 'Your {EVENT_NAME} Dealer registration has been ' + action
     if group.email:
         send_email(c.MARKETPLACE_EMAIL,
                    group.email,
                    subject,
                    email,
                    bcc=c.MARKETPLACE_EMAIL,
                    model=group)
     if action == 'waitlisted':
         group.status = c.WAITLISTED
     else:
         message = _decline_and_convert_dealer_group(
             session, group, not convert)
     session.commit()
     return {'success': True, 'message': message}
示例#13
0
    def video_review(self, session, message='', **params):
        review = session.indie_game_review(params)
        if cherrypy.request.method == 'POST':
            if review.video_status == c.PENDING:
                message = 'You must select a Video Status to tell us whether or not you were able to view the video'
            elif review.video_status == c.MIVS_VIDEO_REVIEWED and review.video_score == c.PENDING:
                message = 'You must indicate whether or not you believe the game should pass to round 2'
            else:
                if review.video_status in c.MIVS_PROBLEM_STATUSES\
                        and review.video_status != review.orig_value_of('video_status'):
                    body = render('emails/admin_video_broken.txt', {'review': review})
                    send_email(c.MIVS_EMAIL, c.MIVS_EMAIL, 'MIVS Video Submission Marked as Broken', body)
                raise HTTPRedirect('index?message={}{}', review.game.title, ' video review has been uploaded')

        return {
            'message': message,
            'review': review
        }
示例#14
0
def report_critical_exception(msg, subject="Critical Error"):
    """
    Log an exception with as much context as possible and send an email.

    Call this function when you really want to make some noise about
    something going really badly wrong.

    Args:
        msg (str): Message to prepend to output.
        subject (str): Subject for alert emails. Defaults
            to "Critical Error".

    """
    from uber.notifications import send_email

    # Log with lots of cherrypy context in here
    uber.server.log_exception_with_verbose_context(msg)

    # Also attempt to email the admins
    send_email(c.ADMIN_EMAIL, [c.ADMIN_EMAIL], subject, msg + '\n{}'.format(traceback.format_exc()))
示例#15
0
def detect_duplicates():
    '''
    Every day, this function looks through registered attendees for attendees with the same names and email addresses.
    It first deletes any unpaid duplicates, then sets paid duplicates from "Completed" to "New" and sends an email to
    the registration email address. This allows us to see new duplicate attendees without repetitive emails.
    '''
    if c.PRE_CON and (c.DEV_BOX or c.SEND_EMAILS):
        subject = c.EVENT_NAME + ' Duplicates Report for ' + localized_now(
        ).strftime('%Y-%m-%d')
        with Session() as session:
            if session.no_email(subject):
                grouped = defaultdict(list)
                for a in session.query(Attendee).filter(Attendee.first_name != '')\
                        .filter(Attendee.badge_status == c.COMPLETED_STATUS).options(joinedload(Attendee.group))\
                        .order_by(Attendee.registered):
                    if not a.group or a.group.status not in [
                            c.WAITLISTED, c.UNAPPROVED
                    ]:
                        grouped[a.full_name, a.email.lower()].append(a)

                dupes = {k: v for k, v in grouped.items() if len(v) > 1}

                for who, attendees in dupes.items():
                    paid = [a for a in attendees if a.paid == c.HAS_PAID]
                    unpaid = [a for a in attendees if a.paid == c.NOT_PAID]
                    if len(paid) == 1 and len(attendees) == 1 + len(unpaid):
                        for a in unpaid:
                            session.delete(a)
                        del dupes[who]
                    for a in paid:
                        a.badge_status = c.NEW_STATUS

                if dupes:
                    body = render('emails/daily_checks/duplicates.html',
                                  {'dupes': sorted(dupes.items())})
                    send_email(c.ADMIN_EMAIL,
                               c.REGDESK_EMAIL,
                               subject,
                               body,
                               format='html',
                               model='n/a')
示例#16
0
def check_placeholders():
    if c.PRE_CON and c.CHECK_PLACEHOLDERS and (c.DEV_BOX or c.SEND_EMAILS):
        emails = [['Staff', c.STAFF_EMAIL, Attendee.staffing == True],
                  [
                      'Panelist', c.PANELS_EMAIL,
                      or_(Attendee.badge_type == c.GUEST_BADGE,
                          Attendee.ribbon.contains(c.PANELIST_RIBBON))
                  ],
                  [
                      'Attendee', c.REGDESK_EMAIL,
                      not_(
                          or_(Attendee.staffing == True,
                              Attendee.badge_type == c.GUEST_BADGE,
                              Attendee.ribbon.contains(c.PANELIST_RIBBON)))
                  ]]  # noqa: E712

        with Session() as session:
            for badge_type, dest, per_email_filter in emails:
                weeks_until = (c.EPOCH - localized_now()).days // 7
                subject = '{} {} Placeholder Badge Report ({} weeks to go)'.format(
                    c.EVENT_NAME, badge_type, weeks_until)

                if session.no_email(subject):
                    placeholders = (session.query(Attendee).filter(
                        Attendee.placeholder == True, Attendee.registered <
                        localized_now() - timedelta(days=3),
                        Attendee.badge_status.in_(
                            [c.NEW_STATUS,
                             c.COMPLETED_STATUS]), per_email_filter).options(
                                 joinedload(Attendee.group)).order_by(
                                     Attendee.registered,
                                     Attendee.full_name).all())  # noqa: E712
                    if placeholders:
                        body = render('emails/daily_checks/placeholders.html',
                                      {'placeholders': placeholders})
                        send_email(c.ADMIN_EMAIL,
                                   dest,
                                   subject,
                                   body,
                                   format='html',
                                   model='n/a')
示例#17
0
    def group_members(self, session, id, message='', **params):
        group = session.group(id)
        charge = Charge(group)
        if group.status != c.APPROVED and 'name' in params:
            # Both the Attendee class and Group class have identically named
            # address fields. In order to distinguish the two sets of address
            # fields in the params, the Group fields are prefixed with "group_"
            # when the form is submitted. To prevent instantiating the Group object
            # with the Attendee's address fields, we must clone the params and
            # rename all the "group_" fields.
            group_params = dict(params)
            for field_name in [
                    'country', 'region', 'zip_code', 'address1', 'address2',
                    'city'
            ]:
                group_params[field_name] = params.get(
                    'group_{}'.format(field_name), '')

            group.apply(group_params, restricted=True)
            message = check(group, prereg=True)
            if message:
                session.rollback()
            else:
                session.commit()
                if group.is_dealer:
                    send_email(
                        c.MARKETPLACE_EMAIL,
                        c.MARKETPLACE_EMAIL,
                        'Dealer Application Changed',
                        render('emails/dealers/appchange_notification.html',
                               {'group': group}),
                        'html',
                        model=group)

                message = 'Thank you! Your application has been updated.'

            raise HTTPRedirect('group_members?id={}&message={}', group.id,
                               message)
        return {'group': group, 'charge': charge, 'message': message}
示例#18
0
    def game_review(self, session, message='', **params):
        review = session.indie_game_review(params, bools=['game_content_bad'])
        if cherrypy.request.method == 'POST':
            if review.game_status == c.PENDING:
                message = 'You must select a Game Status to tell us ' \
                    'whether or not you were able to download and run the game'
            elif review.game_status == c.PLAYABLE and not review.game_score:
                message = 'You must indicate whether or not you believe the game should be accepted'
            elif review.game_status != c.PLAYABLE and review.game_score:
                message = 'If the game is not playable, please leave the score field blank'
            else:
                if review.game_status in c.MIVS_PROBLEM_STATUSES\
                        and review.game_status != review.orig_value_of('game_status'):
                    body = render('emails/admin_game_broken.txt', {'review': review})
                    send_email(c.MIVS_EMAIL, c.MIVS_EMAIL, 'MIVS Game Submission Marked as Broken', body)
                raise HTTPRedirect('index?message={}{}', review.game.title, ' game review has been uploaded')

        return {
            'review': review,
            'message': message,
            'game_code': session.code_for(review.game)
        }
示例#19
0
    def unset_group_member(self, session, id):
        attendee = session.attendee(id)
        try:
            send_email(c.REGDESK_EMAIL,
                       attendee.email,
                       '{EVENT_NAME} group registration dropped',
                       render('emails/reg_workflow/group_member_dropped.txt',
                              {'attendee': attendee}),
                       model=attendee)
        except Exception:
            log.error('unable to send group unset email', exc_info=True)

        session.assign_badges(attendee.group,
                              attendee.group.badges + 1,
                              new_badge_type=attendee.badge_type,
                              new_ribbon_type=attendee.ribbon,
                              registered=attendee.registered,
                              paid=attendee.paid)

        session.delete_from_group(attendee, attendee.group)
        raise HTTPRedirect(
            'group_members?id={}&message={}', attendee.group_id,
            'Attendee unset; you may now assign their badge to someone else')
示例#20
0
    def add_bulk_admin_accounts(self, session, message='', **params):
        ids = params.get('ids')
        if isinstance(ids, str):
            ids = str(ids).split(",")
        success_count = 0
        for id in ids:
            try:
                uuid.UUID(id)
            except ValueError:
                pass
            else:
                match = session.query(Attendee).filter(
                    Attendee.id == id).first()
                if match:
                    account = session.admin_account(params,
                                                    checkgroups=['access'])
                    if account.is_new:
                        password = genpasswd()
                        account.hashed = bcrypt.hashpw(password,
                                                       bcrypt.gensalt())
                        account.attendee = match
                        session.add(account)
                        body = render('emails/accounts/new_account.txt', {
                            'account': account,
                            'password': password
                        })
                        send_email(c.ADMIN_EMAIL, match.email,
                                   'New ' + c.EVENT_NAME + ' RAMS Account',
                                   body)

                        success_count += 1
        if success_count == 0:
            message = 'No new accounts were created.'
        else:
            session.commit()
            message = '%d new accounts have been created, and emailed their passwords.' % success_count
        return message
示例#21
0
    def check_if_preregistered(self, session, message='', **params):
        if 'email' in params:
            attendee = session.query(Attendee).filter(
                func.lower(Attendee.email) == func.lower(
                    params['email'])).first()
            message = 'Thank you! You will receive a confirmation email if ' \
                'you are registered for {}.'.format(c.EVENT_NAME_AND_YEAR)

            subject = c.EVENT_NAME_AND_YEAR + ' Registration Confirmation'

            if attendee:
                last_email = (session.query(Email).filter_by(
                    dest=attendee.email,
                    subject=subject).order_by(Email.when.desc()).first())
                if not last_email or last_email.when < (localized_now() -
                                                        timedelta(days=7)):
                    send_email(c.REGDESK_EMAIL,
                               attendee.email,
                               subject,
                               render('emails/reg_workflow/prereg_check.txt',
                                      {'attendee': attendee}),
                               model=attendee)

        return {'message': message}
示例#22
0
    def resend_email(self, session, id):
        """
        Resend a particular email to the model's current email address.

        This is useful for if someone had an invalid email address and did not receive an automated email.
        """

        email = session.email(id)
        if email:
            # If this was an automated email, we can send out an updated template with the correct 'from' address
            if email.ident in AutomatedEmail.instances:
                email_category = AutomatedEmail.instances[email.ident]
                sender = email_category.sender
                body = email_category.render(email.fk)
            else:
                sender = c.ADMIN_EMAIL
                body = email.html

            try:
                send_email(sender,
                           email.rcpt_email,
                           email.subject,
                           body,
                           model=email.fk,
                           ident=email.ident)
            except Exception:
                return {
                    'success': False,
                    'message': 'Email not sent: unknown error.'
                }
            else:
                return {'success': True, 'message': 'Email resent.'}
        return {
            'success': False,
            'message': 'Email not sent: no email found with that ID.'
        }
示例#23
0
    def form(self, session, message='', edit_id=None, **params):
        """
        Our production NGINX config caches the page at /preregistration/form.
        Since it's cached, we CAN'T return a session cookie with the page. We
        must POST to a different URL in order to bypass the cache and get a
        valid session cookie. Thus, this page is also exposed as "post_form".
        """
        params['id'] = 'None'  # security!

        # Both the Attendee class and Group class have identically named
        # address fields. In order to distinguish the two sets of address
        # fields in the params, the Group fields are prefixed with "group_"
        # when the form is submitted. To prevent instantiating the Group object
        # with the Attendee's address fields, we must clone the params and
        # rename all the "group_" fields.
        group_params = dict(params)
        for field_name in [
                'country', 'region', 'zip_code', 'address1', 'address2', 'city'
        ]:
            group_params[field_name] = params.get(
                'group_{}'.format(field_name), '')
            if params.get('copy_address'):
                params[field_name] = group_params[field_name]

        if edit_id is not None:
            attendee, group = self._get_unsaved(
                edit_id,
                if_not_found=HTTPRedirect(
                    'form?message={}',
                    'That preregistration has already been finalized'))

            attendee.apply(params, restricted=True)
            group.apply(group_params, restricted=True)
            params.setdefault('badges', group.badges)
        else:
            attendee = session.attendee(params,
                                        ignore_csrf=True,
                                        restricted=True)
            group = session.group(group_params,
                                  ignore_csrf=True,
                                  restricted=True)

        message = ''
        if c.BADGE_PROMO_CODES_ENABLED and 'promo_code' in params:
            message = session.add_promo_code_to_attendee(
                attendee, params.get('promo_code'))

        if not attendee.badge_type:
            attendee.badge_type = c.ATTENDEE_BADGE
        if attendee.badge_type not in c.PREREG_BADGE_TYPES:
            message = 'Invalid badge type!'

        if message:
            return {
                'message': message,
                'attendee': attendee,
                'group': group,
                'edit_id': edit_id,
                'badges': params.get('badges'),
                'affiliates': session.affiliates(),
                'cart_not_empty': Charge.unpaid_preregs,
                'copy_address': params.get('copy_address')
            }

        if attendee.is_dealer and not c.DEALER_REG_OPEN:
            return render('static_views/dealer_reg_closed.html') if c.AFTER_DEALER_REG_SHUTDOWN \
                else render('static_views/dealer_reg_not_open.html')

        if 'first_name' in params:
            message = check(attendee, prereg=True)
            if not message and attendee.badge_type in [
                    c.PSEUDO_DEALER_BADGE, c.PSEUDO_GROUP_BADGE
            ]:
                message = check(group, prereg=True)

            if not message:
                if attendee.badge_type in [
                        c.PSEUDO_DEALER_BADGE, c.PSEUDO_GROUP_BADGE
                ]:
                    attendee.paid = c.PAID_BY_GROUP
                    group.attendees = [attendee]
                    session.assign_badges(group, params['badges'])
                    if attendee.badge_type == c.PSEUDO_GROUP_BADGE:
                        attendee.badge_type = c.ATTENDEE_BADGE
                        group.tables = 0
                    elif attendee.badge_type == c.PSEUDO_DEALER_BADGE:
                        group.status = c.WAITLISTED if c.DEALER_REG_SOFT_CLOSED else c.UNAPPROVED
                        attendee.ribbon = add_opt(attendee.ribbon_ints,
                                                  c.DEALER_RIBBON)
                        attendee.badge_type = c.ATTENDEE_BADGE

                if attendee.is_dealer:
                    session.add_all([attendee, group])
                    session.commit()
                    try:
                        send_email(c.MARKETPLACE_EMAIL,
                                   c.MARKETPLACE_EMAIL,
                                   'Dealer Application Received',
                                   render(
                                       'emails/dealers/reg_notification.txt',
                                       {'group': group}),
                                   model=group)
                        send_email(c.MARKETPLACE_EMAIL,
                                   attendee.email,
                                   'Dealer Application Received',
                                   render('emails/dealers/application.html',
                                          {'group': group}),
                                   'html',
                                   model=group)
                    except Exception:
                        log.error(
                            'unable to send marketplace application confirmation email',
                            exc_info=True)
                    raise HTTPRedirect('dealer_confirmation?id={}', group.id)
                else:
                    target = group if group.badges else attendee
                    track_type = c.EDITED_PREREG if target.id in Charge.unpaid_preregs else c.UNPAID_PREREG
                    Charge.unpaid_preregs[target.id] = to_sessionized(
                        attendee, group)
                    Tracking.track(track_type, attendee)
                    if group.badges:
                        Tracking.track(track_type, group)

                if session.attendees_with_badges().filter_by(
                        first_name=attendee.first_name,
                        last_name=attendee.last_name,
                        email=attendee.email).count():

                    raise HTTPRedirect(
                        'duplicate?id={}', group.id
                        if attendee.paid == c.PAID_BY_GROUP else attendee.id)

                if attendee.banned:
                    raise HTTPRedirect(
                        'banned?id={}', group.id
                        if attendee.paid == c.PAID_BY_GROUP else attendee.id)

                if c.PREREG_REQUEST_HOTEL_INFO_OPEN:
                    hotel_page = 'hotel?edit_id={}' if edit_id else 'hotel?id={}'
                    raise HTTPRedirect(
                        hotel_page, group.id
                        if attendee.paid == c.PAID_BY_GROUP else attendee.id)
                else:
                    raise HTTPRedirect('index')

        else:
            if edit_id is None:
                attendee.can_spam = True  # Only defaults to True on new forms, not edit forms
                if attendee.badge_type == c.PSEUDO_DEALER_BADGE:
                    # All new dealer signups should default to receiving the
                    # hotel info email, even if the deadline has passed.
                    # There's a good chance some dealers will apply for a table
                    # AFTER the hotel booking deadline, but BEFORE the hotel
                    # booking is sent out. This ensures they'll still receive
                    # the email, as requested by the Marketplace Department.
                    attendee.requested_hotel_info = True

            if attendee.badge_type == c.PSEUDO_DEALER_BADGE and c.DEALER_REG_SOFT_CLOSED:
                message = 'Dealer registration is closed, but you can ' \
                    'fill out this form to add yourself to our waitlist'

        return {
            'message': message,
            'attendee': attendee,
            'group': group,
            'edit_id': edit_id,
            'badges': params.get('badges'),
            'affiliates': session.affiliates(),
            'cart_not_empty': Charge.unpaid_preregs,
            'copy_address': params.get('copy_address')
        }
示例#24
0
def _decline_and_convert_dealer_group(session, group, delete_when_able=False):
    """
    Deletes the waitlisted dealer group and converts all of the group members
    to the appropriate badge type. Unassigned, unpaid badges will be deleted.
    """
    admin_note = 'Converted badge from waitlisted dealer group "{}".'.format(
        group.name)

    if not group.is_unpaid:
        group.tables = 0
        for attendee in group.attendees:
            attendee.append_admin_note(admin_note)
            attendee.ribbon = remove_opt(attendee.ribbon_ints, c.DEALER_RIBBON)
        return 'Group dealer status removed'

    message = ['Group declined']
    emails_failed = 0
    emails_sent = 0
    badges_converted = 0
    badges_deleted = 0

    group.leader = None
    for attendee in list(group.attendees):
        if (delete_when_able or attendee.is_unassigned
            ) and _is_attendee_disentangled(attendee):
            session.delete(attendee)
            badges_deleted += 1

        else:
            if _is_dealer_convertible(attendee):
                attendee.badge_status = c.NEW_STATUS
                attendee.overridden_price = attendee.new_badge_cost

                try:
                    send_email(c.REGDESK_EMAIL,
                               attendee.email,
                               'Do you still want to come to {EVENT_NAME}?',
                               render('emails/dealers/badge_converted.html', {
                                   'attendee': attendee,
                                   'group': group
                               }),
                               format='html',
                               model=attendee)
                    emails_sent += 1
                except Exception:
                    emails_failed += 1

            badges_converted += 1

            if attendee.paid not in [c.HAS_PAID, c.NEED_NOT_PAY]:
                attendee.paid = c.NOT_PAID

            attendee.append_admin_note(admin_note)
            attendee.ribbon = remove_opt(attendee.ribbon_ints, c.DEALER_RIBBON)
            group.attendees.remove(attendee)

    session.delete(group)

    for count, template in [(badges_converted, '{} badge{} converted'),
                            (emails_sent, '{} email{} sent'),
                            (emails_failed, '{} email{} failed to send'),
                            (badges_deleted, '{} badge{} deleted')]:

        if count > 0:
            message.append(template.format(count, pluralize(count)))

    return ', '.join(message)
示例#25
0
def do_send_notifications(session):
    for attraction in session.query(Attraction):
        now = datetime.now(pytz.UTC)
        from_time = now - timedelta(seconds=300)
        to_time = now + timedelta(seconds=300)
        signups = attraction.signups_requiring_notification(
            session, from_time, to_time, [
                subqueryload(AttractionSignup.attendee).subqueryload(
                    Attendee.attraction_notifications),
                subqueryload(AttractionSignup.event).subqueryload(
                    AttractionEvent.feature)
            ])

        for signup, advance_notices in signups.items():
            attendee = signup.attendee
            if not attendee.first_name or not attendee.email:
                try:
                    log.error(
                        'ERROR: Unassigned attendee signed up for an attraction, deleting signup:\n'
                        '\tAttendee.id: {}\n'
                        '\tAttraction.id: {}\n'
                        '\tAttractionEvent.id: {}\n'
                        '\tAttractionSignup.id: {}'.format(
                            attendee.id, signup.attraction_id,
                            signup.attraction_event_id, signup.id))

                    session.delete(signup)
                    session.commit()
                except Exception:
                    log.error(
                        'ERROR: Failed to delete signup with unassigned attendee',
                        exc_info=True)
                continue

            # The first time someone signs up for an attractions, they always
            # receive the welcome email (even if they've chosen SMS or None
            # for their notification prefs). If they've chosen to receive SMS
            # notifications, they'll also get a text message.
            is_first_signup = not (attendee.attraction_notifications)

            if not is_first_signup and attendee.notification_pref == Attendee._NOTIFICATION_NONE:
                continue

            use_text = twilio_client \
                and attendee.cellphone \
                and attendee.notification_pref == Attendee._NOTIFICATION_TEXT

            event = signup.event

            # If we overlap multiple notices, we only want to send a single
            # notification. So if we have both "5 minutes before checkin" and
            # "when checkin starts", we only want to send the notification
            # for "when checkin starts".
            advance_notice = min(advance_notices)
            if advance_notice == -1 or advance_notice > 1800:
                checkin = 'is at {}'.format(event.checkin_start_time_label)
            else:
                checkin = humanize_timedelta(event.time_remaining_to_checkin,
                                             granularity='minutes',
                                             separator=' ',
                                             prefix='is in ',
                                             now='is right now',
                                             past_prefix='was ',
                                             past_suffix=' ago')

            ident = AttractionEvent.get_ident(event.id, advance_notice)
            try:
                if use_text:
                    type_ = Attendee._NOTIFICATION_TEXT
                    type_str = 'TEXT'
                    from_ = c.PANELS_TWILIO_NUMBER
                    to_ = attendee.cellphone
                    body = TEXT_TEMPLATE.format(signup=signup, checkin=checkin)
                    subject = ''
                    sid = send_sms(to_, body, from_)

                if not use_text or is_first_signup:
                    type_ = Attendee._NOTIFICATION_EMAIL
                    type_str = 'EMAIL'
                    from_ = c.ATTRACTIONS_EMAIL
                    to_ = attendee.email
                    if is_first_signup:
                        template = 'emails/attractions_welcome.html'
                        subject = 'Welcome to {} Attractions'.format(
                            c.EVENT_NAME)
                    else:
                        template = 'emails/attractions_notification.html'
                        subject = 'Checkin for {} is at {}'.format(
                            event.name, event.checkin_start_time_label)

                    body = render(template, {
                        'signup': signup,
                        'checkin': checkin,
                        'c': c
                    }).decode('utf-8')
                    sid = ident
                    send_email(from_,
                               to_,
                               subject=subject,
                               body=body,
                               format='html',
                               model=attendee,
                               ident=ident)
            except Exception:
                log.error('Error sending notification\n'
                          '\tfrom: {}\n'
                          '\tto: {}\n'
                          '\tsubject: {}\n'
                          '\tbody: {}\n'
                          '\ttype: {}\n'
                          '\tattendee: {}\n'
                          '\tident: {}\n'.format(from_, to_, subject, body,
                                                 type_str, attendee.id, ident),
                          exc_info=True)
            else:
                session.add(
                    AttractionNotification(attraction_event_id=event.id,
                                           attraction_id=event.attraction_id,
                                           attendee_id=attendee.id,
                                           notification_type=type_,
                                           ident=ident,
                                           sid=sid,
                                           sent_time=datetime.now(pytz.UTC),
                                           subject=subject,
                                           body=body))
                session.commit()