1 package Koha::REST::V1::Checkouts;
3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use Mojo::Base 'Mojolicious::Controller';
23 use C4::Auth qw( haspermission );
25 use C4::Circulation qw( AddIssue AddRenewal CanBookBeRenewed );
27 use Koha::Old::Checkouts;
30 use Try::Tiny qw( catch try );
34 Koha::REST::V1::Checkout
42 List Koha::Checkout objects
47 my $c = shift->openapi->valid_input or return;
49 my $checked_in = delete $c->validation->output->{checked_in};
55 $checkouts_set = Koha::Old::Checkouts->new;
57 $checkouts_set = Koha::Checkouts->new;
60 my $checkouts = $c->objects->search( $checkouts_set );
67 $c->unhandled_exception($_);
78 my $c = shift->openapi->valid_input or return;
80 my $checkout_id = $c->validation->param('checkout_id');
81 my $checkout = Koha::Checkouts->find( $checkout_id );
82 $checkout = Koha::Old::Checkouts->find( $checkout_id )
88 openapi => { error => "Checkout doesn't exist" }
95 openapi => $checkout->to_api
99 $c->unhandled_exception($_);
103 =head3 _check_availability
105 Internal function to call CanBookBeIssued and return an appropriately filtered
110 sub _check_availability {
111 my ( $c, $patron, $item ) = @_;
113 my $inprocess = 0; # What does this do?
114 my $ignore_reserves = 0; # Don't ignore reserves
115 my $params = { item => $item };
117 my ( $impossible, $confirmation, $alerts, $messages ) =
118 C4::Circulation::CanBookBeIssued( $patron, undef, undef, $inprocess,
119 $ignore_reserves, $params );
121 if ( $c->stash('is_public') ) {
123 # Upgrade some confirmations to blockers
125 qw/TOO_MANY ISSUED_TO_ANOTHER RESERVED RESERVED_WAITING TRANSFERRED PROCESSING AGE_RESTRICTION/;
126 for my $block (@should_block) {
127 if ( exists( $confirmation->{$block} ) ) {
128 $impossible->{$block} = $confirmation->{$block};
129 delete $confirmation->{$block};
133 # Remove any non-public info that's returned by CanBookBeIssued
134 my @restricted_keys =
135 qw/issued_borrowernumber issued_cardnumber issued_firstname issued_surname resborrowernumber resbranchcode rescardnumber reserve_id resfirstname resreservedate ressurname item_notforloan/;
136 for my $key (@restricted_keys) {
137 delete $confirmation->{$key};
138 delete $impossible->{$key};
139 delete $alerts->{$key};
140 delete $messages->{$key};
144 return ( $impossible, $confirmation, { %{$alerts}, %{$messages} } );
147 =head3 get_availability
149 Controller function that handles retrieval of Checkout availability
153 sub get_availability {
154 my $c = shift->openapi->valid_input or return;
155 my $user = $c->stash('koha.user');
157 my $patron = Koha::Patrons->find( $c->param('patron_id') );
158 my $item = Koha::Items->find( $c->param('item_id') );
160 my ( $impossible, $confirmation, $warnings ) =
161 $c->_check_availability( $patron, $item );
163 my $confirm_keys = join( ":", sort keys %{$confirmation} );
164 $confirm_keys = $user->id . ":" . $item->id . ":" . $confirm_keys;
165 my $token = Koha::Token->new->generate_jwt( { id => $confirm_keys } );
168 blockers => $impossible,
169 confirms => $confirmation,
170 warnings => $warnings,
171 confirmation_token => $token
174 return $c->render( status => 200, openapi => $response );
184 my $c = shift->openapi->valid_input or return;
185 my $user = $c->stash('koha.user');
187 my $body = $c->req->json;
188 my $item_id = $body->{item_id};
189 my $patron_id = $body->{patron_id};
190 my $onsite = $body->{onsite_checkout};
192 if ( $c->stash('is_public')
193 && !C4::Context->preference('OpacTrustedCheckout') )
198 error => 'Feature disabled',
199 error_code => 'FEATURE_DISABLED'
205 my $item = Koha::Items->find($item_id);
210 error => 'Item not found',
211 error_code => 'ITEM_NOT_FOUND',
216 my $patron = Koha::Patrons->find($patron_id);
221 error => 'Patron not found',
222 error_code => 'PATRON_NOT_FOUND',
227 my ( $impossible, $confirmation, $warnings ) =
228 $c->_check_availability( $patron, $item );
230 # * Fail for blockers - render 403
231 if ( keys %{$impossible} ) {
232 my @errors = keys %{$impossible};
235 openapi => { error => "Checkout not authorized (@errors)" }
239 # * If confirmation required, check variable set above
240 # and render 412 if variable is false
241 if ( keys %{$confirmation} ) {
244 # Check for existence of confirmation token
245 # and if exists check validity
246 if ( my $token = $c->param('confirmation') ) {
247 my $confirm_keys = join( ":", sort keys %{$confirmation} );
248 $confirm_keys = $user->id . ":" . $item->id . ":" . $confirm_keys;
249 $confirmed = Koha::Token->new->check_jwt(
250 { id => $confirm_keys, token => $token } );
253 unless ($confirmed) {
256 openapi => { error => "Confirmation error" }
262 my $checkout = AddIssue( $patron->unblessed, $item->barcode );
264 $c->res->headers->location(
265 $c->req->url->to_string . '/' . $checkout->id );
268 openapi => $checkout->to_api
274 openapi => { error => 'Unknown error during checkout' }
279 $c->unhandled_exception($_);
285 List Koha::Checkout::Renewals
290 my $c = shift->openapi->valid_input or return;
293 my $checkout_id = $c->validation->param('checkout_id');
294 my $checkout = Koha::Checkouts->find($checkout_id);
295 $checkout = Koha::Old::Checkouts->find($checkout_id)
301 openapi => { error => "Checkout doesn't exist" }
305 my $renewals_rs = $checkout->renewals;
306 my $renewals = $c->objects->search( $renewals_rs );
314 $c->unhandled_exception($_);
326 my $c = shift->openapi->valid_input or return;
328 my $checkout_id = $c->validation->param('checkout_id');
329 my $seen = $c->validation->param('seen') || 1;
330 my $checkout = Koha::Checkouts->find( $checkout_id );
335 openapi => { error => "Checkout doesn't exist" }
340 my ($can_renew, $error) = CanBookBeRenewed($checkout->patron, $checkout);
345 openapi => { error => "Renewal not authorized ($error)" }
350 $checkout->borrowernumber,
351 $checkout->itemnumber,
352 $checkout->branchcode,
357 $checkout = Koha::Checkouts->find($checkout_id);
359 $c->res->headers->location( $c->req->url->to_string );
362 openapi => $checkout->to_api
366 $c->unhandled_exception($_);
370 =head3 allows_renewal
372 Checks if the checkout could be renewed and return the related information.
377 my $c = shift->openapi->valid_input or return;
379 my $checkout_id = $c->validation->param('checkout_id');
380 my $checkout = Koha::Checkouts->find( $checkout_id );
385 openapi => { error => "Checkout doesn't exist" }
390 my ($can_renew, $error) = CanBookBeRenewed($checkout->patron, $checkout);
392 my $renewable = Mojo::JSON->false;
393 $renewable = Mojo::JSON->true if $can_renew;
395 my $rule = Koha::CirculationRules->get_effective_rule(
397 categorycode => $checkout->patron->categorycode,
398 itemtype => $checkout->item->effective_itemtype,
399 branchcode => $checkout->branchcode,
400 rule_name => 'renewalsallowed',
406 allows_renewal => $renewable,
407 max_renewals => $rule->rule_value,
408 current_renewals => $checkout->renewals_count,
409 unseen_renewals => $checkout->unseen_renewals,
415 $c->unhandled_exception($_);