コード例 #1
0
    def before_create_object(self, data, view_kwargs):
        """
        before create object method for OrderListPost Class
        :param data:
        :param view_kwargs:
        :return:
        """
        for ticket_holder in data['ticket_holders']:
            # Ensuring that the attendee exists and doesn't have an associated order.
            try:
                ticket_holder_object = self.session.query(
                    TicketHolder).filter_by(id=int(ticket_holder),
                                            deleted_at=None).one()
                if ticket_holder_object.order_id:
                    raise ConflictException(
                        {'pointer': '/data/relationships/attendees'},
                        "Order already exists for attendee with id {}".format(
                            str(ticket_holder)))
            except NoResultFound:
                raise ConflictException(
                    {'pointer': '/data/relationships/attendees'},
                    "Attendee with id {} does not exists".format(
                        str(ticket_holder)))

        if data.get('cancel_note'):
            del data['cancel_note']

        if data.get('payment_mode') != 'free' and not data.get('amount'):
            raise ConflictException({'pointer': '/data/attributes/amount'},
                                    "Amount cannot be null for a paid order")

        if not data.get('amount'):
            data['amount'] = 0
        # Apply discount only if the user is not event admin
        if data.get('discount') and not has_access('is_coorganizer',
                                                   event_id=data['event']):
            discount_code = safe_query_without_soft_deleted_entries(
                self, DiscountCode, 'id', data['discount'], 'discount_code_id')
            if not discount_code.is_active:
                raise UnprocessableEntity({'source': 'discount_code_id'},
                                          "Inactive Discount Code")
            else:
                now = datetime.utcnow()
                valid_from = datetime.strptime(discount_code.valid_from,
                                               '%Y-%m-%d %H:%M:%S')
                valid_till = datetime.strptime(discount_code.valid_till,
                                               '%Y-%m-%d %H:%M:%S')
                if not (valid_from <= now <= valid_till):
                    raise UnprocessableEntity({'source': 'discount_code_id'},
                                              "Inactive Discount Code")
                if not TicketingManager.match_discount_quantity(
                        discount_code, data['ticket_holders']):
                    raise UnprocessableEntity({'source': 'discount_code_id'},
                                              'Discount Usage Exceeded')

            if discount_code.event.id != data[
                    'event'] and discount_code.user_for == TICKET:
                raise UnprocessableEntity({'source': 'discount_code_id'},
                                          "Invalid Discount Code")
コード例 #2
0
def create_onsite_attendees_for_order(data):
    """
    Creates on site ticket holders for an order and adds it into the request data.
    :param data: data initially passed in the POST request for order.
    :return:
    """
    on_site_tickets = data.get('on_site_tickets')

    if not on_site_tickets:
        raise UnprocessableEntityError(
            {'pointer': 'data/attributes/on_site_tickets'},
            'on_site_tickets info missing')

    data['ticket_holders'] = []

    for on_site_ticket in on_site_tickets:
        ticket_id = on_site_ticket['id']
        quantity = int(on_site_ticket['quantity'])

        ticket = safe_query_without_soft_deleted_entries(
            Ticket, 'id', ticket_id, 'ticket_id')

        ticket_sold_count = get_count(
            db.session.query(TicketHolder.id).filter_by(ticket_id=int(
                ticket.id),
                                                        deleted_at=None))

        # Check if the ticket is already sold out or not.
        if ticket_sold_count + quantity > ticket.quantity:
            # delete the already created attendees.
            for holder in data['ticket_holders']:
                ticket_holder = (db.session.query(TicketHolder).filter(
                    id == int(holder)).one())
                db.session.delete(ticket_holder)
                try:
                    db.session.commit()
                except Exception:
                    logging.exception('DB Exception!')
                    db.session.rollback()

            raise ConflictError(
                {'pointer': '/data/attributes/on_site_tickets'},
                "Ticket with id: {} already sold out. You can buy at most {} tickets"
                .format(ticket_id, ticket.quantity - ticket_sold_count),
            )

        for _ in range(1, quantity):
            ticket_holder = TicketHolder(
                firstname='onsite',
                lastname='attendee',
                email='*****@*****.**',
                ticket_id=ticket.id,
                event_id=data.get('event'),
            )
            save_to_db(ticket_holder)
            data['ticket_holders'].append(ticket_holder.id)

    # delete from the data.
    del data['on_site_tickets']
コード例 #3
0
def create_onsite_attendees_for_order(data):
    """
    Creates on site ticket holders for an order and adds it into the request data.
    :param data: data initially passed in the POST request for order.
    :return:
    """
    on_site_tickets = data.get('on_site_tickets')

    if not on_site_tickets:
        raise UnprocessableEntity({'pointer': 'data/attributes/on_site_tickets'}, 'on_site_tickets info missing')

    data['ticket_holders'] = []

    for on_site_ticket in on_site_tickets:
        ticket_id = on_site_ticket['id']
        quantity = int(on_site_ticket['quantity'])

        ticket = safe_query_without_soft_deleted_entries(db, Ticket, 'id', ticket_id, 'ticket_id')

        ticket_sold_count = get_count(db.session.query(TicketHolder.id).
                                      filter_by(ticket_id=int(ticket.id), deleted_at=None))

        # Check if the ticket is already sold out or not.
        if ticket_sold_count + quantity > ticket.quantity:
            # delete the already created attendees.
            for holder in data['ticket_holders']:
                ticket_holder = db.session.query(TicketHolder).filter(id == int(holder)).one()
                db.session.delete(ticket_holder)
                try:
                    db.session.commit()
                except Exception as e:
                    logging.error('DB Exception! %s' % e)
                    db.session.rollback()

            raise ConflictException(
                {'pointer': '/data/attributes/on_site_tickets'},
                "Ticket with id: {} already sold out. You can buy at most {} tickets".format(ticket_id,
                                                                                             ticket.quantity -
                                                                                             ticket_sold_count)
            )

        for _ in range(1, quantity):
            ticket_holder = TicketHolder(firstname='onsite', lastname='attendee', email='*****@*****.**',
                                         ticket_id=ticket.id, event_id=data.get('event'))
            save_to_db(ticket_holder)
            data['ticket_holders'].append(ticket_holder.id)

    # delete from the data.
    del data['on_site_tickets']
コード例 #4
0
    def before_create_object(self, data, view_kwargs):
        """
        before create object method for OrderListPost Class
        :param data:
        :param view_kwargs:
        :return:
        """
        for ticket_holder in data['ticket_holders']:
            # Ensuring that the attendee exists and doesn't have an associated order.
            try:
                ticket_holder_object = self.session.query(TicketHolder).filter_by(id=int(ticket_holder),
                                                                                  deleted_at=None).one()
                if ticket_holder_object.order_id:
                    raise ConflictException({'pointer': '/data/relationships/attendees'},
                                            "Order already exists for attendee with id {}".format(str(ticket_holder)))
            except NoResultFound:
                raise ConflictException({'pointer': '/data/relationships/attendees'},
                                        "Attendee with id {} does not exists".format(str(ticket_holder)))

        if data.get('cancel_note'):
            del data['cancel_note']

        if data.get('payment_mode') != 'free' and not data.get('amount'):
            raise ConflictException({'pointer': '/data/attributes/amount'},
                                    "Amount cannot be null for a paid order")

        # Apply discount only if the user is not event admin
        if data.get('discount') and not has_access('is_coorganizer', event_id=data['event']):
            discount_code = safe_query_without_soft_deleted_entries(self, DiscountCode, 'id', data['discount'],
                                                                    'discount_code_id')
            if not discount_code.is_active:
                raise UnprocessableEntity({'source': 'discount_code_id'}, "Inactive Discount Code")
            else:
                now = datetime.utcnow()
                valid_from = datetime.strptime(discount_code.valid_from, '%Y-%m-%d %H:%M:%S')
                valid_till = datetime.strptime(discount_code.valid_till, '%Y-%m-%d %H:%M:%S')
                if not (valid_from <= now <= valid_till):
                    raise UnprocessableEntity({'source': 'discount_code_id'}, "Inactive Discount Code")
                if not TicketingManager.match_discount_quantity(discount_code, data['ticket_holders']):
                    raise UnprocessableEntity({'source': 'discount_code_id'}, 'Discount Usage Exceeded')

            if discount_code.event.id != data['event'] and discount_code.user_for == TICKET:
                raise UnprocessableEntity({'source': 'discount_code_id'}, "Invalid Discount Code")
