Bug 29032: Pre-load ILL backends to speed up response
[koha.git] / Koha / REST / V1 / Illrequests.pm
1 package Koha::REST::V1::Illrequests;
2
3 # This file is part of Koha.
4 #
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.
9 #
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.
14 #
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>.
17
18 use Modern::Perl;
19
20 use Mojo::Base 'Mojolicious::Controller';
21
22 use C4::Context;
23 use Koha::Illrequests;
24 use Koha::Illrequestattributes;
25 use Koha::Libraries;
26 use Koha::Patrons;
27 use Koha::Libraries;
28 use Koha::DateUtils qw( format_sqldatetime );
29
30 =head1 NAME
31
32 Koha::REST::V1::Illrequests
33
34 =head2 Operations
35
36 =head3 list
37
38 Return a list of ILL requests, after applying filters.
39
40 =cut
41
42 sub list {
43     my $c = shift->openapi->valid_input or return;
44
45     my $args = $c->req->params->to_hash // {};
46     my $output = [];
47     my @format_dates = ( 'placed', 'updated', 'completed' );
48
49     # Create a hash where all keys are embedded values
50     # Enables easy checking
51     my %embed;
52     my $args_arr = (ref $args->{embed} eq 'ARRAY') ? $args->{embed} : [ $args->{embed} ];
53     if (defined $args->{embed}) {
54         %embed = map { $_ => 1 }  @{$args_arr};
55         delete $args->{embed};
56     }
57
58     # Get the pipe-separated string of hidden ILL statuses
59     my $hidden_statuses_string = C4::Context->preference('ILLHiddenRequestStatuses') // q{};
60     # Turn into arrayref
61     my $hidden_statuses = [ split /\|/, $hidden_statuses_string ];
62
63     # Get all requests
64     # If necessary, only get those from a specified patron
65     my @requests = Koha::Illrequests->search({
66         $hidden_statuses
67         ? ( status => { 'not in' => $hidden_statuses } )
68         : (),
69         $args->{borrowernumber}
70         ? ( borrowernumber => $args->{borrowernumber} )
71         : ()
72     })->as_list;
73
74     my $fetch_backends = {};
75     foreach my $request (@requests) {
76         $fetch_backends->{ $request->backend } ||=
77           Koha::Illrequest->new->load_backend( $request->backend );
78     }
79
80     # Pre-load the backend object to avoid useless backend lookup/loads
81     @requests = map { $_->_backend( $fetch_backends->{ $_->backend } ); $_ } @requests;
82
83     # Identify patrons & branches that
84     # we're going to need and get them
85     my $to_fetch = {
86         patrons      => {},
87         branches     => {},
88         capabilities => {}
89     };
90     foreach my $req (@requests) {
91         $to_fetch->{patrons}->{$req->borrowernumber} = 1 if $embed{patron};
92         $to_fetch->{branches}->{$req->branchcode} = 1 if $embed{library};
93         $to_fetch->{capabilities}->{$req->backend} = 1 if $embed{capabilities};
94     }
95
96     # Fetch the patrons we need
97     my $patron_arr = [];
98     if ($embed{patron}) {
99         my @patron_ids = keys %{$to_fetch->{patrons}};
100         if (scalar @patron_ids > 0) {
101             my $where = {
102                 borrowernumber => { -in => \@patron_ids }
103             };
104             $patron_arr = Koha::Patrons->search($where)->unblessed;
105         }
106     }
107
108     # Fetch the branches we need
109     my $branch_arr = [];
110     if ($embed{library}) {
111         my @branchcodes = keys %{$to_fetch->{branches}};
112         if (scalar @branchcodes > 0) {
113             my $where = {
114                 branchcode => { -in => \@branchcodes }
115             };
116             $branch_arr = Koha::Libraries->search($where)->unblessed;
117         }
118     }
119
120     # Fetch the capabilities we need
121     if ($embed{capabilities}) {
122         my @backends = keys %{$to_fetch->{capabilities}};
123         if (scalar @backends > 0) {
124             foreach my $bc(@backends) {
125                 $to_fetch->{$bc} = $fetch_backends->{$bc}->capabilities;
126             }
127         }
128     }
129
130     # Now we've got all associated users and branches,
131     # we can augment the request objects
132     my @output = ();
133     foreach my $req(@requests) {
134         my $to_push = $req->unblessed;
135         $to_push->{id_prefix} = $req->id_prefix;
136         # Create new "formatted" columns for each date column
137         # that needs formatting
138         foreach my $field(@format_dates) {
139             if (defined $to_push->{$field}) {
140                 $to_push->{$field . "_formatted"} = format_sqldatetime(
141                     $to_push->{$field},
142                     undef,
143                     undef,
144                     1
145                 );
146             }
147         }
148
149         foreach my $p(@{$patron_arr}) {
150             if ($p->{borrowernumber} == $req->borrowernumber) {
151                 $to_push->{patron} = {
152                     patron_id => $p->{borrowernumber},
153                     firstname      => $p->{firstname},
154                     surname        => $p->{surname},
155                     cardnumber     => $p->{cardnumber}
156                 };
157                 last;
158             }
159         }
160         foreach my $b(@{$branch_arr}) {
161             if ($b->{branchcode} eq $req->branchcode) {
162                 $to_push->{library} = $b;
163                 last;
164             }
165         }
166         if ($embed{metadata}) {
167             my $metadata = Koha::Illrequestattributes->search(
168                 { illrequest_id => $req->illrequest_id },
169                 { columns => [qw/type value/] }
170             )->unblessed;
171             my $meta_hash = {};
172             foreach my $meta(@{$metadata}) {
173                 $meta_hash->{$meta->{type}} = $meta->{value};
174             }
175             $to_push->{metadata} = $meta_hash;
176         }
177         if ($embed{capabilities}) {
178             $to_push->{capabilities} = $to_fetch->{$req->backend};
179         }
180         if ($embed{comments}) {
181             $to_push->{comments} = $req->illcomments->count;
182         }
183         if ($embed{status_alias}) {
184             $to_push->{status_alias} = $req->statusalias;
185         }
186         if ($embed{requested_partners}) {
187             $to_push->{requested_partners} = $req->requested_partners;
188         }
189         push @output, $to_push;
190     }
191
192     return $c->render( status => 200, openapi => \@output );
193 }
194
195 1;