Пример #1
0
def price_notice(label, takedown, amount_extra=0, discount=0):
    if not takedown:
        takedown = c.ESCHATON

    prereg_pages = ['/preregistration/form', '/preregistration/post_form', '/preregistration/register_group_member']

    if c.PAGE_PATH not in prereg_pages:
        return ''  # we only display notices for new attendees
    else:
        badge_price = c.BADGE_PRICE  # optimization.  this call is VERY EXPENSIVE.
        on_or_by = "no later than" if c.PRICE_LIMITS else "on"

        for day, price in sorted(c.PRICE_BUMPS.items()):
            if day < takedown and localized_now() < day and price > badge_price:
                new_price = price - int(discount) + int(amount_extra)
                new_price_date = day - timedelta(days=1)
                return safe_string(
                    '<div class="prereg-price-notice">Price goes up to ${} {} 11:59pm {} on {}</div>'.format(
                        new_price, on_or_by, new_price_date.strftime('%Z'), new_price_date.strftime('%A, %b %e')))
            elif localized_now() < day and takedown == c.PREREG_TAKEDOWN and takedown < c.EPOCH and price > badge_price:
                new_price = price + amount_extra
                return safe_string((
                    '<div class="prereg-type-closing">'
                    '{} closes at 11:59pm {} on {}. Price goes up to ${} at-door.'
                    '</div>').format(
                        label, takedown.strftime('%Z'), takedown.strftime('%A, %b %e'), new_price))
        if takedown < c.EPOCH:
            return safe_string(
                '<div class="prereg-type-closing">{} closes at 11:59pm {} on {}</div>'.format(
                    jinja2.escape(label), takedown.strftime('%Z'), takedown.strftime('%A, %b %e')))
        else:
            return ''
Пример #2
0
def price_notice(label, takedown, amount_extra=0, discount=0):
    if not takedown:
        takedown = c.ESCHATON

    prereg_pages = ['/preregistration/form', '/preregistration/post_form', '/preregistration/register_group_member']

    if c.PAGE_PATH not in prereg_pages:
        return ''  # we only display notices for new attendees
    else:
        badge_price = c.BADGE_PRICE  # optimization.  this call is VERY EXPENSIVE.
        on_or_by = "no later than" if c.PRICE_LIMITS else "on"

        for day, price in sorted(c.PRICE_BUMPS.items()):
            if day < takedown and localized_now() < day and price > badge_price:
                new_price = price - int(discount) + int(amount_extra)
                new_price_date = day - timedelta(days=1)
                return safe_string(
                    '<div class="prereg-price-notice">Price goes up to ${} {} 11:59pm {} on {}</div>'.format(
                        new_price, on_or_by, new_price_date.strftime('%Z'), new_price_date.strftime('%A, %b %e')))
            elif localized_now() < day and takedown == c.PREREG_TAKEDOWN and takedown < c.EPOCH and price > badge_price:
                new_price = price + amount_extra
                return safe_string((
                    '<div class="prereg-type-closing">'
                    '{} closes at 11:59pm {} on {}. Price goes up to ${} at-door.'
                    '</div>').format(
                        label, takedown.strftime('%Z'), takedown.strftime('%A, %b %e'), new_price))
        if takedown < c.EPOCH:
            return safe_string(
                '<div class="prereg-type-closing">{} closes at 11:59pm {} on {}</div>'.format(
                    jinja2.escape(label), takedown.strftime('%Z'), takedown.strftime('%A, %b %e')))
        else:
            return ''
Пример #3
0
    def now(self, session, when=None):
        if when:
            now = c.EVENT_TIMEZONE.localize(
                datetime(*map(int, when.split(','))))
        else:
            now = c.EVENT_TIMEZONE.localize(
                datetime.combine(localized_now().date(),
                                 time(localized_now().hour)))

        current, upcoming = [], []
        for loc, desc in c.EVENT_LOCATION_OPTS:
            approx = session.query(Event).filter(
                Event.location == loc,
                Event.start_time >= now - timedelta(hours=6),
                Event.start_time <= now).all()
            for event in approx:
                if now in event.half_hours:
                    current.append(event)

            next_events = session.query(Event).filter(
                Event.location == loc,
                Event.start_time >= now + timedelta(minutes=30),
                Event.start_time <=
                now + timedelta(hours=4)).order_by('start_time').all()

            if next_events:
                upcoming.extend(
                    event for event in next_events
                    if event.start_time == next_events[0].start_time)

        return {
            'now': now if when else localized_now(),
            'current': current,
            'upcoming': upcoming
        }
Пример #4
0
    def now(self, session, when=None):
        if when:
            now = c.EVENT_TIMEZONE.localize(datetime(*map(int, when.split(','))))
        else:
            now = c.EVENT_TIMEZONE.localize(datetime.combine(localized_now().date(), time(localized_now().hour)))

        current, upcoming = [], []
        for loc, desc in c.EVENT_LOCATION_OPTS:
            approx = session.query(Event).filter(Event.location == loc,
                                                 Event.start_time >= now - timedelta(hours=6),
                                                 Event.start_time <= now).all()
            for event in approx:
                if now in event.half_hours:
                    current.append(event)

            next_events = session.query(Event).filter(
                Event.location == loc,
                Event.start_time >= now + timedelta(minutes=30),
                Event.start_time <= now + timedelta(hours=4)).order_by('start_time').all()

            if next_events:
                upcoming.extend(event for event in next_events if event.start_time == next_events[0].start_time)

        return {
            'now': now if when else localized_now(),
            'current': current,
            'upcoming': upcoming
        }
Пример #5
0
    def form(self, session, message='', return_to='', omit_badge='', check_in='', **params):
        attendee = session.attendee(
            params, checkgroups=Attendee.all_checkgroups, bools=Attendee.all_bools, allow_invalid=True)

        if 'first_name' in params:
            attendee.group_id = params['group_opt'] or None
            if (c.AT_THE_CON and omit_badge) or not attendee.badge_num:
                attendee.badge_num = None

            if 'no_override' in params:
                attendee.overridden_price = None

            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 message:
                message = check(attendee)

            if not message:
                # Free group badges are only considered 'registered' when they are actually claimed.
                if attendee.paid == c.PAID_BY_GROUP and attendee.group_id and attendee.group.cost == 0:
                    attendee.registered = localized_now()
                if check_in:
                    attendee.checked_in = localized_now()
                session.add(attendee)

                if attendee.is_new and \
                        session.attendees_with_badges().filter_by(first_name=attendee.first_name,
                                                                  last_name=attendee.last_name,
                                                                  email=attendee.email).count():
                    raise HTTPRedirect('duplicate?id={}&return_to={}', attendee.id, return_to or 'index')

                msg_text = '{} has been saved'.format(attendee.full_name)
                if params.get('save') == 'save_return_to_search':
                    if return_to:
                        raise HTTPRedirect(return_to + '&message={}', 'Attendee data saved')
                    else:
                        raise HTTPRedirect(
                            'index?uploaded_id={}&message={}&search_text={}',
                            attendee.id,
                            msg_text,
                            '{} {}'.format(attendee.first_name, attendee.last_name) if c.AT_THE_CON else '')
                else:
                    raise HTTPRedirect('form?id={}&message={}&return_to={}', attendee.id, msg_text, return_to)

        return {
            'message':    message,
            'attendee':   attendee,
            'check_in':   check_in,
            'return_to':  return_to,
            'omit_badge': omit_badge,
            'admin_can_change_status': session.admin_attendee().is_dept_head_of(c.DEFAULT_REGDESK_INT),
            'group_opts': [(g.id, g.name) for g in session.query(Group).order_by(Group.name).all()],
            'unassigned': {
                group_id: unassigned
                for group_id, unassigned in session.query(Attendee.group_id, func.count('*')).filter(
                    Attendee.group_id != None, Attendee.first_name == '').group_by(Attendee.group_id).all()}
        }  # noqa: E711
Пример #6
0
    def form(self, session, message='', return_to='', omit_badge='', check_in='', **params):
        attendee = session.attendee(
            params, checkgroups=Attendee.all_checkgroups, bools=Attendee.all_bools, allow_invalid=True)

        if 'first_name' in params:
            attendee.group_id = params['group_opt'] or None
            if (c.AT_THE_CON and omit_badge) or not attendee.badge_num:
                attendee.badge_num = None

            if 'no_override' in params:
                attendee.overridden_price = None

            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 message:
                message = check(attendee)

            if not message:
                # Free group badges are only considered 'registered' when they are actually claimed.
                if attendee.paid == c.PAID_BY_GROUP and attendee.group_id and attendee.group.cost == 0:
                    attendee.registered = localized_now()
                if check_in:
                    attendee.checked_in = localized_now()
                session.add(attendee)

                if attendee.is_new and \
                        session.attendees_with_badges().filter_by(first_name=attendee.first_name,
                                                                  last_name=attendee.last_name,
                                                                  email=attendee.email).count():
                    raise HTTPRedirect('duplicate?id={}&return_to={}', attendee.id, return_to or 'index')

                msg_text = '{} has been saved'.format(attendee.full_name)
                if params.get('save') == 'save_return_to_search':
                    if return_to:
                        raise HTTPRedirect(return_to + '&message={}', 'Attendee data saved')
                    else:
                        raise HTTPRedirect(
                            'index?uploaded_id={}&message={}&search_text={}',
                            attendee.id,
                            msg_text,
                            '{} {}'.format(attendee.first_name, attendee.last_name) if c.AT_THE_CON else '')
                else:
                    raise HTTPRedirect('form?id={}&message={}&return_to={}', attendee.id, msg_text, return_to)

        return {
            'message':    message,
            'attendee':   attendee,
            'check_in':   check_in,
            'return_to':  return_to,
            'omit_badge': omit_badge,
            'admin_can_change_status': session.admin_attendee().is_dept_head_of(c.DEFAULT_REGDESK_INT),
            'group_opts': [(g.id, g.name) for g in session.query(Group).order_by(Group.name).all()],
            'unassigned': {
                group_id: unassigned
                for group_id, unassigned in session.query(Attendee.group_id, func.count('*')).filter(
                    Attendee.group_id != None, Attendee.first_name == '').group_by(Attendee.group_id).all()}
        }  # noqa: E711
Пример #7
0
 def should_send_reminder(self):
     stagger = timedelta(minutes=c.TABLETOP_SMS_STAGGER_MINUTES)
     reminder = timedelta(minutes=c.TABLETOP_SMS_REMINDER_MINUTES)
     return not self.confirmed \
         and not self.reminder \
         and localized_now() < self.tournament.event.start_time \
         and localized_now() > self.signed_up + stagger \
         and localized_now() > self.tournament.event.start_time - reminder
Пример #8
0
 def test_dealer_reg_open(self, monkeypatch):
     monkeypatch.setattr(c, 'DEALER_REG_START',
                         localized_now() - timedelta(days=1))
     monkeypatch.setattr(c, 'DEALER_REG_SHUTDOWN',
                         localized_now() + timedelta(days=1))
     monkeypatch.setattr(uber.config.Config, 'DEALER_REG_SOFT_CLOSED',
                         property(lambda s: False))
     assert c.DEALER_REG_OPEN
Пример #9
0
 def should_send_reminder(self):
     stagger = timedelta(minutes=c.TABLETOP_SMS_STAGGER_MINUTES)
     reminder = timedelta(minutes=c.TABLETOP_SMS_REMINDER_MINUTES)
     return not self.confirmed \
         and not self.reminder \
         and localized_now() < self.tournament.event.start_time \
         and localized_now() > self.signed_up + stagger \
         and localized_now() > self.tournament.event.start_time - reminder
Пример #10
0
 def test_at_door_badge_opts_presold_one_days(self, monkeypatch):
     monkeypatch.setattr(c, 'PRESELL_ONE_DAYS', True)
     monday_after_now = localized_now() + timedelta(
         days=(7 - localized_now().weekday()))
     monkeypatch.setattr(c, 'EPOCH', monday_after_now + timedelta(days=4))
     monkeypatch.setattr(c, 'ESCHATON',
                         monday_after_now + timedelta(days=6))
     assert dict(c.AT_THE_DOOR_BADGE_OPTS).keys() == {
         c.ATTENDEE_BADGE, c.FRIDAY, c.SATURDAY, c.SUNDAY
     }
Пример #11
0
    def reprint_fee(self,
                    session,
                    attendee_id=None,
                    message='',
                    fee_amount=0,
                    reprint_reason='',
                    refund=''):
        attendee = session.attendee(attendee_id)
        fee_amount = int(fee_amount)
        if not fee_amount and not reprint_reason:
            message = "You must charge a fee " \
                      "or enter a reason for a free reprint!"
        if not fee_amount and refund:
            message = "You can't refund a fee of $0!"

        if not message:
            if not fee_amount:
                attendee.for_review += \
                    "Automated message: " \
                    "Badge marked for free reprint by {} on {}. Reason: {}"\
                    .format(session.admin_attendee().full_name,
                            localized_now().strftime('%m/%d, %H:%M'),
                            reprint_reason)
                message = 'Free reprint recorded and badge sent to printer.'
                attendee.print_pending = True
            elif refund:
                attendee.paid = c.REFUNDED
                attendee.amount_refunded += fee_amount
                attendee.for_review += \
                    "Automated message: " \
                    "Reprint fee of ${} refunded by {} on {}. Reason: {}"\
                    .format(fee_amount,
                            session.admin_attendee().full_name,
                            localized_now().strftime('%m/%d, %H:%M'),
                            reprint_reason)
                message = 'Reprint fee of ${} refunded.'.format(fee_amount)
            else:
                attendee.amount_paid += fee_amount
                attendee.for_review += \
                    "Automated message: " \
                    "Reprint fee of ${} charged by {} on {}. Reason: {}"\
                    .format(fee_amount,
                            session.admin_attendee().full_name,
                            localized_now().strftime('%m/%d, %H:%M'),
                            reprint_reason)
                message = 'Reprint fee of ${} charged. Badge sent to printer.'\
                    .format(fee_amount)
                attendee.print_pending = True

        raise HTTPRedirect('../registration/form?id={}&message={}',
                           attendee_id, message)
