# Buggy code
def before_update_object(self, order, data, view_kwargs):
    """
    before update object method of order details
    1. admin can update all the fields.
    2. event organizer
        a. own orders: he/she can update selected fields.
        b. other's orders: can only update the status that too when the order mode is free. No refund system.
    3. order user can update selected fields of his/her order when the status is pending.
    The selected fields mentioned above can be taken from get_updatable_fields method from order model.
    :param order:
    :param data:
    :param view_kwargs:
    :return:
    """
    if (not has_access("is_coorganizer", event_id=order.event_id)) and (
        not current_user.id == order.user_id
    ):
        raise ForbiddenException({"pointer": ""}, "Access Forbidden")

    if has_access("is_coorganizer_but_not_admin", event_id=order.event_id):
        if current_user.id == order.user_id:
            # Order created from the tickets tab.
            for element in data:
                if (
                    data[element] != getattr(order, element, None)
                    and element not in Order.get_updatable_fields()
                ):
                    raise ForbiddenException(
                        {"pointer": "data/{}".format(element)},
                        "You cannot update {} of an order".format(element),
                    )

        else:
            # Order created from the public pages.
            for element in data:
                if data[element] != getattr(order, element, None):
                    if element != "status":
                        raise ForbiddenException(
                            {"pointer": "data/{}".format(element)},
                            "You cannot update {} of an order".format(element),
                        )
                    elif (
                        element == "status"
                        and order.amount
                        and order.status == "completed"
                    ):
                        # Since we don't have a refund system.
                        raise ForbiddenException(
                            {"pointer": "data/status"},
                            "You cannot update the status of a completed paid order",
                        )
                    elif element == "status" and order.status == "cancelled":
                        # Since the tickets have been unlocked and we can't revert it.
                        raise ForbiddenException(
                            {"pointer": "data/status"},
                            "You cannot update the status of a cancelled order",
                        )

    elif current_user.id == order.user_id:
        if order.status != "pending":
            raise ForbiddenException(
                {"pointer": ""}, "You cannot update a non-pending order"
            )
        else:
            for element in data:
                if (
                    data[element] != getattr(order, element, None)
                    and element not in Order.get_updatable_fields()
                ):
                    raise ForbiddenException(
                        {"pointer": "data/{}".format(element)},
                        "You cannot update {} of an order".format(element),
                    )

    if "order_notes" in data:
        if order.order_notes and data["order_notes"] not in order.order_notes.split(
            ","
        ):
            data["order_notes"] = "{},{}".format(order.order_notes, data["order_notes"])


# Traceback (AttributeError)
INFO:werkzeug:127.0.0.1 - - [12/Jul/2018 01:54:15] "PATCH /v1/orders/1 HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/rs/Pradeep/github/open-event-server/app/__init__.py", line 66, in __call__
return self.app(environ, start_response)
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/rs/Pradeep/github/open-event-server/app/api/helpers/permissions.py", line 45, in decorator
return fn(*args, **kwargs)
File "/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/decorators.py", line 32, in wrapper
return func(*args, **kwargs)
File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/resource.py", line 68, in dispatch_request
response = method(*args, **kwargs)
File "/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/decorators.py", line 56, in wrapper
return func(*args, **kwargs)
File "/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/resource.py", line 307, in patch
self._data_layer.update_object(obj, data, kwargs)
File "/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/data_layers/alchemy.py", line 126, in update_object
self.before_update_object(obj, data, view_kwargs)
File "/home/rs/Pradeep/github/open-event-server/app/api/orders.py", line 233, in before_update_object
if data[element] != getattr(order, element, None) and element not in Order.get_updatable_fields():
AttributeError: type object 'Order' has no attribute 'get_updatable_fields'

# Fixed code
def before_update_object(self, order, data, view_kwargs):
    """
    before update object method of order details
    1. admin can update all the fields.
    2. event organizer
        a. own orders: he/she can update selected fields.
        b. other's orders: can only update the status that too when the order mode is free. No refund system.
    3. order user can update selected fields of his/her order when the status is pending.
    The selected fields mentioned above can be taken from get_updatable_fields method from order model.
    :param order:
    :param data:
    :param view_kwargs:
    :return:
    """
    if (not has_access("is_coorganizer", event_id=order.event_id)) and (
        not current_user.id == order.user_id
    ):
        raise ForbiddenException({"pointer": ""}, "Access Forbidden")

    if has_access("is_coorganizer_but_not_admin", event_id=order.event_id):
        if current_user.id == order.user_id:
            # Order created from the tickets tab.
            for element in data:
                if (
                    data[element] != getattr(order, element, None)
                    and element not in get_updatable_fields()
                ):
                    raise ForbiddenException(
                        {"pointer": "data/{}".format(element)},
                        "You cannot update {} of an order".format(element),
                    )

        else:
            # Order created from the public pages.
            for element in data:
                if data[element] != getattr(order, element, None):
                    if element != "status":
                        raise ForbiddenException(
                            {"pointer": "data/{}".format(element)},
                            "You cannot update {} of an order".format(element),
                        )
                    elif (
                        element == "status"
                        and order.amount
                        and order.status == "completed"
                    ):
                        # Since we don't have a refund system.
                        raise ForbiddenException(
                            {"pointer": "data/status"},
                            "You cannot update the status of a completed paid order",
                        )
                    elif element == "status" and order.status == "cancelled":
                        # Since the tickets have been unlocked and we can't revert it.
                        raise ForbiddenException(
                            {"pointer": "data/status"},
                            "You cannot update the status of a cancelled order",
                        )

    elif current_user.id == order.user_id:
        if order.status != "pending":
            raise ForbiddenException(
                {"pointer": ""}, "You cannot update a non-pending order"
            )
        else:
            for element in data:
                if (
                    data[element] != getattr(order, element, None)
                    and element not in get_updatable_fields()
                ):
                    raise ForbiddenException(
                        {"pointer": "data/{}".format(element)},
                        "You cannot update {} of an order".format(element),
                    )

    if "order_notes" in data:
        if order.order_notes and data["order_notes"] not in order.order_notes.split(
            ","
        ):
            data["order_notes"] = "{},{}".format(order.order_notes, data["order_notes"])