11import pymarc
2+ from urllib .parse import urlencode
23from dataclasses import dataclass
4+ from catalog_api .marc import Processor , FieldRuleset
35
46
57class 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+
171386class PhysicalHolding :
172387 def __init__ (self , physical_holding_data : list , bib_id : str , record : pymarc .Record ):
173388 self .data = physical_holding_data
0 commit comments