voyager_api 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/holdings/item.rb CHANGED
@@ -77,7 +77,11 @@ module Voyager
77
77
 
78
78
  # no items = no status available
79
79
  if item_count == "0"
80
- return {:status => 'none', :messages => ['No item status available'] }
80
+ return {:status => 'none',
81
+ :messages => [ {:status_code => '0',
82
+ :short_message => 'Status unknown',
83
+ :long_message => 'No item status available'} ]
84
+ }
81
85
  end
82
86
 
83
87
  # item:itemRecord nodes
@@ -140,112 +144,110 @@ module Voyager
140
144
  def generate_messages(records)
141
145
 
142
146
  messages = []
143
-
144
147
  records.each do |record|
145
- # messages differ based on whether there is a request count
146
- if record[:requestCount] == '0'
147
- messages << generate_message_no_requests(record)
148
- else
149
- messages << generate_message_requests(record)
150
- end
151
-
148
+ messages << generate_message(record)
152
149
  end
153
-
154
150
  messages
155
151
 
156
152
  end
157
153
 
158
154
  # Generate message from a record (item:itemRecord node)
159
- # No request count
160
155
  #
161
156
  # * *Args* :
162
157
  # - +record+ -> Hash of data from an item:itemRecord node
163
158
  # * *Returns* :
164
- # - Formatted message
159
+ # - Formatted message in a hash
160
+ # :status_code => code of status message
161
+ # :short_message => short version of message
162
+ # :long_message => long version of message
165
163
  #
166
- def generate_message_no_requests(record)
167
-
168
- # label is descriptive information for items; optional
169
- labels = []
170
- [:enumeration, :chronology, :year, :caption, :text].each do |type|
171
- labels << record[type] unless record[type].empty?
172
- end
173
- labels.empty? ? label = '' : label = labels.join(' ') + ' '
164
+ def generate_message(record)
174
165
 
175
- datetime = record[:statusDate].split(' ') # split into date/time
176
-
177
- message = ''
178
-
179
- # status patron message otherwise a regular message
166
+ short_message = ''
167
+ long_message = ''
168
+ code = ''
169
+
170
+ # status patron message otherwise regular message
180
171
  if record[:patronGroupCode].strip.match(/^(IND|MIS|ACO)/)
181
172
 
182
- message = record[:lastName].strip + ' ' + record[:firstName].strip
183
-
173
+ code = 'sp'
174
+ long_message = record[:lastName].strip + ' ' + record[:firstName].strip
175
+ # done in two steps in case ending puctuation is missing
176
+ short_message = long_message.gsub(/(Try|Place).+/, '').strip
177
+ short_message = short_message.gsub(/\W$/, '')
178
+
184
179
  else
185
180
 
