Пример #1
0
    def login(self, username, password, workstation=None):
        """Return True if the username/password are good, False otherwise."""

        seed = E1('open-ils.auth.authenticate.init', username)
        """
        We get away with no workstation in proxy auth setup at Windsor,
        need to track down but use staff station for now
        """
        if workstation:
            patronws = workstation
        else:
            patronws = getattr(settings, 'OPENSRF_STAFF_WORKSTATION', None)

        result = E1(
            'open-ils.auth.authenticate.complete', {
                'workstation': patronws,
                'username': username,
                'password': _hsh(seed + _hsh(password)),
                'type': 'opac'
            })
        try:
            authkey = result['payload']['authtoken']
            #cleanup session - we do not use eg authkey locally
            E1('open-ils.auth.session.delete', [authkey])

            return authkey
        except:
            return None
Пример #2
0
        def get_copydetails(barcode, copyids, reserves_loc, bib_part_flag,
                            part_flag, bcs, ids):
            copies_desk = len(copyids)
            copies_lib = copies_desk
            copy_list = []
            lib_parts_list = []
            res_parts_list = []
            copy_sort = None
            part_sort = None
            part_label = ''
            bcs_set, ids_set = collect_set(barcode, bcs, ids)

            for copyid in copyids:
                circinfo = E1(OPENSRF_FLESHED2_CALL, copyid)
                circbarcode = None

                if barcode is not None:
                    circbarcode = circinfo.get("barcode")

                thisloc = circinfo.get("location")

                if thisloc:
                    thisloc = thisloc.get("name")

                #create copy object for supplied barcode - will be all barcodes if none supplied
                if bib_part_flag or part_flag:
                    circ_modifier = circinfo.get("circ_modifier")
                    circs = circinfo.get("circulations")
                    parts = circinfo.get("parts")
                    part = None
                    if parts:
                        part = parts[0]
                    if part:
                        part_label = part.get("label")
                        part_sort = part.get("label_sortkey")
                        if thisloc in reserves_loc:
                            res_parts_list.append(part_sort)
                        lib_parts_list.append(part_sort)

                if thisloc in reserves_loc and (barcode == circbarcode
                                                or circbarcode in bcs_set):
                    if part_sort is not None and copy_sort is None:
                        copy_sort = part_sort

                    id_ind = -1
                    if circbarcode in bcs_set:
                        id_ind = ids_set[bcs_set.index(circbarcode)]
                    copy_list.append(
                        copy_obj(circ_modifier, circs, part_label, part_sort,
                                 id_ind))

            desk_count = len(res_parts_list)
            lib_count = len(lib_parts_list)
            if part_flag and copy_sort is not None:
                desk_count = res_parts_list.count(copy_sort)
                lib_count = lib_parts_list.count(copy_sort)

            return sorted(
                copy_list,
                key=lambda copy: copy.part_sort), desk_count, lib_count
Пример #3
0
 def get_label(bc):
     partlabel = None
     copyinfo = E1(OPENSRF_BARCODE, bc)
     parts = copyinfo.get("parts")
     if parts:
         part = parts[0]
         if part:
             partlabel = part['label']
     return partlabel
Пример #4
0
    def lookup(self, username, login_token=None):
        """Given a username, return a dict, or None. The dict must have
        four keys (first_name, last_name, email, external_username), where
        external_username value is the username parameter."""

        # for now, this backend only returns a user if a login_token is
        # provided; in other words, the only time your personal info is
        # fetched is when you log in.
        if login_token:
            resp = E1('open-ils.auth.session.retrieve', login_token)
            person = dict((j, resp.get(k)) for j, k in [(
                'first_name', 'first_given_name'), (
                    'last_name',
                    'family_name'), ('email',
                                     'email'), ('external_username',
                                                'usrname')])
            return person
