View | Details | Raw Unified | Return to bug 34008
Collapse All | Expand All

(-)a/Koha/ItemType.pm (-32 / +53 lines)
Lines 17-23 package Koha::ItemType; Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
21
use C4::Koha qw( getitemtypeimagelocation );
20
use C4::Koha qw( getitemtypeimagelocation );
22
use C4::Languages;
21
use C4::Languages;
23
use Koha::Caches;
22
use Koha::Caches;
Lines 52-59 sub store { Link Here
52
51
53
    if ( !$self->in_storage ) {
52
    if ( !$self->in_storage ) {
54
        $flush = 1;
53
        $flush = 1;
55
    }
54
    } else {
56
    else {
57
        my $self_from_storage = $self->get_from_storage;
55
        my $self_from_storage = $self->get_from_storage;
58
        $flush = 1 if ( $self_from_storage->description ne $self->description );
56
        $flush = 1 if ( $self_from_storage->description ne $self->description );
59
    }
57
    }
Lines 96-117 sub image_location { Link Here
96
sub translated_description {
94
sub translated_description {
97
    my ( $self, $lang ) = @_;
95
    my ( $self, $lang ) = @_;
98
    if ( my $translated_description = eval { $self->get_column('translated_description') } ) {
96
    if ( my $translated_description = eval { $self->get_column('translated_description') } ) {
97
99
        # If the value has already been fetched (eg. from sarch_with_localization),
98
        # If the value has already been fetched (eg. from sarch_with_localization),
100
        # do not search for it again
99
        # do not search for it again
101
        # Note: This is a bit hacky but should be fast
100
        # Note: This is a bit hacky but should be fast
102
        return $translated_description
101
        return $translated_description
103
             ? $translated_description
102
            ? $translated_description
104
             : $self->description;
103
            : $self->description;
105
    }
104
    }
106
    $lang ||= C4::Languages::getlanguage;
105
    $lang ||= C4::Languages::getlanguage;
107
    my $translated_description = Koha::Localizations->search({
106
    my $translated_description = Koha::Localizations->search(
108
        code => $self->itemtype,
107
        {
109
        entity => 'itemtypes',
108
            code   => $self->itemtype,
110
        lang => $lang
109
            entity => 'itemtypes',
111
    })->next;
110
            lang   => $lang
111
        }
112
    )->next;
112
    return $translated_description
113
    return $translated_description
113
         ? $translated_description->translation
114
        ? $translated_description->translation
114
         : $self->description;
115
        : $self->description;
115
}
116
}
116
117
117
=head3 translated_descriptions
118
=head3 translated_descriptions
Lines 119-136 sub translated_description { Link Here
119
=cut
120
=cut
120
121
121
sub translated_descriptions {
122
sub translated_descriptions {
122
    my ( $self ) = @_;
123
    my ($self) = @_;
123
    my @translated_descriptions = Koha::Localizations->search(
124
    my @translated_descriptions = Koha::Localizations->search(
124
        {   entity => 'itemtypes',
125
        {
126
            entity => 'itemtypes',
125
            code   => $self->itemtype,
127
            code   => $self->itemtype,
126
        }
128
        }
127
    )->as_list;
129
    )->as_list;
128
    return [ map {
130
    return [
129
        {
131
        map {
130
            lang => $_->lang,
132
            {
131
            translation => $_->translation,
133
                lang        => $_->lang,
132
        }
134
                translation => $_->translation,
133
    } @translated_descriptions ];
135
            }
136
        } @translated_descriptions
137
    ];
134
}
138
}
135
139
136
=head3 can_be_deleted
140
=head3 can_be_deleted
Lines 142-149 Counts up the number of biblioitems and items with itemtype (code) and hands bac Link Here
142
=cut
146
=cut
143
147
144
sub can_be_deleted {
148
sub can_be_deleted {
145
    my ($self) = @_;
149
    my ($self)         = @_;
146
    my $nb_items = Koha::Items->search( { itype => $self->itemtype } )->count;
150
    my $nb_items       = Koha::Items->search( { itype => $self->itemtype } )->count;
147
    my $nb_biblioitems = Koha::Biblioitems->search( { itemtype => $self->itemtype } )->count;
151
    my $nb_biblioitems = Koha::Biblioitems->search( { itemtype => $self->itemtype } )->count;
148
    return $nb_items + $nb_biblioitems == 0 ? 1 : 0;
152
    return $nb_items + $nb_biblioitems == 0 ? 1 : 0;
149
}
153
}
Lines 162-171 sub may_article_request { Link Here
162
    my $itemtype = $self->itemtype;
166
    my $itemtype = $self->itemtype;
163
    my $category = $params->{categorycode};
167
    my $category = $params->{categorycode};
164
168
165
    my $guess = Koha::CirculationRules->guess_article_requestable_itemtypes({
169
    my $guess = Koha::CirculationRules->guess_article_requestable_itemtypes(
166
        $category ? ( categorycode => $category ) : (),
170
        {
167
    });
171
            $category ? ( categorycode => $category ) : (),
168
    return ( $guess->{ $itemtype // q{} } || $guess->{ '*' } ) ? 1 : q{};
172
        }
173
    );
174
    return ( $guess->{ $itemtype // q{} } || $guess->{'*'} ) ? 1 : q{};
169
}
175
}
170
176
171
=head3 _library_limits
177
=head3 _library_limits
Lines 176-183 sub may_article_request { Link Here
176
182
177
sub _library_limits {
183
sub _library_limits {
178
    return {
184
    return {
179
        class => "ItemtypesBranch",
185
        class   => "ItemtypesBranch",
180
        id => "itemtype",
186
        id      => "itemtype",
181
        library => "branchcode",
187
        library => "branchcode",
182
    };
188
    };
183
}
189
}
Lines 189-198 sub _library_limits { Link Here
189
=cut
195
=cut
190
196
191
sub parent {
197
sub parent {
192
    my ( $self ) = @_;
198
    my ($self) = @_;
193
    my $parent_rs = $self->_result->parent_type;
199
    my $parent_rs = $self->_result->parent_type;
194
    return unless $parent_rs;
200
    return unless $parent_rs;
195
    return Koha::ItemType->_new_from_dbic( $parent_rs );
201
    return Koha::ItemType->_new_from_dbic($parent_rs);
196
202
197
}
203
}
198
204
Lines 203-210 sub parent { Link Here
203
=cut
209
=cut
204
210
205
sub children_with_localization {
211
sub children_with_localization {
206
    my ( $self ) = @_;
212
    my ($self) = @_;
207
    return Koha::ItemTypes->search_with_localization({ parent_type => $self->itemtype });
213
    return Koha::ItemTypes->search_with_localization( { parent_type => $self->itemtype } );
214
}
215
216
=head3 to_api_mapping
217
218
This method returns the mapping for representing a Koha::ItemType object
219
on the API.
220
221
=cut
222
223
sub to_api_mapping {
224
    return { 'itemtype' => 'item_type' };
225
}
226
227
sub from_api_mapping {
228
    return { 'item_type' => 'itemtype' };
208
}
229
}
209
230
210
=head3 type
231
=head3 type
(-)a/Koha/REST/V1/ItemTypes.pm (+48 lines)
Line 0 Link Here
1
package Koha::REST::V1::ItemTypes;
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::ItemTypes;
23
24
use Try::Tiny;
25
26
=head1 API
27
28
=head2 Methods
29
30
=head3 list
31
32
=cut
33
34
sub list {
35
    my $c = shift->openapi->valid_input or return;
36
37
    return try {
38
        my $itemtypes_set = Koha::ItemTypes->new;
39
        my $itemtypes     = $c->objects->search( $itemtypes_set );
40
41
        return $c->render( status => 200, openapi => $itemtypes );
42
    } catch {
43
        $c->unhandled_exception($_);
44
    };
45
46
}
47
48
1;
(-)a/api/v1/swagger/definitions/item_type.yaml (+96 lines)
Line 0 Link Here
1
---
2
type: object
3
properties:
4
  item_type:
5
    type: string
6
    description: Unique key, a code associated with the item type
7
    readOnly: true
8
  parent_type:
9
    description: Unique key, a code associated with the parent item type
10
    type:
11
      - string
12
      - "null"
13
  description:
14
    description: A plain text explanation of the item type
15
    type: string
16
  rentalcharge:
17
    description: The amount charged when this item is checked out/issued
18
    type:
19
      - number
20
      - "null"
21
  rentalcharge_daily:
22
    description: The amount charged for each day between checkout date and due date
23
    type:
24
      - number
25
      - "null"
26
  rentalcharge_daily_calendar:
27
    description: Controls if the daily rental fee is calculated directly or using finesCalendar
28
    type: boolean
29
  rentalcharge_hourly:
30
    description: The amount charged for each hour between checkout date and due date
31
    type:
32
      - number
33
      - "null"
34
  rentalcharge_hourly_calendar:
35
    description: Controls if the hourly rental fee is calculated directly or using finesCalendar
36
    type: boolean
37
  defaultreplacecost:
38
    description: Default replacement cost
39
    type:
40
      - number
41
      - "null"
42
  processfee:
43
    description: Default text be recorded in the column note when the processing fee is applied
44
    type:
45
      - number
46
      - "null"
47
  notforloan:
48
    description: Controls if the item is available for loan
49
    type:
50
      - boolean
51
      - "null"
52
  imageurl:
53
    description: URL for the item type icon
54
    type:
55
      - string
56
      - "null"
57
  summary:
58
    description: Information from the summary field, may include HTML
59
    type:
60
      - string
61
      - "null"
62
  checkinmsg:
63
    description: Message that is displayed when an item with the given item type is checked in
64
    type:
65
      - string
66
      - "null"
67
  checkinmsgtype:
68
    description: Type (CSS class) for the checkinmsg, can be 'alert' or 'message'
69
    type:
70
      - string
71
      - "null"
72
  sip_media_type:
73
    description: SIP2 protocol media type for this item type
74
    type:
75
      - string
76
      - "null"
77
  hideinopac:
78
    description: Hide the item type from the search options in OPAC
79
    type: boolean
80
  searchcategory:
81
    description: Group this item type with others with the same value on OPAC search options
82
    type:
83
      - string
84
      - "null"
85
  automatic_checkin:
86
    description: Controls if automatic checkin is enabled for items of this type
87
    type: boolean
88
  translated_descriptions:
89
    description: Translations of description plain text
90
    type: array
91
    items:
92
      $ref: "item_type_translated_description.yaml"
93
94
additionalProperties: false
95
required:
96
  - item_type
(-)a/api/v1/swagger/definitions/item_type_translated_description.yaml (+13 lines)
Line 0 Link Here
1
---
2
type: object
3
properties:
4
  lang:
5
    description: Language identifier
6
    type: string
7
  translation:
8
    description: Translated plain text
9
    type: string
10
additionalProperties: false
11
required:
12
  - lang
13
  - translation
(-)a/api/v1/swagger/paths/item_types.yaml (+59 lines)
Line 0 Link Here
1
---
2
/item_types:
3
  get:
4
    x-mojo-to: ItemTypes#list
5
    operationId: listItemTypes
6
    tags:
7
      - item_types
8
    summary: List item types
9
    produces:
10
      - application/json
11
    parameters:
12
      - name: x-koha-embed
13
        in: header
14
        required: false
15
        description: Embed list sent as a request header
16
        type: array
17
        items:
18
          type: string
19
          enum:
20
            - translated_descriptions
21
        collectionFormat: csv
22
      - $ref: "../swagger.yaml#/parameters/match"
23
      - $ref: "../swagger.yaml#/parameters/order_by"
24
      - $ref: "../swagger.yaml#/parameters/page"
25
      - $ref: "../swagger.yaml#/parameters/per_page"
26
      - $ref: "../swagger.yaml#/parameters/q_param"
27
      - $ref: "../swagger.yaml#/parameters/q_body"
28
    responses:
29
      200:
30
        description: A list of item types
31
        schema:
32
          items:
33
            $ref: "../swagger.yaml#/definitions/item_type"
34
          type: array
35
      400:
36
        description: Bad request
37
        schema:
38
          $ref: "../swagger.yaml#/definitions/error"
39
      403:
40
        description: Access forbidden
41
        schema:
42
          $ref: "../swagger.yaml#/definitions/error"
43
      404:
44
        description: Resource not found
45
        schema:
46
          $ref: "../swagger.yaml#/definitions/error"
47
      500:
48
        description: |-
49
          Internal server error. Possible `error_code` attribute values:
50
          * `internal_server_error`
51
        schema:
52
          $ref: "../swagger.yaml#/definitions/error"
53
      503:
54
        description: Under maintenance
55
        schema:
56
          $ref: "../swagger.yaml#/definitions/error"
57
    x-koha-authorization:
58
      permissions:
59
        catalogue: 1
(-)a/api/v1/swagger/swagger.yaml (+7 lines)
Lines 84-89 definitions: Link Here
84
    $ref: ./definitions/item.yaml
84
    $ref: ./definitions/item.yaml
85
  item_group:
85
  item_group:
86
    $ref: ./definitions/item_group.yaml
86
    $ref: ./definitions/item_group.yaml
87
  item_type:
88
    $ref: ./definitions/item_type.yaml
87
  job:
89
  job:
88
    $ref: ./definitions/job.yaml
90
    $ref: ./definitions/job.yaml
89
  library:
91
  library:
Lines 299-304 paths: Link Here
299
    $ref: ./paths/import_batch_profiles.yaml#/~1import_batch_profiles
301
    $ref: ./paths/import_batch_profiles.yaml#/~1import_batch_profiles
300
  "/import_batch_profiles/{import_batch_profile_id}":
302
  "/import_batch_profiles/{import_batch_profile_id}":
301
    $ref: "./paths/import_batch_profiles.yaml#/~1import_batch_profiles~1{import_batch_profile_id}"
303
    $ref: "./paths/import_batch_profiles.yaml#/~1import_batch_profiles~1{import_batch_profile_id}"
304
  /item_types:
305
    $ref: ./paths/item_types.yaml#/~1item_types
302
  /items:
306
  /items:
303
    $ref: ./paths/items.yaml#/~1items
307
    $ref: ./paths/items.yaml#/~1items
304
  "/items/{item_id}":
308
  "/items/{item_id}":
Lines 964-969 tags: Link Here
964
  - description: "Manage items\n"
968
  - description: "Manage items\n"
965
    name: items
969
    name: items
966
    x-displayName: Items
970
    x-displayName: Items
971
  - description: "Manage item types\n"
972
    name: item_types
973
    x-displayName: Item Types
967
  - description: "Manage jobs\n"
974
  - description: "Manage jobs\n"
968
    name: jobs
975
    name: jobs
969
    x-displayName: Jobs
976
    x-displayName: Jobs
(-)a/t/db_dependent/api/v1/item_types.t (-1 / +142 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
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 Test::More tests => 1;
21
use Test::Mojo;
22
23
use t::lib::TestBuilder;
24
use t::lib::Mocks;
25
26
use Koha::ItemTypes;
27
use Koha::Database;
28
29
my $schema  = Koha::Database->new->schema;
30
my $builder = t::lib::TestBuilder->new;
31
32
my $t = Test::Mojo->new('Koha::REST::V1');
33
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
34
35
subtest 'list_item_types() tests' => sub {
36
37
    plan tests => 12;
38
39
    $schema->storage->txn_begin;
40
41
    my $item_type = $builder->build_object(
42
        {
43
            class => 'Koha::ItemTypes',
44
            value => {
45
                itemtype                     => 'TEST_IT',
46
                parent_type                  => undef,
47
                description                  => 'Test item type',
48
                rentalcharge                 => 100.0,
49
                rentalcharge_daily           => 50.,
50
                rentalcharge_daily_calendar  => 0,
51
                rentalcharge_hourly          => 0.60,
52
                rentalcharge_hourly_calendar => 1,
53
                defaultreplacecost           => 1000.0,
54
                processfee                   => 20.0,
55
                notforloan                   => 0,
56
                imageurl          => 'https://upload.wikimedia.org/wikipedia/commons/1/1f/202208_test-tube-4.svg',
57
                summary           => 'An item type for testing',
58
                checkinmsg        => 'Checking in test',
59
                checkinmsgtype    => 'message',
60
                sip_media_type    => 'spt',
61
                hideinopac        => 1,
62
                searchcategory    => 'test search category',
63
                automatic_checkin => 0,
64
            }
65
        }
66
    );
67
68
    my $en = $builder->build_object(
69
        {
70
            class => 'Koha::Localizations',
71
            value => {
72
                entity      => 'itemtypes',
73
                code        => 'TEST_IT',
74
                lang        => 'en',
75
                translation => 'English word "test"',
76
            }
77
        }
78
    );
79
    my $sv = $builder->build_object(
80
        {
81
            class => 'Koha::Localizations',
82
            value => {
83
                entity      => 'itemtypes',
84
                code        => 'TEST_IT',
85
                lang        => 'sv_SE',
86
                translation => 'Swedish word "test"',
87
            }
88
        }
89
    );
90
91
    my $librarian = $builder->build_object(
92
        {
93
            class => 'Koha::Patrons',
94
            value => { flags => 2**2 }    # catalogue flag = 2
95
        }
96
    );
97
    my $password = 'thePassword123';
98
    $librarian->set_password( { password => $password, skip_validation => 1 } );
99
    my $userid = $librarian->userid;
100
101
    my $patron = $builder->build_object(
102
        {
103
            class => 'Koha::Patrons',
104
            value => { flags => 0 }
105
        }
106
    );
107
108
    $patron->set_password( { password => $password, skip_validation => 1 } );
109
    my $unauth_userid = $patron->userid;
110
111
    ## Authorized user tests
112
    # No category, 404 expected
113
    $t->get_ok("//$userid:$password@/api/v1/item_types")->status_is(200)->json_has('/0');
114
115
    for my $json ( @{ $t->tx->res->json } ) {
116
        if ( $json->{item_type} eq 'TEST_IT' ) {
117
            is( $json->{description}, 'Test item type' );
118
            ok( !exists $json->{translated_descriptions} );
119
        }
120
    }
121
122
    $t->get_ok( "//$userid:$password@/api/v1/item_types" => { 'x-koha-embed' => 'translated_descriptions' } )
123
        ->status_is(200)->json_has('/0');
124
125
    for my $json ( @{ $t->tx->res->json } ) {
126
        if ( $json->{item_type} eq 'TEST_IT' ) {
127
            is( $json->{description}, 'Test item type' );
128
            is_deeply(
129
                $json->{translated_descriptions},
130
                [
131
                    { lang => 'en',    translation => 'English word "test"' },
132
                    { lang => 'sv_SE', translation => 'Swedish word "test"' },
133
                ]
134
            );
135
        }
136
    }
137
138
    # Unauthorized access
139
    $t->get_ok("//$unauth_userid:$password@/api/v1/item_types")->status_is(403);
140
141
    $schema->storage->txn_rollback;
142
};

Return to bug 34008