Skip to content

Commit

Permalink
Merge e1731af into 6d2c859
Browse files Browse the repository at this point in the history
  • Loading branch information
zannkukai committed Apr 21, 2020
2 parents 6d2c859 + e1731af commit 88b44cb
Show file tree
Hide file tree
Showing 36 changed files with 2,007 additions and 609 deletions.
3 changes: 2 additions & 1 deletion data/patron_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"description": "Standard patron.",
"organisation": {
"$ref": "https://ils.rero.ch/api/organisations/1"
}
},
"subscription_amount": 10
},
{
"$schema": "https://ils.rero.ch/schema/patron_types/patron_type-v0.0.1.json",
Expand Down
5 changes: 5 additions & 0 deletions rero_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ def _(x):
'schedule': crontab(minute="*/5")
# TODO: in production set this up once a day
},
'clear_and_renew_subscriptions': {
'task':
'rero_ils.modules.patrons.tasks.task_clear_and_renew_subscriptions',
'schedule': crontab(minute='2', hour='2')
}
# 'mef-harvester': {
# 'task': 'rero_ils.modules.apiharvester.tasks.harvest_records',
# 'schedule': timedelta(minutes=60),
Expand Down
9 changes: 6 additions & 3 deletions rero_ils/modules/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
from invenio_circulation.signals import loan_state_changed
from invenio_indexer.signals import before_record_index
from invenio_oaiharvester.signals import oaiharvest_finished
from invenio_records.signals import after_record_delete, after_record_insert, \
after_record_revert, after_record_update
from invenio_records.signals import after_record_insert, after_record_update

from .apiharvester.signals import apiharvest_part
from .documents.listener import enrich_document_data
Expand All @@ -39,7 +38,8 @@
from .patron_transaction_events.listener import \
enrich_patron_transaction_event_data
from .patron_transactions.listener import enrich_patron_transaction_data
from .patrons.listener import enrich_patron_data
from .patrons.listener import create_subscription_patron_transaction, \
enrich_patron_data
from .persons.listener import enrich_persons_data
from .persons.receivers import publish_api_harvested_records
from ..filter import format_date_filter, jsondumps, text_to_id, to_pretty_json
Expand Down Expand Up @@ -102,6 +102,9 @@ def register_signals(self):
before_record_index.connect(enrich_patron_transaction_event_data)
before_record_index.connect(enrich_patron_transaction_data)

after_record_insert.connect(create_subscription_patron_transaction)
after_record_update.connect(create_subscription_patron_transaction)

loan_state_changed.connect(listener_loan_state_changed, weak=False)

oaiharvest_finished.connect(publish_harvested_records, weak=False)
Expand Down
1 change: 0 additions & 1 deletion rero_ils/modules/libraries/jsonresolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,3 @@
def library_resolver(pid):
"""Library resolver."""
return resolve_json_refs('lib', pid)
persistent_id = PersistentIdentifier.get('lib', pid)
61 changes: 21 additions & 40 deletions rero_ils/modules/patron_transaction_events/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
from datetime import datetime, timezone
from functools import partial

from flask import current_app
from flask_babelex import gettext as _

from .models import PatronTransactionEventIdentifier
from ..api import IlsRecord, IlsRecordsSearch
from ..fetchers import id_fetcher
from ..minters import id_minter
from ..providers import Provider
from ..utils import get_ref_for_pid