Пример #5
0
    def __init__(self):
        # establish our OpenSRF connection.
        initialize(self)

        if OSRF_LIB_INSTALLED:
            ils_startup(self.EVERGREEN_SERVER, self.IDL_URL)

        # set up the available/reshelving codes, for the item_status routine.
        status_decode = [
            (str(x['id']), x['name'])
            for x in E1('open-ils.search.config.copy_status.retrieve.all')
        ]

        #for x in E1('open-ils.search.config.copy_status.retrieve.all'):
        #    print "x", x
        self.AVAILABLE = [
            id for id, name in status_decode if name == 'Available'
        ][0]
        self.RESHELVING = [
            id for id, name in status_decode if name == 'Reshelving'
        ][0]
        self.CHECKEDOUT = [
            id for id, name in status_decode if name == 'Checked out'
        ][0]
Пример #6
0
    def cat_search(self, query, start=1, limit=10):
        barcode = ''
        bibid = ''
        partlabel = ''

        is_barcode = re.search('\d{14}', query)

        if query.startswith(self.OPAC_URL):
            results = []
            # query is an Evergreen URL
            # snag the bibid at this point
            if "=" in query and "&" in query:
                params = dict([x.split("=") for x in query.split("&")])
                for key in params.keys():
                    if key.find('?r') != -1:
                        bibid = params[key]
                results = M.marcxml_to_records(I.url_to_marcxml(query))
            else:
                # likely template opac
                # first seq of digits after a / should be the bibid
                match = re.search(r'/(\d+)', query)
                if match:
                    bibid = match.group(1)
                    results = M.marcxml_to_records(
                        self.bib_id_to_marcxml(bibid))
            numhits = len(results)
        elif is_barcode:
            results = []
            numhits = 0
            barcode = query.strip()
            bib = E1('open-ils.search.bib_id.by_barcode', barcode)
            if bib:
                bibid = bib
                copy = E1('open-ils.supercat.record.object.retrieve', bib)
                copyinfo = E1(OPENSRF_BARCODE, barcode)
                parts = copyinfo.get("parts")
                if parts:
                    part = parts[0]
                    if part:
                        partlabel = part['label']

                marc = copy[0]['marc']
                # In some institutions' installations, 'marc' is a string; in
                # others it's unicode. Convert to unicode if necessary.
                if not isinstance(marc, unicode):
                    marc = unicode(marc, 'utf-8')
                tree = M.marcxml_to_records(marc)[0]
                results.append(tree)
                numhits = 1
        else:
            # query is an actual query
            if self.USE_Z3950:
                cat_host, cat_port, cat_db = settings.Z3950_CONFIG
                results, numhits = PZ.search(cat_host, cat_port, cat_db, query,
                                             start, limit)
            else:  # use opensrf
                if not self.OSRF_CAT_SEARCH_ORG_UNIT:
                    raise NotImplementedError, \
                        'Your integration must provide a value for OSRF_CAT_SEARCH_ORG_UNIT.'

                EVERGREEN_SEARCH_DEPTH = getattr(settings,
                                                 'EVERGREEN_SEARCH_DEPTH', 1)
                superpage = E1(
                    'open-ils.search.biblio.multiclass.query', {
                        'org_unit': self.OSRF_CAT_SEARCH_ORG_UNIT,
                        'depth': EVERGREEN_SEARCH_DEPTH,
                        'limit': limit,
                        'offset': start - 1,
                        'visibility_limit': 3000,
                        'default_class': 'keyword'
                    }, query, 1)
                ids = [id for (id, ) in superpage['ids']]
                results = []
                for rec in E1('open-ils.supercat.record.object.retrieve', ids):
                    marc = rec['marc']
                    # In some institutions' installations, 'marc' is a string; in
                    # others it's unicode. Convert to unicode if necessary.
                    if not isinstance(marc, unicode):
                        marc = unicode(marc, 'utf-8')
                    tree = M.marcxml_to_records(marc)[0]
                    results.append(tree)
                numhits = int(superpage['count'])
        return results, numhits, bibid, barcode, partlabel