186
- case record[:statusCode]
187
- when '1'
188
- message = 'Not checked out'
189
- when '2'
190
- message = "Checked out, due #{datetime.join(' ')} - Recall, or try Borrow Direct or ILL."
191
- when '3'
192
- message = "Checked out, due #{datetime.join(' ')} - Recall, or try Borrow Direct or ILL."
193
- when '4'
194
- message = "Overdue as of #{datetime.join(' ')} - Recall, or try Borrow Direct."
195
- when '5'
196
- message = "Requests: #{record[:requestCount]}"
197
- when '6'
198
- message = "Requests: #{record[:requestCount]}"
199
- when '7'
200
- message = "On hold at #{record[:holdLocation]}. Try Borrow Direct or ILL."
201
- when '8'
202
- message = "In transit #{datetime[0]}. Place a hold request."
203
- when '9'
204
- message = "In transit to #{record[:holdLocation]} #{datetime[0]}. Place a hold request."
205
- when '10'
206
- message = "In transit to #{record[:holdLocation]} #{datetime[0]}. Place a hold request."
207
- when '11'
208
- message = "Returned #{datetime[0]}"
209
- when '12'
210
- message = "Missing #{datetime[0]}. Try Borrow Direct or ILL."
211
- when '13'
212
- message = "Unavailable #{datetime[0]}. Try Borrow Direct or ILL."
213
- when '14'
214
- message = "Unavailable #{datetime[0]}. Try Borrow Direct or ILL."
215
- when '18'
216
- message = "Sent to bindery for 1 month on #{datetime[0]}. Try Borrow Direct or ILL."
217
- when '21'
218
- message = "Scheduled"
219
- when '22'
220
- message = "In Process #{datetime[0]}. Place an In Process item request."
221
- when '23'
222
- message = "Requested"
223
- when '24'
224
- message = "Requested"
225
- when '25'
226
- message = "Requested"
181
+ code = record[:statusCode]
182
+ # append suffix to indicate whether there are requests - n = no requests, r = requests
183
+ record[:requestCount] == '0' ? code += 'n' : code += 'r'
184
+
185
+ # get parms for the message being processed
186
+ parms = ITEM_STATUS_CODES[code]
187
+
188
+ raise "Status code not found in config/item_status_codes.yml" unless parms
189
+
190
+ short_message = make_substitutions(parms['short_message'],record)
191
+ long_message = make_substitutions(parms['long_message'],record)
192
+
193
+ end
194
+
195
+ # add labels
196
+ short_message = add_label(short_message,record)
197
+ long_message = add_label(long_message,record)
198
+
199
+ return { :status_code => code,
200
+ :short_message => short_message,
201
+ :long_message => long_message }
202
+
203
+ end
204
+
205
+ def format_datetime(record)
206
+
207
+ # format date / time
208
+ datetime = ''
209
+ unless record[:statusDate].empty?
210
+ # use date in record so we can use stored test features
211
+ todays_date = DateTime.parse(record[:todaysDate])
212
+ # todays_date = DateTime.now
213
+ status_date = DateTime.parse(record[:statusDate])
214
+ diff = status_date - todays_date
215
+ # we have to accommodate dates in the past and the future relative to today
216
+ # remove times from past dates over 1 day old and future dates more than 2 days away
217
+ if diff.to_i > 2 || diff.to_i < 0
218
+ datetime = record[:statusDate].gsub(/\s.+/, '')
227
219
  else
228
- message = "Unknown"
220
+ datetime = record[:statusDate]
229
221
  end
222
+ end
223
+
224
+ datetime
230
225
 
226
+ end
227
+
228
+ def make_substitutions(message,record)
229
+
230
+ datetime = format_datetime(record)
231
+
232
+ # substitute values for tokens in message strings
233
+ # date
234
+ unless datetime.empty?
235
+ message = message.gsub('%DATE', datetime)
236
+ end
237
+ # number of requests
238
+ unless record[:requestCount] == '0'
239
+ message = message.gsub('%REQS', record[:requestCount])
231
240
  end
241
+ # hold location
242
+ unless record[:holdLocation].empty?
243
+ message = message.gsub('%LOC', record[:holdLocation])
244
+ end
245
+
246
+ message
232
247
 
233
- # add label
234
- message.insert(0, label) unless label.empty?
235
-
236
- return message
237
-
238
248
  end
239
-
240
- # Generate message from a record (item:itemRecord node)
241
- # Request count
242
- #
243
- # * *Args* :
244
- # - +record+ -> Hash of data from an item:itemRecord node
245
- # * *Returns* :
246
- # - Formatted message
247
- #
248
- def generate_message_requests(record)
249
+
250
+ def add_label(message,record)
249
251
 
250
252
  # label is descriptive information for items; optional
251
253
  labels = []
@@ -254,69 +256,11 @@ module Voyager
254
256
  end
255
257
  labels.empty? ? label = '' : label = labels.join(' ') + ' '
256
258
 
