From 65bf1e3ccd79ea6a61f0502a3567c3f95f594eaf Mon Sep 17 00:00:00 2001
From: Julian Maurice <julian.maurice@biblibre.com>
Date: Wed, 29 Apr 2020 16:13:08 +0200
Subject: [PATCH] Bug 25375: Fix 'available' facet in elasticsearch

Add a new boolean ES field named 'available', which is true if at least
one item is available, which means the item is not on loan, not
"notforloan", not withdrawn, not lost and not damaged

A full indexation is required

Test plan:
1. Apply patch and run updatedatabase.pl
2. Run `misc/search_tools/rebuild_elasticsearch.pl -d -b`
3. Make sure you have some biblios whose items are all unavailable, some
   biblios whose items are all available, and some biblios with at least
   one item available and at least one item unavailable
4. Use the 'available' filter on both opac and intranet and make sure it
   works as expected.

Signed-off-by: Andrew Fuerste-Henry <andrew@bywatersolutions.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
---
 Koha/SearchEngine/Elasticsearch.pm            | 20 +++++++++++++++++++
 .../Elasticsearch/QueryBuilder.pm             |  2 +-
 .../searchengine/elasticsearch/mappings.yaml  |  3 +++
 .../data/mysql/atomicupdate/bug-25375.perl    |  9 +++++++++
 4 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 installer/data/mysql/atomicupdate/bug-25375.perl

diff --git a/Koha/SearchEngine/Elasticsearch.pm b/Koha/SearchEngine/Elasticsearch.pm
index 85d8cba798..323a2e2b9b 100644
--- a/Koha/SearchEngine/Elasticsearch.pm
+++ b/Koha/SearchEngine/Elasticsearch.pm
@@ -770,6 +770,26 @@ sub marc_records_to_documents {
                 $record_document->{'marc_format'} = 'base64ISO2709';
             }
         }
+
+        # Check if there is at least one available item
+        if ($self->index eq $BIBLIOS_INDEX) {
+            my $biblio = Koha::Biblios->find($record->field('001')->data);
+            my $items = $biblio->items;
+            my $available = 0;
+            while (my $item = $items->next) {
+                next if $item->onloan;
+                next if $item->notforloan;
+                next if $item->withdrawn;
+                next if $item->itemlost;
+                next if $item->damaged;
+
+                $available = 1;
+                last;
+            }
+
+            $record_document->{available} = $available ? \1 : \0;
+        }
+
         push @record_documents, $record_document;
     }
     return \@record_documents;
diff --git a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm
index 3e2cb1b784..7a86a558b9 100644
--- a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm
+++ b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm
@@ -1092,7 +1092,7 @@ sub _fix_limit_special_cases {
             }
         }
         elsif ( $l =~ /^available$/ ) {
-            push @new_lim, 'onloan:false';
+            push @new_lim, 'available:true';
         }
         else {
             my ( $field, $term ) = $l =~ /^\s*([\w,-]*?):(.*)/;
diff --git a/admin/searchengine/elasticsearch/mappings.yaml b/admin/searchengine/elasticsearch/mappings.yaml
index 28429878f9..4ade2baa95 100644
--- a/admin/searchengine/elasticsearch/mappings.yaml
+++ b/admin/searchengine/elasticsearch/mappings.yaml
@@ -2551,6 +2551,9 @@ biblios:
         sort: 0
         suggestible: ''
     type: boolean
+  available:
+    label: available
+    type: boolean
   other-control-number:
     label: other-control-number
     mappings:
diff --git a/installer/data/mysql/atomicupdate/bug-25375.perl b/installer/data/mysql/atomicupdate/bug-25375.perl
new file mode 100644
index 0000000000..7de5ce51e7
--- /dev/null
+++ b/installer/data/mysql/atomicupdate/bug-25375.perl
@@ -0,0 +1,9 @@
+$DBversion = 'XXX';
+if( CheckVersion( $DBversion ) ) {
+    $dbh->do(qq{
+        INSERT IGNORE INTO search_field (name, label, type)
+        VALUES ('available', 'available', 'boolean')
+    });
+
+    NewVersion( $DBversion, '25735', "Add Elasticsearch field 'available'");
+}
-- 
2.30.2