From 870333dc087a541ce9e151022d34fcbb57d6086d Mon Sep 17 00:00:00 2001 From: artunit Date: Wed, 23 Mar 2011 03:20:57 +0000 Subject: [PATCH] thanks to dbs, much better opensrf interaction for update git-svn-id: svn://svn.open-ils.org/ILS-Contrib/servres/trunk@1278 6d9bc8c9-1ec2-4278-b937-99fde70a366f --- conifer/libsystems/evergreen/opensrf.py | 239 ++++++++++++++++++++++---------- conifer/syrup/views/items.py | 3 +- 2 files changed, 170 insertions(+), 72 deletions(-) diff --git a/conifer/libsystems/evergreen/opensrf.py b/conifer/libsystems/evergreen/opensrf.py index a1c704f..501a325 100644 --- a/conifer/libsystems/evergreen/opensrf.py +++ b/conifer/libsystems/evergreen/opensrf.py @@ -1,39 +1,70 @@ # session-based opensrf calls go here +# thanks to dan scott for sorting out the python integration -from conifer.libsystems import marcxml as M -from conifer.libsystems.evergreen import item_status as I -from conifer.libsystems.evergreen.support import initialize, E1 from datetime import date from django.conf import settings -import hashlib import os import re import traceback -def auth_token(username, password, org, workstation): - try: - authtoken = None - payload = E1(settings.OPENSRF_AUTHENTICATE_INIT, username) - pw = hashlib.md5(password).hexdigest() - pw = hashlib.md5(payload + pw).hexdigest() - authinfo = E1(settings.OPENSRF_AUTHENTICATE,{"password":pw, "type":"staff", - "org": org, "username":username, - "workstation":workstation}) - if authinfo: - payload = authinfo.get("payload") - authtoken = payload.get("authtoken") - except: - print "authentication problem: ", username - print "*** print_exc:" - traceback.print_exc() - pass # fail silently in production - return None +import oils.event +import oils.utils.idl +import oils.utils.utils +import osrf.gateway +import osrf.json +import sys +import tempfile +import urllib2 + +class AuthException(Exception): + """ + Exceptions for authentication events + """ + + def __init__(self, msg=''): + """ + Initialize the authentication exception + """ + Exception.__init__(self) + self.msg = msg + + def __str__(self): + """ + Stringify the authentication exception + """ + return 'AuthException: %s' % self.msg +def auth_token(username, password, workstation): + authtoken = None + seed = request( + 'open-ils.auth', + 'open-ils.auth.authenticate.init', username).send() + + # generate the hashed password + password = oils.utils.utils.md5sum(seed + oils.utils.utils.md5sum(password)) + + result = request( + 'open-ils.auth', + 'open-ils.auth.authenticate.complete', { + 'workstation' : workstation, + 'username' : username, + 'password' : password, + 'type' : 'staff' + }).send() + + evt = oils.event.Event.parse_event(result) + if evt and not evt.success: + print "authentication problem: ", AuthException(evt.text_code) + return None + + authtoken = result['payload']['authtoken'] return authtoken def session_cleanup(authtoken): try: - payload = E1(settings.OPENSRF_CLEANUP, authtoken) + result = request( + 'open-ils.auth', + 'open-ils.auth.session.delete', authtoken).send() except: print "session problem: ", authtoken print "*** print_exc:" @@ -43,55 +74,121 @@ def session_cleanup(authtoken): return True -def evergreen_item_update(barcode, callno, modifier, desk): +def load_idl(): + """ + Loads the fieldmapper IDL, registering class hints for the defined objects + + We use a temporary file to store the IDL each time load_idl() + is invoked to ensure that the IDL is in sync with the target + server. One could a HEAD request to do some smarter caching, + perhaps. + """ + + parser = oils.utils.idl.IDLParser() + idlfile = tempfile.TemporaryFile() + + # Get the fm_IDL.xml file from the server + try: + idl = urllib2.urlopen('%s://%s/%s' % + (settings.OSRF_HTTP, settings.EVERGREEN_GATEWAY_SERVER, settings.IDL_URL) + ) + idlfile.write(idl.read()) + # rewind to the beginning of the file + idlfile.seek(0) + + #no pass on these, updates are too critical to ever be out of sync + except urllib2.URLError, exc: + print("Could not open URL to read IDL: %s", exc.code) + + except IOError, exc: + print("Could not write IDL to file: %s", exc.code) + + # parse the IDL + parser.set_IDL(idlfile) + parser.parse_IDL() + +def request(service, method, *args): + """ + Make a JSON request to the OpenSRF gateway + + This is as simple as it gets. Atomic requests will require a bit + more effort. + """ + + req = osrf.gateway.JSONGatewayRequest(service, method, *args) + + # The gateway URL ensures we're using JSON v1, not v0 + req.setPath(settings.GATEWAY_URL) + return req + +def ils_item_update(barcode, callno, modifier, location): try: - token = auth_token(settings.OPENSRF_STAFF_USERID, settings.OPENSRF_STAFF_PW, - settings.OPENSRF_STAFF_ORG, settings.OPENSRF_STAFF_WORKSTATION) - - null = None - true = True - false = False - barcode_copy = E1(settings.OPENSRF_CN_BARCODE, token, barcode); - - copy = None - volumeinfo = None - - if barcode_copy: - volumeinfo = barcode_copy.get("volume") - if volumeinfo: - volume = volumeinfo['__p'] - if volume and volume[7] != callno: - volume[0] = [] - volume[7] = str(callno) - vol_len = len(volume) - 1 - volume[vol_len] = str(volume[vol_len]) - # ok, this is bad, need to find what these values are - for i in range(0, 4): - volume.append(None) - volume.append('1') - # print "volume", volume - updaterec = E1(settings.OPENSRF_VOLUME_UPDATE, - token, [{"__c":"acn","__p":volume}], false, - {"auto_merge_vols":false}) - # print "update", updaterec - copy = barcode_copy.get("copy") - if copy: - # print "copy", copy - detailid = copy['__p'][21] - details = E1(settings.OPENSRF_FLESHEDCOPY_CALL, [detailid]) - if details and (details[0]['__p'][7] != modifier or details[0]['__p'][23] != desk): - details[0]['__p'][7] = str(modifier) - details[0]['__p'][23] = str(desk) - # ditto here too, need to find what these values are - for i in range(0, 6): - details[0]['__p'].append(None) - details[0]['__p'].append('1') - - print "details", details - updaterec = E1(settings.OPENSRF_BATCH_UPDATE, token, details,true) - # print "updaterec", updaterec - - session_cleanup(token) + item_changed = False + callno_changed = False + + # Set the host for our requests + osrf.gateway.GatewayRequest.setDefaultHost(settings.EVERGREEN_GATEWAY_SERVER) + + # Pull all of our object definitions together + load_idl() + + # We get our copy object + req = request('open-ils.search', + 'open-ils.search.asset.copy.fleshed2.find_by_barcode', + barcode) + barcode_copy = req.send() + + # are there changes? + if barcode_copy.location().id != location or barcode_copy.circ_modifier != modifier: + item_changed = True + + # And our call number object + req = request('open-ils.search', + 'open-ils.search.asset.call_number.retrieve', + barcode_copy.call_number()) + call_num = req.send() + + # are there changes? + if call_num.label() != callno: + callno_changed = True + + # there might be nothing to do + if not item_changed and not callno_changed: + return True + + # ok, we are going to update, first we authenticate + authtoken = auth_token(settings.OPENSRF_STAFF_USERID, + settings.OPENSRF_STAFF_PW, + settings.OPENSRF_STAFF_WORKSTATION) + + # item changes first, location and circ modifier + if authtoken and item_changed: + barcode_copy.location().id(location); + barcode_copy.circ_modifier(modifier); + barcode_copy.ischanged(True) + + acp = [barcode_copy] + req = request('open-ils.cat', + 'open-ils.cat.asset.copy.fleshed.batch.update', + authtoken, acp, False, None) + result = req.send() + # print "item result", result + + # on to call number + if authtoken and callno_changed: + call_num.label(callno) + call_num.ischanged(True) + + # volume.fleshed.batch.update expects an array of call number objects + acn = [call_num] + req = request('open-ils.cat', + 'open-ils.cat.asset.volume.fleshed.batch.update', + authtoken, acn, False, None) + result = req.send() + # print "callno result", result + + #clean up session + session_cleanup(authtoken) except: print "item update problem" print "*** print_exc:" diff --git a/conifer/syrup/views/items.py b/conifer/syrup/views/items.py index 5dec0eb..d1ba3ce 100644 --- a/conifer/syrup/views/items.py +++ b/conifer/syrup/views/items.py @@ -361,6 +361,7 @@ def item_add_cat_search(request, site_id, item_id): eg_modifier = None eg_desk = None + #TODO: use python bindings for these interactions bar_num=request.POST.get('bc') if bar_num and settings.OPENSRF_STAFF_USERID: bc = bar_num @@ -456,7 +457,7 @@ def item_edit(request, site_id, item_id): update_status = True if update_option == 'Cat': - update_status = evergreen_item_update(item.barcode, item.orig_callno, + update_status = ils_item_update(item.barcode, item.orig_callno, modifier_option, location_option) #leave values alone if update failed -- 2.11.0