We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Error while sending monthly invoice
```
NoResultFound: No row was found for one()
  File "app/api/helpers/scheduled_jobs.py", line 256, in send_monthly_event_invoice
    db.session.query(TicketFees).filter_by(currency=currency).one()
  File "sqlalchemy/orm/query.py", line 3354, in one
    raise orm_exc.NoResultFound("No row was found for one()")
ObjectNotFound: ({'source': ''}, 'Ticket Fee not set for None')
  File "app/api/helpers/scheduled_jobs.py", line 260, in send_monthly_event_invoice
    {'source': ''}, 'Ticket Fee not set for {}'.format(currency)
```

We should never be throwing unhandled exceptions in jobs where no one can handle them

```
events = [
<Event 'Yogesh Sharma'>
, 
<Event '"/><img src="x" onerror="alert(document.domain)">'>
, 
<Event 'testing'>
, 
<Event 'Hackathon'>
, 
<Event 'Jamia Hamdard Convocation'>
, 
<Event 'OpenTechSummit Day Mekong'>
, 
<Event 'FOSSASIA Meetup - PSLab'>
, 
<Event 'Introduction to open source'>
, 
<Event 'Yogesh Sharma'>
, 
<Event 'OpenTechSummit India'>
]

event = <Event 'Yogesh Sharma'>
```

