Example #1
0
def create_order():
    data, errors = OrderAmountInputSchema().load(request.get_json())
    if errors:
        return make_response(jsonify(errors), 422)

    tickets_dict = data['tickets']
    order_amount = calculate_order_amount(tickets_dict, data.get('discount_code'))
    ticket_ids = {ticket['id'] for ticket in tickets_dict}
    ticket_map = {int(ticket['id']): ticket for ticket in tickets_dict}
    tickets = (
        Ticket.query.filter_by(deleted_at=None).filter(Ticket.id.in_(ticket_ids)).all()
    )

    if not tickets:
        raise UnprocessableEntityError(
            {'source': 'tickets'},
            "Tickets missing in Order request",
        )

    event = tickets[0].event

    try:
        attendees = []
        for ticket in tickets:
            for _ in range(ticket_map[ticket.id]['quantity']):
                ticket.raise_if_unavailable()
                attendees.append(
                    TicketHolder(firstname='', lastname='', ticket=ticket, event=event)
                )
                db.session.commit()
    except Exception as e:
        db.session.rollback()
        raise e

    validate_attendees({attendee.id for attendee in attendees})

    if data.get('amount') is not None and (
        current_user.is_staff or has_access('is_coorganizer', event_id=event.id)
    ):
        # If organizer or admin has overrided the amount of order
        order_amount['total'] = data['amount']

    order = Order(
        amount=order_amount['total'],
        event=event,
        discount_code_id=data.get('discount_code'),
        ticket_holders=attendees,
    )
    db.session.commit()
    order.populate_and_save()

    order_tickets = OrderTicket.query.filter_by(order_id=order.id).all()
    for order_ticket in order_tickets:
        ticket_info = ticket_map[order_ticket.ticket.id]
        order_ticket.price = ticket_info.get('price')
        save_to_db(order_ticket)
    
    return OrderSchema().dump(order)
Example #2
0
def create_order():
    data, errors = OrderAmountInputSchema().load(request.get_json())
    if errors:
        return make_response(jsonify(errors), 422)

    tickets_dict = data['tickets']
    order_amount = calculate_order_amount(tickets_dict, data.get('discount_code'))
    ticket_ids = {ticket['id'] for ticket in tickets_dict}
    ticket_map = {int(ticket['id']): ticket for ticket in tickets_dict}
    tickets = (
        Ticket.query.filter_by(deleted_at=None).filter(Ticket.id.in_(ticket_ids)).all()
    )

    if not tickets:
        raise UnprocessableEntityError(
            {'source': 'tickets'}, "Tickets missing in Order request",
        )

    event = tickets[0].event

    try:
        attendees = []
        for ticket in tickets:
            for _ in range(ticket_map[ticket.id]['quantity']):
                ticket.raise_if_unavailable()
                attendees.append(
                    TicketHolder(firstname='', lastname='', ticket=ticket, event=event)
                )
                db.session.commit()
    except Exception as e:
        db.session.rollback()
        raise e

    validate_attendees({attendee.id for attendee in attendees})
    order = Order(
        amount=order_amount['total'],
        event=event,
        discount_code_id=data.get('discount_code'),
        ticket_holders=attendees,
    )
    db.session.commit()
    order.populate_and_save()

    return OrderSchema().dumps(order)
Example #3
0
    def add_target(self, data, obj):
        if obj.target is None:
            # handler -> if target data is deleted after generation of notification.
            # to be implemented in future -> delete notification if target is deleted ex. RoleInvite.
            return {}
        event = None
        if obj.target_type == 'Order':
            serialized = normalize_jsonapi_data(
                OrderSchema(only=('id', 'amount', 'identifier')), obj.target
            )
            data['order'] = serialized
            event = obj.target.event
        elif obj.target_type == 'Session':
            serialized = normalize_jsonapi_data(
                SessionSchema(only=('id', 'title')), obj.target
            )
            data['session'] = serialized
            event = obj.target.event
        elif obj.target_type == 'EventInvoice':
            serialized = normalize_jsonapi_data(
                EventInvoiceSchema(
                    only=('id', 'identifier', 'amount', 'issued_at', 'due_at', 'status')
                ),
                obj.target,
            )
            data['invoice'] = serialized
            event = obj.target.event
        elif obj.target_type == 'RoleInvite':
            serialized = normalize_jsonapi_data(RoleInviteSchema(), obj.target)
            data['event_invite'] = serialized
            data['role'] = normalize_jsonapi_data(RoleSchema(), obj.target.role)
            event = obj.target.event

        if event:
            data['event'] = normalize_jsonapi_data(
                EventSchemaPublic(only=('id', 'name', 'identifier')), obj.target.event
            )
        return data
