Browse Source

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>
20.11.x
Nick Clemens 4 years ago
committed by Jonathan Druart
parent
commit
83d4713945
  1. 14
      Koha/Hold.pm
  2. 32
      Koha/REST/V1/Holds.pm
  3. 3
      api/v1/swagger/paths.json
  4. 57
      api/v1/swagger/paths/holds.json
  5. 6
      koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc
  6. 1
      koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt
  7. 30
      koha-tmpl/intranet-tmpl/prog/js/holds.js

14
Koha/Hold.pm

@ -338,6 +338,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

32
Koha/REST/V1/Holds.pm

@ -395,4 +395,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;

3
api/v1/swagger/paths.json

@ -59,6 +59,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"
},

57
api/v1/swagger/paths/holds.json

@ -613,5 +613,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"
}
}
}
}
}

6
koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc

@ -132,9 +132,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>

1
koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt

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

30
koha-tmpl/intranet-tmpl/prog/js/holds.js

@ -302,4 +302,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();
},
});
});
});

Loading…
Cancel
Save