diff --git a/data/loans.json b/data/loans.json index 1a1d2d4863..a334b97076 100644 --- a/data/loans.json +++ b/data/loans.json @@ -3,6 +3,7 @@ "barcode": "reroils1", "loans": { "active": 2, + "overdue": 1, "requested_by_others": 2 }, "requests": { @@ -13,7 +14,8 @@ { "barcode": "2000000001", "loans": { - "active": 1 + "active": 1, + "overdue": 1 }, "requests": { "requests": 1 @@ -22,7 +24,8 @@ { "barcode": "10000001", "loans": { - "active": 2 + "active": 2, + "overdue": 1 }, "requests": { "requests": 1 @@ -40,7 +43,8 @@ { "barcode": "kad001", "loans": { - "active": 1 + "active": 1, + "overdue": 1 }, "requests": { "requests": 1 @@ -49,7 +53,8 @@ { "barcode": "kad002", "loans": { - "active": 1 + "active": 1, + "overdue": 1 }, "requests": { "requests": 1 @@ -286,5 +291,17 @@ "rank_1": 1, "requests": 1 } + }, + { + "barcode": "999999", + "loans": { + "active": 1, + "overdue": 1, + "requested_by_others": 1 + }, + "requests": { + "rank_1": 1, + "rank_2": 1 + } } ] diff --git a/data/users.json b/data/users.json index a69ca13145..115ce53643 100644 --- a/data/users.json +++ b/data/users.json @@ -939,5 +939,26 @@ "street": "Lungolago 118", "communication_channel": "email", "communication_language": "ita" + }, + { + "$schema": "https://ils.rero.ch/schema/patrons/patron-v0.0.1.json", + "barcode": "999999", + "birth_date": "1970-01-01", + "city": "Flueli-Ranft", + "email": "reroilstest+guillaumeB@gmail.com", + "first_name": "Guillaume", + "roles": [ + "patron" + ], + "last_name": "de Baskerville", + "password": "123456", + "patron_type": { + "$ref": "https://ils.rero.ch/api/patron_types/5" + }, + "phone": "+41324993585", + "postal_code": "6073", + "street": "Ranftweg 1", + "communication_channel": "email", + "communication_language": "eng" } ] diff --git a/rero_ils/modules/fees/api.py b/rero_ils/modules/fees/api.py index b10456b7b5..cb3c111c24 100644 --- a/rero_ils/modules/fees/api.py +++ b/rero_ils/modules/fees/api.py @@ -31,6 +31,7 @@ from ..fetchers import id_fetcher from ..locations.api import Location from ..minters import id_minter +from ..organisations.api import Organisation from ..providers import Provider # fee provider @@ -73,6 +74,20 @@ def transaction_location_pid(self): """Return transaction location pid.""" return self.replace_refs().get('location').get('pid') + @property + def loan_pid(self): + """Return the loan pid of the fee .""" + from ..notifications.api import Notification + notification_pid = self.replace_refs().get('notification').get('pid') + return Notification.get_record_by_pid(notification_pid).loan_pid + + @property + def patron_pid(self): + """Return the patron pid of the fee .""" + from ..notifications.api import Notification + notification_pid = self.replace_refs().get('notification').get('pid') + return Notification.get_record_by_pid(notification_pid).patron_pid + @classmethod def create_fee_from_notification(cls, notification): """Create a new fee.""" @@ -118,10 +133,6 @@ def create_fee_from_notification(cls, notification): holding_circulation_category_pid ) data['amount'] = cipo.get('reminder_fee_amount') - currency = current_app.config.get('RERO_ILS_DEFAULT_CURRENCY') - if notification.organisation: - currency = notification.organisation.get('default_currency') - data['currency'] = currency data['status'] = 'open' record = cls.create( data, @@ -130,3 +141,10 @@ def create_fee_from_notification(cls, notification): delete_pid=True ) return record + + @property + def currency(self): + """Return fee currency.""" + organisation_pid = self.organisation_pid + return Organisation.get_record_by_pid(organisation_pid).get( + 'default_currency') diff --git a/rero_ils/modules/fees/jsonschemas/fees/fee-v0.0.1.json b/rero_ils/modules/fees/jsonschemas/fees/fee-v0.0.1.json index 0009554e3f..4c0fff5f24 100644 --- a/rero_ils/modules/fees/jsonschemas/fees/fee-v0.0.1.json +++ b/rero_ils/modules/fees/jsonschemas/fees/fee-v0.0.1.json @@ -11,7 +11,6 @@ "fee_type", "location", "amount", - "currency", "status" ], "properties": { diff --git a/rero_ils/modules/fees/listener.py b/rero_ils/modules/fees/listener.py index b7d1862c5a..9cbf2eca9e 100644 --- a/rero_ils/modules/fees/listener.py +++ b/rero_ils/modules/fees/listener.py @@ -35,3 +35,11 @@ def enrich_fee_data(sender, json=None, record=None, index=None, json['organisation'] = { 'pid': org_pid } + if fee.loan_pid: + json['loan'] = { + 'pid': fee.loan_pid + } + if fee.patron_pid: + json['patron'] = { + 'pid': fee.patron_pid + } diff --git a/rero_ils/modules/fees/mappings/v6/fees/fee-v0.0.1.json b/rero_ils/modules/fees/mappings/v6/fees/fee-v0.0.1.json index 5c397be915..2f6607f160 100644 --- a/rero_ils/modules/fees/mappings/v6/fees/fee-v0.0.1.json +++ b/rero_ils/modules/fees/mappings/v6/fees/fee-v0.0.1.json @@ -44,6 +44,20 @@ "status": { "type": "keyword" }, + "loan": { + "properties": { + "pid": { + "type": "keyword" + } + } + }, + "patron": { + "properties": { + "pid": { + "type": "keyword" + } + } + }, "_created": { "type": "date" }, @@ -53,4 +67,4 @@ } } } -} \ No newline at end of file +} diff --git a/rero_ils/modules/loans/api.py b/rero_ils/modules/loans/api.py index 1994bf6719..5554615701 100644 --- a/rero_ils/modules/loans/api.py +++ b/rero_ils/modules/loans/api.py @@ -323,18 +323,3 @@ def get_overdue_loans(): if now > due_date + timedelta(days=days_after): overdue_loans.append(loan) return overdue_loans - - -def get_item_on_loan_loans(): - """Return item on loan.""" - item_on_loan_loans = [] - results = current_circulation.loan_search\ - .source(['pid'])\ - .params(preserve_order=True)\ - .filter('term', state='ITEM_ON_LOAN')\ - .sort({'transaction_date': {'order': 'asc'}})\ - .scan() - for record in results: - loan = Loan.get_record_by_pid(record.pid) - item_on_loan_loans.append(loan) - return item_on_loan_loans diff --git a/rero_ils/modules/loans/cli.py b/rero_ils/modules/loans/cli.py index 5fc66cd3d3..a41eedda10 100644 --- a/rero_ils/modules/loans/cli.py +++ b/rero_ils/modules/loans/cli.py @@ -31,7 +31,7 @@ from ..circ_policies.api import CircPolicy from ..items.api import Item, ItemsSearch, ItemStatus from ..libraries.api import Library -from ..loans.api import get_item_on_loan_loans +from ..loans.api import Loan from ..locations.api import Location from ..notifications.tasks import create_over_and_due_soon_notifications from ..patron_types.api import PatronType @@ -39,12 +39,11 @@ @click.command('create_loans') -@click.option('-f', '--fee', 'fee', is_flag=True, default=False) @click.option('-v', '--verbose', 'verbose', is_flag=True, default=False) @click.option('-d', '--debug', 'debug', is_flag=True, default=False) @click.argument('infile', type=click.File('r')) @with_appcontext -def create_loans(infile, fee, verbose, debug): +def create_loans(infile, verbose, debug): """Create circulation transactions. infile: Json transactions file @@ -115,17 +114,8 @@ def create_loans(infile, fee, verbose, debug): loanable_items, verbose, debug) errors_count = print_message(item_barcode, 'rank_2', errors_count) - if fee: - loan = get_item_on_loan_loans()[0] - - end_date = datetime.now(timezone.utc) - timedelta(days=7) - loan['end_date'] = end_date.isoformat() - loan.update( - loan, - dbcommit=True, - reindex=True - ) - create_over_and_due_soon_notifications() + # create due soon notifications, overdue notifications are auto created. + create_over_and_due_soon_notifications(overdue=False) for key, val in errors_count.items(): click.secho( 'Errors {transaction_type}: {count}'.format( @@ -172,9 +162,20 @@ def create_loan(barcode, transaction_type, loanable_items, verbose=False, document_pid=item.replace_refs()['document']['pid'], item_pid=item.pid, ) - if transaction_type == 'extended': - loan = get_loan_for_item(item.pid) - loan_pid = loan.get('pid') + loan = get_loan_for_item(item.pid) + loan_pid = loan.get('pid') + if transaction_type == 'overdue': + loan = Loan.get_record_by_pid(loan_pid) + end_date = datetime.now(timezone.utc) - timedelta(days=70) + loan['end_date'] = end_date.isoformat() + loan.update( + loan, + dbcommit=True, + reindex=True + ) + notif = loan.create_notification(notification_type='overdue') + + elif transaction_type == 'extended': user_pid, user_location = \ get_random_librarian_and_transaction_location(patron) item.extend_loan( diff --git a/rero_ils/modules/notifications/tasks.py b/rero_ils/modules/notifications/tasks.py index deeb6a1bb6..4fa3932f70 100644 --- a/rero_ils/modules/notifications/tasks.py +++ b/rero_ils/modules/notifications/tasks.py @@ -25,19 +25,21 @@ @shared_task(ignore_result=True) -def create_over_and_due_soon_notifications(): +def create_over_and_due_soon_notifications(overdue=True, due_soon=True): """Creates due_soon and overdue notifications.""" - over_due_loans = get_overdue_loans() no_over_due_loans = 0 - for loan in over_due_loans: - loan.create_notification(notification_type='overdue') - no_over_due_loans += 1 - - due_soon_loans = get_due_soon_loans() no_due_soon_loans = 0 - for loan in due_soon_loans: - loan.create_notification(notification_type='due_soon') - no_due_soon_loans += 1 + if overdue: + over_due_loans = get_overdue_loans() + + for loan in over_due_loans: + loan.create_notification(notification_type='overdue') + no_over_due_loans += 1 + if due_soon: + due_soon_loans = get_due_soon_loans() + for loan in due_soon_loans: + loan.create_notification(notification_type='due_soon') + no_due_soon_loans += 1 return 'created {no_over_due_loans} overdue loans, '\ '{no_due_soon_loans} due soon loans'.format( diff --git a/scripts/setup b/scripts/setup index 49fd21b883..930ea7fcff 100755 --- a/scripts/setup +++ b/scripts/setup @@ -290,7 +290,7 @@ eval ${PREFIX} pipenv run invenio utils runindex -c 4 --raise-on-error # create circulation transactions info_msg "Circulation transactions:" -eval ${PREFIX} pipenv run invenio fixtures create_loans --fee ${DATA_PATH}/loans.json +eval ${PREFIX} pipenv run invenio fixtures create_loans ${DATA_PATH}/loans.json # # ACQUISITION # create vendors diff --git a/tests/api/test_fees.py b/tests/api/test_fees.py index 3f59baa739..065ef6fa2c 100644 --- a/tests/api/test_fees.py +++ b/tests/api/test_fees.py @@ -34,7 +34,7 @@ def test_create_fee(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, - circ_policy_short_martigny): + circ_policy_short_martigny, org_martigny): """Test overdue loans.""" login_user_via_session(client, librarian_martigny_no_email.user) @@ -68,7 +68,7 @@ def test_create_fee(client, librarian_martigny_no_email, fee = list(notification.fees)[0] assert fee.get('amount') == 2 - assert fee.get('currency') == 'CHF' + assert fee.currency == org_martigny.get('default_currency') fee_url = url_for('invenio_records_rest.fee_item', pid_value=fee.pid) @@ -132,7 +132,7 @@ def test_create_fee_euro(client, librarian_martigny_no_email, flush_index(NotificationsSearch.Meta.index) flush_index(LoansSearch.Meta.index) fee = list(notification.fees)[0] - assert fee.get('currency') == org.get('default_currency') + assert fee.currency == org.get('default_currency') def test_filtered_fees_get( diff --git a/tests/api/test_loans_rest.py b/tests/api/test_loans_rest.py index fed113c038..a97ea68072 100644 --- a/tests/api/test_loans_rest.py +++ b/tests/api/test_loans_rest.py @@ -136,6 +136,8 @@ def test_due_soon_loans(client, librarian_martigny_no_email, item_pid = item.pid patron_pid = patron_martigny_no_email.pid + assert not get_last_transaction_loc_for_item(item_pid) + assert not item.is_loaned_to_patron(patron_martigny_no_email.get( 'barcode')) assert item.can_delete @@ -170,6 +172,9 @@ def test_due_soon_loans(client, librarian_martigny_no_email, assert due_soon_loans[0].get('pid') == loan_pid # test due date hour, should be 22:59 UTC+0 (Europe/Zurich) + assert get_last_transaction_loc_for_item( + item_pid) == loc_public_martigny.pid + # test due date hour checkout_loan = Loan.get_record_by_pid(loan_pid) end_date = ciso8601.parse_datetime( checkout_loan.get('end_date')) diff --git a/tests/data/data.json b/tests/data/data.json index f0c5d67a10..e0239bbd98 100644 --- a/tests/data/data.json +++ b/tests/data/data.json @@ -1916,7 +1916,6 @@ "$ref": "https://ils.rero.ch/api/locations/loc1" }, "amount": 0.5, - "currency": "CHF", "status": "open" } }