def item_on_shelf(app, document, item_on_shelf_data, location, item_type): """.""" item = Item.create( data=item_on_shelf_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(ItemsSearch.Meta.index) return item
def index_items_with_temporary_location(): """Index items with temporary location.""" query = ItemsSearch() \ .filter('exists', field='temporary_location').source(['pid']) ids = [(hit.meta.id, hit.pid) for hit in query.scan()] for id, pid in ids: item = Item.get_record_by_id(id) item.reindex() LOGGER.info(f' * Reindexed item#{pid}')
def item_lib_fully(app, document, item_lib_fully_data, loc_public_fully, item_type_standard_martigny): """Create item of fully library.""" item = Item.create(data=item_lib_fully_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(ItemsSearch.Meta.index) return item
def item2_lib_sion(app, document, item2_lib_sion_data, loc_restricted_sion, item_type_regular_sion): """Create item of sion library.""" item = Item.create(data=item2_lib_sion_data, delete_pid=False, dbcommit=True, reindex=True) flush_index(ItemsSearch.Meta.index) return item
def test_item_different_actions(client, librarian_martigny_no_email, lib_martigny, patron_martigny_no_email, loc_public_martigny, item_lib_martigny, json_header, item_type_standard_martigny, circ_policy_short_martigny, patron_type_children_martigny, lib_saxon, loc_public_saxon, librarian_saxon_no_email): """Test item possible actions other scenarios.""" login_user_via_session(client, librarian_martigny_no_email.user) circ_policy_origin = deepcopy(circ_policy_short_martigny) circ_policy = circ_policy_short_martigny patron_pid = patron_martigny_no_email.pid res = client.get( url_for('api_item.item', item_barcode='does not exist', patron_pid=patron_pid)) assert res.status_code == 404 res, data = postdata( client, 'api_item.checkout', dict(item_pid=item_lib_martigny.pid, patron_pid=patron_pid)) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') record = Item.get_record_by_pid(item_lib_martigny.pid) class current_i18n: class locale: language = 'en' with mock.patch('rero_ils.modules.items.api.current_i18n', current_i18n): text = item_status_text(record, format='medium', locale='en') assert 'due until' in text res, _ = postdata( client, 'api_item.checkin', dict(item_pid='does not exist', pid=loan_pid, transaction_location_pid=loc_public_saxon.pid), ) assert res.status_code == 404 res, data = postdata( client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, pid=loan_pid, transaction_location_pid=loc_public_saxon.pid), ) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKIN].get('pid') data = {'pid': loan_pid} return_data = item_lib_martigny.prior_checkout_actions(data) assert return_data == {}
def get_items(self): """Get items. :param self: self :return: list of items linked to collection """ return [ Item.get_record_by_pid(item['pid']) for item in self.replace_refs().get('items', []) ]
def get_pickup_locations(item_pid): """HTTP request to return the available pickup locations for an item. :param item_pid: the item pid """ item = Item.get_record_by_pid(item_pid) if not item: abort(404, 'Item not found') locations = record_library_pickup_locations(item) return jsonify({'locations': locations})
def test_holding_delete_after_item_deletion( client, holding_lib_martigny, item_lib_martigny): """Test automatic holding delete after deleting last item.""" for pid in Item.get_all_pids(): if pid != item_lib_martigny.pid: item = Item.get_record_by_pid(pid) Item.delete(item, dbcommit=True, delindex=True) flush_index(ItemsSearch.Meta.index) pid = holding_lib_martigny.pid holding = Holding.get_record_by_pid(pid) assert not holding.can_delete item_lib_martigny.delete(dbcommit=True, delindex=True) flush_index(ItemsSearch.Meta.index) pid = holding_lib_martigny.pid holding = Holding.get_record_by_pid(pid) assert not holding
def test_item_create(item_lib_martigny_data_tmp, item_lib_martigny): """Test itemanisation creation.""" item = Item.create(item_lib_martigny_data_tmp, delete_pid=True) assert item == item_lib_martigny_data_tmp # we have used item_lib_martigny_data_tmp two times -> pid == 2 assert item.get('pid') == '2' assert item.can_delete item = Item.get_record_by_pid('1') item_lib_martigny_data_tmp['pid'] = '1' assert item == item_lib_martigny_data_tmp fetched_pid = item_id_fetcher(item.id, item) assert fetched_pid.pid_value == '1' assert fetched_pid.pid_type == 'item' item_lib_martigny.delete_from_index() assert not item_lib_martigny.delete_from_index() item_lib_martigny.dbcommit(forceindex=True)
def test_checkout_on_item_on_loan( item_on_loan_martigny_patron_and_loan_on_loan, patron_martigny_no_email, patron2_martigny_no_email, loc_public_martigny, librarian_martigny_no_email): """Test CHECKOUT on an ON_LOAN item.""" # Prepare a new item with an ITEM_ON_LOAN loan onloan_item, patron, loan = item_on_loan_martigny_patron_and_loan_on_loan assert onloan_item.number_of_requests() == 0 # the following tests the circulation action CHECKOUT_3_1 # an ON_LOAN item # checkout patron = patron of current loan # can NOT be CHECKOUT params = { 'patron_pid': patron_martigny_no_email.pid, 'transaction_location_pid': loc_public_martigny.pid, 'transaction_user_pid': librarian_martigny_no_email.pid, 'pickup_location_pid': loc_public_martigny.pid } # Checkout it! CHECKOUT patron == current LOAN patron assert params['patron_pid'] == patron['pid'] with pytest.raises(NoValidTransitionAvailableError): asked_item, actions = onloan_item.checkout(**params, pid=loan.pid) # Check item is ON_SHELF (because no # other request + item_member = transaction one) checkout_loan = Loan.get_record_by_pid(loan.pid) asked_item = Item.get_record_by_pid(onloan_item.pid) assert asked_item.status == ItemStatus.ON_LOAN assert checkout_loan['state'] == LoanState.ITEM_ON_LOAN # the following tests the circulation action CHECKOUT_3_2 # an ON_LOAN item # checkout patron != patron of current loan # can NOT be CHECKOUT params['patron_pid'] = patron2_martigny_no_email.pid assert params['patron_pid'] != patron['pid'] with pytest.raises(ItemNotAvailableError): asked_item, actions = onloan_item.checkout(**params) asked_item = Item.get_record_by_pid(onloan_item.pid) checkout_loan = Loan.get_record_by_pid(loan.pid) assert asked_item.status == ItemStatus.ON_LOAN assert checkout_loan['state'] == LoanState.ITEM_ON_LOAN assert asked_item.number_of_requests() == 0
def can_extend(loan_pid): """Loan can extend.""" loan = Loan.get_record_by_pid(loan_pid) item_pid = loan.get('item_pid', {}).get('value') can_extend = {'can': False, 'reasons': []} if item_pid: item = Item.get_record_by_pid(item_pid) can, reasons = item.can(ItemCirculationAction.EXTEND, loan=loan) can_extend = {'can': can, 'reasons': reasons} return jsonify(can_extend)
def test_less_than_one_day_checkout( circ_policy_less_than_one_day_martigny, patron_martigny_no_email, patron2_martigny_no_email, item_lib_martigny, loc_public_martigny, librarian_martigny_no_email, item_on_shelf_martigny_patron_and_loan_pending): """Test checkout on an ON_SHELF item with 'less than one day' cipo.""" # Create a new item in ON_SHELF (without Loan) data = deepcopy(item_lib_martigny) data.pop('barcode') data.setdefault('status', ItemStatus.ON_SHELF) created_item = Item.create(data=data, dbcommit=True, reindex=True, delete_pid=True) # Check item is ON_SHELF and NO PENDING loan exist! assert created_item.number_of_requests() == 0 assert created_item.status == ItemStatus.ON_SHELF assert not created_item.is_requested_by_patron( patron2_martigny_no_email.get('patron', {}).get('barcode')) # the following tests the circulation action CHECKOUT_1_1 # an ON_SHELF item # WITHOUT pending loan # CAN be CHECKOUT for less than one day params = { 'patron_pid': patron2_martigny_no_email.pid, 'transaction_location_pid': loc_public_martigny.pid, 'transaction_user_pid': librarian_martigny_no_email.pid, 'pickup_location_pid': loc_public_martigny.pid } onloan_item, actions = created_item.checkout(**params) loan = Loan.get_record_by_pid(actions[LoanAction.CHECKOUT].get('pid')) # Check loan is ITEM_ON_LOAN and item is ON_LOAN assert onloan_item.number_of_requests() == 0 assert onloan_item.status == ItemStatus.ON_LOAN assert loan['state'] == LoanState.ITEM_ON_LOAN # Check due date loan_end_date = loan.get('end_date') lib = Library.get_record_by_pid(onloan_item.library_pid) today = datetime.now(pytz.utc) # Get next open day next_open_day = lib.next_open(today) if lib.is_open(today): next_open_day = today # Loan date should be in UTC. loan_datetime = ciso8601.parse_datetime(loan_end_date) # Compare year, month and date fail_msg = "Check timezone for Loan and Library. \ It should be the same date, even if timezone changed." assert loan_datetime.year == next_open_day.year, fail_msg assert loan_datetime.month == next_open_day.month, fail_msg assert loan_datetime.day == next_open_day.day, fail_msg
def decorated_view(*args, **kwargs): try: data = flask_request.get_json() description = data.pop('description') except KeyError: # The description parameter is missing. abort(400, str('missing description parameter.')) try: holding_pid = data.pop('holding_pid', None) holding = Holding.get_record_by_pid(holding_pid) if not holding: abort(404, 'Holding not found') # create a provisional item item_metadata = { 'type': 'provisional', 'document': { '$ref': get_ref_for_pid('doc', holding.document_pid) }, 'location': { '$ref': get_ref_for_pid('loc', holding.location_pid) }, 'item_type': { '$ref': get_ref_for_pid('itty', holding.circulation_category_pid) }, 'enumerationAndChronology': description, 'status': ItemStatus.ON_SHELF, 'holding': { '$ref': get_ref_for_pid('hold', holding.pid) } } item = Item.create(item_metadata, dbcommit=True, reindex=True) _, action_applied = func(holding, item, data, *args, **kwargs) return jsonify({'action_applied': action_applied}) except NoCirculationActionIsPermitted: # The circulation specs do not allow updates on some loan states. return jsonify({'status': 'error: Forbidden'}), 403 except MissingRequiredParameterError as error: # Return error 400 when there is a missing required parameter abort(400, str(error)) except CirculationException as error: abort(403, error.description or str(error)) except NotFound as error: raise error except exceptions.RequestError as error: # missing required parameters return jsonify({'status': f'error: {error}'}), 400 except Exception as error: # TODO: need to know what type of exception and document there. # raise error current_app.logger.error(str(error)) return jsonify({'status': f'error: {error}'}), 400
def test_item_create(db, es_clear, item_lib_martigny_data_tmp, item_lib_martigny): """Test itemanisation creation.""" item = Item.create(item_lib_martigny_data_tmp, delete_pid=True) del item['holding'] assert item == item_lib_martigny_data_tmp assert item.get('pid') == '1' assert item.can_delete item = Item.get_record_by_pid('1') del item['holding'] assert item == item_lib_martigny_data_tmp fetched_pid = item_id_fetcher(item.id, item) assert fetched_pid.pid_value == '1' assert fetched_pid.pid_type == 'item' item_lib_martigny.delete_from_index() assert not item_lib_martigny.delete_from_index() item_lib_martigny.dbcommit(forceindex=True)
def test_automatic_checkin(client, librarian_martigny_no_email, lib_martigny, patron_martigny_no_email, loc_public_martigny, item_lib_martigny, json_header, item_type_standard_martigny, circ_policy_short_martigny, patron_type_children_martigny, lib_saxon, loc_public_saxon, librarian_saxon_no_email): """Test item automatic checkin.""" login_user_via_session(client, librarian_saxon_no_email.user) circ_policy_origin = deepcopy(circ_policy_short_martigny) circ_policy = circ_policy_short_martigny record, actions = item_lib_martigny.automatic_checkin() assert actions == {'no': None} res = client.post( url_for('api_item.librarian_request'), data=json.dumps( dict( item_pid=item_lib_martigny.pid, pickup_location_pid=loc_public_saxon.pid, patron_pid=patron_martigny_no_email.pid ) ), content_type='application/json', ) assert res.status_code == 200 data = get_json(res) loan_pid = data.get('action_applied')[LoanAction.REQUEST].get('pid') res = client.post( url_for('api_item.validate_request'), data=json.dumps( dict( item_pid=item_lib_martigny.pid, pid=loan_pid, transaction_location_pid=loc_public_martigny.pid ) ), content_type='application/json', ) assert res.status_code == 200 item = Item.get_record_by_pid(item_lib_martigny.pid) assert item.status == ItemStatus.IN_TRANSIT text = item_status_text(item, format='medium', locale='en') assert text == 'not available (requested) (in_transit)' record, actions = item.automatic_checkin() assert 'receive' in actions item.cancel_loan(pid=loan_pid) assert item.status == ItemStatus.ON_SHELF
def test_nb_item_requests(db, minimal_item_record, minimal_patron_only_record): """Test number of item requests.""" assert minimal_patron_only_record['barcode'] patron_barcode = minimal_patron_only_record['barcode'] item = Item.create({}) item.update(minimal_item_record, dbcommit=True) item.request_item(patron_barcode=patron_barcode) tr_barcode = item['_circulation']['holdings'][2]['patron_barcode'] assert tr_barcode == patron_barcode number_requests = item.number_of_item_requests() assert number_requests == 2
def test_regular_issue_creation_update_delete_api( client, holding_lib_martigny_w_patterns, loc_public_martigny, lib_martigny): """Test create, update and delete of a regular issue API.""" holding = holding_lib_martigny_w_patterns issue_display, expected_date = holding._get_next_issue_display_text( holding.get('patterns')) issue = holding.receive_regular_issue(dbcommit=True, reindex=True) issue_pid = issue.pid assert holding.delete(dbcommit=True, delindex=True) assert not Item.get_record_by_pid(issue_pid)
def test_checkin_on_item_on_loan_with_requests( item3_on_loan_martigny_patron_and_loan_on_loan, loc_public_martigny, librarian_martigny, patron2_martigny): """Test checkin on an on_loan item with requests at local library.""" # the following tests the circulation action CHECKIN_3_2_1 # for an item on_loan, with pending requests. when the pickup library of # the first pending request equal to the transaction library, # checkin the item and item becomes at_desk. # the on_loan is returned and validating the first pending loan request. # # In this test, we will also ensure that the request expiration date of the # automatic validated request is correct item, patron, loan = item3_on_loan_martigny_patron_and_loan_on_loan # create a request on the same item one day after the first loan tomorrow = ciso8601.parse_datetime(loan['start_date']) + timedelta(days=10) with freeze_time(tomorrow.isoformat()): item, actions = item.request( pickup_location_pid=loc_public_martigny.pid, patron_pid=patron2_martigny.pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid ) requested_loan_pid = actions[LoanAction.REQUEST].get('pid') requested_loan = Loan.get_record_by_pid(requested_loan_pid) # Check-in the item # * reload item, loan and requested_loan # * ensure the item is still AT_DESK (because the first pending request # has been automatically validate and pickup location is the same than # previous loan location) # * ensure first loan is concluded # * ensure the requested loan is now "AT_DESK" with a valid request # expiration date next_day = tomorrow + timedelta(days=10) with freeze_time(next_day.isoformat()): item, actions = item.checkin( patron_pid=patron2_martigny.pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid, pickup_location_pid=loc_public_martigny.pid ) item = Item.get_record_by_pid(item.pid) loan = Loan.get_record_by_pid(loan.pid) requested_loan = Loan.get_record_by_pid(requested_loan.pid) assert item.status == ItemStatus.AT_DESK assert loan['state'] == LoanState.ITEM_RETURNED assert requested_loan['state'] == LoanState.ITEM_AT_DESK trans_date = ciso8601.parse_datetime(requested_loan['transaction_date']) assert trans_date.strftime('%Y%m%d') == next_day.strftime('%Y%m%d')
def test_update_loan_pickup_location(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, loc_public_saxon, item3_lib_martigny, circulation_policies): """Test loan pickup location change.""" login_user_via_session(client, librarian_martigny_no_email.user) item_pid = item3_lib_martigny.pid first_loc_pid = loc_public_saxon.pid new_loc_pid = loc_public_martigny.pid # request an item by a librarian res, req_data = postdata( client, 'api_item.librarian_request', dict(item_pid=item_pid, pickup_location_pid=first_loc_pid, patron_pid=patron_martigny_no_email.pid)) assert res.status_code == 200 # Update pickup location of the request, no loan pid loan_pid = req_data.get('action_applied')[LoanAction.REQUEST].get('pid') res, data = postdata( client, 'api_item.update_loan_pickup_location', dict(item_pid=item_pid, pickup_location_pid=new_loc_pid)) assert res.status_code == 400 # Update pickup location of the request, no pickup location pid res, data = postdata(client, 'api_item.update_loan_pickup_location', dict(item_pid=item_pid, loan_pid=loan_pid)) assert res.status_code == 400 # Update pickup location of the request res, data = postdata( client, 'api_item.update_loan_pickup_location', dict(item_pid=item_pid, pickup_location_pid=new_loc_pid, loan_pid=loan_pid)) assert res.status_code == 200 assert data.get('pickup_location_pid') == new_loc_pid # Change loan state to 'ITEM_AT_DESK'. # WARNING: Use loan from test_patron_checkouts_order (item3_lib_martigny) loans = Item.get_loans_by_item_pid(item_pid) for loan in loans: if loan.get('state') == 'ITEM_ON_LOAN': res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan.get('pid')), ) assert res.status_code == 200 # Update pickup location of the request: # loan state different from 'pending' res, data = postdata( client, 'api_item.update_loan_pickup_location', dict(item_pid=item_pid, pickup_location_pid=new_loc_pid, loan_pid=loan_pid)) assert res.status_code == 403
def test_checkout_in_transit_return_same_library( client, librarian_martigny_no_email, librarian_saxon_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, loc_public_saxon, item2_lib_martigny, json_header, circulation_policies): """Test item checkout, in-transit, checkin scenarios.""" login_user_via_session(client, librarian_martigny_no_email.user) # checkout the item at location A res, data = postdata( client, 'api_item.checkout', dict(item_pid=item2_lib_martigny.pid, patron_pid=patron_martigny_no_email.pid, transaction_location_pid=loc_public_martigny.pid)) assert res.status_code == 200 item_data = data.get('metadata') actions = data.get('action_applied') assert item_data.get('status') == ItemStatus.ON_LOAN loan_pid = actions[LoanAction.CHECKOUT].get('pid') # checkin the item at location B res, data = postdata( client, 'api_item.checkin', dict(item_pid=item2_lib_martigny.pid, pid=loan_pid, transaction_location_pid=loc_public_saxon.pid)) assert res.status_code == 200 item_data = data.get('metadata') item = Item.get_record_by_pid(item_data.get('pid')) assert item.get('status') == ItemStatus.IN_TRANSIT # checkin the item at location A res, data = postdata( client, 'api_item.automatic_checkin', dict(item_pid=item2_lib_martigny.pid, pid=loan_pid, transaction_location_pid=loc_public_martigny.pid)) assert res.status_code == 200 item_data = data.get('metadata') item = Item.get_record_by_pid(item2_lib_martigny.pid) assert item.get('status') == ItemStatus.ON_SHELF
def item_lib_martigny_masked(app, document, item_lib_martigny_data, loc_public_martigny, item_type_standard_martigny): """Create item of martigny library.""" data = deepcopy(item_lib_martigny_data) data['pid'] = f'maked-{data["pid"]}' data['_masked'] = True item = Item.create(data=data, delete_pid=False, dbcommit=True, reindex=True) flush_index(ItemsSearch.Meta.index) yield item item.delete(True, True, True)
def test_regular_issue_creation_update_delete_api( client, holding_lib_martigny_w_patterns, loc_public_martigny, lib_martigny): """Test create, update and delete of a regular issue API.""" holding = holding_lib_martigny_w_patterns issue_display, expected_date = holding._get_next_issue_display_text( holding.get('patterns')) issue = holding.receive_regular_issue(dbcommit=True, reindex=True) item = deepcopy(issue) item['issue']['status'] = ItemIssueStatus.DELETED issue.update(data=item, dbcommit=True, reindex=True) created_issue = Item.get_record_by_pid(issue.pid) assert created_issue.get('issue').get('status') == ItemIssueStatus.DELETED # Unable to delete a regular issue with pytest.raises(IlsRecordError.NotDeleted): created_issue.delete(dbcommit=True, delindex=True) # no errors when deleting an irregular issue pid = created_issue.pid created_issue.get('issue')['regular'] = False created_issue.delete(dbcommit=True, delindex=True) assert not Item.get_record_by_pid(pid)
def create_minimal_resources(db, minimal_member_record, minimal_location_record, minimal_item_record, minimal_document_record): """Simple patron record.""" member = MemberWithLocations.create(minimal_member_record, dbcommit=True) location = Location.create(minimal_location_record, dbcommit=True) member.add_location(location) doc = DocumentsWithItems.create(minimal_document_record, dbcommit=True) item = Item.create({}) item.update(minimal_item_record, dbcommit=True) doc.add_item(item, dbcommit=True) db.session.commit() yield doc, item, member, location
def test_checking_out_external_items_at_non_circ_library( client, librarian_martigny, lib_martigny, lib_martigny_bourg, patron_martigny, loc_public_martigny, loc_public_martigny_bourg, item_lib_martigny_bourg, circulation_policies, item_lib_martigny, librarian_martigny_bourg): """Test checkout of external items at non-circ library.""" login_user_via_session(client, librarian_martigny_bourg.user) # A non-circulation library (has no pickup configured) and library hours is # well configured opening_hours = [ { "day": "monday", "is_open": True, "times": [ { "start_time": "07:00", "end_time": "19:00" } ] } ] lib_martigny_bourg['opening_hours'] = opening_hours lib_martigny_bourg.update(lib_martigny_bourg, dbcommit=True, reindex=True) # a librarian from the non-circulating library can checkout items from # another library into his library params = dict( item_pid=item_lib_martigny.pid, patron_pid=patron_martigny.pid, transaction_user_pid=librarian_martigny_bourg.pid, transaction_library_pid=lib_martigny_bourg.pid, ) res, data = postdata( client, 'api_item.checkout', params ) assert res.status_code == 200 # the checkin is possible at the non-circulating library and the item goes # directly to in-transit res, data = postdata( client, 'api_item.checkin', dict( item_pid=item_lib_martigny.pid, transaction_library_pid=lib_martigny_bourg.pid, transaction_user_pid=librarian_martigny_bourg.pid, ) ) assert res.status_code == 200 item = Item.get_record_by_pid(item_lib_martigny.pid) assert item.status == ItemStatus.IN_TRANSIT
def test_get_links_to_me_with_fees(patron_transaction_overdue_saxon): """Test for number loans with fees.""" pttr = patron_transaction_overdue_saxon loan = pttr.loan item = Item.get_record_by_pid(loan.item_pid) assert item.get_links_to_me() == {'fees': 1, 'loans': 1} assert item.get_links_to_me(get_pids=True) == { 'fees': ['1'], 'loans': ['1']} pttr['status'] = 'closed' pttr['total_amount'] = 0 pttr = pttr.update(pttr, reindex=True, dbcommit=True) assert item.get_links_to_me() == {'loans': 1} assert item.get_links_to_me(get_pids=True) == {'loans': ['1']}
def test_holding_delete_after_item_edition(client, holding_lib_saxon, item_lib_saxon, holding_lib_fully): """Test automatic holding delete after item edition.""" item_lib_saxon['location'] = \ {'$ref': 'https://ils.rero.ch/api/locations/loc5'} item_lib_saxon.update(item_lib_saxon, dbcommit=True, reindex=True) flush_index(ItemsSearch.Meta.index) item = Item.get_record_by_pid(item_lib_saxon.pid) assert item.holding_pid == holding_lib_fully.pid holding = Holding.get_record_by_pid(holding_lib_saxon.pid) assert not holding
def test_items_simple_checkout(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, circulation_policies): """Test item checkout.""" 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 # 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) item_data = data.get('metadata') actions = data.get('action_applied') assert item_data.get('status') == ItemStatus.ON_LOAN assert actions.get(LoanAction.CHECKOUT) loan_pid = actions[LoanAction.CHECKOUT].get('pid') item = Item.get_record_by_pid(item_pid) assert item.is_loaned_to_patron(patron_martigny_no_email.get('barcode')) assert not item.available assert not item.can_delete # get loans for the patron 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 # checkin 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 data = get_json(res) item_data = data.get('metadata') actions = data.get('action_applied') assert item_data.get('status') == ItemStatus.ON_SHELF assert actions.get(LoanAction.CHECKIN)
def test_clear_obsolete_temporary_item_type(item_lib_martigny, item_type_on_site_martigny): """test task clear_obsolete_temporary_item_type""" item = item_lib_martigny end_date = datetime.now() + timedelta(days=2) item['temporary_item_type'] = { '$ref': get_ref_for_pid('itty', item_type_on_site_martigny.pid), 'end_date': end_date.strftime('%Y-%m-%d') } item.update(item, dbcommit=True, reindex=True) assert item.item_type_circulation_category_pid == \ item_type_on_site_martigny.pid over_4_days = datetime.now() + timedelta(days=4) with freeze_time(over_4_days.strftime('%Y-%m-%d')): items = Item.get_items_with_obsolete_temporary_item_type() assert len(list(items)) == 1 # run the tasks clean_obsolete_temporary_item_types() # check after task was ran items = Item.get_items_with_obsolete_temporary_item_type() assert len(list(items)) == 0 assert item.item_type_circulation_category_pid == item.item_type_pid
def test_item_different_actions(client, librarian_martigny_no_email, lib_martigny, patron_martigny_no_email, loc_public_martigny, item_lib_martigny, json_header, item_type_standard_martigny, circ_policy_short_martigny, patron_type_children_martigny, lib_saxon, loc_public_saxon, librarian_saxon_no_email): """Test item possible actions other scenarios.""" login_user_via_session(client, librarian_martigny_no_email.user) circ_policy_origin = deepcopy(circ_policy_short_martigny) circ_policy = circ_policy_short_martigny patron_pid = patron_martigny_no_email.pid res = client.get( url_for('api_item.item', item_barcode='does not exist', patron_pid=patron_pid)) assert res.status_code == 404 res, data = postdata( client, 'api_item.checkout', dict(item_pid=item_lib_martigny.pid, patron_pid=patron_pid)) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') record = Item.get_record_by_pid(item_lib_martigny.pid) res, _ = postdata( client, 'api_item.checkin', dict(item_pid='does not exist', pid=loan_pid, transaction_location_pid=loc_public_saxon.pid), ) assert res.status_code == 404 res, data = postdata( client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, pid=loan_pid, transaction_location_pid=loc_public_saxon.pid), ) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKIN].get('pid') data = {'pid': loan_pid} params, actions = item_lib_martigny.prior_checkout_actions(data) assert 'cancel' in actions
def test_automatic_item_creation_no_serials(client, json_header, holding_lib_martigny_w_patterns, item_lib_martigny_data, librarian_martigny_no_email): """Test automatically created items are not attached to serials.""" login_user_via_session(client, librarian_martigny_no_email.user) post_url = 'invenio_records_rest.item_list' res, _ = postdata(client, post_url, item_lib_martigny_data) assert res.status_code == 201 item = Item.get_record_by_pid(item_lib_martigny_data.get('pid')) holding = Holding.get_record_by_pid(item.holding_pid) assert holding.pid != holding_lib_martigny_w_patterns.pid assert holding.location_pid == holding_lib_martigny_w_patterns.location_pid assert holding.get('circulation_category') == \ holding_lib_martigny_w_patterns.get('circulation_category')