Example #4
0
def create_order():
    data = request.get_json()
    tickets, discount_code = calculate_order_amount_wrapper(data)
    attendee = data['attendee']
    for attribute in attendee:
        attendee[attribute.replace('-', '_')] = attendee.pop(attribute)
    schema = AttendeeSchema()
    json_api_attendee = {
        "data": {
            "attributes": data['attendee'],
            "type": "attendee"
        }
    }
    result = schema.load(json_api_attendee)
    if result.errors:
        return make_response(jsonify(result.errors), 422)
    ticket_ids = {int(ticket['id']) for ticket in tickets}
    quantity = {int(ticket['id']): ticket['quantity'] for ticket in tickets}
    ticket_list = (db.session.query(Ticket).filter(
        Ticket.id.in_(ticket_ids)).filter_by(event_id=data['event_id'],
                                             deleted_at=None).all())
    ticket_ids_found = {
        ticket_information.id
        for ticket_information in ticket_list
    }
    tickets_not_found = ticket_ids - ticket_ids_found
    if tickets_not_found:
        return make_response(
            jsonify(
                status='Order Unsuccessful',
                error='Tickets with id {} were not found in Event {}.'.format(
                    tickets_not_found, data['event_id']),
            ),
            404,
        )
    for ticket_info in ticket_list:
        if (ticket_info.quantity - get_count(
                db.session.query(TicketHolder.id).filter_by(
                    ticket_id=int(ticket_info.id),
                    deleted_at=None))) < quantity[ticket_info.id]:
            return make_response(
                jsonify(status='Order Unsuccessful',
                        error='Ticket already sold out.'),
                409,
            )
    attendee_list = []
    for ticket in tickets:
        for ticket_amount in range(ticket['quantity']):
            attendee = TicketHolder(**result[0],
                                    event_id=int(data['event_id']),
                                    ticket_id=int(ticket['id']))
            db.session.add(attendee)
            attendee_list.append(attendee)
    ticket_pricing = calculate_order_amount(tickets, discount_code)
    if not has_access('is_coorganizer', event_id=data['event_id']):
        data['status'] = 'initializing'
    # create on site attendees
    # check if order already exists for this attendee.
    # check for free tickets and verified user
    order = Order(
        amount=ticket_pricing['total_amount'],
        user_id=current_user.id,
        event_id=int(data['event_id']),
        status=data['status'],
    )
    db.session.add(order)
    db.session.commit()
    db.session.refresh(order)
    order_tickets = {}
    for holder in attendee_list:
        holder.order_id = order.id
        db.session.add(holder)
        if not order_tickets.get(holder.ticket_id):
            order_tickets[holder.ticket_id] = 1
        else:
            order_tickets[holder.ticket_id] += 1

    create_pdf_tickets_for_holder(order)

    for ticket in order_tickets:
        od = OrderTicket(order_id=order.id,
                         ticket_id=ticket,
                         quantity=order_tickets[ticket])
        db.session.add(od)

    order.quantity = order.tickets_count
    db.session.add(order)
    db.session.commit()
    db.session.refresh(order)
    order_schema = OrderSchema()
    return order_schema.dump(order)
