Skip to content

Commit 2a120be

Browse files
committed
Set process status type constant
Check the process status type to calculate Unavailable status Check the process status when the value is in process, in combination with the requested value related to pulibrary/orangelight#5715 See https://pul-confluence.atlassian.net/wiki/spaces/ALMA/pages/1025114135/Availability @mzelesky Thank you for sharing your Alma knowledge and contributing to create this documentation https://docs.google.com/document/d/1VzbWI4mEy8M2WWIpGBfYv1UtcgqtI6fj8LoomRT17_4/edit?pli=1&tab=t.0 We've created a simpler approach to calculate the status in bibdata.
1 parent a856de0 commit 2a120be

6 files changed

Lines changed: 429 additions & 52 deletions

File tree

app/adapters/alma_adapter/alma_item.rb

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
class AlmaAdapter
2+
# rubocop:disable Metrics/ClassLength
23
class AlmaItem < SimpleDelegator
34
attr_reader :item
45

@@ -242,7 +243,7 @@ def availability_summary
242243
copy_number: holding_data['copy_id'],
243244
status: status[:code], # Available
244245
status_label: status[:label], # Item in place
245-
status_source: status[:source], # e.g. work_order, process_type, base_status
246+
status_source: status[:source], # e.g. process_type, base_status
246247
process_type: status[:process_type],
247248
on_reserve: on_reserve? ? 'Y' : 'N',
248249
item_type:, # e.g., Gen
@@ -291,36 +292,74 @@ def item_type
291292
item_data.dig('policy', 'value')
292293
end
293294

295+
def process_type_value
296+
item_data.dig('process_type', 'value')
297+
end
298+
299+
def process_type_desc
300+
item_data.dig('process_type', 'desc')
301+
end
302+
303+
def base_status_value
304+
item_data.dig('base_status', 'value')
305+
end
306+
307+
def base_status_desc
308+
item_data.dig('base_status', 'desc')
309+
end
310+
311+
def work_order_type_value
312+
item_data.dig('work_order_type', 'value')
313+
end
314+
315+
def work_order_type_desc
316+
item_data.dig('work_order_type', 'desc')
317+
end
318+
319+
def requested?
320+
item_data['requested'] == true
321+
end
322+
323+
# Currently we handle the 'In Process' logic in the orangelight codebase
324+
def in_process_work_order_type_values
325+
['AcqWorkOrder', 'Firestone']
326+
end
327+
294328
def calculate_status
295-
return status_from_work_order_type if item_data.dig('work_order_type', 'value').present?
296-
return status_from_process_type if item_data.dig('process_type', 'value').present?
329+
return process_type_status_unavailable unless process_type_value.empty?
330+
331+
return no_process_type_calculate_status if process_type_value.empty?
332+
333+
# keep status_from_base_status until we confirm that the alma items
334+
# will always have the process type attribute with or without value
297335

298336
status_from_base_status
299337
end
300338

301-
def status_from_work_order_type
302-
value = item_data['work_order_type']['value']
303-
desc = item_data['work_order_type']['desc']
304-
305-
# [Source for values](https://developers.exlibrisgroup.com/alma/apis/docs/xsd/rest_item.xsd/)
306-
# [Work Order documentation](https://pul-confluence.atlassian.net/wiki/spaces/ALMA/pages/1770142/Work+Orders)
307-
code = if value.in?(%w[Pres AcqWorkOrder CollDev HMT Firestone])
308-
'Unavailable'
309-
else
310-
# "COURSE" or "PHYSICAL_TO_DIGITIZATION"
311-
'Available'
312-
end
313-
{ code:, label: desc, source: 'work_order' }
339+
PROCESS_TYPE_VALUES = %w[ACQ CLAIM_RETURNED_LOAN HOLDSHELF ILL LOAN LOST_ILL LOST_LOAN LOST_LOAN_AND_PAID MISSING REQUESTED TECHNICAL TRANSIT TRANSIT_TO_REMOTE_STORAGE WORK_ORDER_DEPARTMENT].freeze
340+
def process_type_status_unavailable
341+
label, source = if process_type_value.in?(PROCESS_TYPE_VALUES)
342+
if process_type_value == 'WORK_ORDER_DEPARTMENT' && in_process_work_order_type_values.include?(work_order_type_value)
343+
[work_order_type_desc, 'work_order']
344+
else
345+
['Unavailable', 'process_type']
346+
end
347+
end
348+
{ code: 'Unavailable', label:, source:, process_type: process_type_value }
314349
end
315350

