Skip to content

Commit 7c6430e

Browse files
authored
Merge pull request #166 from mlibrary/aeon-open-url
Aeon open url
2 parents 873cdb1 + 4c523b8 commit 7c6430e

File tree

5 files changed

+397
-6
lines changed

5 files changed

+397
-6
lines changed

api/.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"python-envs.defaultEnvManager": "ms-python.python:poetry",
3+
"python-envs.defaultPackageManager": "ms-python.python:poetry",
4+
"python-envs.pythonProjects": []
5+
}

api/catalog_api/entities.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ class FieldElement:
2727
def citation_text(self):
2828
return self.text
2929

30+
def __str__(self):
31+
return self.text
32+
3033

3134
@dataclass(frozen=True)
3235
class PairedField:

api/catalog_api/holdings.py

Lines changed: 216 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pymarc
2+
from urllib.parse import urlencode
23
from dataclasses import dataclass
4+
from catalog_api.marc import Processor, FieldRuleset
35

46

57
class AlmaDigitalItem:
@@ -152,7 +154,9 @@ def reservable(self):
152154
@property
153155
def url(self):
154156
if self.reservable:
155-
return "what"
157+
return ReservableItem.given(
158+
physical_item_data=self.data, record=self.record
159+
).url
156160
# send over the marc record to some classes that can parse the Reserve This item
157161
return f"https://search.lib.umich.edu/catalog/record/{self.bib_id}/get-this/{self.barcode}"
158162

@@ -168,6 +172,217 @@ def physical_location(self):
168172
)
169173

170174

