Bug 16825: Add API route for getting an item
[koha.git] / Koha / REST / V1 / Items.pm
1 package Koha::REST::V1::Items;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
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.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with Koha; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 use Modern::Perl;
19
20 use Mojo::Base 'Mojolicious::Controller';
21 use Mojo::JSON;
22
23 use C4::Auth qw( haspermission );
24 use C4::Items qw( GetHiddenItemnumbers );
25
26 use Koha::Items;
27
28 use Try::Tiny;
29
30 sub get {
31     my $c = shift->openapi->valid_input or return;
32
33     my $item;
34     try {
35         $item = Koha::Items->find($c->validation->param('item_id'));
36         return $c->render( status => 200, openapi => _to_api( $item->TO_JSON ) );
37     }
38     catch {
39         unless ( defined $item ) {
40             return $c->render( status => 404,
41                                openapi => { error => 'Item not found'} );
42         }
43         if ( $_->isa('DBIx::Class::Exception') ) {
44             return $c->render( status  => 500,
45                                openapi => { error => $_->{msg} } );
46         }
47         else {
48             return $c->render( status => 500,
49                 openapi => { error => "Something went wrong, check the logs."} );
50         }
51     };
52 }
53
54 =head3 _to_api
55
56 Helper function that maps unblessed Koha::Hold objects into REST api
57 attribute names.
58
59 =cut
60
61 sub _to_api {
62     my $item = shift;
63
64     # Rename attributes
65     foreach my $column ( keys %{ $Koha::REST::V1::Items::to_api_mapping } ) {
66         my $mapped_column = $Koha::REST::V1::Items::to_api_mapping->{$column};
67         if (    exists $item->{ $column }
68              && defined $mapped_column )
69         {
70             # key != undef
71             $item->{ $mapped_column } = delete $item->{ $column };
72         }
73         elsif (    exists $item->{ $column }
74                 && !defined $mapped_column )
75         {
76             # key == undef
77             delete $item->{ $column };
78         }
79     }
80
81     return $item;
82 }
83
84 =head3 _to_model
85
86 Helper function that maps REST api objects into Koha::Hold
87 attribute names.
88
89 =cut
90
91 sub _to_model {
92     my $item = shift;
93
94     foreach my $attribute ( keys %{ $Koha::REST::V1::Items::to_model_mapping } ) {
95         my $mapped_attribute = $Koha::REST::V1::Items::to_model_mapping->{$attribute};
96         if (    exists $item->{ $attribute }
97              && defined $mapped_attribute )
98         {
99             # key => !undef
100             $item->{ $mapped_attribute } = delete $item->{ $attribute };
101         }
102         elsif (    exists $item->{ $attribute }
103                 && !defined $mapped_attribute )
104         {
105             # key => undef / to be deleted
106             delete $item->{ $attribute };
107         }
108     }
109
110     return $item;
111 }
112
113 =head2 Global variables
114
115 =head3 $to_api_mapping
116
117 =cut
118
119 our $to_api_mapping = {
120     itemnumber => 'item_id',
121     biblionumber => 'biblio_id',
122     biblioitemnumber => undef,
123     barcode => 'external_id',
124     dateaccessioned => 'acquisition_date',
125     booksellerid => 'acquisition_source',
126     homebranch => 'home_library_id',
127     price => 'purchase_price',
128     replacementprice => 'replacement_price',
129     replacementpricedate => 'replacement_price_date',
130     datelastborrowed => 'last_checkout_date',
131     datelastseen => 'last_seen_date',
132     stack => undef,
133     notforloan => 'not_for_loan_status',
134     damaged => 'damaged_status',
135     damaged_on => 'damaged_date',
136     itemlost => 'lost_status',
137     itemlost_on => 'lost_date',
138     withdrawn => 'withdrawn',
139     withdrawn_on => 'withdrawn_date',
140     itemcallnumber => 'callnumber',
141     coded_location_qualifier => 'coded_location_qualifier',
142     issues => 'checkouts_count',
143     renewals => 'renewals_count',
144     reserves => 'holds_count',
145     restricted => 'restricted_status',
146     itemnotes => 'public_notes',
147     itemnotes_nonpublic => 'internal_notes',
148     holdingbranch => 'holding_library_id',
149     paidfor => undef,
150     timestamp => 'timestamp',
151     location => 'location',
152     permanent_location => 'permanent_location',
153     onloan => 'checked_out_date',
154     cn_source => 'call_number_source',
155     cn_sort => 'call_number_sort',
156     ccode => 'collection_code',
157     materials => 'materials_notes',
158     uri => 'uri',
159     itype => 'item_type',
160     more_subfields_xml => 'extended_subfields',
161     enumchron => 'serial_issue_number',
162     copynumber => 'copy_number',
163     stocknumber => 'inventory_number',
164     new_status => 'new_status'
165 };
166
167 =head3 $to_model_mapping
168
169 =cut
170
171 our $to_model_mapping = {
172     item_id => 'itemnumber',
173     biblio_id => 'biblionumber',
174     external_id => 'barcode',
175     acquisition_date => 'dateaccessioned',
176     acquisition_source => 'booksellerid',
177     home_library_id => 'homebranch',
178     purchase_price => 'price',
179     replacement_price => 'replacementprice',
180     replacement_price_date => 'replacementpricedate',
181     last_checkout_date => 'datelastborrowed',
182     last_seen_date => 'datelastseen',
183     not_for_loan_status => 'notforloan',
184     damaged_status => 'damaged',
185     damaged_date => 'damaged_on',
186     lost_status => 'itemlost',
187     lost_date => 'itemlost_on',
188     withdrawn => 'withdrawn',
189     withdrawn_date => 'withdrawn_on',
190     callnumber => 'itemcallnumber',
191     coded_location_qualifier => 'coded_location_qualifier',
192     checkouts_count => 'issues',
193     renewals_count => 'renewals',
194     holds_count => 'reserves',
195     restricted_status => 'restricted',
196     public_notes => 'itemnotes',
197     internal_notes => 'itemnotes_nonpublic',
198     holding_library_id => 'holdingbranch',
199     timestamp => 'timestamp',
200     location => 'location',
201     permanent_location => 'permanent_location',
202     checked_out_date => 'onloan',
203     call_number_source => 'cn_source',
204     call_number_sort => 'cn_sort',
205     collection_code => 'ccode',
206     materials_notes => 'materials',
207     uri => 'uri',
208     item_type => 'itype',
209     extended_subfields => 'more_subfields_xml',
210     serial_issue_number => 'enumchron',
211     copy_number => 'copynumber',
212     inventory_number => 'stocknumber',
213     new_status => 'new_status'
214 };
215
216 1;