From a8402a02b0fef5a065cf595e5e986c5f86f8f7c1 Mon Sep 17 00:00:00 2001
From: Pedro Amorim <pedro.amorim@ptfs-europe.com>
Date: Fri, 14 Jul 2023 15:46:56 +0000
Subject: [PATCH] Bug 34282: Fix availability check in ILL batches

Staging modal area had issues listing availability checks for each request in the batch creation process

To test:
1) Run bash <(curl -s https://raw.githubusercontent.com/ammopt/koha-ill-dev/master/start-ill-dev-plus.sh)
2) Install a metadata enrichment plugin, e.g. https://github.com/PTFS-Europe/koha-plugin-api-pubmed/releases
3) Install and configure an availability plugin, e.g. eds https://github.com/PTFS-Europe/koha-plugin-ill-avail-eds/releases
4) Enable ILLCheckAvailability sys pref
5) Create a new ILL batch and input some pubmedids, i.e. 34898594, 31452466
6) Verify that the availability results show and are working, for each request in the batch
---
 ill/ill-requests.pl                           |   6 +-
 .../prog/en/includes/ill-batch-modal.inc      |   3 +
 .../prog/en/modules/ill/ill-requests.tt       |   1 +
 .../intranet-tmpl/prog/js/ill-batch-modal.js  | 118 ++++++++++--------
 4 files changed, 71 insertions(+), 57 deletions(-)

diff --git a/ill/ill-requests.pl b/ill/ill-requests.pl
index c10bfa5caf..33fa2ca5f7 100755
--- a/ill/ill-requests.pl
+++ b/ill/ill-requests.pl
@@ -553,8 +553,6 @@ sub get_ill_availability {
         }
     }
 
-    my $availability = Koha::Illrequest::Workflow::Availability->new($id_types);
-    return $availability->get_services({
-        ui_context => 'staff'
-    });
+    my $availability = Koha::Illrequest::Workflow::Availability->new($id_types, 'staff');
+    return $availability->get_services();
 }
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/ill-batch-modal.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/ill-batch-modal.inc
index 72903bb48d..9d60711576 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/ill-batch-modal.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/ill-batch-modal.inc
@@ -72,6 +72,9 @@
                                 <th scope="col">Metadata</th>
                                 <th scope="col">Request ID</th>
                                 <th scope="col">Request Status</th>
+                                [% IF Koha.Preference('ILLCheckAvailability') %]
+                                <th scope="col">Availability</th>
+                                [% END %]
                                 <th scope="col"></th>
                             </tr>
                         </thead>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt
index 3c3659eba3..213bba0d86 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt
@@ -910,6 +910,7 @@
     [% INCLUDE 'select2.inc' %]
     [% IF metadata_enrichment_services %]
     <script>
+        var ill_check_availability_syspref = '[% Koha.Preference('ILLCheckAvailability') | html %]';
         var metadata_enrichment_services = [% metadata_enrichment_services | $raw %];
     </script>
     <script>
diff --git a/koha-tmpl/intranet-tmpl/prog/js/ill-batch-modal.js b/koha-tmpl/intranet-tmpl/prog/js/ill-batch-modal.js
index 607e5582f6..d751328d8f 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/ill-batch-modal.js
+++ b/koha-tmpl/intranet-tmpl/prog/js/ill-batch-modal.js
@@ -86,7 +86,6 @@
                 updateTable();
                 updateRowCount();
                 updateProcessTotals();
-                checkAvailability();
             }
         }
     );
@@ -235,53 +234,28 @@
         });
     };
 
