Bug 26988: Add API route to fetch hold pickup locations and use it in the holds table

To test:
1 - Place a number of holds on a record
2 - Have different pickup locations for the holds
3 - Have some libraries that are not pickup locations
4 - Load the holds tab for the record and note libraries not pickup locations are not in dropdowns
5 - Apply patch and restart all things
6 - Reload the holds table
7 - Click on a dropdown, note the spinner, should load successfully
8 - Confirm the dropdown matches the options before the patch
9 - Confirm updating the hold location works

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

Signed-off-by: Bob Bennhoff <bbennhoff@clicweb.org>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
(cherry picked from commit 83d4713945)

Signed-off-by: Andrew Fuerste-Henry <andrew@bywatersolutions.com>
This commit is contained in:
Nick Clemens 2020-11-10 13:35:14 +00:00 committed by Andrew Fuerste-Henry
parent bf38a864d4
commit 9f09d3d16a
7 changed files with 141 additions and 2 deletions

View File

@ -282,6 +282,20 @@ sub biblio {
return $self->{_biblio};
}
=head3 patron
Returns the related Koha::Patron object for this hold
=cut
sub patron {
my ($self) = @_;
$self->{_patron} ||= Koha::Patrons->find( $self->borrowernumber() );
return $self->{_patron};
}
=head3 item
Returns the related Koha::Item object for this Hold

View File

@ -393,4 +393,36 @@ sub update_priority {
};
}
=head3 pickup_locations
Method that returns the possible pickup_locations for a given hold
used for building the dropdown selector
=cut
sub pickup_locations {
my $c = shift->openapi->valid_input or return;
my $hold_id = $c->validation->param('hold_id');
my $hold = Koha::Holds->find($hold_id);
unless ($hold) {
return $c->render(
status => 404,
openapi => { error => "Hold not found" }
);
}
return try {
my $pickup_locations = $hold->itemnumber ?
$hold->item->pickup_locations({ patron => $hold->patron }) : $hold->biblio->pickup_locations({ patron => $hold->patron });
warn Data::Dumper::Dumper( $pickup_locations );
return $c->render( status => 200, openapi => $pickup_locations );
}
catch {
$c->unhandled_exception($_);
};
}
1;

View File

@ -53,6 +53,9 @@
"/holds/{hold_id}/suspension": {
"$ref": "paths/holds.json#/~1holds~1{hold_id}~1suspension"
},
"/holds/{hold_id}/pickup_locations": {
"$ref": "paths/holds.json#/~1holds~1{hold_id}~1pickup_locations"
},
"/items": {
"$ref": "paths/items.json#/~1items"
},

View File

@ -603,5 +603,62 @@
}
}
}
},
"/holds/{hold_id}/pickup_locations": {
"get": {
"x-mojo-to": "Holds#pickup_locations",
"operationId": "getHoldPickupLocations",
"tags": ["holds"],
"parameters": [{
"$ref": "../parameters.json#/hold_id_pp"
}],
"produces": ["application/json"],
"responses": {
"200": {
"description": "Hold pickup location"
},
"400": {
"description": "Missing or wrong parameters",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"401": {
"description": "Authentication required",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"403": {
"description": "Hold pickup location list not allowed",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"404": {
"description": "Hold not found",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"503": {
"description": "Under maintenance",
"schema": {
"$ref": "../definitions.json#/error"
}
}
},
"x-koha-authorization": {
"permissions": {
"reserveforothers": "1"
}
}
}
}
}

View File

@ -130,9 +130,11 @@
[% IF Koha.Preference('IndependentBranches') && Branches.all().size == 1 %]
[% Branches.GetName(hold.branchcode) | html %] <input type="hidden" name="pickup" value="[% hold.branchcode | html %]" />
[% ELSE %]
<select name="pickup">
[% PROCESS options_for_libraries libraries => Branches.pickup_locations( { search_params => { item => hold.itemnumber, biblio => hold.biblionumber, patron => hold.patron }, selected => hold.branchcode }) %]
<select class="pickup_location_dropdown" data-selected="[% hold.branchcode | html %]" data-hold_id="[% hold.reserve_id | html %]" name="pickup">
<option selected="selected" value="[% hold.branchcode | html %]">[% Branches.GetName(hold.branchcode) | html %]</option>
<option value="" disabled="disabled" class="loading">Loading...</option>
</select>
<img class="loading_[% hold.reserve_id %]" src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" style="display:none;"/>
[% END %]
[% END %]
</td>

View File

@ -938,6 +938,7 @@
[% INCLUDE 'calendar.inc' %]
[% INCLUDE 'columns_settings.inc' %]
[% Asset.js("js/circ-patron-search-results.js") | $raw %]
[% Asset.js("js/holds.js") | $raw %]
<script>
var biblionumber = "[% biblionumber | $raw %]";
var borrowernumber = "[% patron.borrowernumber | $raw %]";

View File

@ -295,4 +295,34 @@ $(document).ready(function() {
});
});
$(".pickup_location_dropdown").on( "click",function(){
var this_dropdown = $(this);
if(this_dropdown.data('loaded')===1){ return true};
var hold_id = $(this).data('hold_id');
$(".loading_"+hold_id).show();
var preselected = $(this).data('selected');
var api_url = '/api/v1/holds/'+hold_id+'/pickup_locations';
$.ajax({
method: "GET",
url: api_url,
success: function( data ){
var dropdown = "";
$.each(data, function(index,library) {
if( preselected == library.branchcode ){
selected = ' selected="selected" ';
} else { selected = ""; }
dropdown += '<option value="'+library.branchcode+'"'+selected+'>'+library.branchname+'</option>';
});
this_dropdown.html( dropdown);
this_dropdown.data("loaded",1);
$(".loading_"+hold_id).hide();
},
error: function( jqXHR, textStatus, errorThrown) {
alert('There was an error:'+textStatus+" "+errorThrown);
$(".loading_"+hold_id).hide();
},
});
});
});