Skip to content

Commit 595c15e

Browse files
Merge pull request #433 from NYPL/main
Updated specRequestable logic
2 parents 4a390a1 + c658904 commit 595c15e

17 files changed

+628
-181
lines changed

app.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const express = require('express')
33
const esClient = require('./lib/elasticsearch/client')
44
const loadConfig = require('./lib/load-config')
55
const { preflightCheck } = require('./lib/preflight_check')
6+
const { loadNyplCoreData } = require('./lib/load_nypl_core')
67

78
const swaggerDocs = require('./swagger.v1.1.x.json')
89

@@ -20,7 +21,7 @@ app.set('trust proxy', 'loopback')
2021

2122
app.init = async () => {
2223
await loadConfig.loadConfig()
23-
24+
await loadNyplCoreData()
2425
preflightCheck()
2526

2627
// Load logger after running above to ensure we respect LOG_LEVEL if set

config/production.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ NYPL_OAUTH_URL=https://isso.nypl.org/
1010
ENCRYPTED_NYPL_OAUTH_ID=AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAGswaQYJKoZIhvcNAQcGoFwwWgIBADBVBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDMLKVUQA58B6vprNcAIBEIAoaz0lI9EL2M9NyTuEwT8JDmPBt6aXfMiFs027DEuwsCN0wS0qWeFL1g==
1111
ENCRYPTED_NYPL_OAUTH_SECRET=AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAIcwgYQGCSqGSIb3DQEHBqB3MHUCAQAwcAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAyWz91LOP2YP5fg0q0CARCAQ9inO9SV1M8R0Pkkx84r7UdwlU1FxfXvIjk/z6Qs81KBAVELhby2iD5LawQyDrR9tjhuMbotS6QnydwwMR/p8+qJXHI=
1212

13-
NYPL_CORE_VERSION=v2.22
13+
NYPL_CORE_VERSION=v2.23
1414

1515
LOG_LEVEL=info
1616
FEATURES=on-site-edd

config/qa.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ NYPL_OAUTH_URL=https://isso.nypl.org/
1010
ENCRYPTED_NYPL_OAUTH_ID=AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAGswaQYJKoZIhvcNAQcGoFwwWgIBADBVBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDMLKVUQA58B6vprNcAIBEIAoaz0lI9EL2M9NyTuEwT8JDmPBt6aXfMiFs027DEuwsCN0wS0qWeFL1g==
1111
ENCRYPTED_NYPL_OAUTH_SECRET=AQECAHh7ea2tyZ6phZgT4B9BDKwguhlFtRC6hgt+7HbmeFsrsgAAAIcwgYQGCSqGSIb3DQEHBqB3MHUCAQAwcAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAyWz91LOP2YP5fg0q0CARCAQ9inO9SV1M8R0Pkkx84r7UdwlU1FxfXvIjk/z6Qs81KBAVELhby2iD5LawQyDrR9tjhuMbotS6QnydwwMR/p8+qJXHI=
1212

13-
NYPL_CORE_VERSION=v2.22
13+
NYPL_CORE_VERSION=v2.24
1414

1515
LOG_LEVEL=info
1616
FEATURES=on-site-edd

config/test.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ NYPL_OAUTH_URL=http://oauth.example.com
99
ENCRYPTED_NYPL_OAUTH_ID=encrypted-nypl-oauth-id
1010
ENCRYPTED_NYPL_OAUTH_SECRET=encrypted-nypl-oauth-id
1111

12-
NYPL_CORE_VERSION=v2.21
12+
NYPL_CORE_VERSION=v2.23
1313

1414
LOG_LEVEL=error
1515
FEATURES=on-site-edd

lib/available_delivery_location_types.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
const logger = require('./logger')
22
const { makeNyplDataApiClient } = require('./data-api-client')
3+
const nyplCore = require('./load_nypl_core')
34

45
class AvailableDeliveryLocationTypes {
56
static getScholarRoomByPatronId (patronID) {
67
// If patronID is falsy (i.e. patron is not logged in) they're just a Rearcher:
78
if (!patronID) return Promise.resolve(['Research'])
89

9-
const patronTypeMapping = require('@nypl/nypl-core-objects')('by-patron-type')
1010
return this._getPatronTypeOf(patronID)
1111
.then((patronType) => {
12-
if (this._isUnfamiliarPatronType(patronTypeMapping, patronType)) {
12+
if (this._isUnfamiliarPatronType(patronType)) {
1313
return
1414
}
15-
const patronTypeData = patronTypeMapping[patronType]
15+
const patronTypeData = nyplCore.patronTypes()[patronType]
1616
return patronTypeData.scholarRoom && patronTypeData.scholarRoom.code
1717
})
1818
}
@@ -38,8 +38,8 @@ class AvailableDeliveryLocationTypes {
3838
})
3939
}
4040

41-
static _isUnfamiliarPatronType (patronTypeMapping, patronType) {
42-
if (!patronTypeMapping[patronType]) {
41+
static _isUnfamiliarPatronType (patronType) {
42+
if (!nyplCore.patronTypes()[patronType]) {
4343
logger.info(`Found the Patron Type: ${patronType} is not recognizable.`)
4444
return true
4545
} else {
@@ -48,8 +48,4 @@ class AvailableDeliveryLocationTypes {
4848
}
4949
}
5050

51-
const patronTypeMapping = require('@nypl/nypl-core-objects')('by-patron-type')
52-
53-
AvailableDeliveryLocationTypes.patronTypeMapping = patronTypeMapping
54-
5551
module.exports = AvailableDeliveryLocationTypes

lib/delivery-locations-resolver.js

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
const { itemHasRecapHoldingLocation, barcodeFromItem } = require('./util')
22
const scsbClient = require('./scsb-client')
3-
const recapCustomerCodes = require('@nypl/nypl-core-objects')('by-recap-customer-code')
4-
const sierraLocations = require('@nypl/nypl-core-objects')('by-sierra-location')
3+
const nyplCore = require('./load_nypl_core')
4+
55
const logger = require('./logger')
66
const onsiteEddCriteria = require('../data/onsite-edd-criteria.json')
77
const { isItemNyplOwned } = require('./ownership_determination')
88

99
class DeliveryLocationsResolver {
1010
static nyplCoreLocation (locationCode) {
11-
return sierraLocations[locationCode]
11+
return nyplCore.sierraLocations()[locationCode]
1212
}
1313

1414
static requestableBasedOnHoldingLocation (item) {
15-
const locationCode = this.extractLocationCode(item)
15+
const locationCode = DeliveryLocationsResolver.extractLocationCode(item)
1616

1717
if (!DeliveryLocationsResolver.nyplCoreLocation(locationCode)) {
1818
logger.warn(`DeliveryLocationsResolver: Unrecognized holdingLocation for ${item.uri}: ${locationCode}`)
@@ -50,21 +50,15 @@ class DeliveryLocationsResolver {
5050

5151
// Fetch Sierra delivery locations by recap code
5252
static deliveryLocationsByRecapCustomerCode (customerCode) {
53-
if (recapCustomerCodes[customerCode] && recapCustomerCodes[customerCode].sierraDeliveryLocations) {
54-
return recapCustomerCodes[customerCode].sierraDeliveryLocations
53+
if (nyplCore.recapCustomerCodes()[customerCode] && nyplCore.recapCustomerCodes()[customerCode].sierraDeliveryLocations) {
54+
return nyplCore.recapCustomerCodes()[customerCode].sierraDeliveryLocations
5555
}
5656
}
5757

5858
// Fetch Sierra delivery locations by m2 customer code. Returns undefined if the m2 customer code is not requestable:
5959
static deliveryLocationsByM2CustomerCode (customerCode) {
60-
let m2CustomerCodes
61-
try {
62-
m2CustomerCodes = require('@nypl/nypl-core-objects')('by-m2-customer-code')
63-
} catch (e) {
64-
65-
}
66-
if (m2CustomerCodes && m2CustomerCodes[customerCode] && m2CustomerCodes[customerCode].sierraDeliveryLocations) {
67-
const { sierraDeliveryLocations, requestable } = m2CustomerCodes[customerCode]
60+
if (nyplCore.m2CustomerCodes()?.[customerCode]?.sierraDeliveryLocations) {
61+
const { sierraDeliveryLocations, requestable } = nyplCore.m2CustomerCodes()[customerCode]
6862
if (requestable) {
6963
return sierraDeliveryLocations
7064
} else return undefined
@@ -73,7 +67,7 @@ class DeliveryLocationsResolver {
7367

7468
// Determine eddRequestable by recap customer code:
7569
static __eddRequestableByCustomerCode (customerCode) {
76-
if (recapCustomerCodes[customerCode]) return Boolean(recapCustomerCodes[customerCode].eddRequestable)
70+
if (nyplCore.recapCustomerCodes()[customerCode]) return Boolean(nyplCore.recapCustomerCodes()[customerCode].eddRequestable)
7771
}
7872

7973
// Determine eddRequestable by on-site EDD requestability criteria (presumed on-site):
@@ -172,7 +166,7 @@ class DeliveryLocationsResolver {
172166
return {
173167
id: `loc:${location.code}`,
174168
label: location.label,
175-
sortPosition: this.sortPosition(location)
169+
sortPosition: DeliveryLocationsResolver.sortPosition(location)
176170
}
177171
})
178172
// Either way, sort deliveryLocation entries by name:
@@ -197,14 +191,14 @@ class DeliveryLocationsResolver {
197191
}
198192

199193
static attachRecapDeliveryInfo (item) {
200-
const info = this.getRecapDeliveryInfo(item)
194+
const info = DeliveryLocationsResolver.getRecapDeliveryInfo(item)
201195
item.eddRequestable = info.eddRequestable
202196
item.deliveryLocation = info.deliveryLocation
203197
return item
204198
}
205199

206200
static attachOnsiteDeliveryInfo (item) {
207-
const info = this.getOnsiteDeliveryInfo(item)
201+
const info = DeliveryLocationsResolver.getOnsiteDeliveryInfo(item)
208202
item.eddRequestable = info.eddRequestable
209203
item.deliveryLocation = info.deliveryLocation
210204
return item
@@ -218,15 +212,15 @@ class DeliveryLocationsResolver {
218212
const hasRecapCustomerCode = item.recapCustomerCode && item.recapCustomerCode[0]
219213
const nyplItem = isItemNyplOwned(item)
220214
if (!hasRecapCustomerCode) {
221-
const requestableBasedOnHoldingLocation = nyplItem ? this.requestableBasedOnHoldingLocation(item) : true
215+
const requestableBasedOnHoldingLocation = nyplItem ? DeliveryLocationsResolver.requestableBasedOnHoldingLocation(item) : true
222216
// the length of the list of delivery locations is checked later to determine physical requestability
223217
// In case of an offsite item with no recap customer code, we want this to be based on holding location
224218
// so we put a placeholder '' in case it is requestable based on holding location
225219
deliveryLocation = requestableBasedOnHoldingLocation ? [''] : []
226220
eddRequestable = requestableBasedOnHoldingLocation
227-
} else if (!nyplItem || this.requestableBasedOnHoldingLocation(item)) {
228-
deliveryLocation = this.deliveryLocationsByRecapCustomerCode(item.recapCustomerCode[0])
229-
eddRequestable = this.__eddRequestableByCustomerCode(item.recapCustomerCode[0])
221+
} else if (!nyplItem || DeliveryLocationsResolver.requestableBasedOnHoldingLocation(item)) {
222+
deliveryLocation = DeliveryLocationsResolver.deliveryLocationsByRecapCustomerCode(item.recapCustomerCode[0])
223+
eddRequestable = DeliveryLocationsResolver.__eddRequestableByCustomerCode(item.recapCustomerCode[0])
230224
} else {
231225
deliveryLocation = []
232226
eddRequestable = false
@@ -239,7 +233,7 @@ class DeliveryLocationsResolver {
239233
eddRequestable: false,
240234
deliveryLocation: []
241235
}
242-
const holdingLocationCode = this.extractLocationCode(item)
236+
const holdingLocationCode = DeliveryLocationsResolver.extractLocationCode(item)
243237
const sierraData = DeliveryLocationsResolver.nyplCoreLocation(holdingLocationCode)
244238
if (!sierraData) {
245239
// This case is mainly to satisfy a test which wants eddRequestable = false
@@ -249,15 +243,15 @@ class DeliveryLocationsResolver {
249243
}
250244
// if nypl core says it's unrequestable, it can still be eddRequestable,
251245
// but its definitely not phys requestable.
252-
deliveryInfo.eddRequestable = this.eddRequestableByOnSiteCriteria(item)
253-
if (!this.requestableBasedOnHoldingLocation(item)) {
246+
deliveryInfo.eddRequestable = DeliveryLocationsResolver.eddRequestableByOnSiteCriteria(item)
247+
if (!DeliveryLocationsResolver.requestableBasedOnHoldingLocation(item)) {
254248
return deliveryInfo
255249
}
256250
// if nypl-core reports that a holding location's delivery locations
257251
// should be found by M2 code, but only if the item has an M2 customer code
258252
const deliverableToResolution = sierraData.deliverableToResolution
259253
if (deliverableToResolution === 'm2-customer-code' && item.m2CustomerCode && item.m2CustomerCode[0]) {
260-
deliveryInfo.deliveryLocation = this.deliveryLocationsByM2CustomerCode(item.m2CustomerCode[0])
254+
deliveryInfo.deliveryLocation = DeliveryLocationsResolver.deliveryLocationsByM2CustomerCode(item.m2CustomerCode[0])
261255
}
262256
// if no value, default to sierra location lookup
263257
if (!deliverableToResolution) {
@@ -281,15 +275,15 @@ class DeliveryLocationsResolver {
281275
}
282276

283277
/**
284-
* Given an array of items (ES hits), returns the same items with `eddRequestable` & `deliveryLocations`
278+
* Given an array of items (ES hits), returns the same items with `eddRequestable` & `deliveryLocations`. We verify all recap customer codes because our indexed data may be stale.
285279
*
286280
* @return Promise<Array<items>> A Promise that resolves and array of items, modified to include `eddRequestable` & `deliveryLocations`
287281
*/
288282
static attachDeliveryLocationsAndEddRequestability (items, scholarRoom) {
289283
// Extract ReCAP barcodes from items:
290-
const recapBarcodes = this.extractRecapBarcodes(items)
284+
const recapBarcodes = DeliveryLocationsResolver.extractRecapBarcodes(items)
291285
// Get a map from barcodes to ReCAP customercodes:
292-
return this.__recapCustomerCodesByBarcodes(recapBarcodes)
286+
return DeliveryLocationsResolver.__recapCustomerCodesByBarcodes(recapBarcodes)
293287
.then((barcodeToRecapCustomerCode) => {
294288
// Now map over items to affix deliveryLocations:
295289
return items.map((item) => {
@@ -298,15 +292,15 @@ class DeliveryLocationsResolver {
298292
item.recapCustomerCode = [barcodeToRecapCustomerCode[barcode]]
299293
// If recap has a customer code for this barcode, map it by recap cust code:
300294
if (item.recapCustomerCode[0]) {
301-
item = this.attachRecapDeliveryInfo(item)
295+
item = DeliveryLocationsResolver.attachRecapDeliveryInfo(item)
302296
// Otherwise, it's an onsite item
303297
} else {
304-
item = this.attachOnsiteDeliveryInfo(item)
298+
item = DeliveryLocationsResolver.attachOnsiteDeliveryInfo(item)
305299
}
306300
// Establish default for Electronic Document Delivery flag:
307301
item.eddRequestable = !!item.eddRequestable
308-
const filteredDeliveryLocationsWithScholarRoom = this.filterLocations(item.deliveryLocation, scholarRoom)
309-
item.deliveryLocation = this.formatLocations(filteredDeliveryLocationsWithScholarRoom)
302+
const filteredDeliveryLocationsWithScholarRoom = DeliveryLocationsResolver.filterLocations(item.deliveryLocation, scholarRoom)
303+
item.deliveryLocation = DeliveryLocationsResolver.formatLocations(filteredDeliveryLocationsWithScholarRoom)
310304
return item
311305
})
312306
})

lib/jsonld_serializers.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict'
22

3-
const locations = require('@nypl/nypl-core-objects')('by-sierra-location')
4-
const recordTypes = require('@nypl/nypl-core-objects')('by-record-types')
3+
const nyplCore = require('./load_nypl_core')
54
const NyplSourceMapper = require('research-catalog-indexer/lib/utils/nypl-source-mapper')
65

76
const util = require('./util.js')
@@ -287,7 +286,7 @@ class ResourceSerializer extends JsonLdItemSerializer {
287286
}
288287

289288
ResourceSerializer.getFormattedRecordType = function (recordTypeId) {
290-
const prefLabel = recordTypes[recordTypeId]?.label
289+
const prefLabel = nyplCore.recordTypes()[recordTypeId]?.label
291290
if (!prefLabel) return null
292291
return {
293292
'@id': recordTypeId,
@@ -499,10 +498,10 @@ class AggregationSerializer extends JsonLdItemSerializer {
499498
v.label = p[1]
500499
} else if (field === 'buildingLocation') {
501500
// Build buildingLocation agg labels from nypl-core:
502-
v.label = locations[v.value]?.label
501+
v.label = nyplCore.sierraLocations()[v.value]?.label
503502
} else if (field === 'recordType') {
504503
// Build recordType agg labels from nypl-core:
505-
v.label = recordTypes[v.value]?.label
504+
v.label = nyplCore.recordTypes()[v.value]?.label
506505
// Unknown recordType? Remove it:
507506
if (!v.label) return null
508507
} else {

lib/load_nypl_core.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const _data = {}
2+
const nyplCoreObjects = require('@nypl/nypl-core-objects')
3+
4+
const loadNyplCoreData = () => {
5+
const vocabularies = {
6+
sierraLocations: 'by-sierra-location',
7+
recordTypes: 'by-record-types',
8+
recapCustomerCodes: 'by-recap-customer-code',
9+
m2CustomerCodes: 'by-m2-customer-code',
10+
patronTypes: 'by-patron-type'
11+
}
12+
return Promise.all(Object.keys(vocabularies).map(async (vocab) => {
13+
const nyplCoreValues = await nyplCoreObjects(vocabularies[vocab])
14+
_data[vocab] = nyplCoreValues
15+
}))
16+
}
17+
18+
module.exports = {
19+
loadNyplCoreData,
20+
patronTypes: () => _data.patronTypes || {},
21+
sierraLocations: () => _data.sierraLocations || {},
22+
recapCustomerCodes: () => _data.recapCustomerCodes || {},
23+
recordTypes: () => _data.recordTypes || {},
24+
m2CustomerCodes: () => _data.m2CustomerCodes || {}
25+
}

lib/location_label_updater.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const sierraLocations = require('@nypl/nypl-core-objects')('by-sierra-location')
1+
const nyplCore = require('./load_nypl_core')
22

33
class LocationLabelUpdater {
44
constructor (responseReceived) {
@@ -10,20 +10,22 @@ class LocationLabelUpdater {
1010
const resp = this.elasticSearchResponse
1111
const updatedHits = resp.hits.hits.map((bib) => {
1212
// Update locations for items:
13-
; (bib._source.items || []).forEach((item) => {
13+
const items = bib._source.items || []
14+
items.forEach((item) => {
1415
if (item.holdingLocation && item.holdingLocation.length > 0) {
1516
item.holdingLocation = item.holdingLocation.map((loc) => {
16-
const nyplCoreEntry = sierraLocations[loc.id.replace(/^loc:/, '')]
17+
const nyplCoreEntry = nyplCore.sierraLocations()[loc.id.replace(/^loc:/, '')]
1718
if (nyplCoreEntry) loc.label = nyplCoreEntry.label
1819
return loc
1920
})
2021
}
2122
})
2223
// Update locations for holdings:
23-
; (bib._source.holdings || []).forEach((holding) => {
24+
const holdings = bib._source.holdings || []
25+
holdings.forEach((holding) => {
2426
if (holding.location && holding.location.length > 0) {
2527
holding.location = holding.location.map((loc) => {
26-
const nyplCoreEntry = sierraLocations[loc.code.replace(/^loc:/, '')]
28+
const nyplCoreEntry = nyplCore.sierraLocations()[loc.code.replace(/^loc:/, '')]
2729
if (nyplCoreEntry) loc.label = nyplCoreEntry.label
2830
return loc
2931
})

0 commit comments

Comments
 (0)