module Voyager module Holdings class Item attr_reader :holding_id, :item_count, :temp_locations, :item_status # Item class initializing method # Populates instance variables from the mfhd:mfhdRecord node. # # * *Args* : # - +xml_node+ -> mfhd:mfhdRecord node # def initialize(xml_node) @holding_id = xml_node.attributes["mfhdId"].value # the item collecction item = xml_node.at_css("mfhd|itemCollection") # number of item records @item_count = item.at_css("item|itemCount").content @temp_locations = parse_for_temp_locations(item) # array @item_status = parse_for_circ_status(item, @item_count) # hash end private # Isolates item:itemLocation nodes in the mfhd:itemCollection and # extracts information on items in temp locations. # # * *Args* : # - +item+ -> mfhd:itemCollection node # * *Returns* : # - An array of messages for items found in temp locations # - An empty array if there are no items in temp locations # def parse_for_temp_locations(item) # item:itemLocation nodes # reject nodes that do not have the tmpLoc attribute set itemLocation = item.css("item|itemLocation").reject { |loc| loc.at_css("item|itemLocationData[@name='tmpLoc']").content.empty? } return [] unless itemLocation.length > 0 messages = [] itemLocation.each do |loc| # label is descriptive information for items; optional label = [] ['itemEnum', 'itemChron','itemYear', 'itemCaption', 'itemFreeText'].each do |type| loc_data = loc.at_css("item|itemLocationData[@name=#{type}]") label << loc_data.content unless loc_data.content.empty? end # generate message if label.empty? messages << "Shelved in " + loc.at_css("item|itemLocationData[@name='tempLocation']").content else messages << label.join(" ") + " Shelved in " + loc.at_css("item|itemLocationData[@name='tempLocation']").content end end messages end # Isolates item:itemRecord nodes in the mfhd:itemCollection, # determines circulation status and generates messages # # * *Args* : # - +item+ -> mfhd:itemCollection node # - +item_count+ -> count of item records # * *Returns* : # - Hash containing overall circulation status and a list of circulation messages # { :status => overall item status, :messages => [ one or more circulation messages ] } # - Possible statuses are: 'none', 'available', 'not_available', 'some_avaialble' # - An additional status, 'online', is set in the Record class # def parse_for_circ_status(item,item_count) # no items = no status available if item_count == "0" return {:status => 'none', :messages => ['No item status available'] } end # item:itemRecord nodes itemRecord = item.css("item|itemRecord") # generate an arry of hashes for ease of handling records = itemRecord.collect do |record| data = {} record.css("item|itemData").each do |rec| data[rec.attr("name").to_sym] = rec.content end data end # determine overall status status = determine_status(records,item_count) # generate messages messages = generate_messages(records) return {:status => status, :messages => messages } end # Set the overall circulation status # # * *Args* : # - +records+ -> Array of hashes for data in item:itemRecord nodes # - +item_count+ -> count of item records # * *Returns* : # - Overall circulation status # def determine_status(records,item_count) # this may need to be refined # statusCode = 1 in first (and only) record means nothing has a item status set # assume available status = 'available' # if statusCode > 1 some item status is set so some item is not available; 11 (returned) is the exception if records.first[:statusCode].to_i > 1 && records.first[:statusCode].to_i != 11 # if the number of records (item:itemRecord nodes) with statusCodes > 1 equals the total number of items # everything is unavailable; otherwise, only some items are unavailable if records.length == item_count.to_i status = 'not_available' else status = 'some_available' end end status end # Generate circulation messages # # * *Args* : # - +records+ -> Array of hashes for data in item:itemRecord nodes # * *Returns* : # - Array of circulation messages # def generate_messages(records) messages = [] records.each do |record| # messages differ based on whether there is a request count if record[:requestCount] == '0' messages << generate_message_no_requests(record) else messages << generate_message_requests(record) end end messages end # Generate message from a record (item:itemRecord node) # No request count # # * *Args* : # - +record+ -> Hash of data from an item:itemRecord node # * *Returns* : # - Formatted message # def generate_message_no_requests(record) # label is descriptive information for items; optional labels = [] [:enumeration, :chronology, :year, :caption, :text].each do |type| labels << record[type] unless record[type].empty? end labels.empty? ? label = '' : label = labels.join(' ') + ' ' datetime = record[:statusDate].split(' ') # split into date/time message = '' # status patron message otherwise a regular message if record[:patronGroupCode].strip.match(/^(IND|MIS|ACO)/) message = record[:lastName].strip + ' ' + record[:firstName].strip else case record[:statusCode] when '1' message = 'Not checked out' when '2' message = "Checked out, due #{datetime.join(' ')} - Recall, or try Borrow Direct or ILL." when '3' message = "Checked out, due #{datetime.join(' ')} - Recall, or try Borrow Direct or ILL." when '4' message = "Overdue as of #{datetime.join(' ')} - Recall, or try Borrow Direct." when '5' message = "Requests: #{record[:requestCount]}" when '6' message = "Requests: #{record[:requestCount]}" when '7' message = "On hold at #{record[:holdLocation]}. Try Borrow Direct or ILL." when '8' message = "In transit #{datetime[0]}. Place a hold request." when '9' message = "In transit to #{record[:holdLocation]} #{datetime[0]}. Place a hold request." when '10' message = "In transit to #{record[:holdLocation]} #{datetime[0]}. Place a hold request." when '11' message = "Returned #{datetime[0]}" when '12' message = "Missing #{datetime[0]}. Try Borrow Direct or ILL." when '13' message = "Unavailable #{datetime[0]}. Try Borrow Direct or ILL." when '14' message = "Unavailable #{datetime[0]}. Try Borrow Direct or ILL." when '18' message = "Sent to bindery for 1 month on #{datetime[0]}. Try Borrow Direct or ILL." when '21' message = "Scheduled" when '22' message = "In Process #{datetime[0]}. Place an In Process item request." when '23' message = "Requested" when '24' message = "Requested" when '25' message = "Requested" else message = "Unknown" end end # add label message.insert(0, label) unless label.empty? return message end # Generate message from a record (item:itemRecord node) # Request count # # * *Args* : # - +record+ -> Hash of data from an item:itemRecord node # * *Returns* : # - Formatted message # def generate_message_requests(record) # label is descriptive information for items; optional labels = [] [:enumeration, :chronology, :year, :caption, :text].each do |type| labels << record[type] unless record[type].empty? end labels.empty? ? label = '' : label = labels.join(' ') + ' ' datetime = record[:statusDate].split(' ') # split into date/time message = '' # status patron message otherwise regular message if record[:patronGroupCode].strip.match(/^(IND|MIS|ACO)/) message = record[:lastName].strip + ' ' + record[:firstName].strip else case record[:statusCode] when '1' message = "Not checked out (Requests: #{record[:requestCount]})" when '2' message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '3' message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '4' message = "Overdue as of #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '5' message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '6' message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '7' message = "On hold at #{record[:holdLocation]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '8' message = "In transit #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct" when '9' message = "In transit to #{record[:holdLocation]} #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct." when '10' message = "In transit to #{record[:holdLocation]} #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct" when '11' message = "Returned #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '12' message = "Missing #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '13' message = "Unavailable #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '14' message = "Unavailable #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '18' message = "Sent to bindery for 1 month on #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL." when '21' message = "Scheduled (Requests: #{record[:requestCount]})" when '22' message = "In Process #{datetime[0]} (Requests: #{record[:requestCount]}). Place an In Process item request." when '23' message = "Requests: #{record[:requestCount]}" when '24' message = "Requests: #{record[:requestCount]}" when '25' message = "Requests: #{record[:requestCount]}" else message = "Unknown" end end # add label message.insert(0, label) unless label.empty? return message end end end end