Пример #7
0
        def sort_out_status(barcode, sort_vol, counts, version, sort_lib,
                            sort_desk, sort_avail, sort_callno, sort_dueid,
                            sort_dueinfo, sort_circmod, sort_allcalls,
                            sort_alldues, prefix, suffix, bcs, ids,
                            sort_copyids):

            vol = sort_vol
            lib = sort_lib
            desk = sort_desk
            avail = sort_avail
            callno = sort_callno
            dueinfo = sort_dueinfo
            circmod = sort_circmod
            allcalls = sort_allcalls
            alldues = sort_alldues
            dueid = sort_dueid
            copyids = sort_copyids
            duedisplay = None
            partdisplay = ""

            try:
                if loc in self.RESERVES_DESK_NAME:
                    callprefix = ''
                    callsuffix = ''

                    # get initial call number and total library count
                    callno, lib = initialVals(prefix, suffix, callno, lib)

                    # volume check - based on v.1, etc. in call number
                    voltest = re.search(self.IS_EMBEDDEDVOL, callno)

                    # attachment test
                    attachtest = re.search(self.IS_ATTACHMENT, callno)

                    dueinfo = ''

                    # combine volume designations for embedded values
                    callprefix, callno, callsuffix = add_in_embedded_parts(
                        prefix, suffix, callprefix, callsuffix, callno,
                        voltest, attachtest, vol)

                    if version >= 2.1:
                        #oh-oh, something inconsistent on multiple calls here
                        tmp_copyids = E1(OPENSRF_CN_CALL, bib_id,
                                         [prefix, sort_callno, suffix], org)
                        copyids.extend(tmp_copyids)
                    else:
                        tmp_copyids = E1(OPENSRF_CN_CALL, bib_id, sort_callno,
                                         org)
                        copyids.extend(tmp_copyids)

                    #get copy information
                    copies, desk, copy_lib = get_copydetails(
                        barcode, copyids, self.RESERVES_DESK_NAME,
                        self.BIB_PART_MERGE, self.PART_MERGE, bcs, ids)

                    if desk == 0 or copy_lib == 0:
                        desk = get_desk_counts(counts)
                    else:
                        lib = copy_lib

                    avail = desk
                    copy_parts = []
                    duetime = None
                    earliestdue = None

                    # we want to identify the copy that will be returned first if
                    # all are checked out
                    for copy in copies:
                        if copy.part_label:
                            callno = sort_callno + " " + copy.part_label
                            if copy.part_sort in copy_parts and len(
                                    copy_parts) > 0:
                                partdisplay = copy.part_label
                                #leave alone if locked - otherwise mark as ready
                                if allcalls[len(allcalls) - 1][1] != LOCKED:
                                    allcalls[len(allcalls) - 1] = [
                                        callno, READY, copy.syrup_id,
                                        copy.part_label
                                    ]

                            else:
                                allcalls = callparts(callno, READY,
                                                     copy.syrup_id,
                                                     copy.part_label, allcalls)
                            copy_parts.append(copy.part_sort)

                        bringfw = attachtest

                        # multiple volumes in identified in call number
                        if voltest and callno.find(voltest.group(0)) == -1:
                            bringfw = True

                        if copy.circs and isinstance(copy.circs, list):
                            circ = copy.circs[0]
                            rawdate = circ.get("due_date")
                            #remove offset info, %z is flakey for some reason
                            rawdate = rawdate[:-5]
                            duetime = time.strptime(rawdate, self.TIME_FORMAT)
                        elif len(allcalls) == 0 and copy.syrup_id != -1:
                            dueid = [copy.syrup_id, LOCKED]

                        #get due information - lots of extra pieces needed for embedded parts
                        dueinfo, callprefix, callno, callsuffix = deal_with_dues(
                            duetime, avail, bringfw, copy, callprefix,
                            callsuffix, callno, earliestdue, attachtest,
                            voltest, sort_callno, dueinfo)

                        alldisplay = callno + ' (Available)'

                        if copy.circs and isinstance(copy.circs, list):
                            if (earliestdue is None or duetime < earliestdue):
                                earliestdue = duetime
                                dueinfo = time.strftime(
                                    self.DUE_FORMAT, earliestdue)
                                #will want the link to be to the earliest item if not multipart
                                if len(allcalls) == 0 and dueid[
                                        1] != LOCKED and copy.syrup_id != -1:
                                    dueid = [copy.syrup_id, DUE]

                            #alldisplay = '%s (DUE: %s)' % (callno,time.strftime(self.DUE_FORMAT,earliestdue))
                            duedisplay = '%s (DUE: %s)' % (
                                callno,
                                time.strftime(self.DUE_FORMAT, earliestdue))

                            if len(allcalls) > 0:
                                if allcalls[len(allcalls) - 1][1] != LOCKED:
                                    allcalls[len(allcalls) - 1] = [
                                        duedisplay, DUE, copy.syrup_id,
                                        copy.part_label
                                    ]
                                    if avail >= 1:
                                        avail -= 1
                            elif avail >= 1:
                                avail -= 1

                            if copy.part_label and copy.part_label not in alldisplay:
                                duedisplay = '%s %s (DUE: %s)' % (
                                    callno, copy.part_label,
                                    time.strftime(self.DUE_FORMAT,
                                                  earliestdue))

                        elif len(allcalls) > 0:
                            allcalls[len(allcalls) - 1] = [
                                callno, LOCKED, copy.syrup_id, copy.part_label
                            ]

                        if avail == 0 and duedisplay is not None:
                            alldisplay = duedisplay
                        alldues.append(alldisplay)

                        if voltest or attachtest:
                            callno, vol = last_check_embed(
                                callprefix, callno, callsuffix, voltest, vol)
            except:
                print "due date/call problem: ", bib_id
                print "*** print_exc:"
                traceback.print_exc()

            if avail != 0 and len(allcalls) > 0:
                if allcalls[len(allcalls) - 1][1] == DUE:
                    allcalls[len(allcalls) - 1] = [
                        alldisplay, READY, allcalls[len(allcalls) - 1][2],
                        allcalls[len(allcalls) - 1][3]
                    ]
            return (vol, lib, desk, avail, callno, dueid, dueinfo, circmod,
                    allcalls, alldues, copyids)
