• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / orangelight / 6986da6d-cd09-49a7-b0a9-9fd235638daa

23 Oct 2025 01:27PM UTC coverage: 95.297% (-0.002%) from 95.299%
6986da6d-cd09-49a7-b0a9-9fd235638daa

Pull #5260

circleci

christinach
Remove no_services?
This was added during Covid when the library was closed.

related to [#5236]
Pull Request #5260: Remove no_services?

1 of 1 new or added line in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

6079 of 6379 relevant lines covered (95.3%)

1514.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.48
/app/helpers/requests/application_helper.rb
1
# frozen_string_literal: true
2
# rubocop:disable Metrics/ModuleLength
3
module Requests
3✔
4
  module ApplicationHelper
3✔
5
    def format_label(key)
3✔
6
      label = key.to_s
×
7
      human_label = label.tr('_', ' ')
×
8
      formatted = human_label.split.map(&:capitalize).join(' ')
×
9
      formatted
×
10
    end
11

12
    def error_key_format(key)
3✔
13
      keys_to_ignore = ['items']
×
14
      format_label(key) unless keys_to_ignore.include? key.to_s
×
15
    end
16

17
    # array of error_keys
18
    def guest_user_error?(error_keys)
3✔
19
      user_errors = [:email, :user_name, :barcode]
×
20
      error_keys.any? { |item| user_errors.include? item }
×
21
    end
22

23
    def show_pick_up_service_options(requestable, mfhd_id)
3✔
24
      if requestable.on_shelf?
142✔
25
        display_on_shelf(requestable, mfhd_id)
70✔
26
      else
27
        display_requestable_list(requestable)
71✔
28
      end
29
    end
30

31
    # :reek:FeatureEnvy
32
    def show_service_options(requestable, _mfhd_id)
3✔
33
      if requestable.charged? && !requestable.aeon? && !requestable.ask_me?
2✔
34
        render partial: 'checked_out_options', locals: { requestable: }
1✔
35
      else
36
        display_requestable_list(requestable)
1✔
37
      end
38
    end
39

40
    def hidden_service_options(requestable, fill_in: false)
3✔
41
      return hidden_service_options_fill_in(requestable) if fill_in
131✔
42
      hidden = output_request_input(requestable)
120✔
43
      return hidden if hidden.present?
120✔
44

45
      if requestable.services.include? 'recap'
49✔
46
        recap_print_only_input requestable
40✔
47
      else
48
        request_input(requestable.services.first)
9✔
49
      end
50
    end
51

52
    def output_request_input(requestable)
3✔
53
      output = ""
120✔
54
      ['annex', 'pres', 'ppl', 'lewis', 'paging', 'on_order', 'on_shelf'].each do |type|
120✔
55
        next unless requestable.services.include?(type)
786✔
56
        output = request_input(type)
71✔
57
        break
71✔
58
      end
59
      output
120✔
60
    end
61

62
    # only requestable services that support "user-supplied volume info"
63
    def hidden_service_options_fill_in(requestable)
3✔
64
      if requestable.annex?
11✔
65
        request_input('annex')
2✔
66
      elsif requestable.services.include? 'recap_no_items'
9✔
67
        request_input('recap_no_items')
1✔
68
      else
69
        request_input('paging')
8✔
70
      end
71
    end
72

73
    def recap_print_only_input(requestable)
3✔
74
      content_tag(:fieldset, class: 'recap--print', id: "recap_group_#{requestable.preferred_request_id}") do
40✔
75
        concat hidden_field_tag "requestable[][type]", "", value: 'recap'
40✔
76
      end
77
    end
78

79
    # rubocop:disable Style/NumericPredicate
80
    def enum_copy_display(item)
3✔
81
      return "" if item.blank?
526✔
82
      [item.description, item.copy_value].join(" ").strip
524✔
83
    end
84
    # rubocop:enable Style/NumericPredicate
85

86
    def request_input(type)
3✔
87
      hidden_field_tag "requestable[][type]", "", value: type
97✔
88
    end
89

90
    def gfa_lookup(lib_code)
3✔
91
      if lib_code == "firestone"
6✔
92
        "PA"
×
93
      else
94
        lib = Requests::BibdataService.delivery_locations.select { |_key, hash| hash["library"]["code"] == lib_code }
144✔
95
        lib.keys.first.to_s
6✔
96
      end
97
    end
98

99
    def pick_up_classlist(requestable, collapse)
3✔
100
      class_list = "collapse request--print"
150✔
101
      class_list += " show" if !requestable.digitize? && !collapse
150✔
102
      class_list
150✔
103
    end
104

105
    # move this to requestable object
106
    # Default pick-ups should be available
107
    def pick_up_choices(requestable, default_pick_ups, collapse = false)
3✔
108
      content_tag(:div, id: "fields-print__#{requestable.preferred_request_id}", class: pick_up_classlist(requestable, collapse)) do
139✔
109
        preferred_request_content_tag(requestable, requestable.pick_up_locations || default_pick_ups)
139✔
110
      end
111
    end
112

113
    # :reek:NilCheck
114
    def preferred_request_content_tag(requestable, default_pick_ups)
3✔
115
      (show_pick_up_service_options(requestable, nil) || "".html_safe) +
145✔
116
        content_tag(:div, id: "fields-print__#{requestable.preferred_request_id}_card", class: "card card-body bg-light") do
117
          locs = pick_up_locations(requestable, default_pick_ups)
144✔
118

119
          name = 'requestable[][pick_up]'
144✔
120
          id = "requestable__pick_up_#{requestable.preferred_request_id}"
144✔
121
          if locs.size > 1
144✔
122
            prompt_text = custom_pickup_prompt(requestable, locs) || I18n.t("requests.default.pick_up_placeholder")
64✔
123
            selected_value = find_selected_pickup_value(requestable, locs)
64✔
124
            # For ReCAP items, select the empty prompt instead of any actual option
125
            selected_value = '' if requestable.recap? && selected_value.nil?
64✔
126
            options = [[prompt_text, '', { disabled: true, selected: false }]] + locs.map { |loc| [loc[:label], { 'pick_up' => loc[:gfa_pickup], 'pick_up_location_code' => loc[:pick_up_location_code] }.to_json] }
563✔
127
            select_tag name.to_s, options_for_select(options, selected_value), id: id
64✔
128
          else
129

130
            single_pickup(requestable.charged?, name, id, locs[0])
80✔
131
          end
132
        end
133
    end
134

135
    # rubocop:disable Rails/OutputSafety
136
    def hidden_fields_mfhd(mfhd)
3✔
137
      hidden = ""
75✔
138
      return hidden if mfhd.nil?
75✔
139
      hidden += hidden_field_tag "mfhd[][call_number]", "", value: (mfhd['call_number']).to_s unless mfhd["call_number"].nil?
74✔
140
      hidden += hidden_field_tag "mfhd[][location]", "", value: (mfhd['location']).to_s unless mfhd["location"].nil?
74✔
141
      hidden += hidden_field_tag "mfhd[][library]", "", value: (mfhd['library']).to_s
74✔
142
      hidden.html_safe
74✔
143
    end
144
    # rubocop:enable Rails/OutputSafety
145

146
    def hidden_fields_item(requestable)
3✔
147
      request_id = requestable.preferred_request_id
531✔
148
      hidden = hidden_field_tag "requestable[][bibid]", "", value: requestable.bib[:id].to_s, id: "requestable_bibid_#{request_id}"
531✔
149
      hidden += hidden_field_tag "requestable[][mfhd]", "", value: requestable.holding.mfhd_id, id: "requestable_mfhd_#{request_id}"
531✔
150
      hidden += hidden_field_tag "requestable[][call_number]", "", value: requestable.holding.holding_data['call_number'].to_s, id: "requestable_call_number_#{request_id}" unless requestable.holding.holding_data["call_number"].nil?
531✔
151
      hidden += hidden_field_tag "requestable[][location_code]", "", value: requestable.item_location_code.to_s, id: "requestable_location_#{request_id}"
531✔
152
      hidden += if requestable.item?
531✔
153
                  hidden_fields_for_item(item: requestable.item, preferred_request_id: requestable.preferred_request_id)
518✔
154
                else
155
                  hidden_field_tag("requestable[][item_id]", "", value: requestable.preferred_request_id, id: "requestable_item_id_#{requestable.preferred_request_id}")
13✔
156
                end
157
      hidden += hidden_fields_for_scsb(item: requestable.item) if requestable.partner_holding?
531✔
158
      hidden
531✔
159
    end
160

161
    def suppress_login?(request)
3✔
162
      request.only_aeon?
79✔
163
    end
164

165
    def item_checkbox(requestable, single_item_form)
3✔
166
      disabled = !requestable.will_submit_via_form?
512✔
167
      check_box_tag "requestable[][selected]", true, check_box_selected?(disabled, single_item_form), class: 'request--select', disabled:, aria: { labelledby: "title enum_#{requestable.preferred_request_id}" }, id: "requestable_selected_#{requestable.preferred_request_id}"
512✔
168
    end
169

170
    ## If any requestable items have a temp location assume everything at the holding is in a temp loc?
171
    def current_location_label(holding_location_label, requestable_list)
3✔
172
      first_location = requestable_list.first.location
147✔
173
      location_label = first_location.short_label.blank? ? "" : "- #{first_location.short_label}"
147✔
174
      label = if requestable_list.first.temp_loc_other_than_resource_sharing?
147✔
175
                "#{first_location.library_label}#{location_label}"
4✔
176
              else
177
                holding_location_label
143✔
178
              end
179
      "#{label} #{requestable_list.first.call_number}"
147✔
180
    end
181

182
    def check_box_selected?(disabled, single_item_form)
3✔
183
      if single_item_form
512✔
184
        !disabled
40✔
185
      else
186
        false
472✔
187
      end
188
    end
189

190
    def submit_button_disabled?(requestable_list)
3✔
191
      # temporary chane issue 438 guest can no longer check out materials
192
      return true if @user.blank? || @user.guest
54✔
193
      return unsubmittable? requestable_list unless requestable_list.size == 1
52✔
194
      # temporary changes issue 438 do not disable the button for circulating items
195
      # requestable_list.first.services.empty? || requestable_list.first.on_reserve? || (requestable_list.first.services.include? 'on_shelf') || requestable_list.first.ask_me?
196
      requestable_list.first.services.empty? || requestable_list.first.on_reserve?
43✔
197
    end
198

199
    def unsubmittable?(requestable_list)
3✔
200
      !requestable_list.any? { |requestable| (requestable.services | submitable_services).present? }
18✔
201
    end
202

203
    def submitable_services
3✔
204
      ['on_shelf', 'in_process', 'on_order', 'annex', 'recap', 'recap_edd', 'paging', 'recap_no_items', 'ppl', 'lewis']
9✔
205
    end
206

207
    def submit_message(requestable_list)
3✔
208
      single_item = "Request this Item"
50✔
209
      multi_item = "Request Selected Items"
50✔
210
      no_item = "No Items Available"
50✔
211
      return multi_item unless requestable_list.size == 1
50✔
212
      if requestable_list.first.services.empty?
41✔
213
        no_item
×
214
      elsif requestable_list.first.annex?
41✔
215
        # Annex items have the potential to display the
216
        # use the fill-in form, where a user could potentially
217
        # request multiple volumes.  For that reason, we show
218
        # the plural form "Request Selected Items" in this case
219
        multi_item
3✔
220
      else
221
        single_item
38✔
222
      end
223
    end
224

225
    # only show the table sort if there are enough items
226
    # to make it worthwhile
227
    def show_tablesorter(requestable_list)
3✔
228
      return "tablesorter" if table_sorter_present?(requestable_list)
74✔
229
      ""
65✔
230
    end
231

232
    def table_sorter_present?(requestable_list)
3✔
233
      requestable_list.size > 5
107✔
234
    end
235

236
    def display_label
3✔
237
      {
×
238
        author: "Author/Artist",
239
        title: "Title",
240
        date: "Published/Created",
241
        id: "Bibliographic ID",
242
        mfhd: "Holding ID (mfhd)"
243
      }.with_indifferent_access
244
    end
245

246
    def display_status(requestable)
3✔
247
      content_tag(:span, requestable.item['status']) unless requestable.item.nil?
×
248
    end
249

250
    def system_status_label(requestable)
3✔
251
      return "" if requestable.item.blank?
×
252
      content_tag(:div, requestable.item[:status], class: 'system-status')
×
253
    end
254

255
    def display_urls(requestable)
3✔
256
      content_tag :ol do
×
257
        requestable.urls.each do |key, value|
×
258
          unless key == 'iiif_manifest_paths'
×
259
            value.reverse!
×
260
            concat content_tag(:li, link_to(value.join(": "), key), class: 'link')
×
261
          end
262
        end
263
      end
264
    end
265

266
    def self.recap_annex_available_pick_ups(requestable, default_pick_ups)
3✔
267
      locations = requestable.pick_up_locations || default_pick_ups
65✔
268
      pick_ups = locations.select { |loc| Requests::Location.valid_recap_annex_pickup?(loc) }
762✔
269
      pick_ups << default_pick_ups[0] if pick_ups.empty?
65✔
270
      pick_ups
65✔
271
    end
272

273
    private
3✔
274

275
      def custom_pickup_prompt(requestable, locs)
3✔
276
        # For ReCAP items, return nil to use default prompt
277
        return nil if requestable.recap?
71✔
278

279
        holding_library = normalize_holding_library(requestable)
24✔
280
        return nil if holding_library.blank?
24✔
281

282
        find_prompt_for_holding_library(holding_library, locs)
24✔
283
      end
284

285
      # :reek:UtilityFunction
286
      def normalize_holding_library(requestable)
3✔
287
        requestable.holding_library&.downcase
41✔
288
      end
289

290
      def find_prompt_for_holding_library(holding_library, locs)
3✔
291
        # Check for special engineering library cases first
292
        engineering_prompt = engineering_library_prompt(holding_library, locs)
24✔
293
        return engineering_prompt if engineering_prompt
24✔
294

295
        # Find matching library by code and suggest it in the prompt
296
        suggested_location = find_matching_location_label(holding_library, locs)
20✔
297
        return unless suggested_location
20✔
298
        I18n.t('requests.pick_up_suggested.holding_library', holding_library: suggested_location)
4✔
299
        # "Select a Delivery Location (Recommended: #{suggested_location})"
300
      end
301

302
      def find_matching_location_label(holding_library, locs)
3✔
303
        matching_loc = find_matching_location_by_code(holding_library, locs)
20✔
304
        matching_loc&.dig(:label)
20✔
305
      end
306

307
      # :reek:UtilityFunction
308
      def find_matching_location_by_code(holding_library, locs)
3✔
309
        locs.find do |loc|
35✔
310
          # Extract library code and compare with holding library
311
          location = Requests::Location.new(loc)
173✔
312
          location.library_code&.downcase == holding_library
173✔
313
        end
314
      end
315

316
      # :reek:UtilityFunction
317
      def engineering_library_prompt(holding_library, locs)
3✔
318
        # Special case: lewis, plasma should default to Engineering Library
319
        if ['lewis', 'plasma'].include?(holding_library)
24✔
320
          engineering_loc = locs.find { |loc| loc[:label] == "Engineering Library" }
16✔
321
          return I18n.t('requests.pick_up_suggested.engineering_holding_library', engineering_holding_library: engineering_loc[:label]) if engineering_loc
5✔
322
        end
323
        nil
20✔
324
      end
325

326
      def find_selected_pickup_value(requestable, locs)
3✔
327
        return nil if should_skip_form_preselection?(requestable)
64✔
328

329
        holding_library = normalize_holding_library(requestable)
17✔
330
        return nil if holding_library.blank?
17✔
331

332
        find_form_preselected_location_json(holding_library, locs)
17✔
333
      end
334

335
      # :reek:UtilityFunction
336
      def should_skip_form_preselection?(requestable)
3✔
337
        requestable.recap?
64✔
338
      end
339

340
      def find_form_preselected_location_json(holding_library, locs)
3✔
341
        selected_location = find_engineering_location(holding_library, locs) ||
17✔
342
                            find_matching_location_by_code(holding_library, locs)
343
        return nil unless selected_location
17✔
344

345
        location_to_json(selected_location)
3✔
346
      end
347

348
      # :reek:UtilityFunction
349
      def find_engineering_location(holding_library, locs)
3✔
350
        return nil unless ['lewis', 'plasma'].include?(holding_library)
17✔
351
        locs.find { |loc| Requests::Location.new(loc).engineering_library? }
6✔
352
      end
353

354
      # :reek:UtilityFunction
355
      def location_to_json(location)
3✔
356
        { 'pick_up' => location[:gfa_pickup], 'pick_up_location_code' => location[:pick_up_location_code] }.to_json
3✔
357
      end
358

359
      def display_requestable_list(requestable)
3✔
360
        content_tag(:ul, class: "service-list") do
142✔
361
          if requestable.ill_eligible?
142✔
362
            concat content_tag(:li, sanitize(I18n.t("requests.ill.brief_msg")), class: "service-item")
1✔
363
          else
364
            # there are no instances where more than one actual service is available to an item, so we are going to take the first service that is not edd
365
            filtered_services = if requestable.services.size == 1 && requestable.services.first.include?("edd")
141✔
366
                                  requestable.services
×
367
                                else
368
                                  requestable.services.reject { |service_name| service_name.include?("edd") }
406✔
369
                                end
370
            brief_msg = I18n.t("requests.#{filtered_services.first}.brief_msg")
141✔
371
            concat content_tag(:li, sanitize(brief_msg), class: "service-item")
141✔
372
          end
373
        end
374
      end
375

376
      def display_on_shelf(requestable, _mfhd_id)
3✔
377
        content_tag(:div) do
70✔
378
          display_requestable_list(requestable)
70✔
379
        end
380
      end
381

382
      def pick_up_locations(requestable, default_pick_ups)
3✔
383
        # we don't want to change the ill_eligible rules
384
        return ill_eligible_pick_up_location(default_pick_ups) if requestable.ill_eligible?
146✔
385
        return Requests::ApplicationHelper.recap_annex_available_pick_ups(requestable, default_pick_ups) if requestable.recap? || requestable.annex?
144✔
386
        return default_pick_ups if requestable.location&.standard_circ_location?
82✔
387
        if requestable.delivery_location_label.present?
79✔
388
          [{ label: requestable.delivery_location_label, gfa_pickup: requestable.delivery_location_code, pick_up_location_code: requestable.pick_up_location_code, staff_only: false }]
72✔
389
        else
390
          [{ label: requestable.location.library_label, gfa_pickup: gfa_lookup(requestable.location.library_code), staff_only: false }]
7✔
391
        end
392
      end
393

394
      # :reek:UtilityFunction
395
      def ill_eligible_pick_up_location(default_pick_ups)
3✔
396
        # currently for resource sharing items through Illiad we use firestone Library with gfa_pickup of PA
397
        location = default_pick_ups.find { |location| location[:gfa_pickup] == "PA" }
7✔
398
        [location].compact
2✔
399
      end
400

401
      def hidden_fields_for_item(item:, preferred_request_id:)
3✔
402
        hidden = hidden_field_tag("requestable[][item_id]", "", value: preferred_request_id.to_s, id: "requestable_item_id_#{preferred_request_id}")
518✔
403
        hidden += hidden_field_tag("requestable[][barcode]", "", value: item['barcode'].to_s, id: "requestable_barcode_#{preferred_request_id}") unless item["barcode"].nil?
518✔
404
        hidden += hidden_field_tag("requestable[][enum]", "", value: item.enum_value.to_s, id: "requestable_enum_#{preferred_request_id}") if item.enum_value.present?
518✔
405
        hidden += hidden_field_tag("requestable[][copy_number]", "", value: item.copy_number.to_s, id: "requestable_copy_number_#{preferred_request_id}")
518✔
406
        hidden + hidden_field_tag("requestable[][status]", "", value: item['status'].to_s, id: "requestable_status_#{preferred_request_id}")
518✔
407
      end
408

409
      def hidden_fields_for_scsb(item:)
3✔
410
        hidden = hidden_field_tag("requestable[][cgd]", "", value: item['cgd'].to_s, id: "requestable_cgd_#{item['id']}")
6✔
411
        hidden += hidden_field_tag("requestable[][cc]", "", value: item['collection_code'].to_s, id: "requestable_collection_code_#{item['id']}")
6✔
412
        hidden + hidden_field_tag("requestable[][use_statement]", "", value: item['use_statement'].to_s, id: "requestable_use_statement_#{item['id']}")
6✔
413
      end
414

415
      def single_pickup(is_charged, name, id, location)
3✔
416
        style = if is_charged
80✔
417
                  'margin-top:10px;'
×
418
                else
419
                  ''
80✔
420
                end
421
        hidden = hidden_field_tag name.to_s, "", value: { 'pick_up' => location[:gfa_pickup], 'pick_up_location_code' => location[:pick_up_location_code] }.to_json, class: 'single-pick-up-hidden', id: id
80✔
422
        label = label_tag id, "Pick-up location: #{location[:label]}", class: 'single-pick-up', style: style.to_s
80✔
423
        hidden + label
80✔
424
      end
425

426
      def aeon_base
3✔
UNCOV
427
        Requests.config[:aeon_base]
×
428
      end
429
  end
430
end
431
# rubocop:enable Metrics/ModuleLength
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc