We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Charging user with stripe token throws internal server error when sending email to attendees
**Describe the bug**
Charging user with stripe token sends 500 (Internal Server Error).

**Expected behavior**
Request should succeed successfully.

**Stacktrace**
```
INFO:werkzeug:127.0.0.1 - - [26/Jul/2018 22:43:56] "POST /v1/orders/46aeab2e-36c2-49c4-9b48-9e6e81b55deb/charge? 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 67, 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 204, in post
    obj = self._data_layer.create_object(data, kwargs)
  File "/home/rs/Pradeep/github/open-event-server/app/api/data_layers/ChargesLayer.py", line 46, in create_object
    success, response = TicketingManager.charge_stripe_order_payment(order, data['stripe'])
  File "/home/rs/Pradeep/github/open-event-server/app/api/helpers/ticketing.py", line 122, in charge_stripe_order_payment
    send_email_to_attendees(order, current_user.id)
  File "/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/werkzeug/local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
AttributeError: 'AnonymousUserMixin' object has no attribute 'id'
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `app/api/helpers/ticketing.py`
Content:
```
1 from datetime import datetime
2 
3 from flask_login import current_user
4 
5 from app.api.helpers.db import save_to_db, get_count
6 from app.api.helpers.exceptions import ConflictException
7 from app.api.helpers.files import make_frontend_url
8 from app.api.helpers.mail import send_email_to_attendees
9 from app.api.helpers.notification import send_notif_to_attendees, send_notif_ticket_purchase_organizer
10 from app.api.helpers.order import delete_related_attendees_for_order, create_pdf_tickets_for_holder
11 from app.api.helpers.payment import StripePaymentsManager, PayPalPaymentsManager
12 from app.models import db
13 from app.models.ticket_fee import TicketFees
14 from app.models.ticket_holder import TicketHolder
15 
16 
17 class TicketingManager(object):
18     """All ticketing and orders related helper functions"""
19 
20     @staticmethod
21     def get_order_expiry():
22         return 10
23 
24     @staticmethod
25     def match_discount_quantity(discount_code, ticket_holders=None):
26         qty = 0
27         old_holders = get_count(TicketHolder.query.filter(TicketHolder.ticket_id.in_(discount_code.tickets.split(","))))
28 
29         for holder in ticket_holders:
30             ticket_holder = TicketHolder.query.filter_by(id=holder).one()
31             if ticket_holder.ticket.id in discount_code.tickets.split(","):
32                 qty += 1
33         if (qty+old_holders) <= discount_code.tickets_number and \
34            discount_code.min_quantity <= qty <= discount_code.max_quantity:
35             return True
36 
37         return False
38 
39     @staticmethod
40     def calculate_update_amount(order):
41         discount = None
42         if order.discount_code_id:
43             discount = order.discount_code
44         # Access code part will be done ticket_holders API
45         amount = 0
46         total_discount = 0
47         fees = TicketFees.query.filter_by(currency=order.event.payment_currency).first()
48 
49         for order_ticket in order.order_tickets:
50             with db.session.no_autoflush:
51                 if order_ticket.ticket.is_fee_absorbed or not fees:
52                     ticket_amount = (order_ticket.ticket.price * order_ticket.quantity)
53                     amount += (order_ticket.ticket.price * order_ticket.quantity)
54                 else:
55                     order_fee = fees.service_fee * (order_ticket.ticket.price * order_ticket.quantity) / 100
56                     if order_fee > fees.maximum_fee:
57                         ticket_amount = (order_ticket.ticket.price * order_ticket.quantity) + fees.maximum_fee
58                         amount += (order_ticket.ticket.price * order_ticket.quantity) + fees.maximum_fee
59                     else:
60                         ticket_amount = (order_ticket.ticket.price * order_ticket.quantity) + order_fee
61                         amount += (order_ticket.ticket.price * order_ticket.quantity) + order_fee
62 
63                 if discount and str(order_ticket.ticket.id) in discount.tickets.split(","):
64                     if discount.type == "amount":
65                         total_discount += discount.value * order_ticket.quantity
66                     else:
67                         total_discount += discount.value * ticket_amount / 100
68 
69         if discount:
70             if discount.type == "amount":
71                 order.amount = max(amount - total_discount, 0)
72             elif discount.type == "percent":
73                 order.amount = amount - (discount.value * amount / 100.0)
74         else:
75             order.amount = amount
76         save_to_db(order)
77         return order
78 
79     @staticmethod
80     def charge_stripe_order_payment(order, token_id):
81         """
82         Charge the user through Stripe
83         :param order: Order for which to charge for
84         :param token_id: Stripe token
85         :return:
86         """
87         # save the stripe token with the order
88         order.stripe_token = token_id
89         save_to_db(order)
90 
91         # charge the user
92         try:
93             charge = StripePaymentsManager.capture_payment(order)
94         except ConflictException as e:
95             # payment failed hence expire the order
96             order.status = 'expired'
97             save_to_db(order)
98 
99             # delete related attendees to unlock the tickets
100             delete_related_attendees_for_order(order)
101 
102             raise e
103 
104         # charge.paid is true if the charge succeeded, or was successfully authorized for later capture.
105         if charge.paid:
106             # update the order in the db.
107             order.paid_via = 'stripe'
108             order.payment_mode = charge.source.object
109             order.brand = charge.source.brand
110             order.exp_month = charge.source.exp_month
111             order.exp_year = charge.source.exp_year
112             order.last4 = charge.source.last4
113             order.transaction_id = charge.id
114             order.status = 'completed'
115             order.completed_at = datetime.utcnow()
116             save_to_db(order)
117 
118             # create tickets.
119             create_pdf_tickets_for_holder(order)
120 
121             # send email and notifications.
122             send_email_to_attendees(order, current_user.id)
123             send_notif_to_attendees(order, current_user.id)
124 
125             order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))
126             for organizer in order.event.organizers:
127                 send_notif_ticket_purchase_organizer(organizer, order.invoice_number, order_url, order.event.name)
128 
129             return True, 'Charge successful'
130         else:
131             # payment failed hence expire the order
132             order.status = 'expired'
133             save_to_db(order)
134 
135             # delete related attendees to unlock the tickets
136             delete_related_attendees_for_order(order)
137 
138             # return the failure message from stripe.
139             return False, charge.failure_message
140 
141     @staticmethod
142     def charge_paypal_order_payment(order, paypal_payer_id, paypal_payment_id):
143         """
144         Charge the user through paypal.
145         :param order: Order for which to charge for.
146         :param paypal_payment_id: payment_id
147         :param paypal_payer_id: payer_id
148         :return:
149         """
150 
151         # save the paypal payment_id with the order
152         order.paypal_token = paypal_payment_id
153         save_to_db(order)
154 
155         # create the transaction.
156         status, error = PayPalPaymentsManager.execute_payment(paypal_payer_id, paypal_payment_id)
157 
158         if status:
159             # successful transaction hence update the order details.
160             order.paid_via = 'paypal'
161             order.status = 'completed'
162             order.transaction_id = paypal_payment_id
163             order.completed_at = datetime.utcnow()
164             save_to_db(order)
165 
166             # create tickets
167             create_pdf_tickets_for_holder(order)
168 
169             # send email and notifications
170             send_email_to_attendees(order, order.user_id)
171             send_notif_to_attendees(order, order.user_id)
172 
173             order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))
174             for organizer in order.event.organizers:
175                 send_notif_ticket_purchase_organizer(organizer, order.invoice_number, order_url, order.event.name)
176 
177             return True, 'Charge successful'
178         else:
179             # payment failed hence expire the order
180             order.status = 'expired'
181             save_to_db(order)
182 
183             # delete related attendees to unlock the tickets
184             delete_related_attendees_for_order(order)
185 
186             # return the error message from Paypal
187             return False, error
188
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/app/api/helpers/ticketing.py b/app/api/helpers/ticketing.py
--- a/app/api/helpers/ticketing.py
+++ b/app/api/helpers/ticketing.py
@@ -1,6 +1,6 @@
 from datetime import datetime
 