--- 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/scheduled_jobs.py`
Content:
```
1 import datetime
2 
3 import pytz
4 from dateutil.relativedelta import relativedelta
5 from sqlalchemy.orm.exc import NoResultFound
6 from flask_rest_jsonapi.exceptions import ObjectNotFound
7 from flask import render_template
8 from flask_celeryext import RequestContextTask
9 
10 from app.api.helpers.db import save_to_db
11 from app.api.helpers.files import create_save_pdf
12 from app.api.helpers.mail import (
13     send_email_after_event,
14     send_email_for_monthly_fee_payment,
15     send_followup_email_for_monthly_fee_payment,
16 )
17 from app.api.helpers.notification import (
18     send_followup_notif_monthly_fee_payment,
19     send_notif_after_event,
20     send_notif_monthly_fee_payment,
21 )
22 from app.api.helpers.query import get_user_event_roles_by_role_name
23 from app.api.helpers.storage import UPLOAD_PATHS
24 from app.api.helpers.utilities import monthdelta
25 from app.instance import celery
26 from app.models import db
27 from app.models.event import Event
28 from app.models.event_invoice import EventInvoice
29 from app.models.order import Order
30 from app.models.session import Session
31 from app.models.speaker import Speaker
32 from app.models.ticket_fee import TicketFees, get_fee
33 from app.models.ticket_holder import TicketHolder
34 from app.settings import get_settings
35 
36 
37 @celery.task(base=RequestContextTask, name='send.after.event.mail')
38 def send_after_event_mail():
39     from app.instance import current_app as app
40 
41     with app.app_context():
42         events = Event.query.filter_by(state='published', deleted_at=None).all()
43         for event in events:
44             organizers = get_user_event_roles_by_role_name(event.id, 'organizer')
45             speakers = Speaker.query.filter_by(event_id=event.id, deleted_at=None).all()
46             owner = get_user_event_roles_by_role_name(event.id, 'owner').first()
47             current_time = datetime.datetime.now(pytz.timezone(event.timezone))
48             time_difference = current_time - event.ends_at
49             time_difference_minutes = (time_difference.days * 24 * 60) + (
50                 time_difference.seconds / 60
51             )
52             frontend_url = get_settings()['frontend_url']
53             if current_time > event.ends_at and time_difference_minutes < 1440:
54                 for speaker in speakers:
55                     if not speaker.is_email_overridden:
56                         send_email_after_event(
57                             speaker.user.email, event.name, frontend_url
58                         )
59                         send_notif_after_event(speaker.user, event.name)
60                 for organizer in organizers:
61                     send_email_after_event(organizer.user.email, event.name, frontend_url)
62                     send_notif_after_event(organizer.user, event.name)
63                 if owner:
64                     send_email_after_event(owner.user.email, event.name, frontend_url)
65                     send_notif_after_event(owner.user, event.name)
66 
67 
68 @celery.task(base=RequestContextTask, name='change.session.state.on.event.completion')
69 def change_session_state_on_event_completion():
70     from app.instance import current_app as app
71 
72     with app.app_context():
73         sessions_to_be_changed = (
74             Session.query.join(Event)
75             .filter(Session.state == 'pending')
76             .filter(Event.ends_at < datetime.datetime.now())
77         )
78         for session in sessions_to_be_changed:
79             session.state = 'rejected'
80             save_to_db(
81                 session, 'Changed {} session state to rejected'.format(session.title)
82             )
83 
84 
85 @celery.task(base=RequestContextTask, name='send.event.fee.notification')
86 def send_event_fee_notification():
87     from app.instance import current_app as app
88 
89     with app.app_context():
90         events = Event.query.filter_by(deleted_at=None, state='published').all()
91         for event in events:
92             latest_invoice = (
93                 EventInvoice.query.filter_by(event_id=event.id)
94                 .order_by(EventInvoice.created_at.desc())
95                 .first()
96             )
97 
98             if latest_invoice:
99                 orders = (
100                     Order.query.filter_by(event_id=event.id)
101                     .filter_by(status='completed')
102                     .filter(Order.completed_at > latest_invoice.created_at)
103                     .all()
104                 )
105             else:
106                 orders = (
107                     Order.query.filter_by(event_id=event.id)
108                     .filter_by(status='completed')
109                     .all()
110                 )
111 
112             fee_total = 0
113             for order in orders:
114                 for ticket in order.tickets:
115                     if order.paid_via != 'free' and order.amount > 0 and ticket.price > 0:
116                         fee = ticket.price * (
117                             get_fee(event.payment_country, order.event.payment_currency)
118                             / 100.0
119                         )
120                         fee_total += fee
121 
122             if fee_total > 0:
123                 owner = get_user_event_roles_by_role_name(event.id, 'owner').first()
124                 new_invoice = EventInvoice(
125                     amount=fee_total, event_id=event.id, user_id=owner.user.id
126                 )
127 
128                 if event.discount_code_id and event.discount_code:
129                     r = relativedelta(datetime.datetime.utcnow(), event.created_at)
130                     if r <= event.discount_code.valid_till:
131                         new_invoice.amount = fee_total - (
132                             fee_total * (event.discount_code.value / 100.0)
133                         )
134                         new_invoice.discount_code_id = event.discount_code_id
135 
136                 save_to_db(new_invoice)
137                 prev_month = monthdelta(new_invoice.created_at, 1).strftime(
138                     "%b %Y"
139                 )  # Displayed as Aug 2016
140                 app_name = get_settings()['app_name']
141                 frontend_url = get_settings()['frontend_url']
142                 link = '{}/invoices/{}'.format(frontend_url, new_invoice.identifier)
143                 send_email_for_monthly_fee_payment(
144                     new_invoice.user.email,
145                     event.name,
146                     prev_month,
147                     new_invoice.amount,
148                     app_name,
149                     link,
150                 )
151                 send_notif_monthly_fee_payment(
152                     new_invoice.user,
153                     event.name,
154                     prev_month,
155                     new_invoice.amount,
156                     app_name,
157                     link,
158                     new_invoice.event_id,
159                 )
160 
161 
162 @celery.task(base=RequestContextTask, name='send.event.fee.notification.followup')
163 def send_event_fee_notification_followup():
164     from app.instance import current_app as app
165 
166     with app.app_context():
167         incomplete_invoices = EventInvoice.query.filter(
168             EventInvoice.status != 'paid'
169         ).all()
170         for incomplete_invoice in incomplete_invoices:
171             if incomplete_invoice.amount > 0:
172                 prev_month = monthdelta(incomplete_invoice.created_at, 1).strftime(
173                     "%b %Y"
174                 )  # Displayed as Aug 2016
175                 app_name = get_settings()['app_name']
176                 frontend_url = get_settings()['frontend_url']
177                 link = '{}/event-invoice/{}/review'.format(
178                     frontend_url, incomplete_invoice.identifier
179                 )
180                 send_followup_email_for_monthly_fee_payment(
181                     incomplete_invoice.user.email,
182                     incomplete_invoice.event.name,
183                     prev_month,
184                     incomplete_invoice.amount,
185                     app_name,
186                     link,
187                 )
188                 send_followup_notif_monthly_fee_payment(
189                     incomplete_invoice.user,
190                     incomplete_invoice.event.name,
191                     prev_month,
192                     incomplete_invoice.amount,
193                     app_name,
194                     link,
195                     incomplete_invoice.event.id,
196                 )
197 
198 
199 @celery.task(base=RequestContextTask, name='expire.pending.tickets')
200 def expire_pending_tickets():
201     from app.instance import current_app as app
202 
203     with app.app_context():
204         db.session.query(Order).filter(
205             Order.status == 'pending',
206             (Order.created_at + datetime.timedelta(minutes=30))
207             <= datetime.datetime.now(),
208         ).update({'status': 'expired'})
209         db.session.commit()
210 
211 
212 @celery.task(base=RequestContextTask, name='delete.ticket.holders.no.order.id')
213 def delete_ticket_holders_no_order_id():
214     from app.instance import current_app as app
215 
216     with app.app_context():
217         order_expiry_time = get_settings()['order_expiry_time']
218         TicketHolder.query.filter(
219             TicketHolder.order_id == None,
220             TicketHolder.deleted_at.is_(None),
221             TicketHolder.created_at + datetime.timedelta(minutes=order_expiry_time)
222             < datetime.datetime.utcnow(),
223         ).delete(synchronize_session=False)
224         db.session.commit()
225 
226 
227 @celery.task(base=RequestContextTask, name='event.invoices.mark.due')
228 def event_invoices_mark_due():
229     from app.instance import current_app as app
230 
231     with app.app_context():
232         db.session.query(EventInvoice).filter(
233             EventInvoice.status == 'upcoming',
234             Event.id == EventInvoice.event_id,
235             Event.ends_at >= datetime.datetime.now(),
236             (
237                 EventInvoice.created_at + datetime.timedelta(days=30)
238                 <= datetime.datetime.now()
239             ),
240         ).update({EventInvoice.status: 'due'}, synchronize_session=False)
241 
242 
243 @celery.task(base=RequestContextTask, name='send.monthly.event.invoice')
244 def send_monthly_event_invoice():
245     from app.instance import current_app as app
246 
247     with app.app_context():
248         events = Event.query.filter_by(deleted_at=None, state='published').all()
249         for event in events:
250             # calculate net & gross revenues
251             user = event.owner
252             admin_info = get_settings()
253             currency = event.payment_currency
254             try:
255                 ticket_fee_object = (
256                     db.session.query(TicketFees).filter_by(currency=currency).one()
257                 )
258             except NoResultFound:
259                 raise ObjectNotFound(
260                     {'source': ''}, 'Ticket Fee not set for {}'.format(currency)
261                 )
262             ticket_fee_percentage = ticket_fee_object.service_fee
263             ticket_fee_maximum = ticket_fee_object.maximum_fee
264             orders = Order.query.filter_by(event=event).all()
265             gross_revenue = event.calc_monthly_revenue()
266             invoice_amount = gross_revenue * (ticket_fee_percentage / 100)
267             if invoice_amount > ticket_fee_maximum:
268                 invoice_amount = ticket_fee_maximum
269             net_revenue = gross_revenue - invoice_amount
270             payment_details = {
271                 'tickets_sold': event.tickets_sold,
272                 'gross_revenue': gross_revenue,
273                 'net_revenue': net_revenue,
274                 'amount_payable': invoice_amount,
275             }
276             # save invoice as pdf
277             pdf = create_save_pdf(
278                 render_template(
279                     'pdf/event_invoice.html',
280                     orders=orders,
281                     user=user,
282                     admin_info=admin_info,
283                     currency=currency,
284                     event=event,
285                     ticket_fee_object=ticket_fee_object,
286                     payment_details=payment_details,
287                     net_revenue=net_revenue,
288                 ),
289                 UPLOAD_PATHS['pdf']['event_invoice'],
290                 dir_path='/static/uploads/pdf/event_invoices/',
291                 identifier=event.identifier,
292             )
293             # save event_invoice info to DB
294 
295             event_invoice = EventInvoice(
296                 amount=invoice_amount, invoice_pdf_url=pdf, event_id=event.id
297             )
298             save_to_db(event_invoice)
299 
300 
301 @celery.on_after_configure.connect
302 def setup_scheduled_task(sender, **kwargs):
303     from celery.schedules import crontab
304 
305     # Every day at 5:30
306     sender.add_periodic_task(crontab(hour=5, minute=30), send_after_event_mail)
307     # Every 1st day of month at 0:00
308     sender.add_periodic_task(
309         crontab(minute=0, hour=0, day_of_month=1), send_event_fee_notification
310     )
311     # Every 1st day of month at 0:00
312     sender.add_periodic_task(
313         crontab(minute=0, hour=0, day_of_month=1), send_event_fee_notification_followup
314     )
315     # Every day at 5:30
316     sender.add_periodic_task(
317         crontab(hour=5, minute=30), change_session_state_on_event_completion
318     )
319     # Every 45 minutes
320     sender.add_periodic_task(crontab(minute='*/45'), expire_pending_tickets)
321     # Every 1st day of month at 0:00
322     sender.add_periodic_task(
323         crontab(minute=0, hour=0, day_of_month=1), send_monthly_event_invoice
324     )
325     # Every day at 5:00
326     sender.add_periodic_task(crontab(minute=0, hour=5), event_invoices_mark_due)
327     # Every 5 minutes
328     sender.add_periodic_task(crontab(minute='*/5'), delete_ticket_holders_no_order_id)
329
```
--- 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/scheduled_jobs.py b/app/api/helpers/scheduled_jobs.py
--- a/app/api/helpers/scheduled_jobs.py
+++ b/app/api/helpers/scheduled_jobs.py
@@ -3,7 +3,6 @@
 import pytz
 from dateutil.relativedelta import relativedelta
 from sqlalchemy.orm.exc import NoResultFound
-from flask_rest_jsonapi.exceptions import ObjectNotFound
 from flask import render_template
 from flask_celeryext import RequestContextTask
 
@@ -32,7 +31,9 @@
 from app.models.ticket_fee import TicketFees, get_fee
 from app.models.ticket_holder import TicketHolder
 from app.settings import get_settings
+import logging
 
+logger = logging.getLogger(__name__)
 
 @celery.task(base=RequestContextTask, name='send.after.event.mail')
 def send_after_event_mail():
@@ -256,9 +257,9 @@
                     db.session.query(TicketFees).filter_by(currency=currency).one()
                 )
             except NoResultFound:
-                raise ObjectNotFound(
-                    {'source': ''}, 'Ticket Fee not set for {}'.format(currency)
-                )
+                logger.error('Ticket Fee not found for event id {id}'.format(id=event.id))
+                continue
+
             ticket_fee_percentage = ticket_fee_object.service_fee
             ticket_fee_maximum = ticket_fee_object.maximum_fee
             orders = Order.query.filter_by(event=event).all()

{"golden_diff": "diff --git a/app/api/helpers/scheduled_jobs.py b/app/api/helpers/scheduled_jobs.py\n--- a/app/api/helpers/scheduled_jobs.py\n+++ b/app/api/helpers/scheduled_jobs.py\n@@ -3,7 +3,6 @@\n import pytz\n from dateutil.relativedelta import relativedelta\n from sqlalchemy.orm.exc import NoResultFound\n-from flask_rest_jsonapi.exceptions import ObjectNotFound\n from flask import render_template\n from flask_celeryext import RequestContextTask\n \n@@ -32,7 +31,9 @@\n from app.models.ticket_fee import TicketFees, get_fee\n from app.models.ticket_holder import TicketHolder\n from app.settings import get_settings\n+import logging\n \n+logger = logging.getLogger(__name__)\n \n @celery.task(base=RequestContextTask, name='send.after.event.mail')\n def send_after_event_mail():\n@@ -256,9 +257,9 @@\n                     db.session.query(TicketFees).filter_by(currency=currency).one()\n                 )\n             except NoResultFound:\n-                raise ObjectNotFound(\n-                    {'source': ''}, 'Ticket Fee not set for {}'.format(currency)\n-                )\n+                logger.error('Ticket Fee not found for event id {id}'.format(id=event.id))\n+                continue\n+\n             ticket_fee_percentage = ticket_fee_object.service_fee\n             ticket_fee_maximum = ticket_fee_object.maximum_fee\n             orders = Order.query.filter_by(event=event).all()\n", "issue": "Error while sending monthly invoice\n```\r\nNoResultFound: No row was found for one()\r\n  File \"app/api/helpers/scheduled_jobs.py\", line 256, in send_monthly_event_invoice\r\n    db.session.query(TicketFees).filter_by(currency=currency).one()\r\n  File \"sqlalchemy/orm/query.py\", line 3354, in one\r\n    raise orm_exc.NoResultFound(\"No row was found for one()\")\r\nObjectNotFound: ({'source': ''}, 'Ticket Fee not set for None')\r\n  File \"app/api/helpers/scheduled_jobs.py\", line 260, in send_monthly_event_invoice\r\n    {'source': ''}, 'Ticket Fee not set for {}'.format(currency)\r\n```\r\n\r\nWe should never be throwing unhandled exceptions in jobs where no one can handle them\r\n\r\n```\r\nevents = [\r\n<Event 'Yogesh Sharma'>\r\n, \r\n<Event '\"/><img src=\"x\" onerror=\"alert(document.domain)\">'>\r\n, \r\n<Event 'testing'>\r\n, \r\n<Event 'Hackathon'>\r\n, \r\n<Event 'Jamia Hamdard Convocation'>\r\n, \r\n<Event 'OpenTechSummit Day Mekong'>\r\n, \r\n<Event 'FOSSASIA Meetup - PSLab'>\r\n, \r\n<Event 'Introduction to open source'>\r\n, \r\n<Event 'Yogesh Sharma'>\r\n, \r\n<Event 'OpenTechSummit India'>\r\n]\r\n\r\nevent = <Event 'Yogesh Sharma'>\r\n```\n", "before_files": [{"content": "import datetime\n\nimport pytz\nfrom dateutil.relativedelta import relativedelta\nfrom sqlalchemy.orm.exc import NoResultFound\nfrom flask_rest_jsonapi.exceptions import ObjectNotFound\nfrom flask import render_template\nfrom flask_celeryext import RequestContextTask\n\nfrom app.api.helpers.db import save_to_db\nfrom app.api.helpers.files import create_save_pdf\nfrom app.api.helpers.mail import (\n    send_email_after_event,\n    send_email_for_monthly_fee_payment,\n    send_followup_email_for_monthly_fee_payment,\n)\nfrom app.api.helpers.notification import (\n    send_followup_notif_monthly_fee_payment,\n    send_notif_after_event,\n    send_notif_monthly_fee_payment,\n)\nfrom app.api.helpers.query import get_user_event_roles_by_role_name\nfrom app.api.helpers.storage import UPLOAD_PATHS\nfrom app.api.helpers.utilities import monthdelta\nfrom app.instance import celery\nfrom app.models import db\nfrom app.models.event import Event\nfrom app.models.event_invoice import EventInvoice\nfrom app.models.order import Order\nfrom app.models.session import Session\nfrom app.models.speaker import Speaker\nfrom app.models.ticket_fee import TicketFees, get_fee\nfrom app.models.ticket_holder import TicketHolder\nfrom app.settings import get_settings\n\n\n@celery.task(base=RequestContextTask, name='send.after.event.mail')\ndef send_after_event_mail():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        events = Event.query.filter_by(state='published', deleted_at=None).all()\n        for event in events:\n            organizers = get_user_event_roles_by_role_name(event.id, 'organizer')\n            speakers = Speaker.query.filter_by(event_id=event.id, deleted_at=None).all()\n            owner = get_user_event_roles_by_role_name(event.id, 'owner').first()\n            current_time = datetime.datetime.now(pytz.timezone(event.timezone))\n            time_difference = current_time - event.ends_at\n            time_difference_minutes = (time_difference.days * 24 * 60) + (\n                time_difference.seconds / 60\n            )\n            frontend_url = get_settings()['frontend_url']\n            if current_time > event.ends_at and time_difference_minutes < 1440:\n                for speaker in speakers:\n                    if not speaker.is_email_overridden:\n                        send_email_after_event(\n                            speaker.user.email, event.name, frontend_url\n                        )\n                        send_notif_after_event(speaker.user, event.name)\n                for organizer in organizers:\n                    send_email_after_event(organizer.user.email, event.name, frontend_url)\n                    send_notif_after_event(organizer.user, event.name)\n                if owner:\n                    send_email_after_event(owner.user.email, event.name, frontend_url)\n                    send_notif_after_event(owner.user, event.name)\n\n\n@celery.task(base=RequestContextTask, name='change.session.state.on.event.completion')\ndef change_session_state_on_event_completion():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        sessions_to_be_changed = (\n            Session.query.join(Event)\n            .filter(Session.state == 'pending')\n            .filter(Event.ends_at < datetime.datetime.now())\n        )\n        for session in sessions_to_be_changed:\n            session.state = 'rejected'\n            save_to_db(\n                session, 'Changed {} session state to rejected'.format(session.title)\n            )\n\n\n@celery.task(base=RequestContextTask, name='send.event.fee.notification')\ndef send_event_fee_notification():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        events = Event.query.filter_by(deleted_at=None, state='published').all()\n        for event in events:\n            latest_invoice = (\n                EventInvoice.query.filter_by(event_id=event.id)\n                .order_by(EventInvoice.created_at.desc())\n                .first()\n            )\n\n            if latest_invoice:\n                orders = (\n                    Order.query.filter_by(event_id=event.id)\n                    .filter_by(status='completed')\n                    .filter(Order.completed_at > latest_invoice.created_at)\n                    .all()\n                )\n            else:\n                orders = (\n                    Order.query.filter_by(event_id=event.id)\n                    .filter_by(status='completed')\n                    .all()\n                )\n\n            fee_total = 0\n            for order in orders:\n                for ticket in order.tickets:\n                    if order.paid_via != 'free' and order.amount > 0 and ticket.price > 0:\n                        fee = ticket.price * (\n                            get_fee(event.payment_country, order.event.payment_currency)\n                            / 100.0\n                        )\n                        fee_total += fee\n\n            if fee_total > 0:\n                owner = get_user_event_roles_by_role_name(event.id, 'owner').first()\n                new_invoice = EventInvoice(\n                    amount=fee_total, event_id=event.id, user_id=owner.user.id\n                )\n\n                if event.discount_code_id and event.discount_code:\n                    r = relativedelta(datetime.datetime.utcnow(), event.created_at)\n                    if r <= event.discount_code.valid_till:\n                        new_invoice.amount = fee_total - (\n                            fee_total * (event.discount_code.value / 100.0)\n                        )\n                        new_invoice.discount_code_id = event.discount_code_id\n\n                save_to_db(new_invoice)\n                prev_month = monthdelta(new_invoice.created_at, 1).strftime(\n                    \"%b %Y\"\n                )  # Displayed as Aug 2016\n                app_name = get_settings()['app_name']\n                frontend_url = get_settings()['frontend_url']\n                link = '{}/invoices/{}'.format(frontend_url, new_invoice.identifier)\n                send_email_for_monthly_fee_payment(\n                    new_invoice.user.email,\n                    event.name,\n                    prev_month,\n                    new_invoice.amount,\n                    app_name,\n                    link,\n                )\n                send_notif_monthly_fee_payment(\n                    new_invoice.user,\n                    event.name,\n                    prev_month,\n                    new_invoice.amount,\n                    app_name,\n                    link,\n                    new_invoice.event_id,\n                )\n\n\n@celery.task(base=RequestContextTask, name='send.event.fee.notification.followup')\ndef send_event_fee_notification_followup():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        incomplete_invoices = EventInvoice.query.filter(\n            EventInvoice.status != 'paid'\n        ).all()\n        for incomplete_invoice in incomplete_invoices:\n            if incomplete_invoice.amount > 0:\n                prev_month = monthdelta(incomplete_invoice.created_at, 1).strftime(\n                    \"%b %Y\"\n                )  # Displayed as Aug 2016\n                app_name = get_settings()['app_name']\n                frontend_url = get_settings()['frontend_url']\n                link = '{}/event-invoice/{}/review'.format(\n                    frontend_url, incomplete_invoice.identifier\n                )\n                send_followup_email_for_monthly_fee_payment(\n                    incomplete_invoice.user.email,\n                    incomplete_invoice.event.name,\n                    prev_month,\n                    incomplete_invoice.amount,\n                    app_name,\n                    link,\n                )\n                send_followup_notif_monthly_fee_payment(\n                    incomplete_invoice.user,\n                    incomplete_invoice.event.name,\n                    prev_month,\n                    incomplete_invoice.amount,\n                    app_name,\n                    link,\n                    incomplete_invoice.event.id,\n                )\n\n\n@celery.task(base=RequestContextTask, name='expire.pending.tickets')\ndef expire_pending_tickets():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        db.session.query(Order).filter(\n            Order.status == 'pending',\n            (Order.created_at + datetime.timedelta(minutes=30))\n            <= datetime.datetime.now(),\n        ).update({'status': 'expired'})\n        db.session.commit()\n\n\n@celery.task(base=RequestContextTask, name='delete.ticket.holders.no.order.id')\ndef delete_ticket_holders_no_order_id():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        order_expiry_time = get_settings()['order_expiry_time']\n        TicketHolder.query.filter(\n            TicketHolder.order_id == None,\n            TicketHolder.deleted_at.is_(None),\n            TicketHolder.created_at + datetime.timedelta(minutes=order_expiry_time)\n            < datetime.datetime.utcnow(),\n        ).delete(synchronize_session=False)\n        db.session.commit()\n\n\n@celery.task(base=RequestContextTask, name='event.invoices.mark.due')\ndef event_invoices_mark_due():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        db.session.query(EventInvoice).filter(\n            EventInvoice.status == 'upcoming',\n            Event.id == EventInvoice.event_id,\n            Event.ends_at >= datetime.datetime.now(),\n            (\n                EventInvoice.created_at + datetime.timedelta(days=30)\n                <= datetime.datetime.now()\n            ),\n        ).update({EventInvoice.status: 'due'}, synchronize_session=False)\n\n\n@celery.task(base=RequestContextTask, name='send.monthly.event.invoice')\ndef send_monthly_event_invoice():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        events = Event.query.filter_by(deleted_at=None, state='published').all()\n        for event in events:\n            # calculate net & gross revenues\n            user = event.owner\n            admin_info = get_settings()\n            currency = event.payment_currency\n            try:\n                ticket_fee_object = (\n                    db.session.query(TicketFees).filter_by(currency=currency).one()\n                )\n            except NoResultFound:\n                raise ObjectNotFound(\n                    {'source': ''}, 'Ticket Fee not set for {}'.format(currency)\n                )\n            ticket_fee_percentage = ticket_fee_object.service_fee\n            ticket_fee_maximum = ticket_fee_object.maximum_fee\n            orders = Order.query.filter_by(event=event).all()\n            gross_revenue = event.calc_monthly_revenue()\n            invoice_amount = gross_revenue * (ticket_fee_percentage / 100)\n            if invoice_amount > ticket_fee_maximum:\n                invoice_amount = ticket_fee_maximum\n            net_revenue = gross_revenue - invoice_amount\n            payment_details = {\n                'tickets_sold': event.tickets_sold,\n                'gross_revenue': gross_revenue,\n                'net_revenue': net_revenue,\n                'amount_payable': invoice_amount,\n            }\n            # save invoice as pdf\n            pdf = create_save_pdf(\n                render_template(\n                    'pdf/event_invoice.html',\n                    orders=orders,\n                    user=user,\n                    admin_info=admin_info,\n                    currency=currency,\n                    event=event,\n                    ticket_fee_object=ticket_fee_object,\n                    payment_details=payment_details,\n                    net_revenue=net_revenue,\n                ),\n                UPLOAD_PATHS['pdf']['event_invoice'],\n                dir_path='/static/uploads/pdf/event_invoices/',\n                identifier=event.identifier,\n            )\n            # save event_invoice info to DB\n\n            event_invoice = EventInvoice(\n                amount=invoice_amount, invoice_pdf_url=pdf, event_id=event.id\n            )\n            save_to_db(event_invoice)\n\n\n@celery.on_after_configure.connect\ndef setup_scheduled_task(sender, **kwargs):\n    from celery.schedules import crontab\n\n    # Every day at 5:30\n    sender.add_periodic_task(crontab(hour=5, minute=30), send_after_event_mail)\n    # Every 1st day of month at 0:00\n    sender.add_periodic_task(\n        crontab(minute=0, hour=0, day_of_month=1), send_event_fee_notification\n    )\n    # Every 1st day of month at 0:00\n    sender.add_periodic_task(\n        crontab(minute=0, hour=0, day_of_month=1), send_event_fee_notification_followup\n    )\n    # Every day at 5:30\n    sender.add_periodic_task(\n        crontab(hour=5, minute=30), change_session_state_on_event_completion\n    )\n    # Every 45 minutes\n    sender.add_periodic_task(crontab(minute='*/45'), expire_pending_tickets)\n    # Every 1st day of month at 0:00\n    sender.add_periodic_task(\n        crontab(minute=0, hour=0, day_of_month=1), send_monthly_event_invoice\n    )\n    # Every day at 5:00\n    sender.add_periodic_task(crontab(minute=0, hour=5), event_invoices_mark_due)\n    # Every 5 minutes\n    sender.add_periodic_task(crontab(minute='*/5'), delete_ticket_holders_no_order_id)\n", "path": "app/api/helpers/scheduled_jobs.py"}], "after_files": [{"content": "import datetime\n\nimport pytz\nfrom dateutil.relativedelta import relativedelta\nfrom sqlalchemy.orm.exc import NoResultFound\nfrom flask import render_template\nfrom flask_celeryext import RequestContextTask\n\nfrom app.api.helpers.db import save_to_db\nfrom app.api.helpers.files import create_save_pdf\nfrom app.api.helpers.mail import (\n    send_email_after_event,\n    send_email_for_monthly_fee_payment,\n    send_followup_email_for_monthly_fee_payment,\n)\nfrom app.api.helpers.notification import (\n    send_followup_notif_monthly_fee_payment,\n    send_notif_after_event,\n    send_notif_monthly_fee_payment,\n)\nfrom app.api.helpers.query import get_user_event_roles_by_role_name\nfrom app.api.helpers.storage import UPLOAD_PATHS\nfrom app.api.helpers.utilities import monthdelta\nfrom app.instance import celery\nfrom app.models import db\nfrom app.models.event import Event\nfrom app.models.event_invoice import EventInvoice\nfrom app.models.order import Order\nfrom app.models.session import Session\nfrom app.models.speaker import Speaker\nfrom app.models.ticket_fee import TicketFees, get_fee\nfrom app.models.ticket_holder import TicketHolder\nfrom app.settings import get_settings\nimport logging\n\nlogger = logging.getLogger(__name__)\n\n@celery.task(base=RequestContextTask, name='send.after.event.mail')\ndef send_after_event_mail():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        events = Event.query.filter_by(state='published', deleted_at=None).all()\n        for event in events:\n            organizers = get_user_event_roles_by_role_name(event.id, 'organizer')\n            speakers = Speaker.query.filter_by(event_id=event.id, deleted_at=None).all()\n            owner = get_user_event_roles_by_role_name(event.id, 'owner').first()\n            current_time = datetime.datetime.now(pytz.timezone(event.timezone))\n            time_difference = current_time - event.ends_at\n            time_difference_minutes = (time_difference.days * 24 * 60) + (\n                time_difference.seconds / 60\n            )\n            frontend_url = get_settings()['frontend_url']\n            if current_time > event.ends_at and time_difference_minutes < 1440:\n                for speaker in speakers:\n                    if not speaker.is_email_overridden:\n                        send_email_after_event(\n                            speaker.user.email, event.name, frontend_url\n                        )\n                        send_notif_after_event(speaker.user, event.name)\n                for organizer in organizers:\n                    send_email_after_event(organizer.user.email, event.name, frontend_url)\n                    send_notif_after_event(organizer.user, event.name)\n                if owner:\n                    send_email_after_event(owner.user.email, event.name, frontend_url)\n                    send_notif_after_event(owner.user, event.name)\n\n\n@celery.task(base=RequestContextTask, name='change.session.state.on.event.completion')\ndef change_session_state_on_event_completion():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        sessions_to_be_changed = (\n            Session.query.join(Event)\n            .filter(Session.state == 'pending')\n            .filter(Event.ends_at < datetime.datetime.now())\n        )\n        for session in sessions_to_be_changed:\n            session.state = 'rejected'\n            save_to_db(\n                session, 'Changed {} session state to rejected'.format(session.title)\n            )\n\n\n@celery.task(base=RequestContextTask, name='send.event.fee.notification')\ndef send_event_fee_notification():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        events = Event.query.filter_by(deleted_at=None, state='published').all()\n        for event in events:\n            latest_invoice = (\n                EventInvoice.query.filter_by(event_id=event.id)\n                .order_by(EventInvoice.created_at.desc())\n                .first()\n            )\n\n            if latest_invoice:\n                orders = (\n                    Order.query.filter_by(event_id=event.id)\n                    .filter_by(status='completed')\n                    .filter(Order.completed_at > latest_invoice.created_at)\n                    .all()\n                )\n            else:\n                orders = (\n                    Order.query.filter_by(event_id=event.id)\n                    .filter_by(status='completed')\n                    .all()\n                )\n\n            fee_total = 0\n            for order in orders:\n                for ticket in order.tickets:\n                    if order.paid_via != 'free' and order.amount > 0 and ticket.price > 0:\n                        fee = ticket.price * (\n                            get_fee(event.payment_country, order.event.payment_currency)\n                            / 100.0\n                        )\n                        fee_total += fee\n\n            if fee_total > 0:\n                owner = get_user_event_roles_by_role_name(event.id, 'owner').first()\n                new_invoice = EventInvoice(\n                    amount=fee_total, event_id=event.id, user_id=owner.user.id\n                )\n\n                if event.discount_code_id and event.discount_code:\n                    r = relativedelta(datetime.datetime.utcnow(), event.created_at)\n                    if r <= event.discount_code.valid_till:\n                        new_invoice.amount = fee_total - (\n                            fee_total * (event.discount_code.value / 100.0)\n                        )\n                        new_invoice.discount_code_id = event.discount_code_id\n\n                save_to_db(new_invoice)\n                prev_month = monthdelta(new_invoice.created_at, 1).strftime(\n                    \"%b %Y\"\n                )  # Displayed as Aug 2016\n                app_name = get_settings()['app_name']\n                frontend_url = get_settings()['frontend_url']\n                link = '{}/invoices/{}'.format(frontend_url, new_invoice.identifier)\n                send_email_for_monthly_fee_payment(\n                    new_invoice.user.email,\n                    event.name,\n                    prev_month,\n                    new_invoice.amount,\n                    app_name,\n                    link,\n                )\n                send_notif_monthly_fee_payment(\n                    new_invoice.user,\n                    event.name,\n                    prev_month,\n                    new_invoice.amount,\n                    app_name,\n                    link,\n                    new_invoice.event_id,\n                )\n\n\n@celery.task(base=RequestContextTask, name='send.event.fee.notification.followup')\ndef send_event_fee_notification_followup():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        incomplete_invoices = EventInvoice.query.filter(\n            EventInvoice.status != 'paid'\n        ).all()\n        for incomplete_invoice in incomplete_invoices:\n            if incomplete_invoice.amount > 0:\n                prev_month = monthdelta(incomplete_invoice.created_at, 1).strftime(\n                    \"%b %Y\"\n                )  # Displayed as Aug 2016\n                app_name = get_settings()['app_name']\n                frontend_url = get_settings()['frontend_url']\n                link = '{}/event-invoice/{}/review'.format(\n                    frontend_url, incomplete_invoice.identifier\n                )\n                send_followup_email_for_monthly_fee_payment(\n                    incomplete_invoice.user.email,\n                    incomplete_invoice.event.name,\n                    prev_month,\n                    incomplete_invoice.amount,\n                    app_name,\n                    link,\n                )\n                send_followup_notif_monthly_fee_payment(\n                    incomplete_invoice.user,\n                    incomplete_invoice.event.name,\n                    prev_month,\n                    incomplete_invoice.amount,\n                    app_name,\n                    link,\n                    incomplete_invoice.event.id,\n                )\n\n\n@celery.task(base=RequestContextTask, name='expire.pending.tickets')\ndef expire_pending_tickets():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        db.session.query(Order).filter(\n            Order.status == 'pending',\n            (Order.created_at + datetime.timedelta(minutes=30))\n            <= datetime.datetime.now(),\n        ).update({'status': 'expired'})\n        db.session.commit()\n\n\n@celery.task(base=RequestContextTask, name='delete.ticket.holders.no.order.id')\ndef delete_ticket_holders_no_order_id():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        order_expiry_time = get_settings()['order_expiry_time']\n        TicketHolder.query.filter(\n            TicketHolder.order_id == None,\n            TicketHolder.deleted_at.is_(None),\n            TicketHolder.created_at + datetime.timedelta(minutes=order_expiry_time)\n            < datetime.datetime.utcnow(),\n        ).delete(synchronize_session=False)\n        db.session.commit()\n\n\n@celery.task(base=RequestContextTask, name='event.invoices.mark.due')\ndef event_invoices_mark_due():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        db.session.query(EventInvoice).filter(\n            EventInvoice.status == 'upcoming',\n            Event.id == EventInvoice.event_id,\n            Event.ends_at >= datetime.datetime.now(),\n            (\n                EventInvoice.created_at + datetime.timedelta(days=30)\n                <= datetime.datetime.now()\n            ),\n        ).update({EventInvoice.status: 'due'}, synchronize_session=False)\n\n\n@celery.task(base=RequestContextTask, name='send.monthly.event.invoice')\ndef send_monthly_event_invoice():\n    from app.instance import current_app as app\n\n    with app.app_context():\n        events = Event.query.filter_by(deleted_at=None, state='published').all()\n        for event in events:\n            # calculate net & gross revenues\n            user = event.owner\n            admin_info = get_settings()\n            currency = event.payment_currency\n            try:\n                ticket_fee_object = (\n                    db.session.query(TicketFees).filter_by(currency=currency).one()\n                )\n            except NoResultFound:\n                logger.error('Ticket Fee not found for event id {id}'.format(id=event.id))\n                continue\n\n            ticket_fee_percentage = ticket_fee_object.service_fee\n            ticket_fee_maximum = ticket_fee_object.maximum_fee\n            orders = Order.query.filter_by(event=event).all()\n            gross_revenue = event.calc_monthly_revenue()\n            invoice_amount = gross_revenue * (ticket_fee_percentage / 100)\n            if invoice_amount > ticket_fee_maximum:\n                invoice_amount = ticket_fee_maximum\n            net_revenue = gross_revenue - invoice_amount\n            payment_details = {\n                'tickets_sold': event.tickets_sold,\n                'gross_revenue': gross_revenue,\n                'net_revenue': net_revenue,\n                'amount_payable': invoice_amount,\n            }\n            # save invoice as pdf\n            pdf = create_save_pdf(\n                render_template(\n                    'pdf/event_invoice.html',\n                    orders=orders,\n                    user=user,\n                    admin_info=admin_info,\n                    currency=currency,\n                    event=event,\n                    ticket_fee_object=ticket_fee_object,\n                    payment_details=payment_details,\n                    net_revenue=net_revenue,\n                ),\n                UPLOAD_PATHS['pdf']['event_invoice'],\n                dir_path='/static/uploads/pdf/event_invoices/',\n                identifier=event.identifier,\n            )\n            # save event_invoice info to DB\n\n            event_invoice = EventInvoice(\n                amount=invoice_amount, invoice_pdf_url=pdf, event_id=event.id\n            )\n            save_to_db(event_invoice)\n\n\n@celery.on_after_configure.connect\ndef setup_scheduled_task(sender, **kwargs):\n    from celery.schedules import crontab\n\n    # Every day at 5:30\n    sender.add_periodic_task(crontab(hour=5, minute=30), send_after_event_mail)\n    # Every 1st day of month at 0:00\n    sender.add_periodic_task(\n        crontab(minute=0, hour=0, day_of_month=1), send_event_fee_notification\n    )\n    # Every 1st day of month at 0:00\n    sender.add_periodic_task(\n        crontab(minute=0, hour=0, day_of_month=1), send_event_fee_notification_followup\n    )\n    # Every day at 5:30\n    sender.add_periodic_task(\n        crontab(hour=5, minute=30), change_session_state_on_event_completion\n    )\n    # Every 45 minutes\n    sender.add_periodic_task(crontab(minute='*/45'), expire_pending_tickets)\n    # Every 1st day of month at 0:00\n    sender.add_periodic_task(\n        crontab(minute=0, hour=0, day_of_month=1), send_monthly_event_invoice\n    )\n    # Every day at 5:00\n    sender.add_periodic_task(crontab(minute=0, hour=5), event_invoices_mark_due)\n    # Every 5 minutes\n    sender.add_periodic_task(crontab(minute='*/5'), delete_ticket_holders_no_order_id)\n", "path": "app/api/helpers/scheduled_jobs.py"}]}