SPIKE: MODKBEKBJ-489 & MODKBEKBJ-484- Investigate Cost Per Use Controller API
- Sobha Duvvuri
- Khalilah Gambrell
MODKBEKBJ-489
-
Getting issue details...
STATUS
MODKBEKBJ-484
-
Getting issue details...
STATUS
Khalilah provided mockups for displaying cost per use and usage information within eHoldings. This spike is to figure out if cost per use API provided by EBSCO gives all the information we need to be able to display cost per use and usage at package, title and resource(package-title) level in eHoldings.
Link to Swagger API docs - http://10.26.134.65:32768/swagger-ui.html#/
There are three endpoints provided by Cost-per-use Controller API. APIGEE will be used to proxy requests to cost-per-use controller. More details here
Endpoints to be used:
1. Get token to be passed to APIGEE:
This method of getting APIGEE token is the same for all endpoints of cost-per-use controller.
POST https://apis.ebsco.com/oauth-proxy/token
Sample Request -
curl --location --request POST 'https://apis.ebsco.com/oauth-proxy/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_id=XXXX' \ --data-urlencode 'client_secret=XXXX'
Sample Response -
{ "access_token": "XXXX", "token_type": "Bearer", "expires_in": 3600, "scope": "openid" }
2. Get cost-per-use and usage information for a package:
Mockup - https://drive.google.com/file/d/1oWvhXBeE58KEoxkiaWYsBsKI6LqK8oaB/view?usp=sharing
GET https://apis.ebsco.com/uc/costperuse/package/<package_id>
Sample request:
curl --location --request GET 'https://apis.ebsco.com/uc/costperuse/package/473?fiscalYear=2019&fiscalMonth=Jul&analysisCurrency=AUD&aggregatedFullText=false' \ --header 'custkey: <Encrypted CUSTID to be passed to APIGEE>' \ --header 'Authorization: Bearer <TOKEN OBTAINED in STEP 1 above>'
Sample response:
{ "usage": { "platforms": { "ScienceDirect": { "counts": [ 0, 2, 5, 2, 0, 0, 48, 30, 11, 26, 7, null ], "publisherPlatform": true }, "Taylor & Francis": { "counts": [ 0, ... truncated for brevity ], "publisherPlatform": true }, "BioOne": { "counts": [ 2, null, null, ... truncated for brevity ], "publisherPlatform": false }, ....truncated for brevity } }, "analysis": { "current": { - for the year selected "cost": DOLLARS.CENTS,(or equivalent currency based on what's selected in config) "usage": 221126, - total usage is controlled by aggregatedfulltext - true/false "costPerUse": 0.052733222687517525 }, "previous": { - for the previous year "cost": 12905.393325, "usage": 189462, "costPerUse": 0.06811599859074642 } } }
Details needed by mockup:
1. Fiscal Year - Will be selected in drop-down and passed to backend - this can be passed to api
2. Publisher Platform Dropdown Values - Publisher, Non-Publisher, ALL - Khalilah to decide whether this will be in Settings → eHoldings → Usage Consolidation → PublisherPlatform or package level or both where package level setting overrides the Settings level selection [ Sobha DuvvuriKG: There will be a Default Platform display setting: values will be Publisher Platform only, Non-Publisher Platform only, All. Default selection will be All. When a user is on a package/title-package/title record, s/he can override the default setting with the Filter by platforms - filter.]
2. Publisher Platform(s) - List returned by API response in this endpoint above.
Based on selected value for PublisherPlatform,
if Publisher - we extract usage.platforms.<keys> where publisherPlatform = true
if Non-Publisher - we extract usage.platforms.<keys> where publisherPlatform = false
if ALL is selected - we extract usage.platforms.<keys> where publisherPlatform = true/false
3. Package Cost - analysis.current.cost - we do not have to make any currency conversions because based on query param - 'analysisCurrency' - the correct value is returned
Use analysis.current.cost if its returned in response - If we do not get cost information in response, then we need to compute the value per below
a. Get list of all titles within the package
b. Use the bulk fetch endpoint to fetch all package-title's(resources) information - Sample response below:
{ "356.473": { "current": { "cost": 141.8806, "usage": 26, "costPerUse": 5.456946153846153 }, "previous": { "usage": 52 } }, "491.473": { "current": { "cost": 100.0, "usage": 15, "costPerUse": 6.666666666666667 }, "previous": { "cost": 83.343325, "usage": 74, "costPerUse": 1.1262611486486485 } } }
c. Total package cost = sum of costs of all individual titles within a package - In example response above → "356.473".current.cost + "491.473".current.cost + ...........(for all titles selected within the package)
4. Platform(s) Usage - analysis.current.usage -
if Publisher - we extract analysis.current.usage by passing query parameter 'aggregatedFullText' = false
if Non-Publisher - we extract analysis.current.usage by passing query parameter 'aggregatedFullText' = true
if ALL is selected - we make 2 requests - one by passing 'aggregatedFullText' = true, 2nd by passing 'aggregatedFullText' = false, get analysis.current.usage from both requests and sum them up
5. Cost per use -
if Publisher - we extract analysis.current.costPerUse by passing query parameter 'aggregatedFullText' = false if costPerUse information is provided in response - else we compute it as 3.(Package cost)/4.(Platform(s) usage)
if Non-Publisher - we extract analysis.current.costPerUse by passing query parameter 'aggregatedFullText' = true if costPerUse information is provided in response - else we compute it as 3.(Package cost)/4.(Platform(s) usage)
if ALL is selected - we compute it as 3.(Package cost)/4.(Platform(s) usage)
6. % of budget, Fund Code(s) and PO(s) are not provided by API and are not targeted for initial release
7. Rest of mockup contains list of titles and cost-per-use info for titles which will be covered in next section.
3. Cost-per-use and usage for a list of resources(package-titles) to display on a package record:
Mockup - https://drive.google.com/file/d/1oWvhXBeE58KEoxkiaWYsBsKI6LqK8oaB/view?usp=sharing
POST https://apis.ebsco.com/uc/costperuse/titles
Sample request -
curl --location --request POST 'https://apis.ebsco.com/uc/costperuse/titles?fiscalYear=2019&fiscalMonth=Jul&analysisCurrency=AUD&publisherPlatform=true&previousYear=true' \ --header 'custkey: XXXX' \ --header 'Authorization: Bearer XXXX' \ --header 'Content-Type: application/json' \ --data-raw '[ { "kbid": 356, --> title id "listId": 473 --> package id }, { "kbid": 491, "listId": 473 } ]'
Sample response -
{ "356.473": { "current": { "cost": 141.8806, "usage": 26, "costPerUse": 5.456946153846153 }, "previous": { "usage": 52 } }, "491.473": { "current": { "cost": 100.0, "usage": 15, "costPerUse": 6.666666666666667 }, "previous": { "cost": 83.343325, "usage": 74, "costPerUse": 1.1262611486486485 } } }
Details needed by mockup:
- List of selected titles that belong to a package - UI already has a way to get the list of titles associated with a package
- Get the list of titles from 1. and make a request to the endpoint above passing in currency and publisher platform - publisherPlatform can be "publisher" , "non-publisher" or "All"
- Title - Name of resource - we will not get this from cost-per-use api - we'll have to use existing HoldingsIQ endpoint for this and we already populate it in UI
- Type - Publication type of resource - we will not get this from cost-per-use api - we'll have to use existing HoldingsIQ endpoint for this and we already populate it in UI
- Cost - <titleid.packageid>.current.cost
- Usage - <titleid.packageid>.current.usage
- If 'publisherPlatform' = true - we'll pass the query param 'publisherPlatform' = true
- If 'publisherPlatform' = false - we'll pass the query param 'publisherPlatform' = false
- If 'publisherPlatform' = ALL - we'll have to make 2 requests with 'publisherPlatform' = true and 'publisherPlatform' = false and sum up individual package-titles usage -
for example: <titleid.packageid>.current.usage when 'publisherPlatform' = true and 'publisherPlatform' = false
- Cost Per Use - <titleid.packageid>.current.costPerUse
- If 'publisherPlatform' = true - we'll pass the query param 'publisherPlatform' = true and extract <titleid.packageid>.current.costPerUse
- If 'publisherPlatform' = false - we'll pass the query param 'publisherPlatform' = false and extract <titleid.packageid>.current.costPerUse
- If 'publisherPlatform' = ALL - 5.(Cost)/6.(Usage) - Note that we could use this same formula for a. and b. above instead of using costPerUse info that we get from response
- % of usage - looks like (Usage returned in 6. above divided by Platform(s) usage(2.4 in previous block)) * 100 - Khalilah to clarify with kimie [ Sobha Duvvuri, KG: % of usage represents percentage of usage for the title in the package across all selected titles in a package usage OR total package usage for the selected fiscal year/filter platform selection. We will revise the mockup to align.] - Update: After kimie revised the mockups, the formula used is correct - % of usage = (Usage returned in 6. above divided by Platform(s) usage(2.4 in previous block)) * 100 and the percentage is rounded to the nearest integer.
4. Get cost-per use and usage for a package-title(Reource) record:
Mockup: https://drive.google.com/file/d/1ttgxYvr7bzRYf47DaGU4vgWn0EkbwZ1f/view?usp=sharing
Endpoint: GET https://apis.ebsco.com/uc/costperuse/title/<titleId>/<packageId>
Sample Request:
curl --location --request GET 'https://apis.ebsco.com/uc/costperuse/title/356/473?fiscalYear=2019&fiscalMonth=Jul&analysisCurrency=AUD&aggregatedFullText=false' \ --header 'custkey: <encrypted cust id>' \ --header 'Authorization: Bearer <auth token>'
Sample Response:
{ "usage": { "platforms": { "Wiley Online Library": { "counts": [ 0, 1, 3, 1, 3, 1, 16, 1, null, null, null, null ], "publisherPlatform": true }, "EBSCOhost": { "counts": [ 2, null, 1, null, null, null, 3, 4, null, null, null, null ], "publisherPlatform": false } } }, "analysis": { "current": { "cost": 141.8806, "usage": 26, "costPerUse": 5.456946153846153 }, "previous": { "usage": 52 } } }
Details needed by mockup:
Fiscal Year - Will be selected in drop-down and passed to backend - this can be passed to api
Publisher Platform Dropdown Values - Publisher, Non-Publisher, ALL - Khalilah to decide whether this will be in Settings → eHoldings → Usage Consolidation → PublisherPlatform or package-title level or both where package-title level setting overrides the Settings level selection [ Sobha DuvvuriKG: There will be a Default Platform display setting: values will be Publisher Platform only, Non-Publisher Platform only, All. Default selection will be All. When a user is on a package/title-package/title record, s/he can override the default setting with the Filter by platforms - filter.]
Publisher Platform(s) - List returned by API response in this endpoint above.
Based on selected value for PublisherPlatform,
if Publisher - we extract usage.platforms.<keys> where publisherPlatform = true
if Non-Publisher - we extract usage.platforms.<keys> where publisherPlatform = false
if ALL is selected - we extract usage.platforms.<keys> where publisherPlatform = true/false
- Cost - analysis.current.cost
- Platform(s) usage - analysis.current.usage
if Publisher - we extract analysis.current.usage by passing query parameter 'aggregatedFullText' = false
if Non-Publisher - we extract analysis.current.usage by passing query parameter 'aggregatedFullText' = true
if ALL is selected - we make 2 requests - one by passing 'aggregatedFullText' = true, 2nd by passing 'aggregatedFullText' = false, get analysis.current.usage from both requests and sum them up
- Cost per use - 4.(cost)/ 5.(platform(s) usage)
- % of budget, PO Lines and Fund Code are not supported for initial release
Full Text Requests:
- Publishers Platforms column - usage.platforms.keys - might have to filter based on "publisherPlatform" being 'Publisher', 'Non-publisher' or 'ALL'
- Usage for each publisher platform per month is given in response above - usage.platforms.keys.counts - usage.platforms.keys.counts[0] starts with 'fiscalMonth' passed in query parameter
- Total Count for each publisher platform(each row total) - sum of counts of usage.platforms.keys.counts
- Total Usage for all Publisher/Non-Publisher/ALL Platforms(Based on selection) - For each month for example -
- First filter result set to include objects based on "publisherPlatform"
- Ex: January = usage.platforms.key1.counts[0] + usage.platforms.key2.counts[0] + .....
- Ex: February = usage.platforms.key1.counts[1] + usage.platforms.key2.counts[1] + .....
- Final total for all months = Sum of total usage computed in 4. for all months - For Ex: January total usage + February total usage + ...... Dec total usage - To confirm with khalilah reg mockup values [ Sobha DuvvuriKG: will revise mockup but that total represents total for all months.] - Update - After mockup has been revised, numbers now match and formula in 5. is correct.
5. Get cost-per-use and usage information for a title record:
Mockup: https://drive.google.com/drive/folders/1yQdqZymj8UQ1iLOtcEYX67kYm0DZVkJV
Endpoint: GET https://apis.ebsco.com/uc/costperuse/title/<titleId>/<packageId>
Sample Request:
curl --location --request GET 'https://apis.ebsco.com/uc/costperuse/title/356/473?fiscalYear=2019&fiscalMonth=Jul&analysisCurrency=AUD&aggregatedFullText=false' \ --header 'custkey: <encrypted cust id>' \ --header 'Authorization: Bearer <auth token>'
Sample Response:
{ "usage": { "platforms": { "Wiley Online Library": { "counts": [ 0, 1, 3, 1, 3, 1, 16, 1, null, null, null, null ], "publisherPlatform": true }, "EBSCOhost": { "counts": [ 2, null, 1, null, null, null, 3, 4, null, null, null, null ], "publisherPlatform": false } } }, "analysis": { "current": { "cost": 141.8806, "usage": 26, "costPerUse": 5.456946153846153 }, "previous": { "usage": 52 } } }
Details needed by mockup:
Fiscal Year - Will be selected in drop-down and passed to backend - this can be passed to api
Publisher Platform Dropdown Values - Publisher, Non-Publisher, ALL - Khalilah to decide whether this will be in Settings → eHoldings → Usage Consolidation → PublisherPlatform or title level or both where title level setting overrides the Settings level selection [ Sobha DuvvuriKG: There will be a Default Platform display setting: values will be Publisher Platform only, Non-Publisher Platform only, All. Default selection will be All. When a user is on a package/title-package/title record, s/he can override the default setting with the Filter by platforms - filter.]
- Table 1 - Holdings Summary table
- Text in Column 1 of table 1 is going to be name of the packages that this title is selected in - we need to get list of packages that this title is selected in to populate these values in table.
- Text in Column 2 of table 2 is coverage details - currently, we have a way to figure out coverage settings of a resource(either managed/custom coverage) as shown in the screenshot below using resources endpoint of MODKBEKBJ - Display the coverage details of the resource in this column
- Title Cost - analysis.current.cost from response - 0 if not given in response
- Usage - analysis.current.usage from response
- Cost Per Use - c./d. - cost in c divided by usage in e.
- Table 2 - Full text request by platform usage
- Platform - usage.platforms.<keys> based on 'publisherPlatform' selection
- Counts Jan - Dec - usage.platforms.<keys>.counts based on 'publisherPlatform' selection
- Total at the end of each row - Sum of b. above for each platform
- Publisher - usage.platforms.<keys>.publisherPlatform - true/false
- All Publisher platforms total - where usage.platforms.<keys>.publisherPlatform = true
- for Jan for example - usage.platforms.<key1>.counts[0] + usage.platforms.<key2>.counts[0] + ......
- for Feb for example - usage.platforms.<key1>.counts[1] + usage.platforms.<key2>.counts[1] + ......
- Total for example - Jan + Feb + .... + Dec
- All non-publisher platforms total - where usage.platforms.<keys>.publisherPlatform = false
- for Jan for example - usage.platforms.<key1>.counts[0] + usage.platforms.<key2>.counts[0] + ......
- for Feb for example - usage.platforms.<key1>.counts[1] + usage.platforms.<key2>.counts[1] + ......
- Total for example - Jan + Feb + .... + Dec
- All platforms - irrespective of publisher platform
- for Jan for example - usage.platforms.<key1>.counts[0] + usage.platforms.<key2>.counts[0] + ......
- for Feb for example - usage.platforms.<key1>.counts[1] + usage.platforms.<key2>.counts[1] + ......
- Total for example - Jan + Feb + .... + Dec
Note:
title record in eHoldings is a detailed view based on kbid(titleid) only and gives list of packages that the title belongs to on the title record - a title is always associated with at least one package.
Cost-per-use API provides cost and usage information only for a title associated with a package.From the list of packages listed on a title record, we can pass any package id along with title id to get usage information for a title.
See examples below:
Request for titleid = 50974 within package id 34
curl --location --request GET 'https://apis.ebsco.com/uc/costperuse/title/50974/34?fiscalYear=2019&fiscalMonth=Jan&analysisCurrency=AUD&aggregatedFullText=true' \ --header 'custkey: 1234-5678' \ --header 'Authorization: Bearer token'
Response:
{ "usage": { "platforms": { "EBSCOhost": { "counts": [ 22, 37, 35, 53, 19, 16, 11, 4, 31, 52, null, null ], "publisherPlatform": false } } }, "analysis": { "current": { "usage": 280 }, "previous": { "usage": 379 } } }
Request for title id = 50974 within package id 667
curl --location --request GET 'https://apis.ebsco.com/uc/costperuse/title/50974/667?fiscalYear=2019&fiscalMonth=Jan&analysisCurrency=AUD&aggregatedFullText=true' \ --header 'custkey: 1234-5678' \ --header 'Authorization: Bearer token'
Response:
{ "usage": { "platforms": { "EBSCOhost": { "counts": [ 22, 37, 35, 53, 19, 16, 11, 4, 31, 52, null, null ], "publisherPlatform": false } } }, "analysis": { "current": { "usage": 280 }, "previous": { "usage": 379 } } }
Notice how irrespective of package associated with a title, the usage counts are the same and are at a platform level.
6. Get metric type associated with a custid
CostPerUse team is developing a separate endpoint to support this. Earlier, the decision was to add this information to HoldingsIQ /custid endpoint but that decision has changed due to difficulties in architecture.
Endpoint: GET https://apis.ebsco.com/uc/usageanalysis/analysisMetricType
Sample Request:
curl --location --request GET 'https://apis.ebsco.com/uc/usageanalysis/analysisMetricType' \ --header 'custkey: <encrypted cust id>' --header 'Authorization: Bearer token'
Sample Response:
{ "metricTypeId": 36, "description": "string" }
- In the above response, metric type id can be either 36 or 33
33 is Total Item Requests
36 is Unique Item Requests
- If a customer is not signed up for UC, we'll get a 200 but an empty object for response.
- Please note that this endpoint has been released and is ready for consumption.