Пример #12
0
    def checklist_items_due_soon_grouped(self):
        two_days = []
        one_day = []
        overdue = []
        for key, val in c.MIVS_CHECKLIST.items():
            if localized_now() >= self.checklist_deadline(key):
                overdue.append([val['name'], "mivs_" + key])
            elif (localized_now() -
                  timedelta(days=1)) >= self.checklist_deadline(key):
                one_day.append([val['name'], "mivs_" + key])
            elif (localized_now() -
                  timedelta(days=2)) >= self.checklist_deadline(key):
                two_days.append([val['name'], "mivs_" + key])

        return two_days, one_day, overdue
Пример #13
0
    def reg_take_report(self, session, **params):
        if params:
            start = c.EVENT_TIMEZONE.localize(
                datetime.strptime(
                    '{startday} {starthour}:{startminute}'.format(**params),
                    '%Y-%m-%d %H:%M'))
            end = c.EVENT_TIMEZONE.localize(
                datetime.strptime(
                    '{endday} {endhour}:{endminute}'.format(**params),
                    '%Y-%m-%d %H:%M'))

            sales = session.query(Sale).filter(
                Sale.reg_station == params['reg_station'], Sale.when > start,
                Sale.when <= end).all()

            attendees = session.query(Attendee).filter(
                Attendee.reg_station == params['reg_station'],
                Attendee.amount_paid > 0, Attendee.registered > start,
                Attendee.registered <= end).all()

            params['sales'] = sales
            params['attendees'] = attendees
            params['total_cash'] = \
                sum((a.amount_paid / 100) for a in attendees if a.payment_method == c.CASH) \
                + sum(s.cash for s in sales if s.payment_method == c.CASH)
            params['total_credit'] = \
                sum((a.amount_paid / 100) for a in attendees if a.payment_method in [c.STRIPE, c.SQUARE, c.MANUAL]) \
                + sum(s.cash for s in sales if s.payment_method == c.CREDIT)
        else:
            params['endday'] = localized_now().strftime('%Y-%m-%d')
            params['endhour'] = localized_now().strftime('%H')
            params['endminute'] = localized_now().strftime('%M')

        # list all reg stations associated with attendees and sales
        stations_attendees = session.query(Attendee.reg_station).filter(
            Attendee.reg_station != None,
            Attendee.reg_station > 0)  # noqa: E711

        stations_sales = session.query(Sale.reg_station).filter(
            Sale.reg_station != None, Sale.reg_station > 0)  # noqa: E711

        stations = [
            r for (r, ) in stations_attendees.union(
                stations_sales).distinct().order_by(Attendee.reg_station)
        ]
        params['reg_stations'] = stations
        params.setdefault('reg_station', stations[0] if stations else 0)
        return params
Пример #14
0
def price_notice(label, takedown, amount_extra=0, discount=0):
    if c.HARDCORE_OPTIMIZATIONS_ENABLED:
        # CPU optimizaiton: the calculations done in this function are somewhat expensive and even with caching,
        # still do some expensive DB queries.  if hardcore optimizations mode is enabled, we display a
        # simpler message.  This is intended to be enabled during the heaviest loads at the beginning of an event
        # in order to reduce server load so the system stays up.  After the rush, it should be safe to turn this
        # back off
        return ''

    if not takedown:
        takedown = c.ESCHATON

    prereg_pages = [
        '/preregistration/form', '/preregistration/post_form',
        '/preregistration/register_group_member'
    ]

    if c.PAGE_PATH not in prereg_pages:
        return ''  # we only display notices for new attendees
    else:
        badge_price = c.BADGE_PRICE  # optimization.  this call is VERY EXPENSIVE.
        on_or_by = "no later than" if c.PRICE_LIMITS else "on"

        for day, price in sorted(c.PRICE_BUMPS.items()):
            if day < takedown and localized_now(
            ) < day and price > badge_price:
                new_price = price - int(discount) + int(amount_extra)
                new_price_date = day - timedelta(days=1)
                return safe_string(
                    '<div class="prereg-price-notice">Price goes up to ${} {} 11:59pm {} on {}</div>'
                    .format(new_price, on_or_by, new_price_date.strftime('%Z'),
                            new_price_date.strftime('%A, %b %e')))
            elif localized_now(
            ) < day and takedown == c.PREREG_TAKEDOWN and takedown < c.EPOCH and price > badge_price:
                new_price = price + amount_extra
                return safe_string((
                    '<div class="prereg-type-closing">'
                    '{} closes at 11:59pm {} on {}. Price goes up to ${} at-door.'
                    '</div>').format(label, takedown.strftime('%Z'),
                                     takedown.strftime('%A, %b %e'),
                                     new_price))
        if takedown < c.EPOCH:
            return safe_string(
                '<div class="prereg-type-closing">{} closes at 11:59pm {} on {}</div>'
                .format(jinja2.escape(label), takedown.strftime('%Z'),
                        takedown.strftime('%A, %b %e')))
        else:
            return ''
Пример #15
0
    def check_in(self, session, message='', group_id='', **params):
        bools = ['got_merch'] if c.MERCH_AT_CHECKIN else []
        attendee = session.attendee(params, allow_invalid=True, bools=bools)
        group = attendee.group or (session.group(group_id) if group_id else None)

        pre_badge = attendee.badge_num
        success, increment = False, False

        message = pre_checkin_check(attendee, group)
        if not message and group_id:
            message = session.match_to_group(attendee, group)

        if not message and attendee.paid == c.PAID_BY_GROUP and not attendee.group_id:
            message = 'You must select a group for this attendee.'

        if not message:
            message = ''
            success = True
            attendee.checked_in = localized_now()
            session.commit()
            increment = True
            message += '{} checked in as {}{}'.format(attendee.full_name, attendee.badge, attendee.accoutrements)

        return {
            'success':    success,
            'message':    message,
            'increment':  increment,
            'badge':      attendee.badge,
            'paid':       attendee.paid_label,
            'age_group':  attendee.age_group_conf['desc'],
            'pre_badge':  pre_badge,
            'checked_in': attendee.checked_in and hour_day_format(attendee.checked_in)
        }
