Beispiel #1
0
def create_tickets(order):
    """Creates tickets for an order."""
    if has_created_tickets(order):
        return  # no need to create tickets

    if order.meta.get('users_allocate'):
        multi_users = order.meta.get('users_allocate')
        multi_users = multi_users.get('ids')
        multi_users.insert(0, order.user_id)
    else:
        multi_users = None

    amount = 0
    for ticketorder in order.get_ticketorders():
        for i in range(ticketorder.amount):
            if multi_users and multi_users[amount]:
                ticket = Ticket(ticketorder.id, multi_users[amount])
            else:
                ticket = Ticket(ticketorder.id, order.user_id)
            ticketorder.tickets.append(ticket)
            Session.flush()
            blogger.info("created ticket %s, code %s." %
                         (ticket.id, ticket.get_code()))
            amount += 1

    log_crm("order", order.id, dict(action="created tickets", amount=amount))
    return amount
Beispiel #2
0
def timeout_sessions(max_allowed_duration=600):
    """
    Times out all order sessions that have been created outside a specific 
    time. 
    
    Args:
        max_allowed_duration: amount of seconds an order has before it 
                              times out.
    
    Returns:
        The amount of orders that were timed out.
    """
    try:
        # calculate the datetime of the oldest allowed session
        begin_time = datetime.datetime.utcnow() - datetime.timedelta(
            seconds=max_allowed_duration)
        # fetch all order sessions before this datetime
        orders = Session.query(Order).filter(Order.session_start < begin_time)\
                                     .filter(Order.status.in_([STARTED]))
        # time out found orders
        total = 0
        for order in orders:
            log_crm("order", order.id, dict(action="timeout"))
            order.timeout()
            # update ticket type availability
            for tickettype in order.get_ticket_types():
                update_availability.apply_async(args=[tickettype.id],
                                                countdown=2)
            total += 1
        return total
    except Exception as e:
        tlogger.exception("failed timing out sessions")
Beispiel #3
0
 def checkout(self, user=None):
     """ Locks the order and logs the checkout in the database """
     if self.user_id is None and user is not None:
         self.user = user
     self.lock()
     blogger.info("checkout order %s" % self.id)
     log_crm("order", self.id, dict(action="checkout"))
Beispiel #4
0
 def timeout(self):
     """
     Marks the ``Order`` as timed out and removes
     all associated ``TicketOrder``s.
     """
     blogger.debug("timeout order %s" % self.id)
     log_crm("order", self.id, dict(action="timeout"))
     self.status = TIMEOUT
Beispiel #5
0
 def cancel(self):
     """
     Marks the ``Order`` as cancelled and removes 
     all associated ``TicketOrder``s.
     """
     blogger.info("cancelling order %s" % self.id)
     log_crm("order", self.id, dict(action="cancel"))
     self.status = CANCELLED
Beispiel #6
0
def mail_ticket(ticket_id, fake=False):
    """ Sends a ticket to the user. """
    try:
        ticket = lookup_ticket_by_id(ticket_id)
        event = get_event_of_ticket(ticket)
        order = ticket.ticket_order.order

        env = Environment(loader=PackageLoader('tickee', 'templates'),
                          extensions=['jinja2.ext.with_'])
        body = env.get_template('mail_ticket.html')\
                  .render(ticket=ticket,
                          account=order.account,
                          event=event,
                          order=order,
                          as_guest=False)

        body_plain = env.get_template('mail_ticket.txt')\
                        .render(ticket=ticket,
                                account=order.account,
                                event=event,
                                order=order,
                                as_guest=False)

        # send generated mail
        blogger.info('sending mail for ticket %s to user %s (%s)' %
                     (ticket.id, ticket.user.id, ticket.user.email))

        validate_email(ticket.user.email)

        if not ticket.user.email:
            raise ex.OrderError("user has no email.")

        if not fake:
            send_email("Tickee Ticketing <*****@*****.**>", ticket.user.email,
                       "Your ticket for '%s' is here!" % event.name, body,
                       body_plain)

        log_crm("ticket", ticket.id,
                dict(action="mailed", addressee=ticket.user.email))
        transaction.commit()
        return True

    except Exception as e:
        try:
            email = ticket.user.email
        except:
            email = "no mail found."
        log_crm("ticket", ticket_id, dict(action="mail failed",
                                          addressee=email))
        transaction.commit()
        tlogger.exception("failed sending mail for ticket %s: %s" %
                          (ticket_id, e))
        return False
Beispiel #7
0
def add_tickets(order, tickettype_id, amount):
    """
    Will update the order to include the new amount for a tickettype.
    A pre-existing ticketorder for that tickettype will be updated, else
    a new ticketorder will be created.
    
    The following conditions have to be met:
        -  the order has not been locked or confirmed for purchase
        -  the amount is more than 0
        -  there exists a ticket_type matching the id
        -  the ``TicketType`` is set to active
        -  there are still enough tickets available
        -  the ``TicketType`` is owned by the account connected to the order
        
    When tickets are added to an order, the availabilty of the TicketType
    might change from AVAILABLE to CLAIMED
    
    Raises:
        InvalidAmountError
        OrderLockedError
        TicketTypeNotFoundError
        InactiveTicketTypeError
        AmountNotAvailableError
    """
    # valid amount check
    if amount < 0:
        blogger.debug('failed adding invalid amount %s to order %s' % (amount, order.id))
        raise ex.InvalidAmountError("You must purchase at least one ticket.")
    # order is not locked
    if order.is_locked() or order.status == PURCHASED:
        blogger.debug('failed adding to locked order %s' % order.id)
        raise ex.OrderLockedError("No other tickets can be added to this order.")
    # tickettype exists
    tickettype = lookup_tickettype_by_id(tickettype_id)
    # active tickettype check
    if not tickettype.is_active:
        blogger.debug('failed adding inactive tickettype %s to order %s' % (tickettype_id, order.id))
        raise ex.InactiveTicketTypeError("The ticket type is not active.")
    # tickettype is connected to an event
    if tickettype.get_event() is None:
        raise ex.EventNotFoundError("The tickettype is not connected to any event.")
    # tickettype is owned by account connected to the order
    if order.account != tickettype.get_event().account:
        raise ex.AccountError("only orders for tickettypes of account %s possible" % order.account.id)
    # there are still transactions available for the account or it is a free tickettype.
    if not (has_available_transactions(order.account) or tickettype.is_free()):
        raise ex.SubscriptionError("account has reached maximum allowed transactions.")
    
    ticketorder = order.ordered_tickets.filter(TicketOrder.ticket_type_id==tickettype_id).first()
    
    # creates new ticketorder if none found
    if not ticketorder:
        # check if ticketorder contains one or more tickets
        if amount <= 0:
            raise ex.AmountNotAvailableError('at least 1 ticket required')
        # check if tickettype still has enough available
        if not order.meta.get('gifted', False) and not order.meta.get('paper', False) and not tickettype.has_available(amount):
            blogger.info('failed to add unavailable amount %s of tickettype %s to order %s'\
                          % (amount, tickettype_id, order.id))
            raise ex.AmountNotAvailableError("Not enough tickets available.")
        ticketorder = TicketOrder(order.id, tickettype_id, amount)
        blogger.info('created ticketorder for order %s (%sx tickettype %s)'\
                     % (order.id, amount, tickettype_id))
        log_crm("order", order.id, dict(action="add",
                                        tickettype_id=tickettype_id,
                                        amount=amount))
        Session.add(ticketorder)
    
    # updates amount of existing one
    else:
        if amount == 0:
            # remove ticketorder if amount is 0
            Session.delete(ticketorder)
        else:
            # check if additional amount is still available
            additional_tickets = amount - ticketorder.amount
            if not order.meta.get('gifted', False) and additional_tickets >= 0 and not tickettype.has_available(additional_tickets):
                blogger.debug('failed to add unavailable amount %s of tickettype %s to order %s'\
                              % (amount, tickettype_id, order.id))
                raise ex.AmountNotAvailableError("Not enough tickets available.")
            ticketorder.amount = amount
        
        # report update
        blogger.info('updated ticketorder %s for order %s (%sx tickettype %s)'\
                     % (ticketorder.id, order.id, amount, tickettype_id))
        log_crm("order", order.id, dict(action="update",
                                        tickettype_id=tickettype_id,
                                        amount=amount))
    order.touch()
    update_availability.delay(tickettype.id)
    Session.flush()
Beispiel #8
0
def mail_order(order_id, fake=False, as_guest=False, auto_retry=False):
    """
    Sends the mail of the order to the user.
    """
    # fetch information for template
    try:
        order = om.lookup_order_by_id(order_id)

        # generate template
        env = Environment(loader=PackageLoader('tickee', 'templates'),
                          extensions=['jinja2.ext.with_'])

        validate_email(order.user.email)

        if not order.user.email:
            raise ex.OrderError("user has no email.")

        if len(order.get_tickets()) == 0:
            raise ex.TicketError("no tickets found.")

        # send out a mail per event
        tickets_per_event = order.get_tickets_per_event()
        for event in tickets_per_event:
            tickets = tickets_per_event[event]

            # send generated mail
            blogger.info(
                'sending mail for "order %s - event %s" to user %s (%s)' %
                (order_id, event.id, order.user.id, order.user.email))

            if not fake:
                htmlbody = env.get_template('mail_order_of_event.html')\
                              .render(event=event,
                                      tickets=tickets,
                                      order=order,
                                      as_guest=as_guest,
                                      account=order.account)
                plainbody = env.get_template('mail_order_of_event.txt')\
                               .render(event=event,
                                       tickets=tickets,
                                       order=order,
                                       as_guest=as_guest,
                                       account=order.account)

                send_email("Tickee Ticketing <*****@*****.**>",
                           order.user.email,
                           "Your tickets for '%s' are here!" % event.name,
                           htmlbody, plainbody)

        order.meta['tickets_sent'] = datetime.datetime.utcnow().strftime(
            "%d-%m-%Y %H:%M:%S UTC%z")
        log_crm("order", order.id,
                dict(action="mailed", addressee=order.user.email))
        transaction.commit()
        return True
    except Exception as e:
        tlogger.exception("failed sending mail for order %s: %s" %
                          (order_id, e))
        order.meta['tickets_sent'] = "failed @ %s" % datetime.datetime.utcnow(
        ).strftime("%d-%m-%Y %H:%M:%S UTC%z")
        transaction.commit()
        if auto_retry:
            mail_order.retry(exc=e)
        return False