diff --git a/app/assets/stylesheets/modules/requests.scss b/app/assets/stylesheets/modules/requests.scss index 5983b599..f7012c72 100644 --- a/app/assets/stylesheets/modules/requests.scss +++ b/app/assets/stylesheets/modules/requests.scss @@ -3,3 +3,7 @@ width: auto; } } +.illiad-link { + padding: 6px 12px 6px 0px; + font-size: 1rem; +} diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb index e8649422..a1f10382 100644 --- a/app/controllers/requests_controller.rb +++ b/app/controllers/requests_controller.rb @@ -6,7 +6,7 @@ class RequestsController < ApplicationController before_action :authorize_update!, except: :index rescue_from RequestException, with: :deny_access - # Renders user requests from FOLIO and/or BorrowDirect + # Renders user requests from FOLIO, BorrowDirect, and/or ILLIAD # # GET /requests # GET /requests.json diff --git a/app/models/borrow_direct_requests.rb b/app/models/borrow_direct_requests.rb index 89c7eaaf..f412fe59 100644 --- a/app/models/borrow_direct_requests.rb +++ b/app/models/borrow_direct_requests.rb @@ -66,5 +66,7 @@ def ready_for_pickup? def to_partial_path 'requests/borrow_direct_request' end + + def manage_request_link; end end end diff --git a/app/models/borrow_direct_reshare_requests.rb b/app/models/borrow_direct_reshare_requests.rb index 1dba98a3..78a1955c 100644 --- a/app/models/borrow_direct_reshare_requests.rb +++ b/app/models/borrow_direct_reshare_requests.rb @@ -112,5 +112,7 @@ def title def to_partial_path 'requests/borrow_direct_request' end + + def manage_request_link; end end end diff --git a/app/models/folio/patron.rb b/app/models/folio/patron.rb index 264f9b89..f024e6a4 100644 --- a/app/models/folio/patron.rb +++ b/app/models/folio/patron.rb @@ -166,9 +166,9 @@ def group_checkouts all_checkouts.select(&:proxy_checkout?) end - # Self requests + # Self requests: Combines data from FOLIO, borrow direct, and ILLIAD def requests - @requests ||= folio_requests.reject(&:proxy_request?) + borrow_direct_requests + @requests ||= folio_requests.reject(&:proxy_request?) + borrow_direct_requests + illiad_requests end # Requests from the proxy group @@ -176,6 +176,11 @@ def group_requests folio_requests.select(&:proxy_request?) if sponsor? end + # ILLIAD requests are retrieved separately + def illiad_requests + @illiad_requests ||= IlliadRequests.new(user_info['username']).requests + end + def to_partial_path return 'patron/expired' if expired? return 'patron/fee_borrower' if fee_borrower? diff --git a/app/models/folio/request.rb b/app/models/folio/request.rb index d679af60..50b5af64 100644 --- a/app/models/folio/request.rb +++ b/app/models/folio/request.rb @@ -138,6 +138,8 @@ def date_sort_key ] end + def manage_request_link; end + private def library_key diff --git a/app/models/illiad_requests.rb b/app/models/illiad_requests.rb new file mode 100644 index 00000000..85f99ea1 --- /dev/null +++ b/app/models/illiad_requests.rb @@ -0,0 +1,121 @@ +# frozen_string_literal: true + +### +# Class to handle creation of ILLiad OpenURL request +### +class IlliadRequests + def initialize(user_id) + @user_id = user_id + end + + def requests + request_user_transactions.map do |illiad_result| + IlliadRequests::Request.new(illiad_result) + end + rescue StandardError => e + Honeybadger.notify(e, error_message: "Unable to retrieve ILLIAD transactions with #{e}") + [] + end + + private + + def request_user_transactions + url = "#{Settings.sul_illiad}ILLiadWebPlatform/Transaction/UserRequests/#{@user_id}" + conn = Faraday.new(url: Settings.sul_illiad) do |req| + req.headers['ApiKey'] = Settings.illiad_api_key + req.headers['Accept'] = 'application/json; version=1' + req.adapter Faraday.default_adapter + end + + response = conn.get(url) + JSON.parse(response.body) + end + + class Request + # illiad_result is a hash with the results from the Illiad Request + def initialize(illiad_result) + @illiad_result = illiad_result + end + + def scan_type? + @illiad_result['PhotoJournalTitle'].present? + end + + def key + @illiad_result['TransactionNumber'].to_s + end + + # rubocop:disable Metrics/MethodLength + def sort_key(key) + sort_key = case key + when :library + [pickup_library, title, author, call_number] + when :date + [*date_sort_key, title, author, call_number] + when :title + [title, author, call_number] + when :author + [author, title, call_number] + when :call_number + [call_number] + end + sort_key.join('---') + end + # rubocop:enable Metrics/MethodLength + + def date_sort_key + (expiration_date || Folio::Request::END_OF_DAYS).strftime('%FT%T') + end + + def title + scan_type? ? @illiad_result['PhotoJournalTitle'] : @illiad_result['LoanTitle'] + end + + def call_number + @illiad_result['CallNumber'] + end + + def author + scan_type? ? @illiad_result['PhotoArticleAuthor'] : @illiad_result['LoanAuthor'] + end + + def placed_date + Time.zone.parse(@illiad_result['CreationDate']) + end + + def pickup_library + @illiad_result['ItemInfo4'] + end + + def expiration_date + scan_type? ? placed_date + 2.months : Time.zone.parse(@illiad_result['NotWantedAfter']) + end + + def fill_by_date; end + + def ready_for_pickup? + ready_for_pickup_status = ['Media Microtext Checkout to Customer', + 'Special Collections Checked Out to Customer', + 'Customer Notified via E-Mail'] + ready_for_pickup_status.include?(@illiad_result['TransactionStatus']) + end + + def from_ill? + true + end + + def service_point_name + Mylibrary::Application.config.library_map[pickup_library] || pickup_library + end + + def waitlist_position; end + + def to_partial_path + 'requests/request' + end + + def manage_request_link + "https://sulils.stanford.edu/illiad.dll?Action=10&Form=72&Value=#{key}" + end + end +end diff --git a/app/views/requests/_request.html.erb b/app/views/requests/_request.html.erb index 527595cf..31d2841c 100644 --- a/app/views/requests/_request.html.erb +++ b/app/views/requests/_request.html.erb @@ -10,7 +10,6 @@ <% else %> Deliver to <%= request.service_point_name %> <% end %> - <% if request.expiration_date %>
@@ -40,17 +39,23 @@
<% if patron.can_modify_requests? %> - <% if request.ready_for_pickup? %> - <%= form_tag request_path(request.key), method: :delete do %> - <%= hidden_field_tag :title, request.title %> - <%= hidden_field_tag :group, params[:group] if params[:group] %> - <%= button_tag class: 'btn btn-link btn-request-cancel btn-icon-prefix', type: 'submit' do %> - <%= sul_icon 'outline-cancel-24px' %> Cancel this request - <% end %> - <% end %> + <% if request.manage_request_link %> + <% else %> - <%= link_to edit_request_path(request.key, group: params[:group]), data: { 'mylibrary-modal' => 'trigger', 'convert-button' => true } do %> - <%= sul_icon 'outline-cancel-24px' %> Change or cancel this request + <% if request.ready_for_pickup? %> + <%= form_tag request_path(request.key), method: :delete do %> + <%= hidden_field_tag :title, request.title %> + <%= hidden_field_tag :group, params[:group] if params[:group] %> + <%= button_tag class: 'btn btn-link btn-request-cancel btn-icon-prefix', type: 'submit' do %> + <%= sul_icon 'outline-cancel-24px' %> Cancel this request + <% end %> + <% end %> + <% else %> + <%= link_to edit_request_path(request.key, group: params[:group]), data: { 'mylibrary-modal' => 'trigger', 'convert-button' => true } do %> + <%= sul_icon 'outline-cancel-24px' %> Change or cancel this request + <% end %> <% end %> <% end %> <% end %> @@ -65,10 +70,12 @@
Requested:
<%= l(request.placed_date, format: :short) %>
<% end %> -
Waitlist position:
-
<%= request.waitlist_position %>
+ <% if request.waitlist_position %> +
Waitlist position:
+
<%= request.waitlist_position %>
+ <% end %>
Source:
-
<%= library_name request.library %>
+
<%= request.is_a?(IlliadRequests::Request) ? 'Interlibrary Loan' : library_name(request.library) %>
<%= detail_link_to_searchworks(request.catkey) unless request.from_ill? %> diff --git a/config/settings.yml b/config/settings.yml index 8175c1d1..65c90d6c 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -46,6 +46,10 @@ borrow_direct_reshare: BORROW_DIRECT_CODE: BORROW_DIRECT ILL_CODE: ILL +# Adding Illiad +sul_illiad: https://sul-illiad-test.stanford.edu/ +illiad_api_key: 'AbC123' + purl: url: https://purl.stanford.edu diff --git a/spec/models/illiad_requests_spec.rb b/spec/models/illiad_requests_spec.rb new file mode 100644 index 00000000..a657fe71 --- /dev/null +++ b/spec/models/illiad_requests_spec.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe IlliadRequests do + subject(:ill_request) { described_class.new(patron_sunet_id) } + + let(:patron_sunet_id) { 'sunet' } + let(:hold_recall_result) do + '{"TransactionNumber":347070, + "Username":"sunet", + "LoanAuthor":"Gilbert Roy", + "LoanTitle":"Disney Motion Pictures", + "CreationDate":"2023-10-11T10:49:41.783", + "ItemInfo4":"GREEN", + "NotWantedAfter":"2024-10-11", + "CallNumber":"ABC"}' + end + let(:scan_result) do + '{"TransactionNumber":12345, + "Username":"sunet", + "PhotoArticleAuthor":"Frederick Wright", + "PhotoJournalTitle":"String Beans", + "CreationDate":"2023-10-12T10:49:41.783", + "ItemInfo4":"GREEN", + "CallNumber":"DEF"}' + end + let(:transaction_results) do + "[#{hold_recall_result},#{scan_result}]" + end + + context 'when successful, it correctly retrieves transaction requests' do + before do + stub_request(:get, "#{Settings.sul_illiad}ILLiadWebPlatform/Transaction/UserRequests/#{patron_sunet_id}") + .to_return(status: 200, body: transaction_results, headers: {}) + end + + it 'correctly returns request objects' do + expect(ill_request.requests.length).to be(2) + end + end + + describe 'IlliadRequests::Request' do + context 'when the request is ILLIAD hold/recall' do + subject(:hold) { IlliadRequests::Request.new(JSON.parse(hold_recall_result)) } + + it 'correctly identified hold recall result as not being type scan' do + expect(hold.scan_type?).to be(false) + end + + it 'correctly retrieves title for non-scan transaction' do + expect(hold.title).to eq('Disney Motion Pictures') + end + + it 'correctly retrieves author for non-scan transaction' do + expect(hold.author).to eq('Gilbert Roy') + end + end + + context 'when the request is an ILLIAD scan request' do + subject(:scan) { IlliadRequests::Request.new(JSON.parse(scan_result)) } + + it 'correctly identified scan result as type scan' do + expect(scan.scan_type?).to be(true) + end + + it 'correctly retrieves title for scan transaction' do + expect(scan.title).to eq('String Beans') + end + + it 'correctly retrieves author for scan transaction' do + expect(scan.author).to eq('Frederick Wright') + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f44e85be..a6a1875a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -105,5 +105,7 @@ stub_request(:any, %r{example.com/symws}).to_rack(FakeSymphony) stub_request(:any, /rc\.relais-host\.com/).to_return(status: 200) stub_request(:any, 'https://github.com/sul-dlss/global-alerts/raw/main/sul.yaml').to_return(status: 200) + stub_request(:get, /#{Settings.sul_illiad}/) + .to_return(status: 200, body: '[]', headers: {}) end end diff --git a/spec/views/requests/_request.html.erb_spec.rb b/spec/views/requests/_request.html.erb_spec.rb index 1e918e2e..0981fed7 100644 --- a/spec/views/requests/_request.html.erb_spec.rb +++ b/spec/views/requests/_request.html.erb_spec.rb @@ -21,6 +21,7 @@ title: 'A Book', waitlist_position: nil, patron_key: 'patronkey123', + manage_request_link: nil, **request_attributes ) end