コード例 #5
0
def calculate_order_amount(tickets, discount_code):
    from app.api.helpers.ticketing import TicketingManager
    if discount_code:
        if not TicketingManager.match_discount_quantity(discount_code, tickets, None):
            return UnprocessableEntityError({'source': 'discount-code'}, 'Discount Usage Exceeded').respond()

    event = tax = tax_included = fees = None
    total_amount = total_tax = total_discount = 0.0
    ticket_list = []
    for ticket_info in tickets:
        tax_amount = tax_percent = 0.0
        tax_data = {}
        discount_amount = discount_percent = 0.0
        discount_data = {}
        sub_total = ticket_fee = 0.0

        ticket_identifier = ticket_info['id']
        quantity = ticket_info['quantity']
        ticket = safe_query_without_soft_deleted_entries(db, Ticket, 'id', ticket_identifier, 'id')
        if not event:
            event = ticket.event
            fees = TicketFees.query.filter_by(currency=event.payment_currency).first()
        elif ticket.event.id != event.id:
            raise UnprocessableEntity({'source': 'data/tickets'}, "Invalid Ticket")

        if not tax and event.tax:
            tax = event.tax
            tax_included = tax.is_tax_included_in_price

        if ticket.type == 'donation':
            price = ticket_info.get('price')
            if not price or price > ticket.max_price or price < ticket.min_price:
                raise UnprocessableEntity({'source': 'data/tickets'}, "Price for donation ticket invalid")
        else:
            price = ticket.price

        if discount_code:
            for code in ticket.discount_codes:
                if discount_code.id == code.id:
                    if code.type == 'amount':
                        discount_amount = code.value
                        discount_percent = (discount_amount / price) * 100
                    else:
                        discount_amount = (price * code.value)/100
                        discount_percent = code.value
                    discount_data = {
                        'code': discount_code.code,
                        'percent': round(discount_percent, 2),
                        'amount': round(discount_amount, 2)
                    }

        if tax:
            if not tax_included:
                tax_amount = ((price - discount_amount) * tax.rate)/100
                tax_percent = tax.rate
            else:
                tax_amount = ((price - discount_amount) * tax.rate)/(100 + tax.rate)
                tax_percent = tax.rate
            tax_data = {
                'percent': round(tax_percent, 2),
                'amount': round(tax_amount, 2),
            }

        total_tax = total_tax + tax_amount * quantity
        total_discount = total_discount + discount_amount*quantity
        if fees and not ticket.is_fee_absorbed:
            ticket_fee = fees.service_fee * (price * quantity) / 100
            if ticket_fee > fees.maximum_fee:
                ticket_fee = fees.maximum_fee
        if tax_included:
            sub_total = ticket_fee + (price - discount_amount)*quantity
        else:
            sub_total = ticket_fee + (price + tax_amount - discount_amount)*quantity
        total_amount = total_amount + sub_total
        ticket_list.append({
            'id': ticket.id,
            'name': ticket.name,
            'price': price,
            'quantity': quantity,
            'discount': discount_data,
            'tax': tax_data,
            'ticket_fee': round(ticket_fee, 2),
            'sub_total': round(sub_total, 2)
        })
    return dict(tax_included=tax_included, total_amount=round(total_amount, 2), total_tax=round(total_tax, 2),
                total_discount=round(total_discount, 2), tickets=ticket_list)