-from flask_login import current_user
+from flask_jwt import current_identity as current_user
 
 from app.api.helpers.db import save_to_db, get_count
 from app.api.helpers.exceptions import ConflictException

{"golden_diff": "diff --git a/app/api/helpers/ticketing.py b/app/api/helpers/ticketing.py\n--- a/app/api/helpers/ticketing.py\n+++ b/app/api/helpers/ticketing.py\n@@ -1,6 +1,6 @@\n from datetime import datetime\n \n-from flask_login import current_user\n+from flask_jwt import current_identity as current_user\n \n from app.api.helpers.db import save_to_db, get_count\n from app.api.helpers.exceptions import ConflictException\n", "issue": "Charging user with stripe token throws internal server error when sending email to attendees\n**Describe the bug**\r\nCharging user with stripe token sends 500 (Internal Server Error).\r\n\r\n**Expected behavior**\r\nRequest should succeed successfully.\r\n\r\n**Stacktrace**\r\n```\r\nINFO:werkzeug:127.0.0.1 - - [26/Jul/2018 22:43:56] \"POST /v1/orders/46aeab2e-36c2-49c4-9b48-9e6e81b55deb/charge? HTTP/1.1\" 500 -\r\nTraceback (most recent call last):\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 2309, in __call__\r\n    return self.wsgi_app(environ, start_response)\r\n  File \"/home/rs/Pradeep/github/open-event-server/app/__init__.py\", line 67, in __call__\r\n    return self.app(environ, start_response)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 2295, in wsgi_app\r\n    response = self.handle_exception(e)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py\", line 161, in wrapped_function\r\n    return cors_after_request(app.make_response(f(*args, **kwargs)))\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py\", line 161, in wrapped_function\r\n    return cors_after_request(app.make_response(f(*args, **kwargs)))\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 1741, in handle_exception\r\n    reraise(exc_type, exc_value, tb)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/_compat.py\", line 35, in reraise\r\n    raise value\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 2292, in wsgi_app\r\n    response = self.full_dispatch_request()\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 1815, in full_dispatch_request\r\n    rv = self.handle_user_exception(e)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py\", line 161, in wrapped_function\r\n    return cors_after_request(app.make_response(f(*args, **kwargs)))\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask_cors/extension.py\", line 161, in wrapped_function\r\n    return cors_after_request(app.make_response(f(*args, **kwargs)))\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 1718, in handle_user_exception\r\n    reraise(exc_type, exc_value, tb)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/_compat.py\", line 35, in reraise\r\n    raise value\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 1813, in full_dispatch_request\r\n    rv = self.dispatch_request()\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/app.py\", line 1799, in dispatch_request\r\n    return self.view_functions[rule.endpoint](**req.view_args)\r\n  File \"/home/rs/Pradeep/github/open-event-server/app/api/helpers/permissions.py\", line 45, in decorator\r\n    return fn(*args, **kwargs)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/decorators.py\", line 32, in wrapper\r\n    return func(*args, **kwargs)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/flask/views.py\", line 88, in view\r\n    return self.dispatch_request(*args, **kwargs)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/resource.py\", line 68, in dispatch_request\r\n    response = method(*args, **kwargs)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/decorators.py\", line 56, in wrapper\r\n    return func(*args, **kwargs)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/src/flask-rest-jsonapi/flask_rest_jsonapi/resource.py\", line 204, in post\r\n    obj = self._data_layer.create_object(data, kwargs)\r\n  File \"/home/rs/Pradeep/github/open-event-server/app/api/data_layers/ChargesLayer.py\", line 46, in create_object\r\n    success, response = TicketingManager.charge_stripe_order_payment(order, data['stripe'])\r\n  File \"/home/rs/Pradeep/github/open-event-server/app/api/helpers/ticketing.py\", line 122, in charge_stripe_order_payment\r\n    send_email_to_attendees(order, current_user.id)\r\n  File \"/home/rs/Pradeep/github/open-event-server/env/lib/python3.5/site-packages/werkzeug/local.py\", line 347, in __getattr__\r\n    return getattr(self._get_current_object(), name)\r\nAttributeError: 'AnonymousUserMixin' object has no attribute 'id'\r\n```\n", "before_files": [{"content": "from datetime import datetime\n\nfrom flask_login import current_user\n\nfrom app.api.helpers.db import save_to_db, get_count\nfrom app.api.helpers.exceptions import ConflictException\nfrom app.api.helpers.files import make_frontend_url\nfrom app.api.helpers.mail import send_email_to_attendees\nfrom app.api.helpers.notification import send_notif_to_attendees, send_notif_ticket_purchase_organizer\nfrom app.api.helpers.order import delete_related_attendees_for_order, create_pdf_tickets_for_holder\nfrom app.api.helpers.payment import StripePaymentsManager, PayPalPaymentsManager\nfrom app.models import db\nfrom app.models.ticket_fee import TicketFees\nfrom app.models.ticket_holder import TicketHolder\n\n\nclass TicketingManager(object):\n    \"\"\"All ticketing and orders related helper functions\"\"\"\n\n    @staticmethod\n    def get_order_expiry():\n        return 10\n\n    @staticmethod\n    def match_discount_quantity(discount_code, ticket_holders=None):\n        qty = 0\n        old_holders = get_count(TicketHolder.query.filter(TicketHolder.ticket_id.in_(discount_code.tickets.split(\",\"))))\n\n        for holder in ticket_holders:\n            ticket_holder = TicketHolder.query.filter_by(id=holder).one()\n            if ticket_holder.ticket.id in discount_code.tickets.split(\",\"):\n                qty += 1\n        if (qty+old_holders) <= discount_code.tickets_number and \\\n           discount_code.min_quantity <= qty <= discount_code.max_quantity:\n            return True\n\n        return False\n\n    @staticmethod\n    def calculate_update_amount(order):\n        discount = None\n        if order.discount_code_id:\n            discount = order.discount_code\n        # Access code part will be done ticket_holders API\n        amount = 0\n        total_discount = 0\n        fees = TicketFees.query.filter_by(currency=order.event.payment_currency).first()\n\n        for order_ticket in order.order_tickets:\n            with db.session.no_autoflush:\n                if order_ticket.ticket.is_fee_absorbed or not fees:\n                    ticket_amount = (order_ticket.ticket.price * order_ticket.quantity)\n                    amount += (order_ticket.ticket.price * order_ticket.quantity)\n                else:\n                    order_fee = fees.service_fee * (order_ticket.ticket.price * order_ticket.quantity) / 100\n                    if order_fee > fees.maximum_fee:\n                        ticket_amount = (order_ticket.ticket.price * order_ticket.quantity) + fees.maximum_fee\n                        amount += (order_ticket.ticket.price * order_ticket.quantity) + fees.maximum_fee\n                    else:\n                        ticket_amount = (order_ticket.ticket.price * order_ticket.quantity) + order_fee\n                        amount += (order_ticket.ticket.price * order_ticket.quantity) + order_fee\n\n                if discount and str(order_ticket.ticket.id) in discount.tickets.split(\",\"):\n                    if discount.type == \"amount\":\n                        total_discount += discount.value * order_ticket.quantity\n                    else:\n                        total_discount += discount.value * ticket_amount / 100\n\n        if discount:\n            if discount.type == \"amount\":\n                order.amount = max(amount - total_discount, 0)\n            elif discount.type == \"percent\":\n                order.amount = amount - (discount.value * amount / 100.0)\n        else:\n            order.amount = amount\n        save_to_db(order)\n        return order\n\n    @staticmethod\n    def charge_stripe_order_payment(order, token_id):\n        \"\"\"\n        Charge the user through Stripe\n        :param order: Order for which to charge for\n        :param token_id: Stripe token\n        :return:\n        \"\"\"\n        # save the stripe token with the order\n        order.stripe_token = token_id\n        save_to_db(order)\n\n        # charge the user\n        try:\n            charge = StripePaymentsManager.capture_payment(order)\n        except ConflictException as e:\n            # payment failed hence expire the order\n            order.status = 'expired'\n            save_to_db(order)\n\n            # delete related attendees to unlock the tickets\n            delete_related_attendees_for_order(order)\n\n            raise e\n\n        # charge.paid is true if the charge succeeded, or was successfully authorized for later capture.\n        if charge.paid:\n            # update the order in the db.\n            order.paid_via = 'stripe'\n            order.payment_mode = charge.source.object\n            order.brand = charge.source.brand\n            order.exp_month = charge.source.exp_month\n            order.exp_year = charge.source.exp_year\n            order.last4 = charge.source.last4\n            order.transaction_id = charge.id\n            order.status = 'completed'\n            order.completed_at = datetime.utcnow()\n            save_to_db(order)\n\n            # create tickets.\n            create_pdf_tickets_for_holder(order)\n\n            # send email and notifications.\n            send_email_to_attendees(order, current_user.id)\n            send_notif_to_attendees(order, current_user.id)\n\n            order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))\n            for organizer in order.event.organizers:\n                send_notif_ticket_purchase_organizer(organizer, order.invoice_number, order_url, order.event.name)\n\n            return True, 'Charge successful'\n        else:\n            # payment failed hence expire the order\n            order.status = 'expired'\n            save_to_db(order)\n\n            # delete related attendees to unlock the tickets\n            delete_related_attendees_for_order(order)\n\n            # return the failure message from stripe.\n            return False, charge.failure_message\n\n    @staticmethod\n    def charge_paypal_order_payment(order, paypal_payer_id, paypal_payment_id):\n        \"\"\"\n        Charge the user through paypal.\n        :param order: Order for which to charge for.\n        :param paypal_payment_id: payment_id\n        :param paypal_payer_id: payer_id\n        :return:\n        \"\"\"\n\n        # save the paypal payment_id with the order\n        order.paypal_token = paypal_payment_id\n        save_to_db(order)\n\n        # create the transaction.\n        status, error = PayPalPaymentsManager.execute_payment(paypal_payer_id, paypal_payment_id)\n\n        if status:\n            # successful transaction hence update the order details.\n            order.paid_via = 'paypal'\n            order.status = 'completed'\n            order.transaction_id = paypal_payment_id\n            order.completed_at = datetime.utcnow()\n            save_to_db(order)\n\n            # create tickets\n            create_pdf_tickets_for_holder(order)\n\n            # send email and notifications\n            send_email_to_attendees(order, order.user_id)\n            send_notif_to_attendees(order, order.user_id)\n\n            order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))\n            for organizer in order.event.organizers:\n                send_notif_ticket_purchase_organizer(organizer, order.invoice_number, order_url, order.event.name)\n\n            return True, 'Charge successful'\n        else:\n            # payment failed hence expire the order\n            order.status = 'expired'\n            save_to_db(order)\n\n            # delete related attendees to unlock the tickets\n            delete_related_attendees_for_order(order)\n\n            # return the error message from Paypal\n            return False, error\n", "path": "app/api/helpers/ticketing.py"}], "after_files": [{"content": "from datetime import datetime\n\nfrom flask_jwt import current_identity as current_user\n\nfrom app.api.helpers.db import save_to_db, get_count\nfrom app.api.helpers.exceptions import ConflictException\nfrom app.api.helpers.files import make_frontend_url\nfrom app.api.helpers.mail import send_email_to_attendees\nfrom app.api.helpers.notification import send_notif_to_attendees, send_notif_ticket_purchase_organizer\nfrom app.api.helpers.order import delete_related_attendees_for_order, create_pdf_tickets_for_holder\nfrom app.api.helpers.payment import StripePaymentsManager, PayPalPaymentsManager\nfrom app.models import db\nfrom app.models.ticket_fee import TicketFees\nfrom app.models.ticket_holder import TicketHolder\n\n\nclass TicketingManager(object):\n    \"\"\"All ticketing and orders related helper functions\"\"\"\n\n    @staticmethod\n    def get_order_expiry():\n        return 10\n\n    @staticmethod\n    def match_discount_quantity(discount_code, ticket_holders=None):\n        qty = 0\n        old_holders = get_count(TicketHolder.query.filter(TicketHolder.ticket_id.in_(discount_code.tickets.split(\",\"))))\n\n        for holder in ticket_holders:\n            ticket_holder = TicketHolder.query.filter_by(id=holder).one()\n            if ticket_holder.ticket.id in discount_code.tickets.split(\",\"):\n                qty += 1\n        if (qty+old_holders) <= discount_code.tickets_number and \\\n           discount_code.min_quantity <= qty <= discount_code.max_quantity:\n            return True\n\n        return False\n\n    @staticmethod\n    def calculate_update_amount(order):\n        discount = None\n        if order.discount_code_id:\n            discount = order.discount_code\n        # Access code part will be done ticket_holders API\n        amount = 0\n        total_discount = 0\n        fees = TicketFees.query.filter_by(currency=order.event.payment_currency).first()\n\n        for order_ticket in order.order_tickets:\n            with db.session.no_autoflush:\n                if order_ticket.ticket.is_fee_absorbed or not fees:\n                    ticket_amount = (order_ticket.ticket.price * order_ticket.quantity)\n                    amount += (order_ticket.ticket.price * order_ticket.quantity)\n                else:\n                    order_fee = fees.service_fee * (order_ticket.ticket.price * order_ticket.quantity) / 100\n                    if order_fee > fees.maximum_fee:\n                        ticket_amount = (order_ticket.ticket.price * order_ticket.quantity) + fees.maximum_fee\n                        amount += (order_ticket.ticket.price * order_ticket.quantity) + fees.maximum_fee\n                    else:\n                        ticket_amount = (order_ticket.ticket.price * order_ticket.quantity) + order_fee\n                        amount += (order_ticket.ticket.price * order_ticket.quantity) + order_fee\n\n                if discount and str(order_ticket.ticket.id) in discount.tickets.split(\",\"):\n                    if discount.type == \"amount\":\n                        total_discount += discount.value * order_ticket.quantity\n                    else:\n                        total_discount += discount.value * ticket_amount / 100\n\n        if discount:\n            if discount.type == \"amount\":\n                order.amount = max(amount - total_discount, 0)\n            elif discount.type == \"percent\":\n                order.amount = amount - (discount.value * amount / 100.0)\n        else:\n            order.amount = amount\n        save_to_db(order)\n        return order\n\n    @staticmethod\n    def charge_stripe_order_payment(order, token_id):\n        \"\"\"\n        Charge the user through Stripe\n        :param order: Order for which to charge for\n        :param token_id: Stripe token\n        :return:\n        \"\"\"\n        # save the stripe token with the order\n        order.stripe_token = token_id\n        save_to_db(order)\n\n        # charge the user\n        try:\n            charge = StripePaymentsManager.capture_payment(order)\n        except ConflictException as e:\n            # payment failed hence expire the order\n            order.status = 'expired'\n            save_to_db(order)\n\n            # delete related attendees to unlock the tickets\n            delete_related_attendees_for_order(order)\n\n            raise e\n\n        # charge.paid is true if the charge succeeded, or was successfully authorized for later capture.\n        if charge.paid:\n            # update the order in the db.\n            order.paid_via = 'stripe'\n            order.payment_mode = charge.source.object\n            order.brand = charge.source.brand\n            order.exp_month = charge.source.exp_month\n            order.exp_year = charge.source.exp_year\n            order.last4 = charge.source.last4\n            order.transaction_id = charge.id\n            order.status = 'completed'\n            order.completed_at = datetime.utcnow()\n            save_to_db(order)\n\n            # create tickets.\n            create_pdf_tickets_for_holder(order)\n\n            # send email and notifications.\n            send_email_to_attendees(order, current_user.id)\n            send_notif_to_attendees(order, current_user.id)\n\n            order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))\n            for organizer in order.event.organizers:\n                send_notif_ticket_purchase_organizer(organizer, order.invoice_number, order_url, order.event.name)\n\n            return True, 'Charge successful'\n        else:\n            # payment failed hence expire the order\n            order.status = 'expired'\n            save_to_db(order)\n\n            # delete related attendees to unlock the tickets\n            delete_related_attendees_for_order(order)\n\n            # return the failure message from stripe.\n            return False, charge.failure_message\n\n    @staticmethod\n    def charge_paypal_order_payment(order, paypal_payer_id, paypal_payment_id):\n        \"\"\"\n        Charge the user through paypal.\n        :param order: Order for which to charge for.\n        :param paypal_payment_id: payment_id\n        :param paypal_payer_id: payer_id\n        :return:\n        \"\"\"\n\n        # save the paypal payment_id with the order\n        order.paypal_token = paypal_payment_id\n        save_to_db(order)\n\n        # create the transaction.\n        status, error = PayPalPaymentsManager.execute_payment(paypal_payer_id, paypal_payment_id)\n\n        if status:\n            # successful transaction hence update the order details.\n            order.paid_via = 'paypal'\n            order.status = 'completed'\n            order.transaction_id = paypal_payment_id\n            order.completed_at = datetime.utcnow()\n            save_to_db(order)\n\n            # create tickets\n            create_pdf_tickets_for_holder(order)\n\n            # send email and notifications\n            send_email_to_attendees(order, order.user_id)\n            send_notif_to_attendees(order, order.user_id)\n\n            order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))\n            for organizer in order.event.organizers:\n                send_notif_ticket_purchase_organizer(organizer, order.invoice_number, order_url, order.event.name)\n\n            return True, 'Charge successful'\n        else:\n            # payment failed hence expire the order\n            order.status = 'expired'\n            save_to_db(order)\n\n            # delete related attendees to unlock the tickets\n            delete_related_attendees_for_order(order)\n\n            # return the error message from Paypal\n            return False, error\n", "path": "app/api/helpers/ticketing.py"}]}