Skip to content

Commit 02b680f

Browse files
committed
Add 'book' fields and address some initial code review feedback
1 parent 100109b commit 02b680f

File tree

6 files changed

+316
-47
lines changed

6 files changed

+316
-47
lines changed

.env.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ PRIMO_API_URL=https://api-na.hosted.exlibrisgroup.com/primo/v1
66
PRIMO_SCOPE=cdi
77
PRIMO_TAB=all
88
PRIMO_VID=01MIT_INST:MIT
9+
SYNDETICS_PRIMO_URL=https://syndetics.com/index.php?client=primo
910
TIMDEX_GRAPHQL=https://FAKE_TIMDEX_HOST/graphql
1011
TIMDEX_HOST=FAKE_TIMDEX_HOST
1112
TIMDEX_INDEX=FAKE_TIMDEX_INDEX

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ See `Optional Environment Variables` for more information.
9898
- `PRIMO_SCOPE`: The Primo Search API `scope` param (set to `cdi` for CDI-scoped results).
9999
- `PRIMO_TAB`: The Primo Search API `tab` param (typically `all`).
100100
- `PRIMO_VID`: The Primo Search API `vid` (or 'view ID`) param.
101+
- `SYNDETICS_PRIMO_URL`: The Syndetics API URL for Primo. This is used to construct thumbnail URLs.
101102
- `TIMDEX_GRAPHQL`: Set this to the URL of the GraphQL endpoint. There is no default value in the application.
102103

103104
### Optional Environment Variables

app/models/normalize_primo.rb

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Transforms results from Primo Search API into normalized records
22
class NormalizePrimo
3-
def initialize(record)
3+
def initialize(record, query)
44
@record = record
5+
@query = query
56
end
67

78
def normalize
@@ -17,7 +18,13 @@ def normalize
1718
'identifier' => record_id,
1819
'summary' => summary,
1920
'numbering' => numbering,
20-
'chapter_numbering' => chapter_numbering
21+
'chapter_numbering' => chapter_numbering,
22+
'thumbnail' => thumbnail,
23+
'publisher' => publisher,
24+
'location' => best_location,
25+
'subjects' => subjects,
26+
'availability' => best_availability,
27+
'other_availability' => other_availability?
2128
}
2229
end
2330

@@ -78,8 +85,10 @@ def format
7885
def links
7986
links = []
8087

81-
# Add direct record link as the first link
82-
if record_link.present?
88+
# Use dedup URL as the full record link if available, otherwise use record link
89+
if dedup_url.present?
90+
links << { 'url' => dedup_url, 'kind' => 'full record' }
91+
elsif record_link.present?
8392
links << { 'url' => record_link, 'kind' => 'full record' }
8493
end
8594

@@ -176,12 +185,6 @@ def chapter_numbering
176185
"#{@record['pnx']['addata']['date'].join}, pp. #{@record['pnx']['addata']['pages'].join}"
177186
end
178187

