Lines 11-19
package Koha::REST::V1::Suggestions;
Link Here
|
11 |
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
11 |
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
12 |
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
12 |
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 |
# |
13 |
# |
14 |
# You should have received a copy of the GNU General Public License along |
14 |
# You should have received a copy of the GNU General Public License |
15 |
# with Koha; if not, write to the Free Software Foundation, Inc., |
15 |
# along with Koha; if not, see <http:°www.gnu.org/licenses>. |
16 |
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
|
17 |
|
16 |
|
18 |
use Modern::Perl; |
17 |
use Modern::Perl; |
19 |
|
18 |
|
Lines 28-94
use Koha::Suggestions;
Link Here
|
28 |
|
27 |
|
29 |
use Koha::ItemTypes; |
28 |
use Koha::ItemTypes; |
30 |
use Koha::Libraries; |
29 |
use Koha::Libraries; |
|
|
30 |
use Koha::DateUtils; |
31 |
use List::MoreUtils qw/any/; |
31 |
use List::MoreUtils qw/any/; |
32 |
|
32 |
|
33 |
use Try::Tiny; |
33 |
use Try::Tiny; |
34 |
|
34 |
|
35 |
sub list { |
35 |
=head1 NAME |
36 |
my $c = shift->openapi->valid_input or return; |
|
|
37 |
|
36 |
|
38 |
my $suggestions; |
37 |
Koha::REST::V1::Suggestion |
39 |
my $filter; |
|
|
40 |
my $args = $c->validation->output; |
41 |
|
38 |
|
42 |
for my $filter_param ( keys %$args ) { |
39 |
=head1 API |
43 |
$filter->{$filter_param} = { LIKE => $args->{$filter_param} . '%' }; |
40 |
|
44 |
} |
41 |
=head2 Methods |
|
|
42 |
|
43 |
=head3 list |
44 |
|
45 |
List Koha::Suggestion objects |
46 |
|
47 |
=cut |
48 |
|
49 |
sub list { |
50 |
my $c = shift->openapi->valid_input or return; |
45 |
|
51 |
|
46 |
return try { |
52 |
return try { |
47 |
$suggestions = Koha::Suggestions->search($filter, \&_to_model, \&_to_api); |
53 |
my $suggestion_set = Koha::Suggestions->new; |
48 |
return $c->render( status => 200, openapi => $suggestions ); |
54 |
my $suggestions = $c->objects->search( $suggestion_set ); |
|
|
55 |
return $c->render( |
56 |
status => 200, |
57 |
openapi => $suggestions |
58 |
); |
49 |
} |
59 |
} |
50 |
catch { |
60 |
catch { |
51 |
if ( $_->isa('DBIx::Class::Exception') ) { |
61 |
$c->unhandled_exception($_); |
52 |
return $c->render( status => 500, openapi => { error => $_->{msg} } ); |
|
|
53 |
} |
54 |
else { |
55 |
return $c->render( status => 500, openapi => { error => 'Something went wrong, check the logs.' } ); |
56 |
} |
57 |
}; |
62 |
}; |
58 |
} |
63 |
} |
59 |
|
64 |
|
|
|
65 |
=head3 get |
66 |
|
67 |
Controller function that handles retrieving a single Koha::Suggestion object |
68 |
|
69 |
=cut |
70 |
|
60 |
sub get { |
71 |
sub get { |
61 |
my $c = shift->openapi->valid_input or return; |
72 |
my $c = shift->openapi->valid_input or return; |
62 |
my $args = $c->validation->output; |
|
|
63 |
|
73 |
|
64 |
my $suggestion = Koha::Suggestions->find($args->{suggestionid}); |
74 |
return try { |
65 |
unless ($suggestion) { |
75 |
my $suggestion_id = $c->validation->param('suggestion_id'); |
66 |
return $c->render( status => 404, openapi => {error => 'Suggestion not found'}); |
76 |
my $suggestion = Koha::Suggestions->find($suggestion_id); |
67 |
} |
77 |
|
|
|
78 |
unless ($suggestion) { |
79 |
return $c->render( status => 404, openapi => { error => "Suggestion not found." } ); |
80 |
} |
68 |
|
81 |
|
69 |
return $c->render( status => 200, openapi => $suggestion->unblessed ); |
82 |
return $c->render( status => 200, openapi => $suggestion->to_api ); |
|
|
83 |
} |
84 |
catch { |
85 |
$c->unhandled_exception($_); |
86 |
}; |
70 |
} |
87 |
} |
71 |
|
88 |
|
|
|
89 |
=head3 add |
90 |
|
91 |
Controller function that handles adding a new Koha::Suggestion object |
92 |
|
93 |
=cut |
94 |
|
72 |
sub add { |
95 |
sub add { |
73 |
my $c = shift->openapi->valid_input or return; |
96 |
my $c = shift->openapi->valid_input or return; |
74 |
my $args = $c->validation->output; |
97 |
my $params = $c->validation->param('body'); |
75 |
|
98 |
$params->{'date_created'} = dt_from_string(); |
76 |
my $suggestion = Koha::Suggestion->new( $args->{body} ); |
99 |
$params->{'status'} = 'ASKED' unless defined $params->{'status'}; |
77 |
|
100 |
|
78 |
return try { |
101 |
return try { |
79 |
$suggestion->store; |
102 |
my $suggestion = Koha::Suggestion->new_from_api( $params )->store; |
80 |
return $c->render( status => 200, openapi => $suggestion->unblessed ); |
103 |
$c->res->headers->location( $c->req->url->to_string . '/' . $suggestion->suggestionid ); |
|
|
104 |
return $c->render( |
105 |
status => 201, |
106 |
openapi => $suggestion->to_api |
107 |
); |
81 |
} |
108 |
} |
82 |
catch { |
109 |
catch { |
83 |
if ( $_->isa('DBIx::Class::Exception') ) { |
110 |
|
84 |
return $c->render( status => 500, openapi => { error => $_->msg } ); |
111 |
my $to_api_mapping = Koha::Suggestion->new->to_api_mapping; |
|
|
112 |
|
113 |
unless ( blessed $_ && $_->can('rethrow') ) { |
114 |
return $c->render( |
115 |
status => 500, |
116 |
openapi => { error => "Something went wrong, check Koha logs for details." } |
117 |
); |
118 |
} |
119 |
if ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) { |
120 |
return $c->render( |
121 |
status => 409, |
122 |
openapi => { error => $_->error, conflict => $_->duplicate_id } |
123 |
); |
124 |
} |
125 |
elsif ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) { |
126 |
return $c->render( |
127 |
status => 400, |
128 |
openapi => { |
129 |
error => "Given " |
130 |
. $to_api_mapping->{ $_->broken_fk } |
131 |
. " does not exist" |
132 |
} |
133 |
); |
134 |
} |
135 |
elsif ( $_->isa('Koha::Exceptions::BadParameter') ) { |
136 |
return $c->render( |
137 |
status => 400, |
138 |
openapi => { |
139 |
error => "Given " |
140 |
. $to_api_mapping->{ $_->parameter } |
141 |
. " does not exist" |
142 |
} |
143 |
); |
85 |
} |
144 |
} |
86 |
else { |
145 |
else { |
87 |
return $c->render( status => 500, openapi => { error => 'Something went wrong, check the logs.' } ); |
146 |
$c->unhandled_exception($_); |
88 |
} |
147 |
} |
89 |
} |
148 |
}; |
90 |
} |
149 |
} |
91 |
|
150 |
|
|
|
151 |
=head3 update |
152 |
|
153 |
Controller function that handles modifying Koha::Suggestion object |
154 |
|
155 |
=cut |
156 |
|
92 |
sub update { |
157 |
sub update { |
93 |
my $c = shift->openapi->valid_input or return; |
158 |
my $c = shift->openapi->valid_input or return; |
94 |
|
159 |
|
Lines 98-117
sub update {
Link Here
|
98 |
|
163 |
|
99 |
return try { |
164 |
return try { |
100 |
|
165 |
|
101 |
$suggestion = Koha::Suggestions->find( $args->{suggestionid} ); |
166 |
$suggestion = Koha::Suggestions->find( $args->{suggestion_id} ); |
102 |
|
167 |
|
103 |
my $body = $args->{body}; |
168 |
my $body = $args->{body}; |
104 |
|
169 |
|
105 |
# Remove unchaned fields so that we can use our body validation from the add subroutine |
170 |
# Remove unchaned fields so that we can use our body validation from the add subroutine |
106 |
foreach my $param ( keys %{ $body } ) { |
171 |
foreach my $param ( keys %{ $body } ) { |
107 |
if (exists $body->{$param}) { |
172 |
if (exists $body->{$param}) { |
108 |
delete $body->{$param} if $body->{$param} eq $suggestion->unblessed->{$param}; |
173 |
delete $body->{$param} if $body->{$param} eq $suggestion->to_api->{$param}; |
109 |
} |
174 |
} |
110 |
} |
175 |
} |
111 |
|
176 |
|
112 |
$suggestion->set( $body ); |
177 |
$suggestion->set_from_api( $body ); |
113 |
$suggestion->store(); |
178 |
$suggestion->store(); |
114 |
return $c->render( status => 200, openapi => $suggestion->unblessed ); |
179 |
return $c->render( status => 200, openapi => $suggestion->to_api ); |
115 |
} |
180 |
} |
116 |
catch { |
181 |
catch { |
117 |
if ( not defined $suggestion ) { |
182 |
if ( not defined $suggestion ) { |
Lines 127-132
sub update {
Link Here
|
127 |
|
192 |
|
128 |
} |
193 |
} |
129 |
|
194 |
|
|
|
195 |
=head3 delete |
196 |
|
197 |
Controller function that handles removing a Koha::Suggestion object |
198 |
|
199 |
=cut |
200 |
|
130 |
sub delete { |
201 |
sub delete { |
131 |
my $c = shift->openapi->valid_input or return; |
202 |
my $c = shift->openapi->valid_input or return; |
132 |
|
203 |
|
Lines 135-141
sub delete {
Link Here
|
135 |
my $suggestion; |
206 |
my $suggestion; |
136 |
|
207 |
|
137 |
return try { |
208 |
return try { |
138 |
$suggestion = Koha::Suggestions->find( $args->{suggestionid} ); |
209 |
$suggestion = Koha::Suggestions->find( $args->{suggestion_id} ); |
139 |
$suggestion->delete; |
210 |
$suggestion->delete; |
140 |
return $c->render( status => 200, openapi => '' ); |
211 |
return $c->render( status => 200, openapi => '' ); |
141 |
} |
212 |
} |
Lines 175-185
sub _validate_body {
Link Here
|
175 |
|
246 |
|
176 |
foreach my $param ( keys %{ $body } ) { |
247 |
foreach my $param ( keys %{ $body } ) { |
177 |
unless (any { /^$param$/ } @allowed_fields) { |
248 |
unless (any { /^$param$/ } @allowed_fields) { |
178 |
# Ouch ! User trying to edit field he has no rights to edit! |
249 |
# Ouch ! User trying to edit field they has no rights to edit! |
179 |
my $verb = 'specified '; |
250 |
my $verb = 'specified '; |
180 |
return $c->render( status => 403 , openapi => { |
251 |
return $c->render( status => 403 , openapi => { |
181 |
error => 'You ' . $verb . $param . ', but allowed fields are only ' . join(', ', @allowed_fields)} |
252 |
error => 'You ' . $verb . $param . ', but allowed fields are only ' . join(', ', @allowed_fields)} |
182 |
); |
253 |
); |
183 |
} |
254 |
} |
184 |
} |
255 |
} |
185 |
} |
256 |
} |
Lines 187-193
sub _validate_body {
Link Here
|
187 |
# Set user's branchcode if not specified (after validation input, because user does not |
258 |
# Set user's branchcode if not specified (after validation input, because user does not |
188 |
# necessarily have rights to choose a branchcode) |
259 |
# necessarily have rights to choose a branchcode) |
189 |
if ( not exists $body->{branchcode} ) { |
260 |
if ( not exists $body->{branchcode} ) { |
190 |
$body->{branchcode} = C4::Context->userenv->{branch}; |
261 |
$body->{branchcode} = C4::Context->userenv->{branch}; |
191 |
} |
262 |
} |
192 |
|
263 |
|
193 |
# Is suggester anonymous? |
264 |
# Is suggester anonymous? |
Lines 221-241
sub _validate_body {
Link Here
|
221 |
if ( exists $body->{itemtype} ) { |
292 |
if ( exists $body->{itemtype} ) { |
222 |
my @item_types = map {$_->unblessed->{itemtype}} Koha::ItemTypes->search; |
293 |
my @item_types = map {$_->unblessed->{itemtype}} Koha::ItemTypes->search; |
223 |
return $c->render( status => 400 , openapi => {error => 'itemtype must be one of ' . join(', ', @item_types)} ) |
294 |
return $c->render( status => 400 , openapi => {error => 'itemtype must be one of ' . join(', ', @item_types)} ) |
224 |
unless grep(/^$body->{itemtype}$/, @item_types); |
295 |
unless grep(/^$body->{itemtype}$/, @item_types); |
225 |
} |
296 |
} |
226 |
|
297 |
|
227 |
# Check branchcode is valid |
298 |
# Check branchcode is valid |
228 |
if ( exists $body->{branchcode} ) { |
299 |
if ( exists $body->{branchcode} ) { |
229 |
my @branch_codes = map {$_->unblessed->{branchcode}} Koha::Libraries->search; |
300 |
my @branch_codes = map {$_->unblessed->{branchcode}} Koha::Libraries->search; |
230 |
return $c->render( status => 400 , openapi => {error => 'branchcode must be one of ' . join(', ', @branch_codes)} ) |
301 |
return $c->render( status => 400 , openapi => {error => 'branchcode must be one of ' . join(', ', @branch_codes)} ) |
231 |
unless grep(/^$body->{branchcode}$/, @branch_codes); |
302 |
unless grep(/^$body->{branchcode}$/, @branch_codes); |
232 |
} |
303 |
} |
233 |
|
304 |
|
234 |
# Check patron reason is valid |
305 |
# Check patron reason is valid |
235 |
if ( exists $body->{patronreason} ) { |
306 |
if ( exists $body->{patronreason} ) { |
236 |
my @authorized_values = map { $_->{authorised_value} } @{ C4::Koha::GetAuthorisedValues('OPAC_SUG') }; |
307 |
my @authorized_values = map { $_->{authorised_value} } @{ C4::Koha::GetAuthorisedValues('OPAC_SUG') }; |
237 |
return $c->render( status => 400, openapi => {error => 'patronreason must be one of ' . join(', ', @authorized_values)} ) |
308 |
return $c->render( status => 400, openapi => {error => 'patronreason must be one of ' . join(', ', @authorized_values)} ) |
238 |
unless grep(/^$body->{patronreason}$/, @authorized_values); |
309 |
unless grep(/^$body->{patronreason}$/, @authorized_values); |
239 |
} |
310 |
} |
240 |
|
311 |
|
241 |
# Check suggestedby patron exists |
312 |
# Check suggestedby patron exists |
Lines 253-390
sub _validate_body {
Link Here
|
253 |
# Everything's fine .. |
324 |
# Everything's fine .. |
254 |
return 0; |
325 |
return 0; |
255 |
} |
326 |
} |
256 |
=head3 _to_api |
|
|
257 |
|
258 |
Helper function that maps unblessed Koha::Suggestion objects into REST api |
259 |
attribute names. |
260 |
|
261 |
=cut |
262 |
|
263 |
sub _to_api { |
264 |
my $suggestion = shift; |
265 |
|
266 |
# Rename attributes |
267 |
foreach my $column ( keys %{ $Koha::REST::V1::Suggestions::to_api_mapping } ) { |
268 |
my $mapped_column = $Koha::REST::V1::Suggestions::to_api_mapping->{$column}; |
269 |
if ( exists $suggestion->{ $column } |
270 |
&& defined $mapped_column ) |
271 |
{ |
272 |
# key != undef |
273 |
$suggestion->{ $mapped_column } = delete $suggestion->{ $column }; |
274 |
} |
275 |
elsif ( exists $suggestion->{ $column } |
276 |
&& !defined $mapped_column ) |
277 |
{ |
278 |
# key == undef |
279 |
delete $suggestion->{ $column }; |
280 |
} |
281 |
} |
282 |
|
283 |
return $suggestion; |
284 |
} |
285 |
|
286 |
=head3 _to_model |
287 |
|
288 |
Helper function that maps REST api objects into Koha::Suggestion |
289 |
attribute names. |
290 |
|
291 |
=cut |
292 |
|
293 |
sub _to_model { |
294 |
my $suggestion = shift; |
295 |
|
296 |
foreach my $attribute ( keys %{ $Koha::REST::V1::Suggestions::to_model_mapping } ) { |
297 |
my $mapped_attribute = $Koha::REST::V1::Suggestions::to_model_mapping->{$attribute}; |
298 |
if ( exists $suggestion->{ $attribute } |
299 |
&& defined $mapped_attribute ) |
300 |
{ |
301 |
# key => !undef |
302 |
$suggestion->{ $mapped_attribute } = delete $suggestion->{ $attribute }; |
303 |
} |
304 |
elsif ( exists $suggestion->{ $attribute } |
305 |
&& !defined $mapped_attribute ) |
306 |
{ |
307 |
# key => undef / to be deleted |
308 |
delete $suggestion->{ $attribute }; |
309 |
} |
310 |
} |
311 |
|
312 |
return $suggestion; |
313 |
} |
314 |
|
315 |
=head2 Global variables |
316 |
|
317 |
=head3 $to_api_mapping |
318 |
|
319 |
=cut |
320 |
|
321 |
our $to_api_mapping = { |
322 |
suggestionid => 'suggestion_id', |
323 |
suggestedby => 'suggested_by', |
324 |
suggesteddate => 'suggestion_date', |
325 |
managedby => 'managed_by', |
326 |
manageddate => 'managed_date', |
327 |
accepteddate => 'accepted_date', |
328 |
rejectedby => 'rejected_by', |
329 |
rejectiondate => 'rejected_date', |
330 |
STATUS => 'status', |
331 |
note => 'note', |
332 |
author => 'author', |
333 |
title => 'title', |
334 |
copyrightdate => 'copyright_date', |
335 |
publishercode => 'publisher_code', |
336 |
date => 'date_created', |
337 |
volumedesc => 'volume_desc', |
338 |
publicationyear => 'publication_year', |
339 |
place => 'publication_place', |
340 |
isbn => 'isbn', |
341 |
biblionumber => 'biblio_id', |
342 |
reason => 'reason', |
343 |
patronreason => 'patron_reason', |
344 |
budgetid => 'budget_id', |
345 |
branchcode => 'library_id', |
346 |
collectiontitle => 'collection_title', |
347 |
itemtype => 'item_type', |
348 |
quantity => 'quantity', |
349 |
currency => 'currency', |
350 |
price => 'item_price', |
351 |
total => 'total_price' |
352 |
}; |
353 |
|
354 |
=head3 $to_model_mapping |
355 |
|
356 |
=cut |
357 |
|
358 |
our $to_model_mapping = { |
359 |
suggestion_id => 'suggestionid', |
360 |
suggested_by => 'suggestedby', |
361 |
suggestion_date => 'suggesteddate', |
362 |
managed_by => 'managedby', |
363 |
managed_date => 'manageddate', |
364 |
accepted_date => 'accepteddate', |
365 |
rejected_by => 'rejectedby', |
366 |
rejected_date => 'rejectiondate', |
367 |
status => 'STATUS', |
368 |
note => 'note', |
369 |
author => 'author', |
370 |
title => 'title', |
371 |
copyright_date => 'copyrightdate', |
372 |
publisher_code => 'publishercode', |
373 |
date_created => 'date', |
374 |
volume_desc => 'volumedesc', |
375 |
publication_year => 'publicationyear', |
376 |
publication_place => 'place', |
377 |
isbn => 'isbn', |
378 |
biblio_id => 'biblionumber', |
379 |
reason => 'reason', |
380 |
patron_reason => 'patronreason', |
381 |
budget_id => 'budgetid', |
382 |
library_id => 'branchcode', |
383 |
collection_title => 'collectiontitle', |
384 |
item_type => 'itemtype', |
385 |
quantity => 'quantity', |
386 |
currency => 'currency', |
387 |
item_price => 'price', |
388 |
total_price => 'total' |
389 |
}; |
390 |
1; |
327 |
1; |