316-
def status_from_process_type
317-
# For now we return "Unavailable" for any item that has a process_type.
318-
# You can see a list of all the possible values here:
319-
# https://developers.exlibrisgroup.com/alma/apis/docs/xsd/rest_item.xsd/
320-
value = item_data.dig('process_type', 'value')
321-
desc = item_data.dig('process_type', 'desc')
351+
def no_process_type_calculate_status
352+
# no process type and requested true sends to illiad
353+
code, value, source = if requested?
354+
['Unavailable', 'Unavailable', 'requested_true']
355+
elsif !requested? && base_status_value == '1'
356+
# Currently Orangelight is looking for Item in place for alma items
357+
# this is why we keep base_status_desc
358+
# we can replace this with Available when we refactor Orangelight to look for Available
359+
['Available', base_status_desc, 'base_status']
360+
end
322361

323-
{ code: 'Unavailable', label: desc, source: 'process_type', process_type: value }
362+
{ code:, label: value, source:, process_type: process_type_value }
324363
end
325364

326365
def status_from_base_status
@@ -339,4 +378,5 @@ def holding_location_label(code)
339378
[composite_library_label_display, label].compact_blank.join(' - ')
340379
end
341380
end
381+
# rubocop:enable Metrics/ClassLength
342382
end

spec/adapters/alma_adapter/alma_item_spec.rb

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ def build_item(code:, retention_reason:)
180180
'base_status' => { 'value' => '0', 'desc' => 'Item not in place' },
181181
'process_type' => { 'value' => 'WORK_ORDER_DEPARTMENT', 'desc' => 'In Process' },
182182
'work_order_type' => { 'value' => 'AcqWorkOrder', 'desc' => 'Acquisitions and Cataloging' },
183-
'work_order_at' => { 'value' => 'AcqDepttechserv', 'desc' => 'Acquisitions and Cataloging' }
183+
'work_order_at' => { 'value' => 'AcqDepttechserv', 'desc' => 'Acquisitions and Cataloging' },
184+
'requested' => false
184185
}
185186
)
186187
end
@@ -194,7 +195,8 @@ def build_item(code:, retention_reason:)
194195
'base_status' => { 'value' => '0', 'desc' => 'Item not in place' },
195196
'process_type' => { 'value' => 'WORK_ORDER_DEPARTMENT', 'desc' => 'In Process' },
196197
'work_order_type' => { 'value' => 'CollDev', 'desc' => 'Collection Development Office' },
197-
'work_order_at' => { 'value' => 'CollDev', 'desc' => 'Collection Development Office' }
198+
'work_order_at' => { 'value' => 'CollDev', 'desc' => 'Collection Development Office' },
199+
'requested' => false
198200
}
199201
)
200202
end
@@ -208,7 +210,8 @@ def build_item(code:, retention_reason:)
208210
'base_status' => { 'value' => '1', 'desc' => 'Item in place' },
209211
'process_type' => { 'value' => 'TRANSIT', 'desc' => 'Transit' },
210212
'work_order_type' => { 'value' => 'HMT', 'desc' => 'Holdings Management' },
211-
'work_order_at' => { 'value' => 'HMT', 'desc' => 'Holdings Management' }
213+
'work_order_at' => { 'value' => 'HMT', 'desc' => 'Holdings Management' },
214+
'requested' => false
212215
}
213216
)
214217
end
@@ -220,7 +223,8 @@ def build_item(code:, retention_reason:)
220223
'item_data' => {
221224
'pid' => '23194161020006421',
222225
'base_status' => { 'value' => '0', 'desc' => 'Item not in place' },
223-
'process_type' => { 'value' => 'ACQ', 'desc' => 'Acquisition' }
226+
'process_type' => { 'value' => 'ACQ', 'desc' => 'Acquisition' },
227+
'requested' => false
224228
}
225229
)
226230
end
@@ -229,15 +233,15 @@ def build_item(code:, retention_reason:)
229233
Alma::BibItem.new(
230234
'bib_data' => { 'mms_id' => '9939075533506421' },
231235
'holding_data' => { 'holding_id' => '22194161030006421' },
232-
'item_data' => { 'pid' => '23194161020006421', 'base_status' => { 'value' => '1', 'desc' => 'Item in place' } }
236+
'item_data' => { 'pid' => '23194161020006421', 'process_type' => { 'value' => '' }, 'base_status' => { 'value' => '1', 'desc' => 'Item in place' }, 'requested' => false }
233237
)
234238
end
235239