-    // Identify items that can have their availability checked, and do it
-    function checkAvailability() {
-        // Only proceed if we've got services that can check availability
-        if (!batch_availability_services || batch_availability_services.length === 0) return;
-        var toCheck = tableContent.data;
-        toCheck.forEach(function (row) {
-            if (
-                !row.url &&
-                Object.keys(row.metadata).length > 0 &&
-                !availabilitySent[row.value]
-            ) {
-                availabilitySent[row.value] = 1;
-                getAvailability(row.value, row.metadata);
-            }
-        });
-    };
+    async function populateAvailability(row) {
+        let metadata = row.metadata;
 
-    // Check availability services for immediate availability, if found,
-    // create a link in the table linking to the item
-    function getAvailability(identifier, metadata) {
-        // Prep the metadata for passing to the availability plugins
         let availability_object = {};
         if (metadata.issn) availability_object['issn'] = metadata.issn;
         if (metadata.doi) availability_object['doi'] = metadata.doi;
         if (metadata.pubmedid) availability_object['pubmedid'] = metadata.pubmedid;
-        var prepped = encodeURIComponent(base64EncodeUnicode(JSON.stringify(availability_object)));
-        for (i = 0; i < batch_availability_services.length; i++) {
-            var service = batch_availability_services[i];
-            window.doApiRequest(
-                service.endpoint + prepped
-            )
-                .then(function (response) {
-                    return response.json();
-                })
-                .then(function (data) {
-                    if (data.results.search_results && data.results.search_results.length > 0) {
-                        var result = data.results.search_results[0];
-                        tableContent.data = tableContent.data.map(function (row) {
-                            if (row.value === identifier) {
-                                row.url = result.url;
-                                row.availabilitySupplier = service.name;
-                            }
-                            return row;
-                        });
-                    }
-                });
-        }
+
+        // Check each service and use the first results we get, if any
+            var av_hits = [];
+        for (const service of batch_availability_services){
+            var prepped = encodeURIComponent(base64EncodeUnicode(JSON.stringify(availability_object)));
+
+            var endpoint = service.endpoint + prepped;
+            var availability = await getAvailability(endpoint);
+            if (availability.results.search_results && availability.results.search_results.length > 0) {
+                av_hits.push({name: service.name, url: availability.results.search_results[0].url});
+            }else{
+                av_hits.push({ name: service.name, empty:1 });
+            }
+        };
+        return av_hits;
     };
 
     // Help btoa with > 8 bit strings
@@ -685,6 +659,7 @@
             } else if (alreadyInDeduped.length === 0) {
                 row.metadata = {};
                 row.failed = {};
+                row.availability_hits = {};
                 row.requestId = null;
                 deduped.push(row);
             }
@@ -735,6 +710,16 @@
             } catch (e) {
                 row.failed = ill_populate_failed;
             }
+
+            if (ill_check_availability_syspref == 1){
+                try {
+                    var availability = await populateAvailability(row);
+                    row.availability_hits = availability || {};
+                } catch (e) {
+                    //do nothing
+                }
+            }
+
             newData[i] = row;
             tableContent.data = newData;
         }
@@ -770,6 +755,11 @@
         }
     };
 
+    async function getAvailability(endpoint) {
+        var response = await debounce(doApiRequest)(endpoint);
+        return response.json();
+    };
+
     async function getMetadata(endpoint) {
         var response = await debounce(doApiRequest)(endpoint);
         return response.json();
@@ -820,15 +810,7 @@
         label.innerText = ill_batch_metadata[prop] + ': ';
 
         // Add a link to the availability URL if appropriate
-        var value;
-        if (!data.url) {
-            value = document.createElement('span');
-        } else {
-            value = document.createElement('a');
-            value.setAttribute('href', data.url);
-            value.setAttribute('target', '_blank');
-            value.setAttribute('title', ill_batch_available_via + ' ' + data.availabilitySupplier);
-        }
+        var value = document.createElement('span');
         value.classList.add('metadata-value');
         value.innerText = meta[prop];
         div.appendChild(label);
@@ -930,6 +912,31 @@
         return data.requestStatus || '-';
     }
 
+    function createRequestAvailability(x, y, data) {
+
+        // If the fetch failed
+        if (data.failed.length > 0) {
+            return data.failed;
+        }
+
+        if (Object.keys(data.availability_hits).length === 0){
+            return ill_populate_waiting;
+        }
+
+        let str = '';
+        let has_some = false;
+        for (i = 0; i < data.availability_hits.length; i++) {
+            if (!data.availability_hits[i].empty){
+                has_some = true;
+                str += "<li><a href=" + data.availability_hits[i].url + " target=\"_blank\">" + data.availability_hits[i].name + "</a></li>"
+            }
+        }
+        if(!has_some){
+            str = ill_batch_none;
+        }
+        return str;
+    };
+
     function buildTable(identifiers) {
         table = KohaTable('identifier-table', {
             processing: true,
@@ -963,8 +970,13 @@
                     width: '6.5%',
                     render: createRequestStatus
                 },
+                ...( ill_check_availability_syspref == 1 ? [{
+                    data: '',
+                    width: '13%',
+                    render: createRequestAvailability, }] : []
+                    ),
                 {
-                    width: '18%',
+                    width: '6.5%',
                     render: createActions,
                     className: 'action-column noExport'
                 }
-- 
2.30.2