Skip to content

Commit

Permalink
Merge pull request #431 from NYPL/noref-nypl-core-objects-async
Browse files Browse the repository at this point in the history
specRequest update and async update
  • Loading branch information
charmingduchess authored Dec 20, 2024
2 parents c257110 + dfa867e commit 7b79f1e
Show file tree
Hide file tree
Showing 7 changed files with 525 additions and 33 deletions.
2 changes: 1 addition & 1 deletion config/test.env
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ NYPL_OAUTH_URL=http://oauth.example.com
ENCRYPTED_NYPL_OAUTH_ID=encrypted-nypl-oauth-id
ENCRYPTED_NYPL_OAUTH_SECRET=encrypted-nypl-oauth-id

NYPL_CORE_VERSION=v2.21
NYPL_CORE_VERSION=v2.23

LOG_LEVEL=error
FEATURES=on-site-edd
Expand Down
38 changes: 19 additions & 19 deletions lib/delivery-locations-resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class DeliveryLocationsResolver {
}

static requestableBasedOnHoldingLocation (item) {
const locationCode = this.extractLocationCode(item)
const locationCode = DeliveryLocationsResolver.extractLocationCode(item)

if (!DeliveryLocationsResolver.nyplCoreLocation(locationCode)) {
logger.warn(`DeliveryLocationsResolver: Unrecognized holdingLocation for ${item.uri}: ${locationCode}`)
Expand Down Expand Up @@ -166,7 +166,7 @@ class DeliveryLocationsResolver {
return {
id: `loc:${location.code}`,
label: location.label,
sortPosition: this.sortPosition(location)
sortPosition: DeliveryLocationsResolver.sortPosition(location)
}
})
// Either way, sort deliveryLocation entries by name:
Expand All @@ -191,14 +191,14 @@ class DeliveryLocationsResolver {
}

static attachRecapDeliveryInfo (item) {
const info = this.getRecapDeliveryInfo(item)
const info = DeliveryLocationsResolver.getRecapDeliveryInfo(item)
item.eddRequestable = info.eddRequestable
item.deliveryLocation = info.deliveryLocation
return item
}

static attachOnsiteDeliveryInfo (item) {
const info = this.getOnsiteDeliveryInfo(item)
const info = DeliveryLocationsResolver.getOnsiteDeliveryInfo(item)
item.eddRequestable = info.eddRequestable
item.deliveryLocation = info.deliveryLocation
return item
Expand All @@ -212,15 +212,15 @@ class DeliveryLocationsResolver {
const hasRecapCustomerCode = item.recapCustomerCode && item.recapCustomerCode[0]
const nyplItem = isItemNyplOwned(item)
if (!hasRecapCustomerCode) {
const requestableBasedOnHoldingLocation = nyplItem ? this.requestableBasedOnHoldingLocation(item) : true
const requestableBasedOnHoldingLocation = nyplItem ? DeliveryLocationsResolver.requestableBasedOnHoldingLocation(item) : true
// the length of the list of delivery locations is checked later to determine physical requestability
// In case of an offsite item with no recap customer code, we want this to be based on holding location
// so we put a placeholder '' in case it is requestable based on holding location
deliveryLocation = requestableBasedOnHoldingLocation ? [''] : []
eddRequestable = requestableBasedOnHoldingLocation
} else if (!nyplItem || this.requestableBasedOnHoldingLocation(item)) {
deliveryLocation = this.deliveryLocationsByRecapCustomerCode(item.recapCustomerCode[0])
eddRequestable = this.__eddRequestableByCustomerCode(item.recapCustomerCode[0])
} else if (!nyplItem || DeliveryLocationsResolver.requestableBasedOnHoldingLocation(item)) {
deliveryLocation = DeliveryLocationsResolver.deliveryLocationsByRecapCustomerCode(item.recapCustomerCode[0])
eddRequestable = DeliveryLocationsResolver.__eddRequestableByCustomerCode(item.recapCustomerCode[0])
} else {
deliveryLocation = []
eddRequestable = false
Expand All @@ -233,7 +233,7 @@ class DeliveryLocationsResolver {
eddRequestable: false,
deliveryLocation: []
}
const holdingLocationCode = this.extractLocationCode(item)
const holdingLocationCode = DeliveryLocationsResolver.extractLocationCode(item)
const sierraData = DeliveryLocationsResolver.nyplCoreLocation(holdingLocationCode)
if (!sierraData) {
// This case is mainly to satisfy a test which wants eddRequestable = false
Expand All @@ -243,15 +243,15 @@ class DeliveryLocationsResolver {
}
// if nypl core says it's unrequestable, it can still be eddRequestable,
// but its definitely not phys requestable.
deliveryInfo.eddRequestable = this.eddRequestableByOnSiteCriteria(item)
if (!this.requestableBasedOnHoldingLocation(item)) {
deliveryInfo.eddRequestable = DeliveryLocationsResolver.eddRequestableByOnSiteCriteria(item)
if (!DeliveryLocationsResolver.requestableBasedOnHoldingLocation(item)) {
return deliveryInfo
}
// if nypl-core reports that a holding location's delivery locations
// should be found by M2 code, but only if the item has an M2 customer code
const deliverableToResolution = sierraData.deliverableToResolution
if (deliverableToResolution === 'm2-customer-code' && item.m2CustomerCode && item.m2CustomerCode[0]) {
deliveryInfo.deliveryLocation = this.deliveryLocationsByM2CustomerCode(item.m2CustomerCode[0])
deliveryInfo.deliveryLocation = DeliveryLocationsResolver.deliveryLocationsByM2CustomerCode(item.m2CustomerCode[0])
}
// if no value, default to sierra location lookup
if (!deliverableToResolution) {
Expand All @@ -275,15 +275,15 @@ class DeliveryLocationsResolver {
}

/**
* Given an array of items (ES hits), returns the same items with `eddRequestable` & `deliveryLocations`
* 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.
*
* @return Promise<Array<items>> A Promise that resolves and array of items, modified to include `eddRequestable` & `deliveryLocations`
*/
static attachDeliveryLocationsAndEddRequestability (items, scholarRoom) {
// Extract ReCAP barcodes from items:
const recapBarcodes = this.extractRecapBarcodes(items)
const recapBarcodes = DeliveryLocationsResolver.extractRecapBarcodes(items)
// Get a map from barcodes to ReCAP customercodes:
return this.__recapCustomerCodesByBarcodes(recapBarcodes)
return DeliveryLocationsResolver.__recapCustomerCodesByBarcodes(recapBarcodes)
.then((barcodeToRecapCustomerCode) => {
// Now map over items to affix deliveryLocations:
return items.map((item) => {
Expand All @@ -292,15 +292,15 @@ class DeliveryLocationsResolver {
item.recapCustomerCode = [barcodeToRecapCustomerCode[barcode]]
// If recap has a customer code for this barcode, map it by recap cust code:
if (item.recapCustomerCode[0]) {
item = this.attachRecapDeliveryInfo(item)
item = DeliveryLocationsResolver.attachRecapDeliveryInfo(item)
// Otherwise, it's an onsite item
} else {
item = this.attachOnsiteDeliveryInfo(item)
item = DeliveryLocationsResolver.attachOnsiteDeliveryInfo(item)
}
// Establish default for Electronic Document Delivery flag:
item.eddRequestable = !!item.eddRequestable
const filteredDeliveryLocationsWithScholarRoom = this.filterLocations(item.deliveryLocation, scholarRoom)
item.deliveryLocation = this.formatLocations(filteredDeliveryLocationsWithScholarRoom)
const filteredDeliveryLocationsWithScholarRoom = DeliveryLocationsResolver.filterLocations(item.deliveryLocation, scholarRoom)
item.deliveryLocation = DeliveryLocationsResolver.formatLocations(filteredDeliveryLocationsWithScholarRoom)
return item
})
})
Expand Down
29 changes: 20 additions & 9 deletions lib/requestability_resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,57 @@ const DeliveryLocationsResolver = require('./delivery-locations-resolver')
const { isItemNyplOwned } = require('./ownership_determination')
const { isInRecap } = require('./util')
const logger = require('./logger')

class RequestabilityResolver {
static fixItemRequestability (elasticSearchResponse) {
elasticSearchResponse.hits.hits
.forEach((hit) => {
const parentBibHasFindingAid = !!hit._source.supplementaryContent?.find((el) => el.label.toLowerCase() === 'finding aid')
hit._source.items = hit._source.items.map((item) => {
if (item.electronicLocator) return item
let deliveryInfo
const itemIsInRecap = isInRecap(item)
let physRequestableCriteria
const hasRecapCustomerCode = item.recapCustomerCode && item.recapCustomerCode[0]
const hasRecapCustomerCode = item.recapCustomerCode?.[0]
if (itemIsInRecap) {
// recap items missing codes should default to true for phys and edd
// requestable, unless it has a non-requestable holding location
deliveryInfo = DeliveryLocationsResolver.getRecapDeliveryInfo(item)
physRequestableCriteria = hasRecapCustomerCode
? `${(deliveryInfo.deliveryLocation &&
deliveryInfo.deliveryLocation.length) || 0} delivery locations.`
? `${(deliveryInfo.deliveryLocation?.length) || 0} delivery locations.`
: 'Missing customer code'
} else if (!itemIsInRecap) {
deliveryInfo = DeliveryLocationsResolver.getOnsiteDeliveryInfo(item)
physRequestableCriteria = `${(deliveryInfo.deliveryLocation &&
deliveryInfo.deliveryLocation.length) || 0} delivery locations.`
physRequestableCriteria = `${(deliveryInfo.deliveryLocation?.length) || 0} delivery locations.`
}
item.eddRequestable = !!deliveryInfo.eddRequestable
item.physRequestable = !!(deliveryInfo.deliveryLocation &&
deliveryInfo.deliveryLocation.length)
item.specRequestable = !!item.aeonUrl
item.specRequestable = this.buildSpecRequestable(item, parentBibHasFindingAid)
item.physRequestable = !!deliveryInfo.deliveryLocation?.length
item.eddRequestable = !!deliveryInfo.eddRequestable && !item.specRequestable
// items without barcodes should not be requestable
const hasBarcode = (item.identifier || []).some((identifier) => /^(urn|bf):[bB]arcode:\w+/.test(identifier))
if (isItemNyplOwned(item) && !hasBarcode) {
physRequestableCriteria = 'NYPL item missing barcode'
item.physRequestable = false
}
if (item.specRequestable && item.physRequestable) {
item.physRequestable = false
physRequestableCriteria = 'specRequestable overrides physRequestable location'
}
logger.debug(`item ${item.uri}: `, { physRequestable: item.physRequestable, physRequestableCriteria })
item.requestable = [item.eddRequestable || item.physRequestable || item.specRequestable]
console.log({ specRequestable: item.specRequestable, physRequestable: item.physRequestable, eddRequestable: item.eddRequestable, physRequestableCriteria })
return item
})
})
return elasticSearchResponse
}

static buildSpecRequestable (item, parentBibHasFindingAid) {
const holdingLocation = DeliveryLocationsResolver.extractLocationCode(item)
const nyplCoreLocation = DeliveryLocationsResolver.nyplCoreLocation(holdingLocation)
const isSpecialCollectionsOnlyAccessType = !!(nyplCoreLocation?.collectionAccessType === 'special')
return !!item.aeonUrl || parentBibHasFindingAid || isSpecialCollectionsOnlyAccessType
}
}

module.exports = RequestabilityResolver
152 changes: 152 additions & 0 deletions test/fixtures/specRequestable/findingAid-es-response.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
module.exports = () => {
return {
_shards: {
failed: 0,
successful: 1,
total: 1
},
took: 1,
hits: {
total: 1,
max_score: 1.3862944,
hits: [
{
_id: 'b10980129',
_source: {
supplementaryContent: [{
label: 'Finding aid',
url: 'spaghetti.com'
}],
items: [
{
holdingLocation: [
{
label: 'OFFSITE - Request in Advance',
id: 'loc:rc2ma'
}
],
status_packed: [
'status:na||Not Available'
],
owner: [
{
id: 'orgs:1000',
label: 'Stephen A. Schwarzman Building'
}
],
deliveryLocation: [
{
id: 'loc:mala',
label: 'SASB - Allen Scholar Room'
}
],
deliveryLocation_packed: [
'loc:mala||SASB - Allen Scholar Room'
],
uri: 'i10283664',
accessMessage_packed: [
'accessMessage:2||ADV REQUEST'
],
accessMessage: [
{
id: 'accessMessage:2',
label: 'ADV REQUEST'
}
],
status: [
{
id: 'status:na',
label: 'Not available'
}
],
owner_packed: [
'orgs:1000||Stephen A. Schwarzman Building'
],
requestable: [
false
],
identifier: [
'urn:barcode:1000546836'
],
holdingLocation_packed: [
'loc:rc2ma||OFFSITE - Request in Advance'
],
shelfMark: [
'*OFC 90-2649'
],
suppressed: [
false
]
},
{
holdingLocation: [
{
label: 'OFFSITE - Request in Advance',
id: 'loc:rc2ma'
}
],
status_packed: [
'status:a||Available'
],
owner: [
{
id: 'orgs:1000',
label: 'Stephen A. Schwarzman Building'
}
],
deliveryLocation: [
{
id: 'loc:mala',
label: 'SASB - Allen Scholar Room'
}
],
deliveryLocation_packed: [
'loc:mala||SASB - Allen Scholar Room'
],
uri: 'i102836649',
accessMessage_packed: [
'accessMessage:2||ADV REQUEST'
],
accessMessage: [
{
id: 'accessMessage:2',
label: 'ADV REQUEST'
}
],
status: [
{
id: 'status:a',
label: 'Available'
}
],
owner_packed: [
'orgs:1000||Stephen A. Schwarzman Building'
],
requestable: [
false
],
identifier: [
'urn:barcode:10005468369'
],
holdingLocation_packed: [
'loc:rc2ma||OFFSITE - Request in Advance'
],
shelfMark: [
'*OFC 90-2649 2'
],
suppressed: [
false
]
}
]

},
_type: 'resource',
_index: 'resources-2017-06-13',
_score: 154.93451
}
]
},
timed_out: false
}
}
Loading

0 comments on commit 7b79f1e

Please sign in to comment.