Example #1
0
def get_provisional_items_pids_candidate_to_delete():
    """Returns checked-in provisional items pids.

    Returns list of candidate provisional items pids to delete, based on the
    status of the item. Filtering by the status `ItemStatus.ON_SHELF` removes
    items with active loans. in addition, remove items with active fees.
    :return an item pid generator.
    """
    from rero_ils.modules.items.api import ItemsSearch

    # query ES index for open fees
    query_fees = PatronTransactionsSearch()\
        .filter('term', status='open')\
        .filter('exists', field='item')\
        .filter('range', total_amount={'gt': 0})\
        .source('item')
    # list of item pids with open fees
    item_pids_with_fees = [hit.item.pid for hit in query_fees.scan()]
    query = ItemsSearch()\
        .filter('term', type=TypeOfItem.PROVISIONAL) \
        .filter('terms', status=[ItemStatus.ON_SHELF]) \
        .exclude('terms', pid=item_pids_with_fees)\
        .source('pid')
    for hit in query.scan():
        yield hit.pid
Example #2
0
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}')
Example #3
0
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()]
    errors = 0
    for idx, (id, pid) in enumerate(ids):
        LOGGER.info(f'{idx} * Reindex item: {pid}')
        try:
            item = Item.get_record_by_id(id)
            item.reindex()
        except Exception as err:
            LOGGER.error(f'{idx} * Reindex item: {pid} {err}')
            errors += 1
    return errors
Example #4
0
    def get(self, **kwargs):
        """Search records."""
        search_obj = ItemsSearch()
        search, qs_kwargs = self.search_factory(search_obj)

        return self.make_response(pid_fetcher=None,
                                  search_result=search.scan())
Example #5
0
def test_item_es_mapping(es_clear, db, document, location, item_type,
                         item_on_loan_data_tmp):
    """."""
    search = ItemsSearch()
    mapping = get_mapping(search.Meta.index)
    assert mapping
    Item.create(item_on_loan_data_tmp,
                dbcommit=True,
                reindex=True,
                delete_pid=True)
    assert mapping == get_mapping(search.Meta.index)
Example #6
0
def test_item_es_mapping(document, loc_public_martigny,
                         item_type_standard_martigny,
                         item_lib_martigny_data_tmp):
    """Test item elasticsearch mapping."""
    search = ItemsSearch()
    mapping = get_mapping(search.Meta.index)
    assert mapping
    Item.create(item_lib_martigny_data_tmp,
                dbcommit=True,
                reindex=True,
                delete_pid=True)
    assert mapping == get_mapping(search.Meta.index)
Example #7
0
def test_location_get_links_to_me(loc_public_martigny, loc_public_sion,
                                  item_lib_martigny):
    """Test pickup locations retrieval."""

    assert loc_public_martigny.get_links_to_me() == {'items': 1}
    assert loc_public_martigny.get_links_to_me(get_pids=True) == {
        'items': ['item1']
    }

    assert loc_public_sion.get_links_to_me() == {}
    item_lib_martigny['temporary_location'] = {
        '$ref': f'https://bib.rero.ch/api/locations/{loc_public_sion.pid}'
    }
    item_lib_martigny.update(data=item_lib_martigny,
                             dbcommit=True,
                             reindex=True)
    ItemsSearch.flush_and_refresh()
    assert loc_public_sion.get_links_to_me() == {'items': 1}
    assert loc_public_sion.get_links_to_me(get_pids=True) == {
        'items': ['item1']
    }
Example #8
0
def same_location_validator(item_pid, input_location_pid):
    """Validate that item and transaction location are in same library.

    :param item_pid: the item_pid object
    :type input_location_pid: object
    :return: true if in same library otherwise false
    :rtype: boolean
    """
    from rero_ils.modules.items.api import ItemsSearch
    lib_from_loc = LocationsSearch().get_record_by_pid(
        input_location_pid).library.pid
    lib_from_item = ItemsSearch().get_record_by_pid(
        item_pid.get('value')).library.pid
    return lib_from_loc == lib_from_item
Example #9
0
def negative_availability_changes(sender, record=None, *args, **kwargs):
    """Reindex related items if negative availability changes."""
    if isinstance(record, ItemType):
        ori_record = ItemType.get_record_by_pid(record.pid)
        record_availability = record.get('negative_availability', False)
        original_availability = ori_record.get('negative_availability', False)
        if record_availability != original_availability:
            # get all item uuid's related to the item type and mark them for
            # reindex into a asynchronous celery queue.
            item_uuids = []
            search = ItemsSearch()\
                .filter('bool', should=[
                    Q('match', item_type__pid=record.pid),
                    Q('match', temporary_item_type__pid=record.pid)
                ]) \
                .source().scan()
            for hit in search:
                item_uuids.append(hit.meta.id)
            ItemTypesIndexer().bulk_index(item_uuids)
            process_bulk_queue.apply_async()