175+
class ReservableItem:
176+
@staticmethod
177+
def given(physical_item_data, record):
178+
match physical_item_data["library"]:
179+
case "BENT":
180+
cls = BentleyItem
181+
case "CLEM":
182+
cls = ClementsItem
183+
case _:
184+
cls = ReservableItem
185+
186+
return cls(physical_item_data, record)
187+
188+
"""
189+
The rules come a spreadsheet in the issue SEARCH-1421
190+
"""
191+
192+
def __init__(self, physical_item_data, record):
193+
self.data = physical_item_data
194+
self.record = record
195+
self.processor = Processor(record)
196+
197+
@property
198+
def title(self):
199+
rulesets = [FieldRuleset(tags=["245"], text_sfs="abk")]
200+
return self._format_paired_fields(rulesets)
201+
202+
@property
203+
def author(self):
204+
rulesets = [
205+
FieldRuleset(tags=["100", "110"], text_sfs="abcd"),
206+
FieldRuleset(tags=["111"], text_sfs="anbc"),
207+
FieldRuleset(tags=["130"], text_sfs="aplskf"),
208+
]
209+
return self._format_paired_fields(rulesets)
210+
211+
@property
212+
def date(self):
213+
rulesets = [
214+
FieldRuleset(tags=["260", "264"], text_sfs="c"),
215+
FieldRuleset(tags=["245"], text_sfs="f"),
216+
]
217+
fields = self.processor.generate_unpaired_fields(rulesets)
218+
if fields:
219+
return "; ".join([str(f) for f in fields])
220+
221+
@property
222+
def edition(self):
223+
rulesets = [FieldRuleset(tags=["250"], text_sfs="a")]
224+
return self._format_paired_fields(rulesets)
225+
226+
@property
227+
def publisher(self):
228+
rulesets = [FieldRuleset(tags=["260", "264"], text_sfs="b")]
229+
return self._format_paired_fields(rulesets)
230+
231+
@property
232+
def place(self):
233+
rulesets = [FieldRuleset(tags=["260", "264"], text_sfs="a")]
234+
return self._format_paired_fields(rulesets)
235+
236+
@property
237+
def extent(self):
238+
rulesets = [FieldRuleset(tags=["300"], text_sfs="abcf")]
239+
return self._format_paired_fields(rulesets)
240+
241+
@property
242+
def isbn(self):
243+
"""
244+
This is from the Metadata Component spreadsheet
245+
"""
246+
rulesets = [
247+
FieldRuleset(tags=["020"], text_sfs=["a"]),
248+
FieldRuleset(tags=["020"], text_sfs=["z"]),
249+
]
250+
fields = self.processor.generate_unpaired_fields(rulesets)
251+
if fields:
252+
return str(fields[0])
253+
254+
@property
255+
def issn(self):
256+
"""
257+
This is from the Metadata Component spreadsheet
258+
"""
259+
rulesets = [
260+
FieldRuleset(tags=["022"], text_sfs=["a"]),
261+
FieldRuleset(tags=["022"], text_sfs=["y"]),
262+
FieldRuleset(tags=["022"], text_sfs=["z"]),
263+
FieldRuleset(tags=["776"], text_sfs=["x"]),
264+
]
265+
fields = self.processor.generate_unpaired_fields(rulesets)
266+
if fields:
267+
return str(fields[0])
268+
269+
@property
270+
def sysnum(self):
271+
return self.record["001"].value()
272+
273+
@property
274+
def genre(self):
275+
return self.data.get("material_type")
276+
277+
@property
278+
def barcode(self):
279+
return self.data.get("barcode")
280+
281+
@property
282+
def description(self):
283+
return self.data.get("description")
284+
285+
@property
286+
def library_code(self):
287+
return self.data.get("library")
288+
289+
@property
290+
def location_code(self):
291+
return self.data.get("location")
292+
293+
@property
294+
def call_number(self):
295+
return self.data.get("callnumber")
296+
297+
@property
298+
def inventory_number(self):
299+
return self.data.get("inventory_number")
300+
301+
@property
302+
def fields(self):
303+
return {
304+
"Action": "10",
305+
"Form": "30",
306+
"callnumber": self.call_number,
307+
"genre": self.genre,
308+
"title": self.title,
309+
"author": self.author,
310+
"date": self.date,
311+
"edition": self.edition,
312+
"publisher": self.publisher,
313+
"place": self.place,
314+
"extent": self.extent,
315+
"barcode": self.barcode,
316+
"description": self.description,
317+
"sysnum": self.sysnum,
318+
"location": self.library_code,
319+
"sublocation": self.location_code,
320+
"fixedshelf": self.inventory_number,
321+
"issn": self.issn,
322+
"isbn": self.isbn,
323+
}
324+
325+
@property
326+
def url(self):
327+
# get rid of empty fields
328+
fields = {k: v for k, v in self.fields.items() if v is not None}
329+
return self.base_url() + urlencode(fields)
330+
331+
def base_url(self):
332+
return "https://aeon.lib.umich.edu/logon?"
333+
334+
def _format_paired_fields(self, rulesets, separator="; "):
335+
paired_fields = self.processor.generate_paired_fields(rulesets)
336+
return self._join_paired_fields(paired_fields, separator)
337+
338+
def _join_paired_fields(self, paired_fields, separator="; "):
339+
if paired_fields:
340+
return separator.join(
341+
[self._join_paired_field(pf, separator) for pf in paired_fields]
342+
)
343+
344+
def _join_paired_field(self, paired_field, separator="; "):
345+
pf = [paired_field.original.text]
346+
if paired_field.transliterated:
347+
pf.append(paired_field.transliterated.text)
348+
return separator.join(pf)
349+
350+
351+
class BentleyItem(ReservableItem):
352+
def base_url(self):
353+
return "https://aeon.bentley.umich.edu/login?"
354+
355+
356+
class ClementsItem(ReservableItem):
357+
def base_url(self):
358+
return "https://aeon.clements.umich.edu/logon?"
359+
360+
@property
361+
def author(self):
362+
rulesets = [
363+
FieldRuleset(tags=["100"], text_sfs="abcd"),
364+
FieldRuleset(tags=["110"], text_sfs="ab"),
365+
FieldRuleset(tags=["111"], text_sfs="acd"),
366+
FieldRuleset(tags=["130"], text_sfs="aplskf"),
367+
]
368+
return self._format_paired_fields(rulesets)
369+
370+
@property
371+
def genre(self):
372+
mapping = {
373+
"BOOK": "Book",
374+
"ISSBD": "Book",
375+
"ISSUE": "Book",
376+
"SCORE": "Graphics",
377+
"OTHERVM": "Graphics",
378+
"MIXED": "Manuscripts",
379+
"ATLAS": "Map",
380+
"MAP": "Map",
381+
}
382+
value = self.data.get("material_type")
383+
return mapping.get(value)
384+
385+
171386
class PhysicalHolding:
172387
def __init__(self, physical_holding_data: list, bib_id: str, record: pymarc.Record):
173388
self.data = physical_holding_data

api/catalog_api/record.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,11 +955,13 @@ class CSL:
955955
"figure": "figure",
956956
"Image": "graphic",
957957
"Photographs and Pictorial Works": "graphic",
958+
"Photographs & Pictorial Works": "graphic",
958959
"Photograph": "graphic",
959960
"Drawing": "graphic",
960961
"Painting": "graphic",
961962
"Graphic Arts": "graphic",
962963
"Visual Material": "graphic",
964+
"Board Games": "graphic",
963965
"interview": "interview",
964966
"legislation": "legislation",
965967
"Case": "legal_case",
@@ -973,6 +975,7 @@ class CSL:
973975
"Atlas": "map",
974976
"Map": "map",
975977
"Map-Atlas": "map",
978+
"Maps-Atlas": "map",
976979
"Video Recording": "motion_picture",
977980
"Video (Blu-ray)": "motion_picture",
978981
"Video (DVD)": "motion_picture",
@@ -1067,7 +1070,7 @@ def id(self):
10671070
def type(self):
10681071
formats = self.solr_processor.get("format")
10691072
if formats:
1070-
types = [self.TYPE_MAPPING[f] for f in formats]
1073+
types = [self.TYPE_MAPPING.get(f) for f in formats]
10711074
for t in self.TYPE_ORDER:
10721075
if t in types:
10731076
return t

0 commit comments

Comments
 (0)