Skip to content

Commit

Permalink
notifications: fix notification problems
Browse files Browse the repository at this point in the history
* Closes #2300.
* Closes #2247.

Co-Authored-by: Renaud Michotte <renaud.michotte@gmail.com>
  • Loading branch information
zannkukai authored and iGor milhit committed Aug 26, 2021
1 parent 8ed6304 commit eb7a9b6
Show file tree
Hide file tree
Showing 34 changed files with 797 additions and 666 deletions.
36 changes: 25 additions & 11 deletions rero_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@
from .modules.locations.api import Location
from .modules.locations.permissions import LocationPermission
from .modules.notifications.api import Notification
from .modules.notifications.dispatcher import \
Dispatcher as NotificationDispatcher
from .modules.notifications.models import NotificationType
from .modules.notifications.permissions import NotificationPermission
from .modules.operation_logs.api import OperationLog
from .modules.operation_logs.permissions import OperationLogPermission
Expand Down Expand Up @@ -314,10 +317,7 @@ def _(x):
'task': 'rero_ils.modules.notifications.tasks.create_notifications',
'schedule': crontab(minute=0, hour=5), # Every day at 05:00 UTC,
'kwargs': {
'types': [
Notification.DUE_SOON_NOTIFICATION_TYPE,
Notification.OVERDUE_NOTIFICATION_TYPE
]
'types': [NotificationType.DUE_SOON, NotificationType.OVERDUE]
},
'enabled': False,
# TODO: in production set this up once a day
Expand All @@ -326,31 +326,31 @@ def _(x):
'task': 'rero_ils.modules.notifications.tasks.process_notifications',
'schedule': crontab(minute="*/15"),
'kwargs': {
'notification_type': Notification.DUE_SOON_NOTIFICATION_TYPE
'notification_type': NotificationType.DUE_SOON
},
'enabled': False,
},
'notification-dispatch-overdue': {
'task': 'rero_ils.modules.notifications.tasks.process_notifications',
'schedule': timedelta(minutes=15),
'kwargs': {
'notification_type': Notification.OVERDUE_NOTIFICATION_TYPE
'notification_type': NotificationType.OVERDUE
},
'enabled': False,
},
'notification-dispatch-availability': {
'task': 'rero_ils.modules.notifications.tasks.process_notifications',
'schedule': timedelta(minutes=15),
'kwargs': {
'notification_type': Notification.AVAILABILITY_NOTIFICATION_TYPE
'notification_type': NotificationType.AVAILABILITY
},
'enabled': False,
},
'notification-dispatch-recall': {
'task': 'rero_ils.modules.notifications.tasks.process_notifications',
'schedule': timedelta(minutes=15),
'kwargs': {
'notification_type': Notification.RECALL_NOTIFICATION_TYPE
'notification_type': NotificationType.RECALL
},
'enabled': False,
},
Expand Down Expand Up @@ -2421,12 +2421,26 @@ def _(x):
# Compute the stats with a timeframe given in monthes
RERO_ILS_STATS_TIMEFRAME_IN_MONTHES = 3

