Ejemplo n.º 1
0
    def before_create_object(self, data, view_kwargs):
        """
        before create object method for OrderListPost Class
        :param data:
        :param view_kwargs:
        :return:
        """
        validate_attendees(data['ticket_holders'])

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

        if data.get('payment_mode') != 'free' and not data.get('amount'):
            raise ConflictError(
                {'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_code') and not has_access(
                'is_coorganizer', event_id=data['event']):
            validate_discount_code(
                data['discount_code'],
                ticket_holders=data['ticket_holders'],
                event_id=data['event'],
            )
Ejemplo n.º 2
0
def calculate_order_amount(tickets, discount_code=None):
    from app.api.helpers.ticketing import validate_discount_code, validate_tickets
    from app.models.discount_code import DiscountCode

    ticket_ids = {ticket['id'] for ticket in tickets}
    ticket_map = {int(ticket['id']): ticket for ticket in tickets}
    fetched_tickets = validate_tickets(ticket_ids)

    if tickets and discount_code:
        discount_code = validate_discount_code(discount_code, tickets=tickets)

    event = tax = tax_included = fees = None
    total_amount = total_tax = total_discount = 0.0
    ticket_list = []
    for ticket in fetched_tickets:
        ticket_info = ticket_map[ticket.id]
        discount_amount = 0.0
        discount_data = None
        ticket_fee = 0.0

        quantity = ticket_info.get('quantity', 1)  # Default to single ticket
        if not event:
            event = ticket.event

            if event.deleted_at:
                raise ObjectNotFound({'pointer': 'tickets/event'},
                                     f'Event: {event.id} not found')

            fees = TicketFees.query.filter_by(
                currency=event.payment_currency).first()

        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 UnprocessableEntityError(
                    {'pointer': 'tickets/price'},
                    f"Price for donation ticket should be present and within range "
                    f"{ticket.min_price} to {ticket.max_price}",
                )
        else:
            price = ticket.price if ticket.type != 'free' else 0.0

        if discount_code and ticket.type != 'free':
            code = (DiscountCode.query.with_parent(ticket).filter_by(
                id=discount_code.id).first())
            if code:
                if discount_code.id == code.id:
                    if code.type == 'amount':
                        discount_amount = min(code.value, price)
                        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),
                        'total': round(discount_amount * quantity, 2),
                    }

        total_discount += round(discount_amount * quantity, 2)
        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
        sub_total = ticket_fee + (price - 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,
            'ticket_fee': round(ticket_fee, 2),
            'sub_total': round(sub_total, 2),
        })

    sub_total = total_amount
    tax_dict = None
    if tax:
        if tax_included:
            total_tax = total_amount - total_amount / (1 + tax.rate / 100)
        else:
            total_tax = total_amount * tax.rate / 100
            total_amount += total_tax
        tax_dict = dict(
            included=tax_included,
            amount=round(total_tax, 2),
            percent=tax.rate if tax else 0.0,
            name=tax.name,
        )

    return dict(
        tax=tax_dict,
        sub_total=round(sub_total, 2),
        total=round(total_amount, 2),
        discount=round(total_discount, 2),
        tickets=ticket_list,
    )
def test_validate_discount_code_id(db):
    discount, tickets = _create_discount_code(db)

    assert validate_discount_code(discount.id, tickets=tickets) == discount
    assert validate_discount_code(str(discount.id),
                                  tickets=tickets) == discount
Ejemplo n.º 4
0
 def validate(self, tickets=None, ticket_holders=None, event_id=None):
     return validate_discount_code(self,
                                   tickets=tickets,
                                   ticket_holders=ticket_holders,
                                   event_id=event_id)