示例#1
0
def resend_emails():
    """
    Sends confirmation email for pending and completed orders on organizer request
    :param order_identifier:
    :return: JSON response if the email was succesfully sent
    """
    order_identifier = request.json['data']['order']
    order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
    if (has_access('is_coorganizer', event_id=order.event_id)):
        if order.status == 'completed' or order.status == 'placed':
            # fetch tickets attachment
            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.
            send_email_to_attendees(order=order, purchaser_id=current_user.id, attachments=[ticket_path, invoice_path])
            return jsonify(status=True, message="Verification emails for order : {} has been sent succesfully".
                           format(order_identifier))
        else:
            return UnprocessableEntityError({'source': 'data/order'},
                                            "Only placed and completed orders have confirmation").respond()
    else:
        return ForbiddenError({'source': ''}, "Co-Organizer Access Required").respond()
示例#2
0
    def after_update_object(self, order, data, view_kwargs):
        """
        :param order:
        :param data:
        :param view_kwargs:
        :return:
        """
        # create pdf tickets.
        create_pdf_tickets_for_holder(order)

        if order.status == 'cancelled' and order.deleted_at is None:
            send_order_cancel_email(order)
            send_notif_ticket_cancel(order)

            # delete the attendees so that the tickets are unlocked.
            delete_related_attendees_for_order(order)

        elif (order.status == 'completed'
              or order.status == 'placed') and order.deleted_at is None:
            # Send email to attendees with invoices and tickets attached
            order_identifier = order.identifier

            key = UPLOAD_PATHS['pdf']['ticket_attendee'].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)

            if order.payment_mode in ['free', 'bank', 'cheque', 'onsite']:
                order.completed_at = datetime.utcnow()

            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)
示例#3
0
    def test_generate_hash(self):
        """Test generation of hash for a key."""

        secret_key = 'secret_key'
        test_input = 'case1'
        exepected_output = 'WUFCV0xHVk'
        actual_output = generate_hash(test_input, secret_key)
        self.assertEqual(exepected_output, actual_output)
        self.assertEqual(len(actual_output), 10)

        test_input = '/static/uploads/pdf/temp/'
        exepected_output = 'MzRueVhjY0'
        actual_output = generate_hash(test_input, secret_key)
        self.assertEqual(exepected_output, actual_output)
        self.assertEqual(len(actual_output), 10)
示例#4
0
def order_invoices(order_identifier):
    if current_user:
        try:
            order = Order.query.filter_by(identifier=order_identifier).first()
        except NoResultFound:
            return NotFoundError({
                'source': ''
            }, 'Order Invoice not found').respond()
        if current_user.can_download_tickets(order):
            key = UPLOAD_PATHS['pdf']['order'].format(
                identifier=order_identifier)
            file_path = ('../generated/invoices/{}/{}/'.format(
                key, generate_hash(key)) + order_identifier + '.pdf')
            try:
                return return_file('invoice', file_path, order_identifier)
            except FileNotFoundError:
                create_pdf_tickets_for_holder(order)
                return return_file('invoice', file_path, order_identifier)
        else:
            return ForbiddenError({
                'source': ''
            }, 'Unauthorized Access').respond()
    else:
        return ForbiddenError({
            'source': ''
        }, 'Authentication Required to access Invoice').respond()
示例#5
0
def ticket_attendee_authorized(order_identifier):
    if current_user:
        try:
            order = Order.query.filter_by(identifier=order_identifier).first()
        except NoResultFound:
            raise NotFoundError({'source': ''},
                                'This ticket is not associated with any order')
        if (has_access(
                'is_coorganizer_or_user_itself',
                event_id=order.event_id,
                user_id=order.user_id,
        ) or order.is_attendee(current_user)):
            key = UPLOAD_PATHS['pdf']['tickets_all'].format(
                identifier=order_identifier)
            file_path = (
                '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) +
                order_identifier + '.pdf')
            try:
                return return_file('ticket', file_path, order_identifier)
            except FileNotFoundError:
                create_pdf_tickets_for_holder(order)
                return return_file('ticket', file_path, order_identifier)
        else:
            raise ForbiddenError({'source': ''}, 'Unauthorized Access')
    else:
        raise ForbiddenError({'source': ''},
                             'Authentication Required to access ticket')