# Notification Configuration
# ===========================
RERO_ILS_NOTIFICATIONS_ALLOWED_TEMPATE_FILES = [
# =============================================================================
# NOTIFICATIONS MODULE SPECIFIC SETTINGS
# =============================================================================

# Define which files should be considered as a template file. Each full_path
# file matching one of the specific regular expression will be considered.
RERO_ILS_NOTIFICATIONS_ALLOWED_TEMPLATE_FILES = [
'*.txt',
'*.tpl.*'
]
# Define functions to use when we would send a notification. Each key will be
# the communication channel, value is the function to call. The used functions
# should accept one positional argument.
RERO_ILS_COMMUNICATION_DISPATCHER_FUNCTIONS = {
'email': NotificationDispatcher.send_mail_to_patron,
'mail': NotificationDispatcher.send_mail_for_printing,
# 'sms': not_yet_implemented
# 'telepathy': self.madness_mind
# ...
}

# Login Configuration
# ===================
Expand Down
6 changes: 1 addition & 5 deletions rero_ils/modules/libraries/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from dateutil import parser
from dateutil.rrule import FREQNAMES, rrule

from .exceptions import LibraryNeverOpen
from .models import LibraryIdentifier, LibraryMetadata
from ..api import IlsRecord, IlsRecordsIndexer, IlsRecordsSearch
from ..fetchers import id_fetcher
Expand All @@ -45,11 +46,6 @@
library_id_fetcher = partial(id_fetcher, provider=LibraryProvider)


# define Python user-defined exceptions
class LibraryNeverOpen(Exception):
"""Raised when the library has no open days."""


class LibrariesSearch(IlsRecordsSearch):
"""Libraries search."""

Expand Down
23 changes: 23 additions & 0 deletions rero_ils/modules/libraries/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
#
# RERO ILS
# Copyright (C) 2021 RERO
# Copyright (C) 2021 UCLouvain
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Libraries exceptions."""


class LibraryNeverOpen(Exception):
"""Raised when the library has no open days."""
30 changes: 14 additions & 16 deletions rero_ils/modules/loans/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@
from ..items.utils import item_pid_to_object
from ..libraries.api import LibrariesSearch, Library
from ..locations.api import Location, LocationsSearch
from ..notifications.api import Notification, NotificationsSearch, \
number_of_reminders_sent
from ..notifications.api import Notification, NotificationsSearch
from ..notifications.dispatcher import Dispatcher
from ..notifications.models import NotificationType
from ..notifications.utils import number_of_reminders_sent
from ..patron_transactions.api import PatronTransactionsSearch
from ..patrons.api import Patron, PatronsSearch
from ..utils import date_string_to_utc, get_ref_for_pid
Expand Down Expand Up @@ -725,14 +726,14 @@ def create_notification(self, notification_type=None, counter=0):
loan_state = self.get('state')
# overdue + due_soon
if notif_type in [
Notification.OVERDUE_NOTIFICATION_TYPE,
Notification.DUE_SOON_NOTIFICATION_TYPE] \
NotificationType.OVERDUE,
NotificationType.DUE_SOON] \
and not self.is_notified(notif_type, counter):

# We only need to create a notification if a corresponding reminder
# exists into the linked cipo.
reminder_type = DUE_SOON_REMINDER_TYPE
if notif_type != Notification.DUE_SOON_NOTIFICATION_TYPE:
if notif_type != NotificationType.DUE_SOON:
reminder_type = OVERDUE_REMINDER_TYPE
cipo = get_circ_policy(self)
reminder = cipo.get_reminder(reminder_type, counter)
Expand All @@ -742,21 +743,18 @@ def create_notification(self, notification_type=None, counter=0):
# create the notification and enqueue it.
return self._send_notification(record)

# availibility
# availibility + recall
if notif_type in [
Notification.AVAILABILITY_NOTIFICATION_TYPE,
# recall
Notification.RECALL_NOTIFICATION_TYPE
NotificationType.AVAILABILITY,
NotificationType.RECALL
]:
return self._send_notification(record)

# transit_notice + booking + request
if notif_type in [
# transit_notice
Notification.TRANSIT_NOTICE_NOTIFICATION_TYPE,
# booking
Notification.BOOKING_NOTIFICATION_TYPE,
# request
Notification.REQUEST_NOTIFICATION_TYPE
NotificationType.TRANSIT_NOTICE,
NotificationType.BOOKING,
NotificationType.REQUEST
]:
return self._send_notification(record, True)

Expand Down Expand Up @@ -817,7 +815,7 @@ def can_anonymize(cls, loan_data=None, patron=None):
old and new version of the loan.
:param loan_data: the loan to check.
:param patron_data: the patron to check.
:param patron: the patron to check.
:return True|False.
"""
if cls.concluded(loan_data) and cls.age(loan_data) > 6*365/12:
Expand Down
16 changes: 8 additions & 8 deletions rero_ils/modules/loans/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
from ..libraries.api import Library
from ..loans.api import Loan
from ..locations.api import Location
from ..notifications.api import Notification
from ..notifications.dispatcher import Dispatcher
from ..notifications.models import NotificationType
from ..notifications.tasks import create_notifications
from ..patron_transaction_events.api import PatronTransactionEvent
from ..patron_transactions.api import PatronTransaction
Expand Down Expand Up @@ -315,8 +315,8 @@ def create_loans(infile, verbose, debug):
click.secho(f'Errors {transaction_type}: {count}', fg='red')
result = create_notifications(
types=[
Notification.DUE_SOON_NOTIFICATION_TYPE,
Notification.OVERDUE_NOTIFICATION_TYPE
NotificationType.DUE_SOON,
NotificationType.OVERDUE
],
verbose=verbose
)
Expand Down Expand Up @@ -364,7 +364,7 @@ def create_loan(barcode, transaction_type, loanable_items, verbose=False,
reindex=True
)
notification = loan.create_notification(
notification_type=Notification.DUE_SOON_NOTIFICATION_TYPE)
notification_type=NotificationType.DUE_SOON)
if notification:
notification_pids.append(notification['pid'])