257
- datetime = record[:statusDate].split(' ') # split into date/time
258
-
259
- message = ''
260
-
261
- # status patron message otherwise regular message
262
- if record[:patronGroupCode].strip.match(/^(IND|MIS|ACO)/)
263
-
264
- message = record[:lastName].strip + ' ' + record[:firstName].strip
265
-
266
- else
267
-
268
- case record[:statusCode]
269
- when '1'
270
- message = "Not checked out (Requests: #{record[:requestCount]})"
271
- when '2'
272
- message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
273
- when '3'
274
- message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
275
- when '4'
276
- message = "Overdue as of #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
277
- when '5'
278
- message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
279
- when '6'
280
- message = "Checked out, due #{datetime.join(' ')} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
281
- when '7'
282
- message = "On hold at #{record[:holdLocation]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
283
- when '8'
284
- message = "In transit #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct"
285
- when '9'
286
- message = "In transit to #{record[:holdLocation]} #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct."
287
- when '10'
288
- message = "In transit to #{record[:holdLocation]} #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct"
289
- when '11'
290
- message = "Returned #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
291
- when '12'
292
- message = "Missing #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
293
- when '13'
294
- message = "Unavailable #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
295
- when '14'
296
- message = "Unavailable #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
297
- when '18'
298
- message = "Sent to bindery for 1 month on #{datetime[0]} (Requests: #{record[:requestCount]}). Try Borrow Direct or ILL."
299
- when '21'
300
- message = "Scheduled (Requests: #{record[:requestCount]})"
301
- when '22'
302
- message = "In Process #{datetime[0]} (Requests: #{record[:requestCount]}). Place an In Process item request."
303
- when '23'
304
- message = "Requests: #{record[:requestCount]}"
305
- when '24'
306
- message = "Requests: #{record[:requestCount]}"
307
- when '25'
308
- message = "Requests: #{record[:requestCount]}"
309
- else
310
- message = "Unknown"
311
- end
312
-
313
- end
314
-
315
259
  # add label
316
260
  message.insert(0, label) unless label.empty?
317
-
318
- return message
319
-
261
+
262
+ message
263
+
320
264
  end
321
265
 
322
266
  end
@@ -53,7 +53,10 @@ module Voyager
53
53
  # * *Args* :
54
54
  # - +poLineItems+ -> mfhd:poLineItems node
55
55
  # * *Returns* :
56
- # - Array of messages for orders
56
+ # - Array of message hashes for orders
57
+ # :status_code => status code
58
+ # :short_message => short version of the message
59
+ # :long_message => long version of the message
57
60
  # - An empty array if there is no mfhd:poLineItems node
58
61
  #
59
62
  def parse_order(poLineItems)
@@ -76,22 +79,17 @@ module Voyager
76
79
 
77
80
  status = lineItemStatus.at_css("mfhd|status").content
78
81
  date = lineItemStatus.at_css("mfhd|date").content
79
-
80
- message = ''
81
-
82
- case status
83
- when "0"
84
- message = "In the Pre-Order Process. Try Borrow Direct or ILL."
85
- when "1"
86
- message = "Received #{date}. Place an In Process item request."
87
- when "4"
88
- message = "Not yet received; claimed #{date}. Try Borrow Direct or ILL."
89
- when "8"
90
- message = "Copy On Order #{date}. Try Borrow Direct or ILL."
91
- else
92
- message = "Unknown"
93
- end
94
-
82
+
83
+ # get parms for the message being processed
84
+ parms = ORDER_STATUS_CODES[status]
85
+
86
+ raise "Status code not found in config/order_status_codes.yml" unless parms
87
+
88
+ short_message = parms['short_message'].gsub('%DATE',date)
89
+ long_message = parms['long_message'].gsub('%DATE',date)
90
+
91
+ { :status_code => status, :short_message => short_message, :long_message => long_message }
92
+
95
93
  end
96
94
 
97
95
  end
@@ -3,7 +3,7 @@ module Voyager
3
3
  class Record
4
4
  attr_reader :holding_id, :location_name, :call_number, :summary_holdings, :notes_852, :notes_866, :notes,
5
5
  :shelving_title, :supplements, :indexes, :reproduction_note, :urls, :item_count, :temp_locations,
6
- :item_status, :orders, :current_issues
6
+ :item_status, :orders, :current_issues, :services, :bibid
7
7
 
8
8
  # Record class initializing method
9
9
  # Populates instance variables from the mfhd:marcRecord node of the mfhd:mfhdRecord node.
@@ -13,6 +13,7 @@ module Voyager
13
13
  # - +xml_node+ -> mfhd:mfhdRecord node
14
14
  #
15
15
  def initialize(xml_node)
16
+ @bibid = xml_node.attributes["bibId"].value
16
17
  @holding_id = xml_node.attributes["mfhdId"].value
