Bug 25032: Make existing controllers use unhandled_exception
[srvgit] / Koha / REST / V1 / Patrons.pm
1 package Koha::REST::V1::Patrons;
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 Koha::DateUtils;
23 use Koha::Patrons;
24
25 use Scalar::Util qw(blessed);
26 use Try::Tiny;
27
28 =head1 NAME
29
30 Koha::REST::V1::Patrons
31
32 =head1 API
33
34 =head2 Methods
35
36 =head3 list
37
38 Controller function that handles listing Koha::Patron objects
39
40 =cut
41
42 sub list {
43     my $c = shift->openapi->valid_input or return;
44
45     return try {
46
47         my $patrons_rs = Koha::Patrons->new;
48         my $args = $c->validation->output;
49         my $attributes = {};
50
51         # Extract reserved params
52         my ( $filtered_params, $reserved_params ) = $c->extract_reserved_params($args);
53
54         my $restricted = delete $filtered_params->{restricted};
55
56         # Merge sorting into query attributes
57         $c->dbic_merge_sorting(
58             {
59                 attributes => $attributes,
60                 params     => $reserved_params,
61                 result_set => $patrons_rs
62             }
63         );
64
65         # Merge pagination into query attributes
66         $c->dbic_merge_pagination(
67             {
68                 filter => $attributes,
69                 params => $reserved_params
70             }
71         );
72
73         if ( defined $filtered_params ) {
74
75             # Apply the mapping function to the passed params
76             $filtered_params = $patrons_rs->attributes_from_api($filtered_params);
77             $filtered_params = $c->build_query_params( $filtered_params, $reserved_params );
78         }
79
80         # translate 'restricted' => 'debarred'
81         $filtered_params->{debarred} = { '!=' => undef }
82           if $restricted;
83
84         my $patrons = $patrons_rs->search( $filtered_params, $attributes );
85         if ( $patrons_rs->is_paged ) {
86             $c->add_pagination_headers(
87                 {
88                     total  => $patrons->pager->total_entries,
89                     params => $args,
90                 }
91             );
92         }
93
94         return $c->render( status => 200, openapi => $patrons->to_api );
95     }
96     catch {
97         $c->unhandled_exception($_);
98     };
99 }
100
101
102 =head3 get
103
104 Controller function that handles retrieving a single Koha::Patron object
105
106 =cut
107
108 sub get {
109     my $c = shift->openapi->valid_input or return;
110
111     return try {
112         my $patron_id = $c->validation->param('patron_id');
113         my $patron    = Koha::Patrons->find($patron_id);
114
115         unless ($patron) {
116             return $c->render( status => 404, openapi => { error => "Patron not found." } );
117         }
118
119         return $c->render( status => 200, openapi => $patron->to_api );
120     }
121     catch {
122         $c->unhandled_exception($_);
123     };
124 }
125
126 =head3 add
127
128 Controller function that handles adding a new Koha::Patron object
129
130 =cut
131
132 sub add {
133     my $c = shift->openapi->valid_input or return;
134
135     return try {
136
137         my $patron = Koha::Patron->new_from_api( $c->validation->param('body') )->store;
138
139         $c->res->headers->location( $c->req->url->to_string . '/' . $patron->borrowernumber );
140         return $c->render(
141             status  => 201,
142             openapi => $patron->to_api
143         );
144     }
145     catch {
146
147         my $to_api_mapping = Koha::Patron->new->to_api_mapping;
148
149         unless ( blessed $_ && $_->can('rethrow') ) {
150             return $c->render(
151                 status  => 500,
152                 openapi => { error => "Something went wrong, check Koha logs for details." }
153             );
154         }
155         if ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) {
156             return $c->render(
157                 status  => 409,
158                 openapi => { error => $_->error, conflict => $_->duplicate_id }
159             );
160         }
161         elsif ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) {
162             return $c->render(
163                 status  => 400,
164                 openapi => {
165                           error => "Given "
166                         . $to_api_mapping->{ $_->broken_fk }
167                         . " does not exist"
168                 }
169             );
170         }
171         elsif ( $_->isa('Koha::Exceptions::BadParameter') ) {
172             return $c->render(
173                 status  => 400,
174                 openapi => {
175                           error => "Given "
176                         . $to_api_mapping->{ $_->parameter }
177                         . " does not exist"
178                 }
179             );
180         }
181         else {
182             $c->unhandled_exception($_);
183         }
184     };
185 }
186
187
188 =head3 update
189
190 Controller function that handles updating a Koha::Patron object
191
192 =cut
193
194 sub update {
195     my $c = shift->openapi->valid_input or return;
196
197     my $patron_id = $c->validation->param('patron_id');
198     my $patron    = Koha::Patrons->find( $patron_id );
199
200     unless ($patron) {
201          return $c->render(
202              status  => 404,
203              openapi => { error => "Patron not found" }
204          );
205      }
206
207     return try {
208
209         $patron->set_from_api($c->validation->param('body'))->store;
210         $patron->discard_changes;
211         return $c->render( status => 200, openapi => $patron->to_api );
212     }
213     catch {
214         unless ( blessed $_ && $_->can('rethrow') ) {
215             return $c->render(
216                 status  => 500,
217                 openapi => {
218                     error => "Something went wrong, check Koha logs for details."
219                 }
220             );
221         }
222         if ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) {
223             return $c->render(
224                 status  => 409,
225                 openapi => { error => $_->error, conflict => $_->duplicate_id }
226             );
227         }
228         elsif ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) {
229             return $c->render(
230                 status  => 400,
231                 openapi => { error => "Given " .
232                             $patron->to_api_mapping->{$_->broken_fk}
233                             . " does not exist" }
234             );
235         }
236         elsif ( $_->isa('Koha::Exceptions::MissingParameter') ) {
237             return $c->render(
238                 status  => 400,
239                 openapi => {
240                     error      => "Missing mandatory parameter(s)",
241                     parameters => $_->parameter
242                 }
243             );
244         }
245         elsif ( $_->isa('Koha::Exceptions::BadParameter') ) {
246             return $c->render(
247                 status  => 400,
248                 openapi => {
249                     error      => "Invalid parameter(s)",
250                     parameters => $_->parameter
251                 }
252             );
253         }
254         elsif ( $_->isa('Koha::Exceptions::NoChanges') ) {
255             return $c->render(
256                 status  => 204,
257                 openapi => { error => "No changes have been made" }
258             );
259         }
260         else {
261             $c->unhandled_exception($_);
262         }
263     };
264 }
265
266 =head3 delete
267
268 Controller function that handles deleting a Koha::Patron object
269
270 =cut
271
272 sub delete {
273     my $c = shift->openapi->valid_input or return;
274
275     my $patron;
276
277     return try {
278         $patron = Koha::Patrons->find( $c->validation->param('patron_id') );
279
280         # check if loans, reservations, debarrment, etc. before deletion!
281         $patron->delete;
282         return $c->render( status => 200, openapi => {} );
283     }
284     catch {
285         unless ($patron) {
286             return $c->render(
287                 status  => 404,
288                 openapi => { error => "Patron not found" }
289             );
290         }
291         else {
292             $c->unhandled_exception($_);
293         }
294     };
295 }
296
297 =head3 guarantors_can_see_charges
298
299 Method for setting whether guarantors can see the patron's charges.
300
301 =cut
302
303 sub guarantors_can_see_charges {
304     my $c = shift->openapi->valid_input or return;
305
306     return try {
307         if ( C4::Context->preference('AllowPatronToSetFinesVisibilityForGuarantor') ) {
308             my $patron = $c->stash( 'koha.user' );
309             my $privacy_setting = ($c->req->json->{allowed}) ? 1 : 0;
310
311             $patron->privacy_guarantor_fines( $privacy_setting )->store;
312
313             return $c->render(
314                 status  => 200,
315                 openapi => {}
316             );
317         }
318         else {
319             return $c->render(
320                 status  => 403,
321                 openapi => {
322                     error =>
323                       'The current configuration doesn\'t allow the requested action.'
324                 }
325             );
326         }
327     }
328     catch {
329         $c->unhandled_exception($_);
330     };
331 }
332
333 =head3 guarantors_can_see_checkouts
334
335 Method for setting whether guarantors can see the patron's checkouts.
336
337 =cut
338
339 sub guarantors_can_see_checkouts {
340     my $c = shift->openapi->valid_input or return;
341
342     return try {
343         if ( C4::Context->preference('AllowPatronToSetCheckoutsVisibilityForGuarantor') ) {
344             my $patron = $c->stash( 'koha.user' );
345             my $privacy_setting = ( $c->req->json->{allowed} ) ? 1 : 0;
346
347             $patron->privacy_guarantor_checkouts( $privacy_setting )->store;
348
349             return $c->render(
350                 status  => 200,
351                 openapi => {}
352             );
353         }
354         else {
355             return $c->render(
356                 status  => 403,
357                 openapi => {
358                     error =>
359                       'The current configuration doesn\'t allow the requested action.'
360                 }
361             );
362         }
363     }
364     catch {
365         $c->unhandled_exception($_);
366     };
367 }
368
369 1;