# provider
PatronTransactionEventProvider = type(
Expand Down Expand Up @@ -75,8 +76,25 @@ def create_event_from_patron_transaction(
cls, patron_transaction=None, dbcommit=None, reindex=None,
delete_pid=None, update_parent=True):
"""Create a patron transaction event from patron transaction."""
data = build_patron_transaction_event_ref(patron_transaction, {})
data['creation_date'] = patron_transaction.get('creation_date')
data = {
'creation_date': patron_transaction.get('creation_date'),
'type': 'fee',
'amount': patron_transaction.get('total_amount'),
'parent': {
'$ref': get_ref_for_pid('pttr', patron_transaction.pid)
}
}
if patron_transaction.get('type') == 'overdue':
data['library'] = {
'$ref': get_ref_for_pid(
'lib',
patron_transaction.notification_transaction_library_pid
)
}
data['subtype'] = 'overdue'
elif patron_transaction.get('type') == 'subscription':
data['subtype'] = 'other'
data['data'] = _('Initial charge')
record = cls.create(
data,
dbcommit=dbcommit,
Expand Down Expand Up @@ -136,40 +154,3 @@ def organisation_pid(self):
patron_transaction = PatronTransaction.get_record_by_pid(
self.parent_pid)
return patron_transaction.organisation_pid


def build_patron_transaction_event_ref(patron_transaction, data):
"""Create $ref for a patron transaction event."""
schemas = current_app.config.get('RECORDS_JSON_SCHEMA')
data_schema = {
'base_url': current_app.config.get('RERO_ILS_APP_BASE_URL'),
'schema_endpoint': current_app.config.get('JSONSCHEMAS_ENDPOINT'),
'schema': schemas['ptre']
}
data['$schema'] = '{base_url}{schema_endpoint}{schema}'\
.format(**data_schema)
base_url = current_app.config.get('RERO_ILS_APP_BASE_URL')
url_api = '{base_url}/api/{doc_type}/{pid}'
for record in [
{
'resource': 'parent',
'doc_type': 'patron_transactions',
'pid': patron_transaction.pid
}, {
'resource': 'library',
'doc_type': 'libraries',
'pid': patron_transaction.notification_transaction_library_pid
},
]:
data[record['resource']] = {
'$ref': url_api.format(
base_url=base_url,
doc_type='{}'.format(record['doc_type']),
pid=record['pid'])
}
if patron_transaction.get('type') == 'overdue':
data['type'] = 'fee'
data['subtype'] = 'overdue'
data['amount'] = patron_transaction.get('total_amount')

return data
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"pid",
"creation_date",
"parent",
"type",
"library"
"type"
],
"properties": {
"$schema": {
Expand Down
144 changes: 100 additions & 44 deletions rero_ils/modules/patron_transactions/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from datetime import datetime, timezone
from functools import partial

from flask import current_app
from flask_babelex import gettext as _

from .models import PatronTransactionIdentifier
from ..api import IlsRecord, IlsRecordsSearch
Expand All @@ -30,6 +30,7 @@
from ..patron_transaction_events.api import PatronTransactionEvent, \
PatronTransactionEventsSearch
from ..providers import Provider
from ..utils import get_ref_for_pid

# provider
PatronTransactionProvider = type(
Expand Down Expand Up @@ -72,6 +73,37 @@ def create(cls, data, id_=None, delete_pid=False,
delete_pid=delete_pid, update_parent=False)
return record

@classmethod
def _build_transaction_query(cls, patron_pid, status=None):
"""Private function to build a transaction query linked to a patron."""
query = PatronTransactionsSearch() \
.filter('term', patron__pid=patron_pid)
if status:
query = query.filter('term', status=status)
return query

@classmethod
def get_transactions_pids_for_patron(cls, patron_pid, status=None):
"""Get patron transactions linked to a patron.
:param patron_pid: the patron pid being searched
:param status: (optional) transaction status filter,
"""
query = cls._build_transaction_query(patron_pid, status)
results = query.source('pid').scan()
for result in results:
yield result.pid

@classmethod
def get_transactions_count_for_patron(cls, patron_pid, status=None):
"""Get patron transactions count linked to a patron.
:param patron_pid: the patron pid being searched
:param status: (optional) transaction status filter,
"""
query = cls._build_transaction_query(patron_pid, status)
return query.source().count()

@property
def loan_pid(self):
"""Return the loan pid of the the overdue patron transaction."""
Expand Down Expand Up @@ -138,12 +170,67 @@ def create_patron_transaction_from_notification(
cls, notification=None, dbcommit=None, reindex=None,
delete_pid=None):
"""Create a patron transaction from notification."""
from ..notifications.api import calculate_overdue_amount
record = {}
if notification.get('notification_type') == 'overdue':
data = build_patron_transaction_ref(notification, {})
data['creation_date'] = datetime.now(timezone.utc).isoformat()
data['type'] = 'overdue'
data['status'] = 'open'
data = {
'notification': {
'$ref': get_ref_for_pid('notif', notification.pid)
},
'patron': {
'$ref': get_ref_for_pid('ptrn', notification.patron_pid)
},
'organisation': {
'$ref': get_ref_for_pid(
'org',
notification.organisation_pid
)
},
'total_amount': calculate_overdue_amount(notification),
'creation_date': datetime.now(timezone.utc).isoformat(),
'type': 'overdue',
'status': 'open'
}
record = cls.create(
data,
dbcommit=dbcommit,
reindex=reindex,
delete_pid=delete_pid
)
return record

@classmethod
def create_subscription_for_patron(cls, patron, patron_type, start_date,
end_date, dbcommit=None, reindex=None,
delete_pid=None):
"""Create a subscription patron transaction for a patron.
:param patron: the patron linked to the subscription
:param patron_type: the patron_type for which we need to create the
subscription
:param start_date: As `datetime`, the starting date of the subscription
:param end_date: As `datetime`, the ending date of the subscription
"""
record = {}
if patron_type.is_subscription_required:
data = {
'patron': {
'$ref': get_ref_for_pid('ptrn', patron.pid)
},
'organisation': {
'$ref': get_ref_for_pid('org', patron.organisation_pid)
},
'total_amount': patron_type.get('subscription_amount'),
'creation_date': datetime.now(timezone.utc).isoformat(),
'type': 'subscription',
'status': 'open',
'note': _("Subscription for '{name}' from {start} to {end}")
.format(
name=patron_type.get('name'),
start=start_date.strftime('%Y-%m-%d'),
end=end_date.strftime('%Y-%m-%d')
)
}
record = cls.create(
data,
dbcommit=dbcommit,
Expand All @@ -162,18 +249,19 @@ def currency(self):
@property
def events(self):
"""Shortcut for events of the patron transaction."""
# events = []
results = PatronTransactionEventsSearch().filter(
'term', parent__pid=self.pid
).source().scan()
results = PatronTransactionEventsSearch()\
.filter('term', parent__pid=self.pid)\
.source()\
.scan()
for result in results:
yield PatronTransactionEvent.get_record_by_pid(result.pid)

def get_number_of_patron_transaction_events(self):
"""Get number of patron transaction events."""
results = PatronTransactionEventsSearch().filter(
'term', parent__pid=self.pid).source().count()
return results
return PatronTransactionEventsSearch()\
.filter('term', parent__pid=self.pid)\
.source()\
.count()

def get_links_to_me(self):
"""Get number of links."""
Expand All @@ -190,35 +278,3 @@ def reasons_not_to_delete(self):
if links:
cannot_delete['links'] = links
return cannot_delete


def build_patron_transaction_ref(notification, data):
"""Create $ref for a patron transaction."""
from ..notifications.api import calculate_overdue_amount
schemas = current_app.config.get('RECORDS_JSON_SCHEMA')
data_schema = {
'base_url': current_app.config.get(
'RERO_ILS_APP_BASE_URL'
),
'schema_endpoint': current_app.config.get(
'JSONSCHEMAS_ENDPOINT'
),
'schema': schemas['pttr']
}
data['$schema'] = '{base_url}{schema_endpoint}{schema}'\
.format(**data_schema)
base_url = current_app.config.get('RERO_ILS_APP_BASE_URL')
url_api = '{base_url}/api/{doc_type}/{pid}'
for record in [
{'resource': 'notification', 'pid': notification.pid},
{'resource': 'patron', 'pid': notification.patron_pid},
{'resource': 'organisation', 'pid': notification.organisation_pid}
]:
data[record['resource']] = {
'$ref': url_api.format(
base_url=base_url,
doc_type='{}s'.format(record['resource']),
pid=record['pid'])
}
data['total_amount'] = calculate_overdue_amount(notification)
return data

0 comments on commit 88b44cb

Please sign in to comment.