Expand All @@ -376,7 +376,7 @@ def create_loan(barcode, transaction_type, loanable_items, verbose=False,
reindex=True
)
notification = loan.create_notification(
notification_type=Notification.OVERDUE_NOTIFICATION_TYPE)
notification_type=NotificationType.OVERDUE)
if notification:
notification_pids.append(notification['pid'])

Expand All @@ -389,7 +389,7 @@ def create_loan(barcode, transaction_type, loanable_items, verbose=False,
reindex=True
)
notification = loan.create_notification(
notification_type=Notification.DUE_SOON_NOTIFICATION_TYPE)
notification_type=NotificationType.DUE_SOON)
if notification:
notification_pids.append(notification['pid'])

Expand All @@ -401,7 +401,7 @@ def create_loan(barcode, transaction_type, loanable_items, verbose=False,
reindex=True
)
notification = notif = loan.create_notification(
notification_type=Notification.OVERDUE_NOTIFICATION_TYPE)
notification_type=NotificationType.OVERDUE)
if notification:
notification_pids.append(notification['pid'])
patron_transaction = next(notif.patron_transactions)
Expand Down Expand Up @@ -450,7 +450,7 @@ def create_loan(barcode, transaction_type, loanable_items, verbose=False,
document_pid=extracted_data_from_ref(item.get('document')),
)
notification = loan.create_notification(
notification_type=Notification.RECALL_NOTIFICATION_TYPE)
notification_type=NotificationType.RECALL)
if notification:
notification_pids.append(notification['pid'])
Dispatcher.dispatch_notifications(notification_pids, verbose=verbose)
Expand Down
15 changes: 7 additions & 8 deletions rero_ils/modules/loans/listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ..items.api import Item
from ..loans.api import Loan, LoanState
from ..loans.logs.api import LoanOperationLog
from ..notifications.api import Notification
from ..notifications.models import NotificationType
from ..patron_transactions.api import PatronTransaction


Expand Down Expand Up @@ -52,31 +52,30 @@ def listener_loan_state_changed(_, initial_loan, loan, trigger):
# is the item on loan
if checkedout_loan_pid:
checked_out_loan = Loan.get_record_by_pid(checkedout_loan_pid)
if not checked_out_loan.is_notified(
Notification.RECALL_NOTIFICATION_TYPE):
if not checked_out_loan.is_notified(NotificationType.RECALL):
checked_out_loan.create_notification(
Notification.RECALL_NOTIFICATION_TYPE)
NotificationType.RECALL)
elif not item.temp_item_type_negative_availability:
# request notification only if the item is not on loan
loan.create_notification(
notification_type=Notification.REQUEST_NOTIFICATION_TYPE)
notification_type=NotificationType.REQUEST)
# availability
elif loan['state'] == LoanState.ITEM_AT_DESK:
loan.create_notification(
notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE)
notification_type=NotificationType.AVAILABILITY)
# transit_notice
elif loan['state'] == LoanState.ITEM_IN_TRANSIT_TO_HOUSE:
item = Item.get_record_by_pid(item_pid)
if item.number_of_requests() == 0:
loan.create_notification(
notification_type=Notification.TRANSIT_NOTICE_NOTIFICATION_TYPE
notification_type=NotificationType.TRANSIT_NOTICE
)
# booking
if trigger == 'checkin':
item = Item.get_record_by_pid(item_pid)
if item.number_of_requests():
loan.create_notification(
notification_type=Notification.BOOKING_NOTIFICATION_TYPE)
notification_type=NotificationType.BOOKING)

# Create fees for checkin or extend operations
if trigger in ['checkin', 'extend']:
Expand Down
Loading

0 comments on commit eb7a9b6

Please sign in to comment.