Пример #8
0
    def _item_status(self, bib_id, barcode, bclist, idlist):

        #sanity variables for multipart titles
        DUE = 0
        READY = 1
        LOCKED = 2  #lock in an available copy

        class copy_obj:
            def __init__(self, circ_modifier, circs, part_label, part_sort,
                         syrup_id):
                self.circ_modifier = circ_modifier
                self.circs = circs
                self.part_label = part_label
                self.part_sort = part_sort
                self.syrup_id = syrup_id

        def make_obj_list(objlist):
            objset = []
            objcoll = objlist.split(";")
            for o in objcoll:
                objset.append(o.split("/"))

            return objset

        #is current barcode one of identified sets
        def collect_set(barcode, bcs, ids):
            bc_dups = []
            id_dups = []
            i = 0
            for bc in bcs:
                if barcode in bc:
                    return bc, ids[i]
                i = i + 1

            return bc_dups, id_dups

        #syrup tries to store as little as possible about an
        #item, which leads to a lot of hoops when combining
        #volumes/parts
        def get_copydetails(barcode, copyids, reserves_loc, bib_part_flag,
                            part_flag, bcs, ids):
            copies_desk = len(copyids)
            copies_lib = copies_desk
            copy_list = []
            lib_parts_list = []
            res_parts_list = []
            copy_sort = None
            part_sort = None
            part_label = ''
            bcs_set, ids_set = collect_set(barcode, bcs, ids)

            for copyid in copyids:
                circinfo = E1(OPENSRF_FLESHED2_CALL, copyid)
                circbarcode = None

                if barcode is not None:
                    circbarcode = circinfo.get("barcode")

                thisloc = circinfo.get("location")

                if thisloc:
                    thisloc = thisloc.get("name")

                #create copy object for supplied barcode - will be all barcodes if none supplied
                if bib_part_flag or part_flag:
                    circ_modifier = circinfo.get("circ_modifier")
                    circs = circinfo.get("circulations")
                    parts = circinfo.get("parts")
                    part = None
                    if parts:
                        part = parts[0]
                    if part:
                        part_label = part.get("label")
                        part_sort = part.get("label_sortkey")
                        if thisloc in reserves_loc:
                            res_parts_list.append(part_sort)
                        lib_parts_list.append(part_sort)

                if thisloc in reserves_loc and (barcode == circbarcode
                                                or circbarcode in bcs_set):
                    if part_sort is not None and copy_sort is None:
                        copy_sort = part_sort

                    id_ind = -1
                    if circbarcode in bcs_set:
                        id_ind = ids_set[bcs_set.index(circbarcode)]
                    copy_list.append(
                        copy_obj(circ_modifier, circs, part_label, part_sort,
                                 id_ind))

            desk_count = len(res_parts_list)
            lib_count = len(lib_parts_list)
            if part_flag and copy_sort is not None:
                desk_count = res_parts_list.count(copy_sort)
                lib_count = lib_parts_list.count(copy_sort)

            return sorted(
                copy_list,
                key=lambda copy: copy.part_sort), desk_count, lib_count

        #deal with call numbers that have embedded parts - ugh!
        def get_dueinfo(callprefix, callsuffix, callno, earliestdue,
                        attachtest, voltest, sort_callno, bringfw, dueinfo):

            tmpinfo = ''

            _callprefix = callprefix
            _callsuffix = callsuffix
            _callno = callno
            _dueinfo = dueinfo

            if voltest:
                if (int(voltest.group(1)) > vol):
                    if len(_dueinfo) > 0:
                        _dueinfo = _dueinfo + "/"
                    _dueinfo = _dueinfo + voltest.group(
                        0) + ': ' + time.strftime(self.DUE_FORMAT, earliestdue)
                else:
                    tmpinfo = _dueinfo
                    _dueinfo = voltest.group(0) + ': ' + time.strftime(
                        self.DUE_FORMAT, earliestdue)
                    if len(tmpinfo) > 0:
                        _dueinfo = _dueinfo + "/" + tmpinfo
                _callprefix = _callsuffix = ''
            elif attachtest:
                tmpinfo = _dueinfo
                _dueinfo = attachtest.group(0) + ': ' + time.strftime(
                    self.DUE_FORMAT, earliestdue)
                if len(_callno) > 0:
                    _callno = _callno + '/' + sort_callno
                    _callprefix = _callsuffix = ''
                else:
                    _callno = sort_callno
                if len(tmpinfo) > 0:
                    _dueinfo = _dueinfo + "/" + tmpinfo

            if not bringfw:
                _dueinfo = time.strftime(self.DUE_FORMAT, earliestdue)
                #_callno = sort_callno

            return _dueinfo, _callno, _callprefix, _callsuffix

        #get due information - lots of pieces passed on for embedded parts
        def deal_with_dues(duetime, avail, bringfw, copy, callprefix,
                           callsuffix, callno, earliestdue, attachtest,
                           voltest, sort_callno, dueinfo):

            earlydue = earliestdue
            due = dueinfo
            due_callprefix = callprefix
            due_callno = callno
            due_callsuffix = callsuffix

            if copy.circs and len(copy.circs) > 0:
                if len(dueinfo) == 0 or bringfw:
                    earlydue = duetime
                    due, due_due_callno, due_callprefix, due_callsuffix = get_dueinfo(
                        callprefix, callsuffix, callno, earlydue, attachtest,
                        voltest, sort_callno, bringfw, dueinfo)

                if (earlydue is None or duetime < earlydue) and not bringfw:
                    earlydue = duetime
                    due = time.strftime(self.DUE_FORMAT, earliestdue)

            return due, due_callprefix, due_callno, due_callsuffix

        #create initial call no and counts
        def initialVals(prefix, suffix, callno, lib):
            initial_callno = callno
            if prefix:
                initial_callno = prefix + callno
            if suffix:
                initial_callno = callno + suffix
            initial_avail = stats.get(self.AVAILABLE, 0)
            initial_avail += stats.get(self.RESHELVING, 0)
            anystatus_here = sum(stats.values())

            return initial_callno, lib + anystatus_here

        #sometimes part information is in the callno directly, try to combine for display by
        #shifting to suffix - otherwise treat normally
        def add_in_embedded_parts(prefix, suffix, callprefix, callsuffix,
                                  callno, voltest, attachtest, vol):
            embed_prefix = callprefix
            embed_callno = callno
            embed_suffix = callsuffix

            if (voltest and vol > 0):
                if (int(voltest.group(1)) > vol):
                    embed_suffix = "/" + callno
                else:
                    embed_prefix = callno + "/"
            elif attachtest and callno.find(attachtest.group(0)) == -1:
                if len(callno) > 0:
                    embed_suffix = "/" + callno
                else:
                    embed_prefix = callno
            else:
                embed_callno = prefix + callno + suffix

            return embed_prefix, embed_callno, embed_suffix

        #probably not needed but final sanity check for embedded parts
        def last_check_embed(callprefix, callno, callsuffix, voltest, vol):
            last_call = callno
            last_vol = vol
            if callno.find(callprefix) == -1:
                last_call = callprefix + callno
            if callno.find(callsuffix) == -1:
                last_call = last_call + callsuffix
            if voltest:
                last_vol = int(voltest.group(1))

            return last_call, last_vol

        #make sure request call number is limited to unique entries
        def callparts(callno, status, syrup_id, label, allcalls):
            partcalls = allcalls
            if len(partcalls) > 0:
                multipart = allcalls[len(partcalls) - 1]
                if callno != multipart[0] and label != multipart[3]:
                    partcalls.append([callno, status, syrup_id, label])
            else:
                partcalls.append([callno, status, syrup_id, label])

            return partcalls

        #use counts from system if not parts
        def get_desk_counts(counts):
            desk_count = 0
            for i, j, k, l, m, n in counts:
                if m in self.RESERVES_DESK_NAME:
                    desk_count += n.get(self.AVAILABLE, 0)
                    desk_count += n.get(self.RESHELVING, 0)
                    desk_count += n.get(self.CHECKEDOUT, 0)
            return desk_count

        #pull together status information
        def sort_out_status(barcode, sort_vol, counts, version, sort_lib,
                            sort_desk, sort_avail, sort_callno, sort_dueid,
                            sort_dueinfo, sort_circmod, sort_allcalls,
                            sort_alldues, prefix, suffix, bcs, ids,
                            sort_copyids):

            vol = sort_vol
            lib = sort_lib
            desk = sort_desk
            avail = sort_avail
            callno = sort_callno
            dueinfo = sort_dueinfo
            circmod = sort_circmod
            allcalls = sort_allcalls
            alldues = sort_alldues
            dueid = sort_dueid
            copyids = sort_copyids
            duedisplay = None
            partdisplay = ""

            try:
                if loc in self.RESERVES_DESK_NAME:
                    callprefix = ''
                    callsuffix = ''

                    # get initial call number and total library count
                    callno, lib = initialVals(prefix, suffix, callno, lib)

                    # volume check - based on v.1, etc. in call number
                    voltest = re.search(self.IS_EMBEDDEDVOL, callno)

                    # attachment test
                    attachtest = re.search(self.IS_ATTACHMENT, callno)

                    dueinfo = ''

                    # combine volume designations for embedded values
                    callprefix, callno, callsuffix = add_in_embedded_parts(
                        prefix, suffix, callprefix, callsuffix, callno,
                        voltest, attachtest, vol)

                    if version >= 2.1:
                        #oh-oh, something inconsistent on multiple calls here
                        tmp_copyids = E1(OPENSRF_CN_CALL, bib_id,
                                         [prefix, sort_callno, suffix], org)
                        copyids.extend(tmp_copyids)
                    else:
                        tmp_copyids = E1(OPENSRF_CN_CALL, bib_id, sort_callno,
                                         org)
                        copyids.extend(tmp_copyids)

                    #get copy information
                    copies, desk, copy_lib = get_copydetails(
                        barcode, copyids, self.RESERVES_DESK_NAME,
                        self.BIB_PART_MERGE, self.PART_MERGE, bcs, ids)

                    if desk == 0 or copy_lib == 0:
                        desk = get_desk_counts(counts)
                    else:
                        lib = copy_lib

                    avail = desk
                    copy_parts = []
                    duetime = None
                    earliestdue = None

                    # we want to identify the copy that will be returned first if
                    # all are checked out
                    for copy in copies:
                        if copy.part_label:
                            callno = sort_callno + " " + copy.part_label
                            if copy.part_sort in copy_parts and len(
                                    copy_parts) > 0:
                                partdisplay = copy.part_label
                                #leave alone if locked - otherwise mark as ready
                                if allcalls[len(allcalls) - 1][1] != LOCKED:
                                    allcalls[len(allcalls) - 1] = [
                                        callno, READY, copy.syrup_id,
                                        copy.part_label
                                    ]

                            else:
                                allcalls = callparts(callno, READY,
                                                     copy.syrup_id,
                                                     copy.part_label, allcalls)
                            copy_parts.append(copy.part_sort)

                        bringfw = attachtest

                        # multiple volumes in identified in call number
                        if voltest and callno.find(voltest.group(0)) == -1:
                            bringfw = True

                        if copy.circs and isinstance(copy.circs, list):
                            circ = copy.circs[0]
                            rawdate = circ.get("due_date")
                            #remove offset info, %z is flakey for some reason
                            rawdate = rawdate[:-5]
                            duetime = time.strptime(rawdate, self.TIME_FORMAT)
                        elif len(allcalls) == 0 and copy.syrup_id != -1:
                            dueid = [copy.syrup_id, LOCKED]

                        #get due information - lots of extra pieces needed for embedded parts
                        dueinfo, callprefix, callno, callsuffix = deal_with_dues(
                            duetime, avail, bringfw, copy, callprefix,
                            callsuffix, callno, earliestdue, attachtest,
                            voltest, sort_callno, dueinfo)

                        alldisplay = callno + ' (Available)'

                        if copy.circs and isinstance(copy.circs, list):
                            if (earliestdue is None or duetime < earliestdue):
                                earliestdue = duetime
                                dueinfo = time.strftime(
                                    self.DUE_FORMAT, earliestdue)
                                #will want the link to be to the earliest item if not multipart
                                if len(allcalls) == 0 and dueid[
                                        1] != LOCKED and copy.syrup_id != -1:
                                    dueid = [copy.syrup_id, DUE]

                            #alldisplay = '%s (DUE: %s)' % (callno,time.strftime(self.DUE_FORMAT,earliestdue))
                            duedisplay = '%s (DUE: %s)' % (
                                callno,
                                time.strftime(self.DUE_FORMAT, earliestdue))

                            if len(allcalls) > 0:
                                if allcalls[len(allcalls) - 1][1] != LOCKED:
                                    allcalls[len(allcalls) - 1] = [
                                        duedisplay, DUE, copy.syrup_id,
                                        copy.part_label
                                    ]
                                    if avail >= 1:
                                        avail -= 1
                            elif avail >= 1:
                                avail -= 1

                            if copy.part_label and copy.part_label not in alldisplay:
                                duedisplay = '%s %s (DUE: %s)' % (
                                    callno, copy.part_label,
                                    time.strftime(self.DUE_FORMAT,
                                                  earliestdue))

                        elif len(allcalls) > 0:
                            allcalls[len(allcalls) - 1] = [
                                callno, LOCKED, copy.syrup_id, copy.part_label
                            ]

                        if avail == 0 and duedisplay is not None:
                            alldisplay = duedisplay
                        alldues.append(alldisplay)

                        if voltest or attachtest:
                            callno, vol = last_check_embed(
                                callprefix, callno, callsuffix, voltest, vol)
            except:
                print "due date/call problem: ", bib_id
                print "*** print_exc:"
                traceback.print_exc()

            if avail != 0 and len(allcalls) > 0:
                if allcalls[len(allcalls) - 1][1] == DUE:
                    allcalls[len(allcalls) - 1] = [
                        alldisplay, READY, allcalls[len(allcalls) - 1][2],
                        allcalls[len(allcalls) - 1][3]
                    ]
            return (vol, lib, desk, avail, callno, dueid, dueinfo, circmod,
                    allcalls, alldues, copyids)

        #get lists of barcodes and ids
        bcs = make_obj_list(bclist)
        ids = make_obj_list(idlist)

        # At this point, status information does not require the opensrf
        # bindings, I am not sure there is a use case where an evergreen
        # site would not have access to these but will leave for now
        # since there are no hardcoded references
        assert self.RESERVES_DESK_NAME, 'No RESERVES_DESK_NAME specified!'

        lib = desk = avail = vol = anystatus_here = 0
        dueid = ['', READY]
        dueinfo = ''
        callno = ''
        circmod = ''
        allcalls = []
        alldues = []
        tot_allcalls = []
        tot_alldues = []
        copyids = []
        cpname = 'copies'

        EVERGREEN_STATUS_ORG = getattr(settings, 'EVERGREEN_STATUS_ORG', 1)
        EVERGREEN_STATUS_DEPTH = getattr(settings, 'EVERGREEN_STATUS_DEPTH', 0)

        counts = E1(OPENSRF_COPY_COUNTS, bib_id, EVERGREEN_STATUS_ORG,
                    EVERGREEN_STATUS_DEPTH)

        version = getattr(settings, 'EVERGREEN_VERSION', 2.4)

        if version >= 2.1:
            #this loop is needed in case there are multiple reserves locations
            for org, prefix, callno, suffix, loc, stats in counts:
                if len(prefix) > 0:
                    prefix += ' '
                if len(suffix) > 0:
                    suffix = ' ' + suffix
                vol, lib, desk, avail, callno, dueid, dueinfo, circmod, allcalls, alldues, copyids = sort_out_status(
                    barcode, vol, counts, version, lib, desk, avail, callno,
                    dueid, dueinfo, circmod, allcalls, alldues, prefix, suffix,
                    bcs, ids, copyids)
                tot_allcalls.extend(allcalls)
                tot_alldues.extend(alldues)
        else:
            for org, callno, loc, stats in counts:
                vol, lib, desk, avail, callno, dueid, dueinfo, circmod, allcalls, alldues, copyids = sort_out_status(
                    barcode, vol, counts, version, lib, desk, avail, callno,
                    dueid, dueinfo, circmod, allcalls, alldues, bcs, ids,
                    copyids)

        if len(allcalls) > 0:
            cpname = 'copies/parts'

        return (cpname, lib, desk, avail, callno, dueid[0], dueinfo, circmod,
                allcalls, alldues)