示例#6
0
def event_invoices(invoice_identifier):
    if not current_user:
        raise ForbiddenError({'source': ''},
                             'Authentication Required to access Invoice')
    try:
        event_invoice = EventInvoice.query.filter_by(
            identifier=invoice_identifier).first()
        event_id = event_invoice.event_id
    except NoResultFound:
        raise NotFoundError({'source': ''}, 'Event Invoice not found')
    if not current_user.is_organizer(event_id) and not current_user.is_staff:
        raise ForbiddenError({'source': ''}, 'Unauthorized Access')
    key = UPLOAD_PATHS['pdf']['event_invoices'].format(
        identifier=invoice_identifier)
    file_path = (
        '../generated/invoices/{}/{}/'.format(key, generate_hash(key)) +
        invoice_identifier + '.pdf')
    try:
        return return_file('event-invoice', file_path, invoice_identifier)
    except FileNotFoundError:
        raise ObjectNotFound(
            {'source': ''},
            "The Event Invoice isn't available at the moment. \
                             Invoices are usually issued on the 1st of every month",
        )
示例#7
0
def ticket_attendee_authorized(order_identifier):
    if current_user:
        try:
            order = Order.query.filter_by(identifier=order_identifier).first()
        except NoResultFound:
            return NotFoundError({
                'source': ''
            }, 'This ticket is not associated with any order').respond()
        if current_user.can_download_tickets(order):
            key = UPLOAD_PATHS['pdf']['tickets_all'].format(
                identifier=order_identifier)
            file_path = (
                '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) +
                order_identifier + '.pdf')
            try:
                return return_file('ticket', file_path, order_identifier)
            except FileNotFoundError:
                create_pdf_tickets_for_holder(order)
                return return_file('ticket', file_path, order_identifier)
        else:
            return ForbiddenError({
                'source': ''
            }, 'Unauthorized Access').respond()
    else:
        return ForbiddenError({
            'source': ''
        }, 'Authentication Required to access ticket').respond()
 def pdf_url_path(self) -> str:
     key = UPLOAD_PATHS['pdf']['tickets_all'].format(
         identifier=self.order.identifier, extra_identifier=self.id
     )
     return (
         'generated/tickets/{}/{}/'.format(key, generate_hash(key))
         + self.order.identifier
         + '.pdf'
     )
示例#9
0
def create_save_resized_image(image_file, basewidth=None, maintain_aspect=None, height_size=None, upload_path=None,
                              ext='jpg', remove_after_upload=False, resize=True):
    """
    Create and Save the resized version of the background image
    :param resize:
    :param upload_path:
    :param ext:
    :param remove_after_upload:
    :param height_size:
    :param maintain_aspect:
    :param basewidth:
    :param image_file:
    :return:
    """
    if not image_file:
        return None
    filename = '{filename}.{ext}'.format(filename=get_file_name(), ext=ext)
    data = urllib.request.urlopen(image_file).read()
    image_file = io.BytesIO(data)
    try:
        im = Image.open(image_file)
    except IOError:
        raise IOError("Corrupt/Invalid Image")

    # Convert to jpeg for lower file size.
    if im.format != 'JPEG':
        img = im.convert('RGB')
    else:
        img = im

    if resize:
        if maintain_aspect:
            width_percent = (basewidth / float(img.size[0]))
            height_size = int((float(img.size[1]) * float(width_percent)))

        img = img.resize((basewidth, height_size), PIL.Image.ANTIALIAS)

    temp_file_relative_path = 'static/media/temp/' + generate_hash(str(image_file)) + get_file_name() + '.jpg'
    temp_file_path = app.config['BASE_DIR'] + '/' + temp_file_relative_path
    dir_path = temp_file_path.rsplit('/', 1)[0]

    # create dirs if not present
    if not os.path.isdir(dir_path):
        os.makedirs(dir_path)

    img.save(temp_file_path)
    upfile = UploadedFile(file_path=temp_file_path, filename=filename)

    if remove_after_upload:
        # os.remove(image_file) No point in removing in memory file
        pass

    uploaded_url = upload(upfile, upload_path)
    os.remove(temp_file_path)

    return uploaded_url