236240
let(:item_base_status_not_in_place) do
237241
Alma::BibItem.new(
238242
'bib_data' => { 'mms_id' => '9939075533506421' },
239243
'holding_data' => { 'holding_id' => '22194161030006421' },
240-
'item_data' => { 'pid' => '23194161020006421', 'base_status' => { 'value' => '0', 'desc' => 'Item not in place' } }
244+
'item_data' => { 'pid' => '23194161020006421', 'process_type' => { 'value' => 'ACQ', 'desc' => 'Acquisition' }, 'base_status' => { 'value' => '0', 'desc' => 'Item not in place' }, 'requested' => false }
241245
)
242246
end
243247

spec/adapters/alma_adapter_spec.rb

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -243,19 +243,23 @@
243243
describe 'holding availability' do
244244
let(:library_lewis_reserves) { file_fixture('alma/library_lewis_reserves.json') }
245245
let(:library_lewis_stacks) { file_fixture('alma/library_lewis_stacks.json') }
246+
let(:library_firestone_stacks) { file_fixture('alma/library_firestone_stacks.json') }
246247

247248
before do
248249
stub_alma_holding_items(mms_id: '9919392043506421', holding_id: '22105104420006421', filename: '9919392043506421_holding_items.json')
249250
stub_alma_holding_items(mms_id: '99122455086806421', holding_id: '22477860740006421', filename: '99122455086806421_holding_items.json')
250251
stub_alma_library(library_code: 'firestone', location_code: 'dixn')
251252
stub_alma_library(library_code: 'firestone', location_code: 'stacks')
252253

254+
stub_alma_holding_items(mms_id: '99126856502706421', holding_id: '22965530090006421', filename: '99126856502706421_process_type_requested.json')
255+
253256
# https://api-na.hosted.exlibrisgroup.com/almaws/v1/bibs/9999362473506421/holdings/22752541670006421/items?limit=100&order_by=enum_a
254257
stub_alma_holding_items(mms_id: '9999362473506421', holding_id: '22752541670006421', filename: '9999362473506421_holding_items.json')
255258
stub_alma_holding_items(mms_id: '9999362473506421', holding_id: '22752541690006421', filename: '9999362473506421_holding_items_two.json')
256259

257260
stub_alma_library(library_code: 'lewis', location_code: 'resterm', body: library_lewis_reserves)
258261
stub_alma_library(library_code: 'lewis', location_code: 'stacks', body: library_lewis_stacks)
262+
stub_alma_library(library_code: 'firestone', location_code: 'stacks', body: library_firestone_stacks)
259263
end
260264

261265
it 'reports holdings availability' do
@@ -276,21 +280,31 @@
276280
# but we are not really using this value anymore.
277281
expect(item[:on_reserve]).to eq 'N'
278282

279-
# Make sure temp locations are handled and the permanent location is preserved.
280-
availability = adapter.get_availability_holding(id: '9999362473506421', holding_id: '22752541690006421')
283+
create(:holding_location, code: 'firestone$stacks', label: 'Stacks')
284+
availability = adapter.get_availability_holding(id: '99126856502706421', holding_id: '22965530090006421')
281285
item = availability.first
282-
expect(item[:in_temp_library]).to be true
283-
expect(item[:temp_library_code]).to eq 'lewis'
284-
285-
# Test an actual response. These values are not particularly meaningful, but to make sure we don't
286-
# inadvertently change them when refactoring.
287-
item_test = { barcode: '32101099065268', id: '23752541680006421', holding_id: '22752541690006421', copy_number: '0',
288-
status: 'Available', status_label: 'Item in place', status_source: 'base_status', process_type: nil,
289-
on_reserve: 'Y', item_type: 'Gen', pickup_location_id: 'lewis', pickup_location_code: 'lewis',
290-
location: 'lewis$resterm', label: 'Lewis Library - Term Loan Reserves', description: '', enum_display: '',
291-
chron_display: '', requested: false, in_temp_library: true, temp_library_code: 'lewis',
292-
temp_library_label: 'Lewis Library - Term Loan Reserves', temp_location_code: 'lewis$resterm',
293-
temp_location_label: 'Lewis Library - Term Loan Reserves' }
286+
expect(item[:in_temp_library]).to be false
287+
expect(item[:temp_library_code]).to be_nil
288+
289+
item_test = { barcode: '32101116415405',
290+
id: '23965530080006421',
291+
holding_id: '22965530090006421',
292+
copy_number: '',
293+
status: 'Unavailable',
294+
status_label: 'Unavailable',
295+
status_source: 'process_type',
296+
process_type: 'HOLDSHELF',
297+
on_reserve: 'N',
298+
item_type: 'Gen',
299+
pickup_location_id: 'firestone',
300+
pickup_location_code: 'firestone',
301+
location: 'firestone$stacks',
302+
label: 'Firestone Library - Stacks',
303+
description: '',
304+
enum_display: '',
305+
chron_display: '',
306+
requested: true,
307+
in_temp_library: false }
294308
expect(item).to eq item_test
295309
end
296310