Пример #16
0
def check_duplicate_registrations():
    """
    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')
Пример #17
0
    def schedule_tsv(self, session):
        cherrypy.response.headers['Content-Type'] = 'text/tsv'
        cherrypy.response.headers[
            'Content-Disposition'] = 'attachment;filename=Schedule-{}.tsv'.format(
                int(localized_now().timestamp()))

        schedule = defaultdict(list)
        for event in session.query(Event).order_by('start_time').all():
            schedule[event.location_label].append(
                dict(
                    event.to_dict(), **{
                        'date':
                        event.start_time_local.strftime('%m/%d/%Y'),
                        'start_time':
                        event.start_time_local.strftime('%I:%M:%S %p'),
                        'end_time': (event.start_time_local + timedelta(
                            minutes=event.minutes)).strftime('%I:%M:%S %p'),
                        'description':
                        normalize_newlines(event.description).replace(
                            '\n', ' ')
                    }))

        return render(
            'schedule/schedule.tsv', {
                'schedule':
                sorted(schedule.items(),
                       key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0][
                           'location']))
            })
Пример #18
0
def check_pending_badges():
    if c.PRE_CON and (c.DEV_BOX or c.SEND_EMAILS):
        emails = [[
            'Staff', c.STAFF_EMAIL, Attendee.badge_type == c.STAFF_BADGE,
            'staffing_admin'
        ],
                  [
                      'Attendee', c.REGDESK_EMAIL,
                      Attendee.badge_type != c.STAFF_BADGE, 'registration'
                  ]]
        subject = c.EVENT_NAME + ' Pending {} Badge Report for ' + localized_now(
        ).strftime('%Y-%m-%d')
        with Session() as session:
            for badge_type, to, per_email_filter, site_section in emails:
                pending = session.query(Attendee).filter_by(
                    badge_status=c.PENDING_STATUS).filter(
                        per_email_filter).all()
                if pending and session.no_email(subject.format(badge_type)):
                    body = render('emails/daily_checks/pending.html', {
                        'pending': pending,
                        'site_section': site_section
                    })
                    send_email(c.ADMIN_EMAIL,
                               to,
                               subject.format(badge_type),
                               body,
                               format='html',
                               model='n/a')
Пример #19
0
 def test_dealer_reg_not_soft_closed_optimizations(self, monkeypatch):
     monkeypatch.setattr(c, 'DEALER_REG_DEADLINE',
                         localized_now() + timedelta(days=1))
     monkeypatch.setattr(uber.config.Config, 'DEALER_APPS', 10)
     monkeypatch.setattr(c, 'MAX_DEALER_APPS', 1)
     monkeypatch.setattr(c, 'HARDCORE_OPTIMIZATIONS_ENABLED', True)
     assert not c.DEALER_REG_SOFT_CLOSED
Пример #20
0
    def check_in(self, session, message='', group_id='', **params):
        attendee = session.attendee(params, allow_invalid=True)
        group = attendee.group or (session.group(group_id) if group_id else None)

        pre_badge = attendee.badge_num
        success, increment = False, False

        message = pre_checkin_check(attendee, group)
        if not message and group_id:
            message = session.match_to_group(attendee, group)

        if not message and attendee.paid == c.PAID_BY_GROUP and not attendee.group_id:
            message = 'You must select a group for this attendee.'

        if not message:
            message = ''
            success = True
            attendee.checked_in = localized_now()
            session.commit()
            increment = True
            message += '{} checked in as {}{}'.format(attendee.full_name, attendee.badge, attendee.accoutrements)

        return {
            'success':    success,
            'message':    message,
            'increment':  increment,
            'badge':      attendee.badge,
            'paid':       attendee.paid_label,
            'age_group':  attendee.age_group_conf['desc'],
            'pre_badge':  pre_badge,
            'checked_in': attendee.checked_in and hour_day_format(attendee.checked_in)
        }
Пример #21
0
def notify_admins_of_pending_emails():
    """
    Generate and email a report which alerts admins that there are automated
    emails which are ready to send, but can't be sent until they are approved
    by an admin.

    This is important so we don't forget to let certain automated emails send.
    """
    if not c.ENABLE_PENDING_EMAILS_REPORT or not c.PRE_CON or not (c.DEV_BOX or c.SEND_EMAILS):
        return None

    with Session() as session:
        pending_emails = session.query(AutomatedEmail).filter(*AutomatedEmail.filters_for_pending).all()
        pending_emails_by_sender = groupify(pending_emails, ['sender', 'ident'])

        for sender, emails_by_ident in pending_emails_by_sender.items():
            if sender == c.STAFF_EMAIL:
                # STOPS receives a report on ALL the pending emails.
                emails_by_sender = pending_emails_by_sender
            else:
                emails_by_sender = {sender: emails_by_ident}

            subject = '{} Pending Emails Report for {}'.format(c.EVENT_NAME, utils.localized_now().strftime('%Y-%m-%d'))
            body = render('emails/daily_checks/pending_emails.html', {
                'pending_emails_by_sender': emails_by_sender,
                'primary_sender': sender,
            })
            send_email(c.STAFF_EMAIL, sender, subject, body, format='html', model='n/a', session=session)

        return groupify(pending_emails, 'sender', 'ident')
Пример #22
0
def printed_badge_change(attendee):
    if attendee.badge_printed_name != attendee.orig_value_of('badge_printed_name') \
            and not AdminAccount.admin_name() \
            and localized_now() > c.get_printed_badge_deadline_by_type(attendee.badge_type_real):

        return '{} badges have already been ordered, so you cannot change the badge printed name.'.format(
            attendee.badge_type_label if attendee.badge_type in c.PREASSIGNED_BADGE_TYPES else "Supporter")
Пример #23
0
def pre_print_check(session, attendee, printer_id, dry_run=False, **params):
    fee_amount = params.get('fee_amount', 0)
    reprint_reason = params.get('reprint_reason')

    try:
        fee_amount = int(fee_amount)
    except Exception:
        return False, "What you entered for Reprint Fee ({}) isn't even a number".format(
            fee_amount)

    if not fee_amount and not reprint_reason and c.BADGE_REPRINT_FEE and attendee.times_printed > 0:
        return False, "You must set a fee or enter a reason for a free reprint!"

    print_id, errors = session.add_to_print_queue(
        attendee, printer_id,
        params.get('reg_station', cherrypy.session.get('reg_station')),
        fee_amount, dry_run)
    if errors:
        return False, "<br>".join(errors)

    if not fee_amount:
        if c.BADGE_REPRINT_FEE and attendee.times_printed > 0:
            attendee.for_review += \
                "Automated message: " \
                "Badge marked for free reprint by {} on {}.{}"\
                .format(session.admin_attendee().full_name,
                        localized_now().strftime('%m/%d, %H:%M'),
                        " Reason: " + reprint_reason if reprint_reason else '')
            return True, '{}adge sent to printer.'.format(
                "B" if not c.BADGE_REPRINT_FEE or attendee.times_printed == 0
                else "Free reprint recorded and b")
    else:
        return True, 'Badge sent to printer with reprint fee of ${}.'.format(
            fee_amount)
    return True, 'Badge sent to printer.'
Пример #24
0
def test_assign_extra_create_arguments(session):
    group = Group()
    registered = localized_now()
    session.assign_badges(group, 2, registered=registered)
    assert 2 == group.badges == len(group.attendees)
    for attendee in group.attendees:
        assert attendee.registered == registered
Пример #25
0
    def waiver(self, session, message='', **params):
        if params.get('id'):
            session.log_in_as_mits_team(params['id'], redirect_to='waiver')
        else:
            team = session.logged_in_mits_team()

        if cherrypy.request.method == 'POST':
            if not params['waiver_signature']:
                message = "Please enter your full name to sign the waiver."

            else:
                for applicant in team.applicants:
                    if getattr(
                            applicant.attendee, 'full_name',
                            applicant.full_name) == params['waiver_signature']:
                        team.waiver_signature = params['waiver_signature']
                        team.waiver_signed = localized_now()
                        break
                else:
                    message = "The name you entered did not match any of this team's members."

            if not message:
                raise HTTPRedirect('index?message={}',
                                   'Thank you for signing the waiver!')
        return {
            'team': team,
            'message': message,
        }
Пример #26
0
def test_match_to_group(match_to_group_preconditions):
    with Session() as session:
        console = session.query(Department).filter_by(name='Console_01').one()
        late_comer = Attendee(
            first_name='Late',
            last_name='Comer',
            email='*****@*****.**',
            zip_code='21211',
            ec_name='Nana Fearless',
            ec_phone='555-555-1234',
            cellphone='555-555-2345',
            birthdate=date(1964, 12, 30),
            registered=localized_now(),
            paid=c.NEED_NOT_PAY,
            badge_type=c.STAFF_BADGE,
            badge_num=99,
            badge_printed_name='Lateness',
            ribbon='',
            staffing=True,
            assigned_depts=[console])

        group = session.query(Group).get(match_to_group_preconditions)

        assert [6, 7, 8, 9] == sorted([a.badge_num for a in group.attendees])
        session.match_to_group(late_comer, group)
        assert [6, 7, 8, 99] == sorted([a.badge_num for a in group.attendees])
Пример #27
0
    def waiver(self, session, message='', **params):
        if params.get('id'):
            session.log_in_as_mits_team(params['id'], redirect_to='waiver')
        else:
            team = session.logged_in_mits_team()

        if cherrypy.request.method == 'POST':
            if not params['waiver_signature']:
                message = "Please enter your full name to sign the waiver."

            else:
                for applicant in team.applicants:
                    if getattr(applicant.attendee, 'full_name', applicant.full_name) == params['waiver_signature']:
                        team.waiver_signature = params['waiver_signature']
                        team.waiver_signed = localized_now()
                        break
                else:
                    message = "The name you entered did not match any of this team's members."

            if not message:
                raise HTTPRedirect('index?message={}', 'Thank you for signing the waiver!')
        return {
            'team': team,
            'message': message,
        }
Пример #28
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(
                    to=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.delay(
                        c.REGDESK_EMAIL,
                        attendee.email,
                        subject,
                        render('emails/reg_workflow/prereg_check.txt',
                               {'attendee': attendee},
                               encoding=None),
                        model=attendee.to_dict('id'))

        return {'message': message}
Пример #29
0
    def register_group_member(self, session, group_id, message='', **params):
        # Safe to ignore csrf tokens here, because an attacker would need to know the group id a priori
        group = session.group(group_id, ignore_csrf=True)
        attendee = session.attendee(params, restricted=True, ignore_csrf=True)
        must_be_staffing = False
        
        if group.unassigned[0].staffing:
            must_be_staffing = True
            attendee.staffing = True
            params['staffing'] = True

        message = check_pii_consent(params, attendee) or message
        if not message and 'first_name' in params:
            message = check(attendee, prereg=True)
            if not message and not params['first_name']:
                message = 'First and Last Name are required fields'
            if not message:
                if not group.unassigned:
                    raise HTTPRedirect(
                        'register_group_member?group_id={}&message={}',
                        group_id,
                        'No more unassigned badges exist in this group')

                attrs_to_preserve_from_unassigned_group_member = [
                    'id',
                    'group_id',
                    'badge_type',
                    'badge_num',
                    'base_badge_price',
                    'ribbon',
                    'paid',
                    'overridden_price',
                    'requested_hotel_info']

                attendee = group.unassigned[0]
                for attr in attrs_to_preserve_from_unassigned_group_member:
                    if attr in params:
                        del params[attr]

                attendee.apply(params, restricted=True)

                # Free group badges are considered registered' when they are actually claimed.
                if group.cost == 0:
                    attendee.registered = localized_now()

                if attendee.amount_unpaid:
                    raise HTTPRedirect('attendee_donation_form?id={}', attendee.id)
                else:
                    raise HTTPRedirect('badge_updated?id={}&message={}', attendee.id, 'Badge registered successfully')

        return {
            'message':  message,
            'group_id': group_id,
            'group': group,
            'attendee': attendee,
            'affiliates': session.affiliates(),
            'badge_cost': 0,
            'must_be_staffing': must_be_staffing,
        }
def test_localized_now(fixed_localized_now):
    """
    Asserts that our localized_now monkeypatch is working as expected.
    """
    assert fixed_localized_now == utils.localized_now()
    assert not before(fixed_localized_now)()
    assert before(fixed_localized_now + timedelta(microseconds=1))()
    assert not before(fixed_localized_now - timedelta(microseconds=1))()
 def returned(self, session, game_id):
     try:
         session.tabletop_game(
             game_id).checked_out.returned = localized_now()
         session.commit()
     except Exception:
         pass
     return {'message': 'Success!', 'games': _games(session)}
Пример #32
0
def test_hotel_shifts_required(monkeypatch):
    monkeypatch.setattr(c, 'SHIFTS_CREATED', localized_now())
    assert not Attendee().hotel_shifts_required
    monkeypatch.setattr(Attendee, 'takes_shifts', True)
    monkeypatch.setattr(Attendee, 'hotel_nights', [c.THURSDAY, c.FRIDAY])
    assert Attendee().hotel_shifts_required
    monkeypatch.setattr(Attendee, 'is_dept_head', True)
    assert not Attendee().hotel_shifts_required
Пример #33
0
 def onsite_jobs(self, session, message=''):
     attendee = session.logged_in_volunteer()
     return {
         'message': message,
         'attendee': attendee,
         'jobs': [job for job in attendee.possible_and_current
                  if getattr(job, 'taken', False) or job.start_time > localized_now()]
     }
Пример #34
0
def test_hotel_shifts_required(monkeypatch):
    monkeypatch.setattr(c, 'SHIFTS_CREATED', localized_now())
    assert not Attendee().hotel_shifts_required
    monkeypatch.setattr(Attendee, 'takes_shifts', True)
    monkeypatch.setattr(Attendee, 'hotel_nights', [c.THURSDAY, c.FRIDAY])
    assert Attendee().hotel_shifts_required
    monkeypatch.setattr(Attendee, 'is_dept_head', True)
    assert not Attendee().hotel_shifts_required
Пример #35
0
 def lost_badge(self, session, id):
     a = session.attendee(id, allow_invalid=True)
     a.for_review += "Automated message: Badge reported lost on {}. Previous payment type: {}.".format(
         localized_now().strftime('%m/%d, %H:%M'), a.paid_label)
     a.paid = c.LOST_BADGE
     session.add(a)
     session.commit()
     raise HTTPRedirect('index?message={}', 'Badge has been recorded as lost.')
Пример #36
0
 def lost_badge(self, session, id):
     a = session.attendee(id, allow_invalid=True)
     a.for_review += "Automated message: Badge reported lost on {}. Previous payment type: {}.".format(
         localized_now().strftime('%m/%d, %H:%M'), a.paid_label)
     a.paid = c.LOST_BADGE
     session.add(a)
     session.commit()
     raise HTTPRedirect('index?message={}', 'Badge has been recorded as lost.')
Пример #37
0
    def confirm(self,
                session,
                message='',
                return_to='confirm',
                undoing_extra='',
                **params):
        attendee = session.attendee(params, restricted=True)

        if attendee.badge_status == c.REFUNDED_STATUS:
            raise HTTPRedirect('repurchase?id={}', attendee.id)

        placeholder = attendee.placeholder
        if 'email' in params and not message:
            attendee.placeholder = False
            message = check(attendee, prereg=True)
            if not message:
                if placeholder:
                    attendee.confirmed = localized_now()
                    message = 'Your registration has been confirmed'
                else:
                    message = 'Your information has been updated'

                page = ('badge_updated?id=' + attendee.id +
                        '&') if return_to == 'confirm' else (return_to + '?')
                if attendee.amount_unpaid:
                    raise HTTPRedirect('attendee_donation_form?id={}',
                                       attendee.id)
                else:
                    raise HTTPRedirect(page + 'message=' + message)

        elif attendee.amount_unpaid and attendee.zip_code and not undoing_extra:
            # Don't skip to payment until the form is filled out
            raise HTTPRedirect('attendee_donation_form?id={}&message={}',
                               attendee.id, message)

        attendee.placeholder = placeholder
        if not message and attendee.placeholder:
            attendee.can_spam = True
            message = 'You are not yet registered!  You must fill out this form to complete your registration.'
        elif not message:
            message = 'You are already registered but you may update your information with this form.'

        return {
            'undoing_extra':
            undoing_extra,
            'return_to':
            return_to,
            'attendee':
            attendee,
            'message':
            message,
            'affiliates':
            session.affiliates(),
            'badge_cost':
            attendee.badge_cost if attendee.paid != c.PAID_BY_GROUP else 0,
        }
Пример #38
0
 def returned(self, session, game_id):
     try:
         session.tabletop_game(game_id).checked_out.returned = localized_now()
         session.commit()
     except Exception:
         pass
     return {
         'message': 'Success!',
         'games': _games(session)
     }
Пример #39
0
def check_unassigned_volunteers():
    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')
Пример #40
0
    def past_checklist_deadline(self, slug):
        """

        Args:
            slug: A standardized name, which should match the checklist's section name in config.
            E.g., the properties above ending in _status

        Returns: A timedelta object representing how far from the deadline this team is for a particular checklist item

        """
        return localized_now() - self.checklist_deadline(slug)
Пример #41
0
    def register_group_member(self, session, group_id, message='', **params):
        # Safe to ignore csrf tokens here, because an attacker would need to know the group id a priori
        group = session.group(group_id, ignore_csrf=True)
        attendee = session.attendee(params, restricted=True, ignore_csrf=True)

        message = check_pii_consent(params, attendee) or message
        if not message and 'first_name' in params:
            message = check(attendee, prereg=True)
            if not message and not params['first_name']:
                message = 'First and Last Name are required fields'
            if not message:
                if not group.unassigned:
                    raise HTTPRedirect(
                        'register_group_member?group_id={}&message={}',
                        group_id,
                        'No more unassigned badges exist in this group')

                attrs_to_preserve_from_unassigned_group_member = [
                    'id',
                    'group_id',
                    'badge_type',
                    'badge_num',
                    'base_badge_price',
                    'ribbon',
                    'paid',
                    'overridden_price',
                    'requested_hotel_info']

                attendee = group.unassigned[0]
                for attr in attrs_to_preserve_from_unassigned_group_member:
                    if attr in params:
                        del params[attr]

                attendee.apply(params, restricted=True)

                # Free group badges are considered registered' when they are actually claimed.
                if group.cost == 0:
                    attendee.registered = localized_now()

                if attendee.amount_unpaid:
                    raise HTTPRedirect('attendee_donation_form?id={}', attendee.id)
                else:
                    raise HTTPRedirect('badge_updated?id={}&message={}', attendee.id, 'Badge registered successfully')

        return {
            'message':  message,
            'group_id': group_id,
            'group': group,
            'attendee': attendee,
            'affiliates': session.affiliates(),
            'badge_cost': 0
        }
Пример #42
0
 def shifts(self, session, id, shift_id='', message=''):
     attendee = session.attendee(id, allow_invalid=True)
     attrs = Shift.to_dict_default_attrs + ['worked_label']
     return {
         'message': message,
         'shift_id': shift_id,
         'attendee': attendee,
         'shifts': {s.id: s.to_dict(attrs) for s in attendee.shifts},
         'jobs': [
             (job.id, '({}) [{}] {}'.format(job.timespan(), job.department_name, job.name))
             for job in attendee.available_jobs
             if job.start_time + timedelta(hours=job.duration + 2) > localized_now()]
     }
Пример #43
0
    def reg_take_report(self, session, **params):
        if params:
            start = c.EVENT_TIMEZONE.localize(
                datetime.strptime('{startday} {starthour}:{startminute}'.format(**params), '%Y-%m-%d %H:%M'))
            end = c.EVENT_TIMEZONE.localize(
                datetime.strptime('{endday} {endhour}:{endminute}'.format(**params), '%Y-%m-%d %H:%M'))

            sales = session.query(Sale).filter(
                Sale.reg_station == params['reg_station'], Sale.when > start, Sale.when <= end).all()

            attendees = session.query(Attendee).filter(
                Attendee.reg_station == params['reg_station'], Attendee.amount_paid > 0,
                Attendee.registered > start, Attendee.registered <= end).all()

            params['sales'] = sales
            params['attendees'] = attendees
            params['total_cash'] = \
                sum(a.amount_paid for a in attendees if a.payment_method == c.CASH) \
                + sum(s.cash for s in sales if s.payment_method == c.CASH)
            params['total_credit'] = \
                sum(a.amount_paid for a in attendees if a.payment_method in [c.STRIPE, c.SQUARE, c.MANUAL]) \
                + sum(s.cash for s in sales if s.payment_method == c.CREDIT)
        else:
            params['endday'] = localized_now().strftime('%Y-%m-%d')
            params['endhour'] = localized_now().strftime('%H')
            params['endminute'] = localized_now().strftime('%M')

        # list all reg stations associated with attendees and sales
        stations_attendees = session.query(Attendee.reg_station).filter(
            Attendee.reg_station != None, Attendee.reg_station > 0)  # noqa: E711

        stations_sales = session.query(Sale.reg_station).filter(
            Sale.reg_station != None, Sale.reg_station > 0)  # noqa: E711

        stations = [r for (r,) in stations_attendees.union(stations_sales).distinct().order_by(Attendee.reg_station)]
        params['reg_stations'] = stations
        params.setdefault('reg_station', stations[0] if stations else 0)
        return params
Пример #44
0
    def update_promo_code(self, session, message='', **params):
        if 'id' in params:
            promo_code = session.promo_code(params)
            message = check(promo_code)
            if message:
                session.rollback()
            else:
                if 'expire' in params:
                    promo_code.expiration_date = localized_now() - timedelta(days=1)

                message = 'Promo code updated'
                session.commit()

            raise HTTPRedirect('view_promo_codes?message={}', message)
Пример #45
0
    def checklist_completion(self, out, session):
        header_row = ['Studio']
        for key, val in c.MIVS_CHECKLIST.items():
            header_row.append(val['name'])
            header_row.append('Past Due?')
        out.writerow(header_row)

        for studio in session.query(IndieStudio).join(IndieStudio.group).join(Group.guest):
            row = [studio.name]
            for key, val in c.MIVS_CHECKLIST.items():
                row.extend([
                    'Not Completed' if getattr(studio, key + "_status", None) is None
                    else getattr(studio, key + "_status"),
                    'No' if localized_now() <= studio.checklist_deadline(key)
                    else humanize_timedelta(studio.past_checklist_deadline(key), granularity='hours'),
                ])
            out.writerow(row)
Пример #46
0
    def schedule_tsv(self, session):
        cherrypy.response.headers['Content-Type'] = 'text/tsv'
        cherrypy.response.headers['Content-Disposition'] = 'attachment;filename=Schedule-{}.tsv'.format(
            int(localized_now().timestamp()))

        schedule = defaultdict(list)
        for event in session.query(Event).order_by('start_time').all():
            schedule[event.location_label].append(dict(event.to_dict(), **{
                'date': event.start_time_local.strftime('%m/%d/%Y'),
                'start_time': event.start_time_local.strftime('%I:%M:%S %p'),
                'end_time': (event.start_time_local + timedelta(minutes=event.minutes)).strftime('%I:%M:%S %p'),
                'description': normalize_newlines(event.description).replace('\n', ' ')
            }))

        return render('schedule/schedule.tsv', {
            'schedule': sorted(schedule.items(), key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0]['location']))
        })
Пример #47
0
 def setup_cherrypy_fake_env(self, monkeypatch):
     monkeypatch.setattr(AdminAccount, 'admin_name', Mock(return_value='Bruce'))
     monkeypatch.setattr(cherrypy.request, 'request_line', "/uber/location3/hello")
     monkeypatch.setattr(cherrypy.request, 'params', {
         'id': '32',
         'action': 'reload',
         'thing': 3,                 # use a non-string
         'attachment': MockPart(),   # add fake attachment based on cherrypy's Part() class, make sure we handle OK
     })
     monkeypatch.setattr(cherrypy, 'session', {'session_id': '762876'})
     headers = [
         ('Content-Type', 'text/html'),
         ('Server', 'Null CherryPy'),
         ('Date', localized_now()),
         ('Content-Length', '80'),
     ]
     monkeypatch.setattr(cherrypy.request, 'header_list', headers)
Пример #48
0
    def everywhere(self, session, message='', show_restricted='', show_nonpublic=''):
        job_filters = [Job.start_time > localized_now() - timedelta(hours=2)]
        if not show_restricted:
            job_filters.append(Job.restricted == False)  # noqa: E712
        if not show_nonpublic:
            job_filters.append(Job.department_id.in_(
                select([Department.id]).where(
                    Department.solicits_volunteers == True)))  # noqa: E712

        jobs = session.jobs().filter(*job_filters)

        return {
            'message': message,
            'show_restricted': show_restricted,
            'show_nonpublic': show_nonpublic,
            'attendees': session.staffers_for_dropdown(),
            'jobs': [job_dict(job) for job in jobs]
        }
Пример #49
0
def match_to_group_preconditions():
    group_id = None
    # leader_id = None
    with Session() as session:
        console = Department(name='Console_01', description='Console_01')
        leader = Attendee(
            first_name='Fearless',
            last_name='Leader',
            email='*****@*****.**',
            zip_code='21211',
            ec_name='Nana Fearless',
            ec_phone='555-555-1234',
            cellphone='555-555-2345',
            birthdate=date(1964, 12, 30),
            registered=localized_now(),
            paid=c.PAID_BY_GROUP,
            badge_type=c.STAFF_BADGE,
            badge_printed_name='Fearmore',
            ribbon='',
            staffing=True,
            assigned_depts=[console])

        group = Group(name='Too Many Badges!')
        group.auto_recalc = False
        group.attendees = [leader]
        group.leader = leader
        session.add(leader)
        session.add(group)
        assert session.assign_badges(
            group,
            4,
            new_badge_type=c.STAFF_BADGE,
            new_ribbon_type='',
            paid=c.PAID_BY_GROUP) is None
        session.flush()

        group_id = group.id
        # leader_id = leader.id

    yield group_id

    with Session() as session:
        session.query(Group).filter(Group.id == group_id).delete(
            synchronize_session=False)
Пример #50
0
    def confirm(self, session, message='', return_to='confirm', undoing_extra='', **params):
        # Safe to ignore csrf tokens here, because an attacker would need to know the attendee id a priori
        attendee = session.attendee(params, restricted=True, ignore_csrf=True)

        if attendee.badge_status == c.REFUNDED_STATUS:
            raise HTTPRedirect('repurchase?id={}', attendee.id)

        placeholder = attendee.placeholder
        if 'email' in params and not message:
            attendee.placeholder = False
            message = check(attendee, prereg=True)
            if not message:
                if placeholder:
                    attendee.confirmed = localized_now()
                    message = 'Your registration has been confirmed'
                else:
                    message = 'Your information has been updated'

                page = ('badge_updated?id=' + attendee.id + '&') if return_to == 'confirm' else (return_to + '?')
                if attendee.amount_unpaid:
                    raise HTTPRedirect('attendee_donation_form?id={}', attendee.id)
                else:
                    raise HTTPRedirect(page + 'message=' + message)

        elif attendee.amount_unpaid and attendee.zip_code and not undoing_extra and cherrypy.request.method == 'POST':
            # Don't skip to payment until the form is filled out
            raise HTTPRedirect('attendee_donation_form?id={}&message={}', attendee.id, message)

        attendee.placeholder = placeholder
        if not message and attendee.placeholder:
            message = 'You are not yet registered!  You must fill out this form to complete your registration.'
        elif not message:
            message = 'You are already registered but you may update your information with this form.'

        return {
            'undoing_extra': undoing_extra,
            'return_to':     return_to,
            'attendee':      attendee,
            'message':       message,
            'affiliates':    session.affiliates(),
            'attractions':   session.query(Attraction).filter_by(is_public=True).all(),
            'badge_cost':    attendee.badge_cost if attendee.paid != c.PAID_BY_GROUP else 0,
        }
Пример #51
0
    def check_if_applied(self, session, message='', **params):
        if cherrypy.request.method == 'POST':
            subject = c.EVENT_NAME_AND_YEAR + ' MITS Team Confirmation'

            if 'email' not in params:
                message = "Please enter an email address."

            if not message:
                last_email = (session.query(Email)
                              .filter(Email.to.ilike(params['email']))
                              .filter_by(subject=subject)
                              .order_by(Email.when.desc()).first())
                if not last_email or last_email.when < (
                            localized_now() - timedelta(days=7)):
                    can_send_email = True
                else:
                    can_send_email = False

                mits_teams = session.query(MITSTeam).all()

                match_counter = 0
                for team in mits_teams:
                    if params['email'] in team.email:
                        match_counter += 1

                        if can_send_email:
                            send_email.delay(
                                c.MITS_EMAIL,
                                params['email'],
                                subject,
                                render('emails/mits/mits_check.txt',
                                       {'team': team}, encoding=None),
                                cc=team.email,
                                model=team.to_dict('id'))

                if match_counter:
                    message = 'We found {} team{}.{}'\
                        .format(match_counter, 's' if match_counter > 1 else '',
                                ' Please check your email for a link to your application.'
                                if can_send_email else ' Please check your spam or junk folder.')

        return {'message': message}
Пример #52
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(to=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.delay(
                        c.REGDESK_EMAIL,
                        attendee.email,
                        subject,
                        render('emails/reg_workflow/prereg_check.txt', {'attendee': attendee}, encoding=None),
                        model=attendee.to_dict('id'))

        return {'message': message}
Пример #53
0
    def new_checkin(self, session, message='', **params):
        attendee = session.attendee(params, allow_invalid=True)
        group = session.group(attendee.group_id) if attendee.group_id else None

        checked_in = ''
        if 'reg_station' not in cherrypy.session:
            raise HTTPRedirect('new_reg_station')

        message = pre_checkin_check(attendee, group)

        if message:
            session.rollback()
        else:
            if group:
                session.match_to_group(attendee, group)
            attendee.checked_in = localized_now()
            attendee.reg_station = cherrypy.session['reg_station']
            message = '{a.full_name} checked in as {a.badge}{a.accoutrements}'.format(a=attendee)
            checked_in = attendee.id
            session.commit()

        raise HTTPRedirect('new?message={}&checked_in={}', message, checked_in)
Пример #54
0
def test_datetime_val(job):
    format = '%Y-%m-%d %H:%M:%S'
    assert job.start_time is None
    now = localized_now()
    job.apply({'start_time': now.strftime(format)}, restricted=False)
    assert job.start_time.strftime(format) == now.strftime(format)
Пример #55
0
def now_localized():
    return localized_now()
Пример #56
0
def duplicate_badge_num_preconditions():
    group_id = None
    leader_id = None
    with Session() as session:
        leader = Attendee(
            first_name='Fearless',
            last_name='Leader',
            email='*****@*****.**',
            zip_code='21211',
            ec_name='Nana Fearless',
            ec_phone='555-555-1234',
            cellphone='555-555-2345',
            birthdate=date(1964, 12, 30),
            registered=localized_now(),
            paid=c.PAID_BY_GROUP,
            ribbon='',
            staffing=True,
            badge_type=c.PSEUDO_GROUP_BADGE)

        group = Group(name='Too Many Badges!')
        group.attendees = [leader]
        group.leader = leader
        session.add(leader)
        session.add(group)
        assert session.assign_badges(
            group,
            15,
            new_badge_type=c.STAFF_BADGE,
            new_ribbon_type='',
            paid=c.NEED_NOT_PAY) is None
        session.flush()

        group_id = group.id
        leader_id = leader.id

    with Session() as session:
        console = Department(name='DEPT_01', description='DEPT_01')
        leader = session.query(Attendee).get(leader_id)
        leader.paid = c.NEED_NOT_PAY
        leader.badge_printed_name = 'Fearmore'
        leader.badge_type = c.STAFF_BADGE
        leader.assigned_depts = [console]

        group = session.query(Group).get(group_id)
        group.auto_recalc = False

    for i in range(10):
        with Session() as session:
            console = session.query(Department).filter_by(name='DEPT_01').one()
            group = session.query(Group).get(group_id)

            is_staff = (i < 9)
            params = {
                'first_name': 'Doubtful',
                'last_name': 'Follower{}'.format(i),
                'email': 'fearsome{}@example.com'.format(i),
                'zip_code': '21211',
                'ec_name': 'Nana Fearless',
                'ec_phone': '555-555-1234',
                'cellphone': '555-555-321{}'.format(i),
                'birthdate': date(1964, 12, 30),
                'registered': localized_now(),
                'staffing': is_staff,
                'badge_status': str(c.COMPLETED_STATUS),
                'badge_printed_name': 'Fears{}'.format(i) if is_staff else '',
                'assigned_depts': [console] if is_staff else ''}

            attendee = group.unassigned[0]
            attendee.apply(params, restricted=False)

        with Session() as session:
            group = session.query(Group).get(group_id)
            badge_nums = [a.badge_num for a in group.attendees]
            # SQLite doesn't support deferred constraints, so our test database
            # doesn't actually have a unique constraint on the badge_num
            # column. So we have to manually check for duplicate badge numbers.
            assert_unique(badge_nums)

    yield group_id

    with Session() as session:
        session.query(Group).filter(Group.id == group_id).delete(
            synchronize_session=False)
Пример #57
0
    MIVSEmailFixture(
        IndieGame,
        'Your MIVS application has been waitlisted',
        'mivs/game_waitlisted.txt',
        lambda game: game.status == c.WAITLISTED,
        ident='mivs_game_waitlisted')

    MIVSEmailFixture(
        IndieGame,
        'Last chance to accept your MIVS booth',
        'mivs/game_accept_reminder.txt',
        lambda game: (
            game.status == c.ACCEPTED
            and not game.confirmed
            and (localized_now() - timedelta(days=2)) > game.studio.confirm_deadline),
        ident='mivs_accept_booth_reminder')

    MIVSEmailFixture(
        IndieGame,
        'MIVS December Updates: Hotels and Magfest Versus!',
        'mivs/december_updates.txt',
        lambda game: game.confirmed,
        ident='mivs_december_updates')

    MIVSEmailFixture(
        IndieGame,
        'REQUIRED: Pre-flight for MIVS due by midnight, January 2nd',
        'mivs/game_preflight.txt',
        lambda game: game.confirmed,
        ident='mivs_game_preflight_reminder')