示例#10
0
def create_save_resized_image(image_file, basewidth=None, maintain_aspect=None, height_size=None, upload_path=None,
                              ext='jpg', remove_after_upload=False, resize=True):
    """
    Create and Save the resized version of the background image
    :param resize:
    :param upload_path:
    :param ext:
    :param remove_after_upload:
    :param height_size:
    :param maintain_aspect:
    :param basewidth:
    :param image_file:
    :return:
    """
    if not image_file:
        return None
    filename = '{filename}.{ext}'.format(filename=get_file_name(), ext=ext)
    data = urllib.request.urlopen(image_file).read()
    image_file = io.BytesIO(data)
    try:
        im = Image.open(image_file)
    except IOError:
        raise IOError("Corrupt/Invalid Image")

    # Convert to jpeg for lower file size.
    if im.format is not 'JPEG':
        img = im.convert('RGB')
    else:
        img = im

    if resize:
        if maintain_aspect:
            width_percent = (basewidth / float(img.size[0]))
            height_size = int((float(img.size[1]) * float(width_percent)))

        img = img.resize((basewidth, height_size), PIL.Image.ANTIALIAS)

    temp_file_relative_path = 'static/media/temp/' + generate_hash(str(image_file)) + get_file_name() + '.jpg'
    temp_file_path = app.config['BASE_DIR'] + '/' + temp_file_relative_path
    dir_path = temp_file_path.rsplit('/', 1)[0]

    # create dirs if not present
    if not os.path.isdir(dir_path):
        os.makedirs(dir_path)

    img.save(temp_file_path)
    upfile = UploadedFile(file_path=temp_file_path, filename=filename)

    if remove_after_upload:
        # os.remove(image_file) No point in removing in memory file
        pass

    uploaded_url = upload(upfile, upload_path)
    os.remove(temp_file_path)

    return uploaded_url
示例#11
0
def on_order_completed(order):
    # send e-mail and notifications if the order status is completed
    if not (order.status == 'completed' or order.status == 'placed'):
        return
    # fetch tickets attachment
    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)

    if order.payment_mode in ['free', 'bank', 'cheque', 'onsite']:
        order.completed_at = datetime.utcnow()

    order_url = make_frontend_url(path='/orders/{identifier}'.format(
        identifier=order.identifier))
    for organizer in set(order.event.organizers + order.event.coorganizers +
                         [order.event.owner]):
        if not organizer:
            continue
        send_notif_ticket_purchase_organizer(
            organizer,
            order.invoice_number,
            order_url,
            order.event.name,
            order.identifier,
        )
示例#12
0
def create_system_image(image_file=None,
                        upload_path=None,
                        unique_identifier=None,
                        ext='jpg'):
    """
    Create System Images for Event Topics
    :param upload_path:
    :param ext:
    :param remove_after_upload:
    :param image_file:
    :return:
    """
    # Get an unique identifier from uuid if not provided
    filename = '{filename}.{ext}'.format(filename=get_file_name(), ext=ext)
    if image_file:
        with urllib.request.urlopen(image_file) as img_data:
            image_file = io.BytesIO(img_data.read())
    else:
        file_relative_path = 'static/default_system_image.png'
        image_file = current_app.config['BASE_DIR'] + '/' + file_relative_path
    try:
        im = Image.open(image_file)
    except IOError:
        raise IOError("Corrupt/Invalid Image")

    # Convert to jpeg for lower file size.
    if im.format != 'JPEG':
        img = im.convert('RGB')
    else:
        img = im

    temp_file_relative_path = ('static/media/temp/' +
                               generate_hash(str(image_file)) +
                               get_file_name() + '.jpg')
    temp_file_path = current_app.config[
        'BASE_DIR'] + '/' + temp_file_relative_path
    dir_path = temp_file_path.rsplit('/', 1)[0]

    # create dirs if not present
    if not os.path.isdir(dir_path):
        os.makedirs(dir_path)

    img.save(temp_file_path)
    upfile = UploadedFile(file_path=temp_file_path, filename=filename)

    if not upload_path:
        upload_path = UPLOAD_PATHS['event_topic']['system_image'].format(
            event_topic_id=unique_identifier)

    uploaded_url = upload(upfile, upload_path)
    os.remove(temp_file_path)

    image = {'system_image_url': uploaded_url}
    return image