@@ -312,30 +326,42 @@
312326
before do
313327
stub_alma_ids(ids: '9965126093506421', status: 200)
314328
stub_alma_holding_items(mms_id: '9965126093506421', holding_id: '22202918790006421', filename: '9965126093506421_holding_items.json')
329+
stub_alma_holding_items(mms_id: '99131644166406421', holding_id: '221091258440006421', filename: '99131644166406421_in_process_acq.json')
315330
stub_alma_ids(ids: '9943506421', status: 200)
316331
stub_alma_holding_items(mms_id: '9943506421', holding_id: '22261963850006421', filename: '9943506421_holding_items.json')
317332
stub_alma_library(library_code: 'firestone', location_code: 'stacks')
318333
stub_alma_library(library_code: 'recap', location_code: 'xr')
319334
end
320335

321-
it 'uses the work_order to calculate status' do
322-
availability = adapter.get_availability_holding(id: '9965126093506421', holding_id: '22202918790006421')
323-
item = availability.first
324-
expect(item[:status]).to eq 'Unavailable'
325-
expect(item[:status_label]).to eq 'Holdings Management'
326-
expect(item[:status_source]).to eq 'work_order'
336+
context 'item with process type value' do
337+
# PROCESS_TYPE_VALUES = ACQ CLAIM_RETURNED_LOAN HOLDSHELF ILL LOAN LOST_ILL LOST_LOAN LOST_LOAN_AND_PAID MISSING REQUESTED TECHNICAL TRANSIT TRANSIT_TO_REMOTE_STORAGE WORK_ORDER_DEPARTMENT
338+
it '-WORK_ORDER_DEPARTMENT- and work order not AcqWorkOrder or Firestone it has status and label Unavailable' do
339+
availability = adapter.get_availability_holding(id: '9965126093506421', holding_id: '22202918790006421')
340+
item = availability.first
341+
expect(item[:status]).to eq 'Unavailable'
342+
expect(item[:status_label]).to eq 'Unavailable'
343+
expect(item[:status_source]).to eq 'process_type'
344+
end
345+
346+
it '-WORK_ORDER_DEPARTMENT- and work order is AcqWorkOrder it has status Unavailable and label Acquisitions and Cataloging' do
347+
availability = adapter.get_availability_holding(id: '99131644166406421', holding_id: '221091258440006421')
348+
item = availability.first
349+
expect(item[:status]).to eq 'Unavailable'
350+
expect(item[:status_label]).to eq 'Acquisitions and Cataloging'
351+
expect(item[:status_source]).to eq 'work_order'
352+
end
327353
end
328354

329355
it 'uses the process_type to calculate status' do
330356
availability = adapter.get_availability_holding(id: '9943506421', holding_id: '22261963850006421')
331357
item = availability.find { |bib_item| bib_item[:id] == '23261963800006421' }
332358
expect(item[:status]).to eq 'Unavailable'
333-
expect(item[:status_label]).to eq 'Transit'
359+
expect(item[:status_label]).to eq 'Unavailable'
334360
expect(item[:status_source]).to eq 'process_type'
335361
expect(item[:process_type]).to eq 'TRANSIT'
336362
end
337363

338-
it 'uses the base_status to calculate status' do
364+
it 'when there is no process_type value it uses the base_status to calculate status' do
339365
availability = adapter.get_availability_holding(id: '9943506421', holding_id: '22261963850006421')
340366
item = availability.first
341367
expect(item[:status]).to eq 'Available'

0 commit comments

Comments
 (0)