def get_counts(pid, action):
    """Calculate items_count and public_items_count.

    :param str pid: holding pid.
    :param str action: upgrade or downgrade.
    :return: items_count and public_items_count
    """
    if action == 'upgrade':
        item_search = ItemsSearch()[0:0]\
                .filter('term', holding__pid=pid)\
                .filter('term', issue__status="received")
    else:
        item_search = ItemsSearch()[0:0]\
                .filter('term', holding__pid=pid)

    items_count = item_search.count()
    results = item_search.source([]).scan()
    public_items_count = len([res for res in results
                              if "_masked" not in res
                              or not res['_masked']])

    return items_count, public_items_count
Example #11
0
def get_items_by_organisation_pid(organisation_pid):
    """Get items by organisation pid."""
    query = ItemsSearch().filter(
            'term', organisation__pid=organisation_pid)\
        .source('pid')
    return [item.pid for item in query.scan()]
Example #12
0
def test_item_organisation_pid(client, org_martigny, item_lib_martigny):
    """Test organisation pid has been added during the indexing."""
    search = ItemsSearch()
    item = next(search.filter('term', pid=item_lib_martigny.pid).scan())
    assert item.organisation.pid == org_martigny.pid
Example #13
0
def get_holdings_items(document_pid,
                       organisation_pids=None,
                       library_pids=None,
                       location_pids=None):
    """Create Holding and Item informations.

    :param document_pid: document pid to use for holdings search
    :param organisation_pids: Which organisations items to add.
    :param library_pids: Which from libraries items to add.
    :param location_pids: Which from locations items to add.

    :returns: list of holding informations with associated organisation,
              library and location pid, name informations.
    """
    def get_name(resource, pid):
        """Get name from resource.

        The name will be cached.
        :param resource: Resource class to use.
        :param pid: Pid for the resource to get the name from.
        :returns: name from the resource
        """
        data = resource.get_record_by_pid(pid)
        if data:
            return data.get('name')

    results = []
    if document_pid:
        holding_pids = Holding.get_holdings_pid_by_document_pid(
            document_pid=document_pid, with_masked=False)

        holding_pids = list(holding_pids)
        organisations = {}
        libraries = {}
        locations = {}
        query = HoldingsSearch().filter('terms', pid=holding_pids)
        if organisation_pids:
            query = query.filter(
                {'terms': {
                    'organisation.pid': organisation_pids
                }})
        if library_pids:
            query = query.filter({'terms': {'library.pid': library_pids}})
        if location_pids:
            query = query.filter({'terms': {'location.pid': location_pids}})
        for hit in query.scan():
            holding = hit.to_dict()
            organisation_pid = hit.organisation.pid
            if organisation_pid not in organisations:
                organisations[organisation_pid] = get_name(
                    Organisation, organisation_pid)
            library_pid = hit.library.pid
            if library_pid not in libraries:
                libraries[library_pid] = get_name(Library, library_pid)
            location_pid = hit.location.pid
            if location_pid not in locations:
                locations[location_pid] = get_name(Location, location_pid)

            result = {
                'organisation': {
                    'pid': organisation_pid,
                    'name': organisations[organisation_pid]
                },
                'library': {
                    'pid': library_pid,
                    'name': libraries[library_pid]
                },
                'location': {
                    'pid': location_pid,
                    'name': locations[location_pid]
                },
                'holdings': {
                    'call_number':
                    holding.get('call_number'),
                    'second_call_number':
                    holding.get('second_call_number'),
                    'enumerationAndChronology':
                    holding.get('enumerationAndChronology'),
                    'electronic_location':
                    holding.get('electronic_location', []),
                    'notes':
                    holding.get('notes', []),
                    'supplementaryContent':
                    holding.get('supplementaryContent'),
                    'index':
                    holding.get('index'),
                    'missing_issues':
                    holding.get('missing_issues'),
                }
            }
            if hit.holdings_type == 'standard':
                item_pids = Item.get_items_pid_by_holding_pid(
                    hit.pid, with_masked=False)
                item_hits = ItemsSearch() \
                    .filter('terms', pid=list(item_pids)) \
                    .scan()
                for item_hit in item_hits:
                    item_data = item_hit.to_dict()
                    item_result = result
                    item_result['item'] = {
                        'barcode':
                        item_data.get('barcode'),
                        'all_number':
                        item_data.get('all_number'),
                        'second_call_number':
                        item_data.get('second_call_number'),
                        'enumerationAndChronology':
                        item_data.get('enumerationAndChronology'),
                        'url':
                        item_data.get('url'),
                        'notes':
                        item_data.get('notes', []),
                    }
                    results.append(item_result)
            else:
                results.append(result)
    return results