示例#13
0
def create_system_image(image_file=None, upload_path=None, unique_identifier=None,
                        ext='jpg'):
    """
    Create System Images for Event Topics
    :param upload_path:
    :param ext:
    :param remove_after_upload:
    :param image_file:
    :return:
    """
    # Get an unique identifier from uuid if not provided
    filename = '{filename}.{ext}'.format(filename=get_file_name(), ext=ext)
    if image_file:
        with urllib.request.urlopen(image_file) as img_data:
            image_file = io.BytesIO(img_data.read())
    else:
        file_relative_path = 'static/default_system_image.png'
        image_file = app.config['BASE_DIR'] + '/' + file_relative_path
    try:
        im = Image.open(image_file)
    except IOError:
        raise IOError("Corrupt/Invalid Image")

    # Convert to jpeg for lower file size.
    if im.format is not 'JPEG':
        img = im.convert('RGB')
    else:
        img = im

    temp_file_relative_path = 'static/media/temp/' + generate_hash(str(image_file)) + get_file_name() + '.jpg'
    temp_file_path = app.config['BASE_DIR'] + '/' + temp_file_relative_path
    dir_path = temp_file_path.rsplit('/', 1)[0]

    # create dirs if not present
    if not os.path.isdir(dir_path):
        os.makedirs(dir_path)

    img.save(temp_file_path)
    upfile = UploadedFile(file_path=temp_file_path, filename=filename)

    if not upload_path:
        upload_path = UPLOAD_PATHS['event_topic']['system_image'].format(event_topic_id=unique_identifier)

    uploaded_url = upload(upfile, upload_path)
    os.remove(temp_file_path)

    image = {'system_image_url': uploaded_url}
    return image
示例#14
0
def order_invoices(order_identifier):
    if current_user:
        try:
            order = Order.query.filter_by(identifier=order_identifier).first()
            user_id = order.user.id
        except NoResultFound:
            return NotFoundError({'source': ''}, 'Order Invoice not found').respond()
        if current_user.id == user_id:
            key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)
            file_path = '../generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
            response = make_response(send_file(file_path))
            response.headers['Content-Disposition'] = 'attachment; filename=invoice-%s.zip' % order_identifier
            return response
        else:
            return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()
    else:
        return ForbiddenError({'source': ''}, 'Authentication Required to access Invoice').respond()
示例#15
0
def ticket_attendee_authorized(order_identifier):
    if current_user:
        try:
            order = Order.query.filter_by(identifier=order_identifier).first()
            user_id = order.user.id
        except NoResultFound:
            return NotFoundError({'source': ''}, 'This ticket is not associated with any order').respond()
        if current_user.id == user_id:
            key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)
            file_path = '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
            try:
                response = make_response(send_file(file_path))
                response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.zip' % order_identifier
                return response
            except FileNotFoundError:
                create_pdf_tickets_for_holder(order)
                return redirect(url_for('ticket_blueprint.ticket_attendee_authorized', order_identifier=order_identifier))
        else:
            return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()
    else:
        return ForbiddenError({'source': ''}, 'Authentication Required to access ticket').respond()
示例#16
0
 def invoice_pdf_path(self) -> str:
     key = UPLOAD_PATHS['pdf']['order'].format(identifier=self.identifier)
     return ('generated/invoices/{}/{}/'.format(key, generate_hash(key)) +
             self.identifier + '.pdf')
示例#17
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)
示例#18
0
    def after_create_object(self, order, data, view_kwargs):
        """
        after create object method for OrderListPost Class
        :param order: Object created from mashmallow_jsonapi
        :param data:
        :param view_kwargs:
        :return:
        """
        order_tickets = {}
        for holder in order.ticket_holders:
            save_to_db(holder)
            if not order_tickets.get(holder.ticket_id):
                order_tickets[holder.ticket_id] = 1
            else:
                order_tickets[holder.ticket_id] += 1

        order.user = current_user

        # create pdf tickets.
        create_pdf_tickets_for_holder(order)

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

        order.quantity = order.tickets_count
        save_to_db(order)
        #         if not has_access('is_coorganizer', event_id=data['event']):
        #             TicketingManager.calculate_update_amount(order)

        # send e-mail and notifications if the order status is completed
        if order.status == 'completed' or order.status == 'placed':
            # fetch tickets attachment
            order_identifier = order.identifier

            key = UPLOAD_PATHS['pdf']['ticket_attendee'].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)

            if order.payment_mode in ['free', 'bank', 'cheque', 'onsite']:
                order.completed_at = datetime.utcnow()

            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)

        data['user_id'] = current_user.id