17
18
  @location_name = xml_node.at_css("mfhd|mfhdData[@name='locationDisplayName']").content
18
19
  # marc record node
@@ -64,6 +65,9 @@ module Voyager
64
65
  @current_issues = order.current_issues
65
66
  @orders = order.orders
66
67
 
68
+ # add available services
69
+ @services = determine_services(@location_name,@call_number,@item_status,@orders,@bibid)
70
+
67
71
  end
68
72
 
69
73
  # Collect data from all variables into a hash
@@ -73,6 +77,7 @@ module Voyager
73
77
  #
74
78
  def to_hash
75
79
  {
80
+ :bibid => @bibid,
76
81
  :holding_id => @holding_id,
77
82
  :location_name => @location_name,
78
83
  :call_number => @call_number,
@@ -86,6 +91,7 @@ module Voyager
86
91
  :item_count => @item_count,
87
92
  :temp_locations => @temp_locations,
88
93
  :item_status => @item_status,
94
+ :services => @services,
89
95
  :current_issues => @current_issues,
90
96
  :orders => @orders
91
97
  }
@@ -296,6 +302,99 @@ module Voyager
296
302
 
297
303
  end
298
304
 
305
+ def determine_services(location_name,call_number,item_status,orders,bibid)
306
+
307
+ services = []
308
+
309
+ unless orders.empty?
310
+ orders.each do |order|
311
+ parms = ORDER_STATUS_CODES[order[:status_code]]
312
+ raise "Status code not found in config/order_status_codes.yml" unless parms
313
+ services << parms['services'] unless parms['services'].nil?
314
+ end
315
+ return services.flatten.uniq
316
+ end
317
+
318
+ services << scan_message(location_name)
319
+
320
+ status = item_status[:status]
321
+ messages = item_status[:messages]
322
+
323
+ case status
324
+ when 'online'
325
+ when 'none'
326
+ services << 'in_process' if call_number.match(/in process/i)
327
+ when 'available'
328
+ services << process_available(location_name,bibid)
329
+ when 'some_available'
330
+ services << process_some_available(location_name,bibid,messages)
331
+ when 'not_available'
332
+ services << scan_messages(messages)
333
+ else
334
+ end
335
+
336
+ services.flatten.uniq
337
+
338
+ end
339
+
340
+ def process_available(location_name,bibid)
341
+ # offsite
342
+ if location_name.match(/^Offsite/) &&
343
+ HTTPClient.new.get_content("http://www.columbia.edu/cgi-bin/cul/lookupNBX?" + bibid) == "1"
344
+ return ['offsite']
345
+ end
346
+ # precat
347
+ if location_name.match(/^Precat/)
348
+ return ['precat']
349
+ end
350
+ return []
351
+ end
352
+
353
+ def process_some_available(location_name,bibid,messages)
354
+
355
+ services = []
356
+ # offsite
357
+ if location_name.match(/^Offsite/) &&
358
+ HTTPClient.new.get_content("http://www.columbia.edu/cgi-bin/cul/lookupNBX?" + bibid) == "1"
359
+ services << 'offsite'
360
+ end
361
+
362
+ services << scan_messages(messages)
363
+
364
+ services
365
+
366
+ end
367
+
368
+ def scan_messages(messages)
369
+ services = []
370
+ messages.each do |message|
371
+ # status patrons
372
+ if message[:status_code] == 'sp'
373
+ services << scan_message(message[:long_message])
374
+ else
375
+ parms = ITEM_STATUS_CODES[message[:status_code]]
376
+ raise "Status code not found in config/order_status_codes.yml" unless parms
377
+ services << parms['services'] unless parms['services'].nil?
378
+ end
379
+ end
380
+ services
381
+ end
382
+
383
+
384
+ def scan_message(message)
385
+
386
+ out = []
387
+ out << 'recall_hold' if message =~ /Recall/i
388
+ out << 'recall_hold' if message =~ /hold /
389
+ out << 'borrow_direct' if message =~ /Borrow/
390
+ out << 'ill' if message =~ /ILL/
391
+ out << 'in_process' if message =~ /In Process/
392
+
393
+ out
394
+
395
+ end
396
+
299
397
  end
398
+
300
399
  end
301
400
  end