Example #5
0
def complete_order(order_id):
    data = request.get_json()
    for attribute in data:
        data[attribute.replace('-', '_')] = data.pop(attribute)
    order = Order.query.filter_by(id=order_id).first()
    order_schema = OrderSchema()
    if (not has_access('is_coorganizer', event_id=order.event_id)) and (
            not current_user.id == order.user_id):
        return make_response(
            jsonify(status='Access Forbidden',
                    error='You cannot update an order.'), 403)
    if has_access('is_coorganizer',
                  event_id=order.event_id) and 'status' in data:
        if data['status'] != 'cancelled':
            return make_response(
                jsonify(status='Access Forbidden',
                        error='You can only cancel an order.'),
                403,
            )
        elif data['status'] == 'cancelled':
            order.status = 'cancelled'
            db.session.add(order)
            attendees = (db.session.query(TicketHolder).filter_by(
                order_id=order_id, deleted_at=None).all())
            for attendee in attendees:
                attendee.deleted_at = datetime.now(pytz.utc)
                db.session.add(attendee)
            db.session.commit()
            send_order_cancel_email(order)
            send_notif_ticket_cancel(order)
            return order_schema.dump(order)
    updated_attendees = data['attendees']
    for updated_attendee in updated_attendees:
        for attribute in updated_attendee:
            updated_attendee[attribute.replace(
                '-', '_')] = updated_attendee.pop(attribute)
    if get_count(db.session.query(TicketHolder).filter_by(
            order_id=order_id)) != len(updated_attendees):
        return make_response(
            jsonify(
                status='Unprocessable Entity',
                error='You need to provide info of all attendees.',
            ),
            422,
        )
    else:
        attendees = (db.session.query(TicketHolder).filter_by(
            order_id=order_id, deleted_at=None).all())
    form_fields = (db.session.query(CustomForms).filter_by(
        event_id=order.event_id, form='attendee', is_included=True).all())
    for attendee, updated_attendee in zip(attendees, updated_attendees):
        for field in form_fields:
            if (field.is_required is True
                    and field.field_identifier not in updated_attendee):
                return make_response(
                    jsonify(
                        status='Unprocessable Entity',
                        error='{} is a required field.'.format(
                            field.field_identifier),
                    ),
                    422,
                )
            if field.field_identifier in updated_attendee:
                setattr(
                    attendee,
                    field.field_identifier,
                    updated_attendee[field.field_identifier],
                )
        db.session.add(attendee)
    # modified_at not getting filled
    if order.amount == 0:
        order.status = 'completed'
        order.completed_at = datetime.utcnow()
    elif order.amount > 0:
        if 'payment_mode' not in data:
            return make_response(
                jsonify(status='Unprocessable Entity',
                        error='Payment mode not specified.'),
                422,
            )
        if data['payment_mode'] in ['bank', 'cheque', 'onsite']:
            order.status = 'placed'
            order.completed_at = datetime.utcnow()
        else:
            order.status = 'pending'
        if 'is_billing_enabled' in data:
            if data['is_billing_enabled']:
                if (('company' not in data) or ('address' not in data)
                        or ('city' not in data) or ('zipcode' not in data)
                        or ('country' not in data)):
                    return make_response(
                        jsonify(
                            status='Unprocessable Entity',
                            error='Billing information incomplete.',
                        ),
                        422,
                    )
            else:
                return make_response(
                    jsonify(
                        status='Unprocessable Entity',
                        error='Billing information incomplete.',
                    ),
                    422,
                )
        else:
            return make_response(
                jsonify(
                    status='Unprocessable Entity',
                    error='Billing information is mandatory '
                    'for this order.',
                ),
                422,
            )
        order.company = data['company']
        order.address = data['address']
        order.city = data['city']
        order.zipcode = data['zipcode']
        order.country = data['country']
        order.payment_mode = data['payment_mode']
        if 'state' in data:
            order.state = data['state']
        if 'tax_business_info' in data:
            order.tax_business_info = data['tax_business_info']
    db.session.add(order)
    db.session.commit()
    create_pdf_tickets_for_holder(order)
    if (order.status == 'completed'
            or order.status == 'placed') and (order.deleted_at is None):
        order_identifier = order.identifier

        key = UPLOAD_PATHS['pdf']['tickets_all'].format(
            identifier=order_identifier)
        ticket_path = (
            'generated/tickets/{}/{}/'.format(key, generate_hash(key)) +
            order_identifier + '.pdf')

        key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)
        invoice_path = (
            'generated/invoices/{}/{}/'.format(key, generate_hash(key)) +
            order_identifier + '.pdf')

        # send email and notifications.
        send_email_to_attendees(
            order=order,
            purchaser_id=current_user.id,
            attachments=[ticket_path, invoice_path],
        )

        send_notif_to_attendees(order, current_user.id)
        order_url = make_frontend_url(path='/orders/{identifier}'.format(
            identifier=order.identifier))
        for organizer in order.event.organizers:
            send_notif_ticket_purchase_organizer(
                organizer,
                order.invoice_number,
                order_url,
                order.event.name,
                order.identifier,
            )
        if order.event.owner:
            send_notif_ticket_purchase_organizer(
                order.event.owner,
                order.invoice_number,
                order_url,
                order.event.name,
                order.identifier,
            )

    return order_schema.dump(order)