179-
def openurl
180-
return unless @record['delivery'] && @record['delivery']['almaOpenurl']
181-
182-
@record['delivery']['almaOpenurl'].is_a?(Array) ? @record['delivery']['almaOpenurl'].join : @record['delivery']['almaOpenurl']
183-
end
184-
185188
def sanitize_authors(authors)
186189
authors.map! { |author| author.split(';') }.flatten! if authors.any? { |author| author.include?(';') }
187190
authors.map { |author| author.strip.gsub(/\$\$Q.*$/, '') }
@@ -246,4 +249,68 @@ def construct_primo_openurl
246249
filtered = params.delete_if { |key, _value| key.starts_with?('ctx') }
247250
URI::DEFAULT_PARSER.unescape(filtered.to_param)
248251
end
252+
253+
def thumbnail
254+
return unless @record['pnx']['addata'] && @record['pnx']['addata']['isbn']
255+
256+
# A record can have multiple ISBNs, so we are assuming here that
257+
# the thumbnail URL can be constructed from the first occurrence
258+
isbn = @record['pnx']['addata']['isbn'].first
259+
[ENV['SYNDETICS_PRIMO_URL'], '&isbn=', isbn, '/sc.jpg'].join
260+
end
261+
262+
def publisher
263+
return unless @record['pnx']['addata'] && @record['pnx']['addata']['pub']
264+
@record['pnx']['addata']['pub'].first
265+
end
266+
267+
def best_location
268+
return unless @record['delivery']
269+
return unless @record['delivery']['bestlocation']
270+
loc = @record['delivery']['bestlocation']
271+
["#{loc['mainLocation']} #{loc['subLocation']}", loc['callNumber']]
272+
end
273+
274+
def subjects
275+
return [] unless @record['pnx']['display']['subject']
276+
@record['pnx']['display']['subject']
277+
end
278+
279+
def best_availability
280+
return unless best_location
281+
@record['delivery']['bestlocation']['availabilityStatus']
282+
end
283+
284+
def other_availability?
285+
return unless @record['delivery']['bestlocation']
286+
return unless @record['delivery']['holding']
287+
@record['delivery']['holding'].length > 1
288+
end
289+
290+
# FRBR Group check based on:
291+
# https://knowledge.exlibrisgroup.com/Primo/Knowledge_Articles/Primo_Search_API_-_how_to_get_FRBR_Group_members_after_a_search
292+
def frbrized?
293+
return unless @record['pnx']['facets']
294+
return unless @record['pnx']['facets']['frbrtype']
295+
@record['pnx']['facets']['frbrtype'].join == '5'
296+
end
297+
298+
def dedup_url
299+
return unless frbrized?
300+
return unless @record['pnx']['facets']['frbrgroupid'] &&
301+
@record['pnx']['facets']['frbrgroupid'].length == 1
302+
303+
frbr_group_id = @record['pnx']['facets']['frbrgroupid'].join
304+
base = [ENV['MIT_PRIMO_URL'], '/discovery/search?'].join
305+
306+
query = {
307+
query: "any,contains,#{@query}",
308+
tab: ENV['PRIMO_TAB'],
309+
search_scope: ENV['PRIMO_SCOPE'],
310+
sortby: 'date_d',
311+
vid: ENV['PRIMO_VID'],
312+
facet: "frbrgroupid,include,#{frbr_group_id}"
313+
}.to_query
314+
[base, query].join
315+
end
249316
end

app/models/primo_search.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,12 @@ def initialize
1414

1515
def search(term, per_page)
1616
url = search_url(term, per_page)
17-
Rails.logger.info "Primo Search URL: #{url}"
18-
1917
result = @primo_http.timeout(http_timeout)
2018
.headers(
2119
accept: 'application/json',
2220
Authorization: "apikey #{PRIMO_API_KEY}"
2321
)
2422
.get(url)
25-
26-
Rails.logger.info "Primo Response Status: #{result.status}"
27-
Rails.logger.info "Primo Response Headers: #{result.headers.to_h}"
2823

2924
raise "Primo Error Detected: #{result.status}" unless result.status == 200
3025

test/fixtures/primo/full_record.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
"volume": ["2"],
1616
"issue": ["3"],
1717
"pages": ["123-145"],
18-
"jtitle": ["Journal of Testing"]
18+
"jtitle": ["Journal of Testing"],
19+
"isbn": ["9781234567890", "1234567890"],
20+
"pub": ["MIT Press"]
21+
},
22+
"facets": {
23+
"frbrtype": ["5"],
24+
"frbrgroupid": ["12345"]
1925
},
2026
"search": {
2127
"creationdate": ["2023"]
@@ -29,9 +35,14 @@
2935
"bestlocation": {
3036
"mainLocation": "Hayden Library",
3137
"subLocation": "Stacks",
32-
"callNumber": "QA76.73.R83 2023"
38+
"callNumber": "QA76.73.R83 2023",
39+
"availabilityStatus": "available"
3340
},
41+
"holding": [
42+
{"location": "Main Library"},
43+
{"location": "Branch Library"}
44+
],
3445
"link": [],
35-
"almaOpenurl": "https://example.com/openurl?param=value"
46+
"almaOpenurl": "https://na06.alma.exlibrisgroup.com/view/uresolver/01MIT_INST/openurl?param=value"
3647
}
3748
}

0 commit comments

Comments
 (0)