def test_circ_policy_exist_name_and_organisation_pid(circ_policy): """.""" cipo = circ_policy.replace_refs() assert CircPolicy.exist_name_and_organisation_pid( cipo.get('name'), cipo.get('organisation', {}).get('pid')) assert not CircPolicy.exist_name_and_organisation_pid( 'not exists yet', cipo.get('organisation', {}).get('pid'))
def test_circ_policy_create( circ_policy_martigny_data_tmp, org_martigny, lib_martigny, lib_saxon, patron_type_children_martigny, item_type_standard_martigny, patron_type_adults_martigny, item_type_specific_martigny, item_type_regular_sion, patron_type_youngsters_sion): """Test circulation policy creation.""" cipo = CircPolicy.create(circ_policy_martigny_data_tmp, delete_pid=True) assert cipo == circ_policy_martigny_data_tmp assert cipo.get('pid') == '1' cipo = CircPolicy.get_record_by_pid('1') assert cipo == circ_policy_martigny_data_tmp fetched_pid = circ_policy_id_fetcher(cipo.id, cipo) assert fetched_pid.pid_value == '1' assert fetched_pid.pid_type == 'cipo' circ_policy = deepcopy(circ_policy_martigny_data_tmp) del circ_policy['$schema'] cipo = CircPolicy.create(circ_policy, delete_pid=True) assert cipo.get('$schema') assert cipo.get('pid') == '2' cipo_data = { '$schema': 'https://ils.rero.ch/schemas/' 'circ_policies/circ_policy-v0.0.1.json', 'pid': 'cipo_test', 'name': 'test', 'organisation': { '$ref': 'https://ils.rero.ch/api/organisations/org1' }, 'is_default': False, 'allow_requests': True, 'policy_library_level': False, 'settings': [{ 'patron_type': { '$ref': 'https://ils.rero.ch/api/patron_types/ptty3' }, 'item_type': { '$ref': 'https://ils.rero.ch/api/item_types/itty1' } }, { 'patron_type': { '$ref': 'https://ils.rero.ch/api/patron_types/ptty2' }, 'item_type': { '$ref': 'https://ils.rero.ch/api/item_types/itty4' } }] } with pytest.raises(RecordValidationError): cipo = CircPolicy.create(cipo_data, delete_pid=False)
def test_circ_policy_exist_name_and_organisation_pid( circ_policy_short_martigny): """Test policy name existence.""" cipo = circ_policy_short_martigny.replace_refs() assert CircPolicy.exist_name_and_organisation_pid( cipo.get('name'), cipo.get('organisation', {}).get('pid')) assert not CircPolicy.exist_name_and_organisation_pid( 'not exists yet', cipo.get('organisation', {}).get('pid'))
def test_circ_policy_es_mapping(es, db, org_martigny, circ_policy_martigny_data_tmp): """Test circulation policy elasticsearch mapping.""" search = CircPoliciesSearch() mapping = get_mapping(search.Meta.index) assert mapping CircPolicy.create(circ_policy_martigny_data_tmp, dbcommit=True, reindex=True, delete_pid=True) assert mapping == get_mapping(search.Meta.index)
def test_circ_policy_es_mapping(es, db, organisation, circ_policy_data_tmp): """.""" search = CircPoliciesSearch() mapping = get_mapping(search.Meta.index) assert mapping CircPolicy.create( circ_policy_data_tmp, dbcommit=True, reindex=True, delete_pid=True ) assert mapping == get_mapping(search.Meta.index)
def test_checkout_temporary_item_type(client, librarian_martigny, lib_martigny, loc_public_martigny, patron_martigny, item_lib_martigny, item_type_on_site_martigny, circ_policy_short_martigny, circ_policy_default_martigny): """Test checkout or item with temporary item_types""" login_user_via_session(client, librarian_martigny.user) item = item_lib_martigny assert item.status == ItemStatus.ON_SHELF # test basic behavior cipo_used = CircPolicy.provide_circ_policy( lib_martigny.organisation_pid, lib_martigny.pid, patron_martigny.patron_type_pid, item.item_type_circulation_category_pid) assert cipo_used == circ_policy_short_martigny # add a temporary_item_type on item # due to this change, the cipo used during circulation operation should # be different from the first cipo found. item['temporary_item_type'] = { '$ref': get_ref_for_pid('itty', item_type_on_site_martigny.pid) } item = item.update(data=item, dbcommit=True, reindex=True) cipo_tmp_used = CircPolicy.provide_circ_policy( lib_martigny.organisation_pid, lib_martigny.pid, patron_martigny.patron_type_pid, item.item_type_circulation_category_pid) assert cipo_tmp_used == circ_policy_default_martigny delta = timedelta(cipo_tmp_used.get('checkout_duration')) expected_date = datetime.now() + delta expected_dates = [expected_date, lib_martigny.next_open(expected_date)] expected_dates = [d.strftime('%Y-%m-%d') for d in expected_dates] # try a checkout and check the transaction end_date is related to the cipo # corresponding to the temporary item_type params = dict(item_pid=item.pid, patron_pid=patron_martigny.pid, transaction_user_pid=librarian_martigny.pid, transaction_location_pid=loc_public_martigny.pid) res, data = postdata(client, 'api_item.checkout', params) assert res.status_code == 200 transaction_end_date = data['action_applied']['checkout']['end_date'] transaction_end_date = ciso8601.parse_datetime(transaction_end_date).date() transaction_end_date = transaction_end_date.strftime('%Y-%m-%d') assert transaction_end_date in expected_dates # reset the item to original value del item['temporary_item_type'] item.update(data=item, dbcommit=True, reindex=True)
def test_circ_policy_search(app, circulation_policies): """Test finding a circulation policy.""" data = [{ 'library_pid': 'lib1', 'patron_type_pid': 'ptty1', 'item_type_pid': 'itty1', 'cipo': 'cipo2' }, { 'library_pid': 'lib1', 'patron_type_pid': 'ptty2', 'item_type_pid': 'itty2', 'cipo': 'cipo3' }, { 'library_pid': 'lib2', 'patron_type_pid': 'ptty2', 'item_type_pid': 'itty2', 'cipo': 'cipo1' }, { 'library_pid': 'lib1', 'patron_type_pid': 'ptty3', 'item_type_pid': 'itty2', 'cipo': 'cipo1' }, { 'library_pid': 'lib1', 'patron_type_pid': 'ptty1', 'item_type_pid': 'itty2', 'cipo': 'cipo1' }] for row in data: cipo = CircPolicy.provide_circ_policy(row['library_pid'], row['patron_type_pid'], row['item_type_pid']) assert cipo.pid == row['cipo']
def test_checkout_default_policy(client, lib_martigny, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, circulation_policies): """Test circ policy parameters""" 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 from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy(item.library_pid, 'ptty1', 'itty1') # checkout res, data = postdata(client, 'api_item.checkout', dict(item_pid=item_pid, patron_pid=patron_pid)) assert res.status_code == 200 actions = data.get('action_applied') loan = actions[LoanAction.CHECKOUT] end_date = loan.get('end_date') start_date = loan.get('start_date') checkout_duration = (ciso8601.parse_datetime(end_date) - ciso8601.parse_datetime(start_date)).days assert checkout_duration >= circ_policy.get('checkout_duration') # checkin res, _ = postdata(client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan.get('pid'))) assert res.status_code == 200
def test_item_possible_actions(client, item_on_shelf, user_librarian_no_email, user_patron_no_email): """Possible action changes according to params of cipo""" login_user_via_session(client, user_librarian_no_email.user) item = item_on_shelf patron_pid = user_patron_no_email.pid res = client.get( url_for('api_item.item', item_barcode=item.get('barcode'), patron_pid=patron_pid)) assert res.status_code == 200 data = get_json(res) actions = data.get('metadata').get('item').get('actions') assert 'checkout' in actions from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy(item.library_pid, 'ptty1', 'itty1') circ_policy['allow_checkout'] = False circ_policy.update(circ_policy, dbcommit=True, reindex=True) res = client.get( url_for('api_item.item', item_barcode=item.get('barcode'), patron_pid=patron_pid)) assert res.status_code == 200 data = get_json(res) actions = data.get('metadata').get('item').get('actions') assert 'checkout' not in actions circ_policy['allow_checkout'] = True circ_policy.update(circ_policy, dbcommit=True, reindex=True) assert circ_policy['allow_checkout']
def circ_policy_default_sion(app, org_sion, circ_policy_default_sion_data): """Create default circ policy for organisation sion.""" cipo = CircPolicy.create(data=circ_policy_default_sion_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) return cipo
def test_circ_policy_can_delete(app, circ_policy_martigny_data_tmp): """Test can delete a policy.""" circ_policy_martigny_data_tmp['is_default'] = False cipo = CircPolicy.create(circ_policy_martigny_data_tmp, delete_pid=True) can, reasons = cipo.can_delete assert can assert reasons == {}
def circ_policy(app, organisation, circ_policy_data): """.""" cipo = CircPolicy.create(data=circ_policy_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) return cipo
def test_due_soon_loans(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): """Test overdue 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 assert not item.is_loaned_to_patron( patron_martigny_no_email.get('barcode')) assert item.can_delete assert item.available from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy( item.library_pid, patron_martigny_no_email.patron_type_pid, item.item_type_pid) circ_policy['number_of_days_before_due_date'] = 7 circ_policy['checkout_duration'] = 3 circ_policy.update(circ_policy, dbcommit=True, reindex=True) # 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('pid') due_soon_loans = get_due_soon_loans() assert due_soon_loans[0].get('pid') == loan_pid # test due date hour checkout_loan = Loan.get_record_by_pid(loan_pid) end_date = ciso8601.parse_datetime(checkout_loan.get('end_date')) assert end_date.minute == 59 and end_date.hour == 23 new_timezone = pytz.timezone('US/Pacific') end_date = ciso8601.parse_datetime( checkout_loan.get('end_date')).astimezone(new_timezone) assert end_date.minute == 59 and end_date.hour != 23 new_timezone = pytz.timezone('Europe/Amsterdam') end_date = ciso8601.parse_datetime( checkout_loan.get('end_date')).astimezone(new_timezone) assert end_date.minute == 59 and end_date.hour != 23 # 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, pid=loan_pid)), content_type='application/json', ) assert res.status_code == 200
def test_extend_possible_actions(client, item_lib_martigny, loc_public_martigny, librarian_martigny_no_email, patron_martigny_no_email, circ_policy_short_martigny): """Extend action changes according to params of cipo.""" login_user_via_session(client, librarian_martigny_no_email.user) item = item_lib_martigny patron_pid = patron_martigny_no_email.pid res, _ = postdata( client, 'api_item.checkout', dict(item_pid=item.pid, patron_pid=patron_pid, transaction_user_pid=librarian_martigny_no_email.pid, transaction_location_pid=loc_public_martigny.pid)) # check the item is now in patron loaned item res = client.get(url_for('api_item.loans', patron_pid=patron_pid)) assert res.status_code == 200 data = get_json(res) assert data['hits']['total']['value'] == 1 hit = data.get('hits').get('hits')[0].get('item') assert hit.get('barcode') == item.get('barcode') # check the item can be checked-in res = client.get(url_for('api_item.item', item_barcode=item.get('barcode'))) assert res.status_code == 200 data = get_json(res) actions = data.get('metadata').get('item').get('actions', []) assert 'checkin' in actions from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy(item.library_pid, 'ptty1', 'itty1') circ_policy['number_renewals'] = 0 circ_policy.update(circ_policy, dbcommit=True, reindex=True) res = client.get(url_for('api_item.item', item_barcode=item.get('barcode'))) assert res.status_code == 200 data = get_json(res) actions = data.get('metadata').get('item').get('actions', []) assert 'extend_loan' not in actions assert 'checkin' in actions # reset used objects loan_pid = data.get('metadata').get('loan').get('pid') res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item.pid, pid=loan_pid, transaction_user_pid=librarian_martigny_no_email.pid, transaction_location_pid=loc_public_martigny.pid)) assert res.status_code == 200 circ_policy['number_renewals'] = 1 circ_policy.update(circ_policy, dbcommit=True, reindex=True) assert circ_policy['number_renewals'] == 1
def test_circ_policy_create(db, circ_policy_martigny_data_tmp): """Test circulation policy creation.""" cipo = CircPolicy.create(circ_policy_martigny_data_tmp, delete_pid=True) assert cipo == circ_policy_martigny_data_tmp assert cipo.get('pid') == '1' cipo = CircPolicy.get_record_by_pid('1') assert cipo == circ_policy_martigny_data_tmp fetched_pid = circ_policy_id_fetcher(cipo.id, cipo) assert fetched_pid.pid_value == '1' assert fetched_pid.pid_type == 'cipo' circ_policy = deepcopy(circ_policy_martigny_data_tmp) del circ_policy['$schema'] cipo = CircPolicy.create(circ_policy, delete_pid=True) assert cipo.get('$schema') assert cipo.get('pid') == '2'
def test_due_soon_loans(client, librarian_martigny, patron_martigny, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, circ_policy_short_martigny): """Test overdue loans.""" login_user_via_session(client, librarian_martigny.user) item = item_lib_martigny item_pid = item.pid patron_pid = patron_martigny.pid assert not get_last_transaction_loc_for_item(item_pid) assert not item.patron_has_an_active_loan_on_item(patron_martigny) assert item.can_delete assert item.available from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy( item.organisation_pid, item.library_pid, patron_martigny.patron_type_pid, item.item_type_pid) circ_policy['reminders'][0]['days_delay'] = 7 circ_policy['checkout_duration'] = 3 circ_policy.update(circ_policy, dbcommit=True, reindex=True) # checkout res, data = postdata( client, 'api_item.checkout', dict( item_pid=item_pid, patron_pid=patron_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid, )) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') due_soon_loans = get_due_soon_loans() assert due_soon_loans[0].get('pid') == loan_pid # test due date regarding multiple timezones checkout_loan = Loan.get_record_by_pid(loan_pid) loan_date = ciso8601.parse_datetime(checkout_loan.get('end_date')) # as instance timezone is Europe/Zurich, it should be either 21 or 22 check_timezone_date(pytz.utc, loan_date, [21, 22]) # should be 14:59/15:59 in US/Pacific (because of daylight saving time) check_timezone_date(pytz.timezone('US/Pacific'), loan_date, [14, 15]) check_timezone_date(pytz.timezone('Europe/Amsterdam'), loan_date) # checkin the item to put it back to it's original state res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid)) assert res.status_code == 200
def circ_policy_ebooks_sion(app, patron_type_youngsters_sion, patron_type_grown_sion, item_type_online_sion, circ_policy_ebooks_sion_data): """Create ebooks circ policy for organisation sion.""" cipo = CircPolicy.create(data=circ_policy_ebooks_sion_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) return cipo
def circ_policy_less_than_one_day_martigny( app, patron_type_adults_martigny, item_type_standard_martigny, circ_policy_less_than_one_day_martigny_data): """Create short circ policy for organisation martigny.""" cipo = CircPolicy.create(data=circ_policy_less_than_one_day_martigny_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) return cipo
def test_circ_policy_can_not_delete(circ_policy_short_martigny): """Test can not delete a policy.""" org_pid = circ_policy_short_martigny.organisation_pid defaut_cipo = CircPolicy.get_default_circ_policy(org_pid) can, reasons = defaut_cipo.can_delete assert not can assert reasons['others']['is_default'] can, reasons = circ_policy_short_martigny.can_delete assert can assert reasons == {}
def circ_policy_short( circ_policy_data_short, patron_type, patron_type_specific, item_type, item_type_specific, item_type_on_site): """.""" cipo = CircPolicy.create( data=circ_policy_data_short, delete_pid=False, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) return cipo
def circ_policy_ebooks_martigny(app, patron_type_adults_martigny, patron_type_children_martigny, item_type_online_martigny, circ_policy_ebooks_martigny_data): """Create ebooks circ policy for organisation martigny.""" cipo = CircPolicy.create(data=circ_policy_ebooks_martigny_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) return cipo
def upgrade(): """Update circulation policy records.""" query = CircPoliciesSearch() \ .filter('term', allow_requests=True) \ .source(['pid']).scan() for hit in query: cipo = CircPolicy.get_record_by_pid(hit.pid) cipo['pickup_hold_duration'] = 10 # default value is 10 days cipo.update(cipo, dbcommit=True, reindex=True) LOGGER.info(f' * Updated cipo#{cipo.pid}') CircPoliciesSearch.flush_and_refresh() LOGGER.info(f'upgrade to {revision}')
def downgrade(): """Reset circulation policy records.""" query = CircPoliciesSearch() \ .filter('exists', field='pickup_hold_duration') \ .source(['pid']).scan() for hit in query: cipo = CircPolicy.get_record_by_pid(hit.pid) del cipo['pickup_hold_duration'] cipo.update(cipo, dbcommit=True, reindex=True) LOGGER.info(f' * Updated cipo#{cipo.pid}') CircPoliciesSearch.flush_and_refresh() LOGGER.info(f'downgrade to revision {down_revision}')
def test_circ_policy_extended_validation(app, circ_policy_short_martigny, circ_policy_short_martigny_data): """Test extended validation for circ policy""" cipo_data = deepcopy(circ_policy_short_martigny_data) cipo_data['allow_requests'] = False cipo_data['pickup_hold_duration'] = 10 del cipo_data['pid'] cipo = CircPolicy.create(cipo_data) assert cipo assert 'pickup_hold_duration' not in cipo cipo.delete()
def circ_policy_temp_martigny(app, lib_martigny, patron_type_adults_martigny, item_type_on_site_martigny, circ_policy_temp_martigny_data): """Create temporary circ policy for organisation martigny. library martigny. """ cipo = CircPolicy.create(data=circ_policy_temp_martigny_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) return cipo
def test_circ_policy_search( app, circ_policy, circ_policy_short, circ_policy_short_library ): """Test Find circ policy""" data = [ { 'library_pid': 'lib1', 'patron_type_pid': 'ptty1', 'item_type_pid': 'itty1', 'cipo': 'cipo2' }, { 'library_pid': 'lib1', 'patron_type_pid': 'ptty2', 'item_type_pid': 'itty2', 'cipo': 'cipo3' }, { 'library_pid': 'lib2', 'patron_type_pid': 'ptty2', 'item_type_pid': 'itty2', 'cipo': 'cipo1' }, { 'library_pid': 'lib1', 'patron_type_pid': 'ptty3', 'item_type_pid': 'itty2', 'cipo': 'cipo1' }, { 'library_pid': 'lib1', 'patron_type_pid': 'ptty1', 'item_type_pid': 'itty2', 'cipo': 'cipo1' } ] for row in data: cipo = CircPolicy.provide_circ_policy( row['library_pid'], row['patron_type_pid'], row['item_type_pid'] ) assert cipo.pid == row['cipo']
def test_circ_policy_can_delete(app, circ_policy_martigny_data_tmp): """Test can delete a policy.""" circ_policy_martigny_data_tmp['is_default'] = False cipo = CircPolicy.create(circ_policy_martigny_data_tmp, delete_pid=True) assert cipo.get_links_to_me() == {} assert cipo.can_delete reasons = cipo.reasons_not_to_delete() assert 'links' not in reasons with mock.patch( 'rero_ils.modules.circ_policies.api.CircPolicy.get_links_to_me' ) as a: a.return_value = {'object': 1} reasons = cipo.reasons_not_to_delete() assert 'links' in reasons
def test_extend_possible_actions(client, item_lib_martigny, librarian_martigny_no_email, patron_martigny_no_email, circ_policy_short_martigny): """Extend action changes according to params of cipo.""" login_user_via_session(client, librarian_martigny_no_email.user) circ_policy = circ_policy_short_martigny item = item_lib_martigny patron_pid = patron_martigny_no_email.pid res = client.post( url_for('api_item.checkout'), data=json.dumps(dict(item_pid=item.pid, patron_pid=patron_pid)), content_type='application/json', ) res = client.get(url_for('api_item.loans', patron_pid=patron_pid)) assert res.status_code == 200 data = get_json(res) assert data.get('hits').get('total') == 1 actions = data.get('hits').get('hits')[0].get('item').get('actions') assert 'checkin' in actions from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy(item.library_pid, 'ptty1', 'itty1') circ_policy['number_renewals'] = 0 circ_policy.update(circ_policy, dbcommit=True, reindex=True) res = client.get(url_for('api_item.loans', patron_pid=patron_pid)) assert res.status_code == 200 data = get_json(res) assert data.get('hits').get('total') == 1 actions = data.get('hits').get('hits')[0].get('item').get('actions') assert 'extend_loan' not in actions assert 'checkin' in actions loan_pid = data.get('hits').get('hits')[0].get('loan').get('pid') # reset used objects res = client.post( url_for('api_item.checkin'), data=json.dumps(dict(item_pid=item.pid, pid=loan_pid)), content_type='application/json', ) assert res.status_code == 200 circ_policy['number_renewals'] = 1 circ_policy.update(circ_policy, dbcommit=True, reindex=True) assert circ_policy['number_renewals'] == 1
def test_item_possible_actions(client, item_lib_martigny, librarian_martigny, patron_martigny, circulation_policies): """Possible action changes according to params of cipo.""" login_user_via_session(client, librarian_martigny.user) item = item_lib_martigny patron_pid = patron_martigny.pid res = client.get( url_for('api_item.item', item_barcode=item.get('barcode'), patron_pid=patron_pid)) data = get_json(res) assert res.status_code == 200 actions = data.get('metadata').get('item').get('actions') assert 'checkout' in actions from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy(item.organisation_pid, item.library_pid, 'ptty1', 'itty1') original_checkout_duration = circ_policy.get('checkout_duration') if original_checkout_duration is not None: del circ_policy['checkout_duration'] circ_policy.update(circ_policy, dbcommit=True, reindex=True) res = client.get( url_for('api_item.item', item_barcode=item.get('barcode'), patron_pid=patron_pid)) assert res.status_code == 200 data = get_json(res) actions = data.get('metadata').get('item').get('actions') assert 'checkout' not in actions if original_checkout_duration is not None: circ_policy['checkout_duration'] = original_checkout_duration circ_policy.update(circ_policy, dbcommit=True, reindex=True) assert circ_policy.can_checkout
def can_extend(cls, item, **kwargs): """Loan can extend.""" from rero_ils.modules.loans.utils import extend_loan_data_is_valid if 'loan' not in kwargs: # this method is not relevant return True, [] loan = kwargs['loan'] if loan.get('state') != LoanState.ITEM_ON_LOAN: return False, [_('The loan cannot be extended')] patron = Patron.get_record_by_pid(loan.get('patron_pid')) cipo = CircPolicy.provide_circ_policy( item.organisation_pid, item.library_pid, patron.patron_type_pid, item.item_type_circulation_category_pid) extension_count = loan.get('extension_count', 0) if not (cipo.get('number_renewals', 0) > 0 and extension_count < cipo.get('number_renewals', 0) and extend_loan_data_is_valid(loan.get('end_date'), cipo.get('renewal_duration'), item.library_pid)): return False, [_('Circulation policies disallows the operation.')] if item.number_of_requests(): return False, [_('A pending request exists on this item.')] return True, []