Skip to content

Commit

Permalink
notifications: create periodic task to create and send notifications.
Browse files Browse the repository at this point in the history
* Adds celery task cronned every morning at 4h00 to create and send overdue and due_soon notifications.

Signed-off-by: Aly Badr <aly.badr@rero.ch>
  • Loading branch information
Aly Badr committed Jun 17, 2019
1 parent fbb79d4 commit 98f89e9
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 5 deletions.
7 changes: 7 additions & 0 deletions rero_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from datetime import timedelta
from functools import partial

from celery.schedules import crontab
from flask import request
from invenio_circulation.pidstore.pids import CIRCULATION_LOAN_FETCHER, \
CIRCULATION_LOAN_MINTER, CIRCULATION_LOAN_PID_TYPE
Expand Down Expand Up @@ -211,11 +212,17 @@ def _(x):
'schedule': timedelta(minutes=60),
'kwargs': dict(name='ebooks'),
},
'notification-creation': {
'task':
'rero-ils.modules.tasks.create_over_and_due_soon_notifications',
'schedule': crontab(hour=4, minute=00)
},
# 'mef-harvester': {
# 'task': 'rero_ils.modules.apiharvester.tasks.harvest_records',
# 'schedule': timedelta(minutes=60),
# 'kwargs': dict(name='mef'),
# },

}
CELERY_BROKER_HEARTBEAT = 0

Expand Down
5 changes: 2 additions & 3 deletions rero_ils/modules/loans/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,8 @@ def get_due_soon_loans():
due_date = ciso8601.parse_datetime_as_naive(end_date)

days_before = circ_policy.get('number_of_days_before_due_date')
if now < due_date and \
now > due_date - timedelta(days=days_before):
due_soon_loans.append(loan)
if due_date > now > due_date - timedelta(days=days_before):
due_soon_loans.append(loan)
return due_soon_loans


Expand Down
44 changes: 44 additions & 0 deletions rero_ils/modules/notifications/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
# This file is part of RERO ILS.
# Copyright (C) 2017 RERO.
#
# RERO ILS is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# RERO ILS is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RERO ILS; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, RERO does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""Celery tasks for notification records."""

from __future__ import absolute_import, print_function

from celery import shared_task
from flask import current_app

from ..loans.api import get_due_soon_loans, get_overdue_loans


@shared_task(ignore_result=True)
def create_over_and_due_soon_notifications():
"""Creates due_soon and overdue notifications."""
over_due_loans = get_overdue_loans()
for loan in over_due_loans:
loan.create_notification(notification_type='overdue')

due_soon_loans = get_due_soon_loans()
for loan in due_soon_loans:
loan.create_notification(notification_type='due_soon')
4 changes: 2 additions & 2 deletions tests/api/test_loans_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ def test_due_soon_loans(client, librarian_martigny_no_email,
patron_martigny_no_email.patron_type_pid,
item.item_type_pid
)
circ_policy['number_of_days_before_due_date'] = 6
circ_policy['checkout_duration'] = 5
circ_policy['number_of_days_before_due_date'] = 7
circ_policy['checkout_duration'] = 3
circ_policy.update(
circ_policy,
dbcommit=True,
Expand Down
108 changes: 108 additions & 0 deletions tests/api/test_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#
# This file is part of RERO ILS.
# Copyright (C) 2017 RERO.
#
# RERO ILS is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# RERO ILS is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RERO ILS; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, RERO does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""Tasks tests."""

import json
from datetime import datetime, timedelta, timezone

from flask import url_for
from invenio_accounts.testutils import login_user_via_session
from invenio_circulation.search.api import LoansSearch
from utils import flush_index, get_json

from rero_ils.modules.loans.api import Loan, LoanAction, get_due_soon_loans, \
get_overdue_loans
from rero_ils.modules.notifications.api import NotificationsSearch, \
number_of_reminders_sent
from rero_ils.modules.notifications.tasks import \
create_over_and_due_soon_notifications


def test_create_over_and_due_soon_notifications_task(
client, librarian_martigny_no_email, patron_martigny_no_email,
item_lib_martigny, circ_policy_short_martigny):
"""Test overdue and due_soon loans."""
login_user_via_session(client, librarian_martigny_no_email.user)
item = item_lib_martigny
item_pid = item.pid
patron_pid = patron_martigny_no_email.pid
# checkout
res = client.post(
url_for('api_item.checkout'),
data=json.dumps(
dict(
item_pid=item_pid,
patron_pid=patron_pid
)
),
content_type='application/json',
)
assert res.status_code == 200

data = get_json(res)
loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('loan_pid')
loan = Loan.get_record_by_pid(loan_pid)

# test due_soon notification
end_date = datetime.now(timezone.utc) + timedelta(days=3)
loan['end_date'] = end_date.isoformat()
loan.update(loan, dbcommit=True, reindex=True)

due_soon_loans = get_due_soon_loans()

assert due_soon_loans[0].get('loan_pid') == loan_pid

create_over_and_due_soon_notifications()
flush_index(NotificationsSearch.Meta.index)
flush_index(LoansSearch.Meta.index)

assert loan.is_notified(notification_type='due_soon')

# test overdue notification
end_date = datetime.now(timezone.utc) - timedelta(days=7)
loan['end_date'] = end_date.isoformat()
loan.update(loan, dbcommit=True, reindex=True)

overdue_loans = get_overdue_loans()
assert overdue_loans[0].get('loan_pid') == loan_pid

create_over_and_due_soon_notifications()
flush_index(NotificationsSearch.Meta.index)
flush_index(LoansSearch.Meta.index)

assert loan.is_notified(notification_type='overdue')
assert number_of_reminders_sent(loan) == 1

# checkin the item to put it back to it's original state
res = client.post(
url_for('api_item.checkin'),
data=json.dumps(
dict(
item_pid=item_pid,
loan_pid=loan_pid
)
),
content_type='application/json',
)
assert res.status_code == 200

0 comments on commit 98f89e9

Please sign in to comment.