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

(-)a/Koha/ItemType.pm (+11 lines)
Lines 153-158 sub parent { Link Here
153
153
154
}
154
}
155
155
156
=head3 children_with_localization
157
158
    Returns the ItemType objects of the children of this type or undef.
159
160
=cut
161
162
sub children_with_localization {
163
    my ( $self ) = @_;
164
    return Koha::ItemTypes->search_with_localization({ parent_type => $self->itemtype });
165
}
166
156
=head3 type
167
=head3 type
157
168
158
=cut
169
=cut
(-)a/Koha/Template/Plugin/ItemTypes.pm (-2 / +5 lines)
Lines 25-33 use base qw( Template::Plugin ); Link Here
25
use Koha::ItemTypes;
25
use Koha::ItemTypes;
26
26
27
sub GetDescription {
27
sub GetDescription {
28
    my ( $self, $itemtypecode ) = @_;
28
    my ( $self, $itemtypecode, $want_parent ) = @_;
29
    my $itemtype = Koha::ItemTypes->find( $itemtypecode );
29
    my $itemtype = Koha::ItemTypes->find( $itemtypecode );
30
    return $itemtype ? $itemtype->translated_description : q{};
30
    return q{} unless $itemtype;
31
    my $parent;
32
    $parent = $itemtype->parent if $want_parent;
33
    return $parent ? $parent->translated_description . "->" . $itemtype->translated_description : $itemtype->translated_description;
31
}
34
}
32
35
33
sub Get {
36
sub Get {
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt (-1 / +35 lines)
Lines 57-62 Link Here
57
            <li>default (all libraries), all patron categories, same item type</li>
57
            <li>default (all libraries), all patron categories, same item type</li>
58
            <li>default (all libraries), all patron categories, all item types</li>
58
            <li>default (all libraries), all patron categories, all item types</li>
59
        </ul>
59
        </ul>
60
61
        <p>Where an itemtype has a parent, the rule will display as "Parent->Child" and the number of
62
        current checkouts allowed will be limited to either the maximum for the parent (counting sibling types)
63
        or the specific rule's type, whichever is less.</p>
60
        <p>To modify a rule, create a new one with the same patron category and item type.</p>
64
        <p>To modify a rule, create a new one with the same patron category and item type.</p>
61
    </div>
65
    </div>
62
    <div>
66
    <div>
Lines 86-92 Link Here
86
            <table id="default-circulation-rules">
90
            <table id="default-circulation-rules">
87
            <thead>
91
            <thead>
88
            <tr>
92
            <tr>
93
                <th>&nbsp;</th>
89
                <th>Patron category</th>
94
                <th>Patron category</th>
95
                <th>&nbsp;</th>
90
                <th>Item type</th>
96
                <th>Item type</th>
91
                <th>Actions</th>
97
                <th>Actions</th>
92
                <th>Note</th>
98
                <th>Note</th>
Lines 160-165 Link Here
160
                        [% IF show_rule %]
166
                        [% IF show_rule %]
161
                            [% SET row_count = row_count + 1 %]
167
                            [% SET row_count = row_count + 1 %]
162
                            <tr row_countd="row_[% row_count | html %]">
168
                            <tr row_countd="row_[% row_count | html %]">
169
                                    <td>[% IF ( c == undef ) %]1[% ELSE %]0[% END %]</td>
163
                                    <td>
170
                                    <td>
164
                                        [% IF c == undef %]
171
                                        [% IF c == undef %]
165
                                            <em>All</em>
172
                                            <em>All</em>
Lines 167-177 Link Here
167
                                            [% Categories.GetName(c) | html %]
174
                                            [% Categories.GetName(c) | html %]
168
                                        [% END %]
175
                                        [% END %]
169
                                    </td>
176
                                    </td>
177
                                    <td>[% IF ( i == undef ) %]1[% ELSE %]0[% END %]</td>
170
                                    <td>
178
                                    <td>
171
                                        [% IF i == undef %]
179
                                        [% IF i == undef %]
172
                                            <em>All</em>
180
                                            <em>All</em>
173
                                        [% ELSE %]
181
                                        [% ELSE %]
174
                                            [% ItemTypes.GetDescription(i) | html %]
182
                                            [% ItemTypes.GetDescription(i,1) | html %]
175
                                        [% END %]
183
                                        [% END %]
176
                                    </td>
184
                                    </td>
177
                                    <td class="actions">
185
                                    <td class="actions">
Lines 310-315 Link Here
310
                    [% END %]
318
                    [% END %]
311
                [% END %]
319
                [% END %]
312
                <tr id="edit_row">
320
                <tr id="edit_row">
321
                    <td>2</td>
313
                    <td>
322
                    <td>
314
                        <select name="categorycode" id="categorycode">
323
                        <select name="categorycode" id="categorycode">
315
                            <option value="*">All</option>
324
                            <option value="*">All</option>
Lines 318-328 Link Here
318
                        [% END %]
327
                        [% END %]
319
                        </select>
328
                        </select>
320
                    </td>
329
                    </td>
330
                    <td>0</td>
321
                    <td>
331
                    <td>
322
                        <select name="itemtype" id="matrixitemtype" style="width:13em;">
332
                        <select name="itemtype" id="matrixitemtype" style="width:13em;">
323
                            <option value="*">All</option>
333
                            <option value="*">All</option>
324
                        [% FOREACH itemtypeloo IN itemtypeloop %]
334
                        [% FOREACH itemtypeloo IN itemtypeloop %]
335
                            [% NEXT IF itemtypeloo.parent_type %]
325
                            <option value="[% itemtypeloo.itemtype | html %]">[% itemtypeloo.translated_description | html %]</option>
336
                            <option value="[% itemtypeloo.itemtype | html %]">[% itemtypeloo.translated_description | html %]</option>
337
                            [% SET children = itemtypeloo.children_with_localization %]
338
                            [% IF children %]
339
                                <optgroup>
340
                                [% FOREACH child IN children %]
341
                                    <option value="[% child.itemtype | html %]">[% child.translated_description | html %]</option>
342
                                [% END %]
343
                                </optgroup>
344
                            [% END %]
326
                        [% END %]
345
                        [% END %]
327
                        </select>
346
                        </select>
328
                    </td>
347
                    </td>
Lines 412-418 Link Here
412
                </tr>
431
                </tr>
413
                <tfoot>
432
                <tfoot>
414
                    <tr>
433
                    <tr>
434
                      <th>&nbsp;</th>
415
                      <th>Patron category</th>
435
                      <th>Patron category</th>
436
                      <th>&nbsp;</th>
416
                      <th>Item type</th>
437
                      <th>Item type</th>
417
                      <th>&nbsp;</th>
438
                      <th>&nbsp;</th>
418
                      <th>Note</th>
439
                      <th>Note</th>
Lines 922-929 Link Here
922
943
923
[% MACRO jsinclude BLOCK %]
944
[% MACRO jsinclude BLOCK %]
924
    [% Asset.js("js/admin-menu.js") | $raw %]
945
    [% Asset.js("js/admin-menu.js") | $raw %]
946
    [% INCLUDE 'datatables.inc' %]
925
    [% INCLUDE 'calendar.inc' %]
947
    [% INCLUDE 'calendar.inc' %]
926
    <script>
948
    <script>
949
        $(document).ready(function() {
950
            $("#default-circulation-rules").dataTable($.extend(true,{},dataTablesDefaults, {
951
                "aoColumnDefs": [
952
                    { "bVisible": false, "aTargets": [ 0,2 ] },
953
                    { "bSortable": false, "aTargets": ["_all"] }
954
                ],
955
                "aaSortingFixed": [ [0,'asc'], [1,'asc'], [2,'asc'], [3,'asc'] ],
956
                "bPaginate": false,
957
                "bAutoWidth": false
958
            }));
959
        });
927
960
928
        function clear_edit(){
961
        function clear_edit(){
929
            var cancel = confirm(_("Are you sure you want to cancel your changes?"));
962
            var cancel = confirm(_("Are you sure you want to cancel your changes?"));
Lines 1009-1014 Link Here
1009
                        // select the corresponding option
1042
                        // select the corresponding option
1010
                        $(current_column).find("select option").each(function(){
1043
                        $(current_column).find("select option").each(function(){
1011
                            opt = $(this).text().toLowerCase();
1044
                            opt = $(this).text().toLowerCase();
1045
                            itm = itm.replace(/.*->(.*)/,"$1"); //If item type is part of a group we need to clear the parent description
1012
                            opt = opt.replace(/^\s*|\s*$/g,'');
1046
                            opt = opt.replace(/^\s*|\s*$/g,'');
1013
                            if ( opt == itm.toLowerCase() ) {
1047
                            if ( opt == itm.toLowerCase() ) {
1014
                                $(this).attr('selected', 'selected');
1048
                                $(this).attr('selected', 'selected');
(-)a/t/db_dependent/Koha/ItemTypes.t (-66 / +43 lines)
Lines 20-26 Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Data::Dumper;
22
use Data::Dumper;
23
use Test::More tests => 24;
23
use Test::More tests => 13;
24
24
25
use t::lib::Mocks;
25
use t::lib::Mocks;
26
use t::lib::TestBuilder;
26
use t::lib::TestBuilder;
Lines 40-93 BEGIN { Link Here
40
my $database = Koha::Database->new();
40
my $database = Koha::Database->new();
41
my $schema   = $database->schema();
41
my $schema   = $database->schema();
42
$schema->txn_begin;
42
$schema->txn_begin;
43
Koha::ItemTypes->delete;
44
43
45
Koha::ItemType->new(
44
my $builder     = t::lib::TestBuilder->new;
46
    {
45
my $initial_count = Koha::ItemTypes->search->count;
47
        itemtype       => 'type1',
46
48
        description    => 'description',
47
my $parent1 = $builder->build_object({ class => 'Koha::ItemTypes', value => { description => 'description' } });
49
        rentalcharge   => '0.00',
48
my $child1  = $builder->build_object({
50
        imageurl       => 'imageurl',
49
        class => 'Koha::ItemTypes',
51
        summary        => 'summary',
50
        value => {
52
        checkinmsg     => 'checkinmsg',
51
            parent_type => $parent1->itemtype,
53
        checkinmsgtype => 'checkinmsgtype',
52
            description => 'description',
54
        processfee         => '0.00',
53
        }
55
        defaultreplacecost => '0.00',
54
    });
56
    }
55
my $child2  = $builder->build_object({
57
)->store;
56
        class => 'Koha::ItemTypes',
58
57
        value => {
59
Koha::ItemType->new(
58
            parent_type => $parent1->itemtype,
60
    {
59
            description => 'description',
61
        itemtype       => 'type2',
60
        }
62
        description    => 'description',
61
    });
63
        rentalcharge   => '0.00',
62
my $child3  = $builder->build_object({
64
        imageurl       => 'imageurl',
63
        class => 'Koha::ItemTypes',
65
        summary        => 'summary',
64
        value => {
66
        checkinmsg     => 'checkinmsg',
65
            parent_type => $parent1->itemtype,
67
        checkinmsgtype => 'checkinmsgtype',
66
            description => 'description',
68
        processfee         => '0.00',
67
        }
69
        defaultreplacecost => '0.00',
68
    });
70
    }
71
)->store;
72
73
Koha::ItemType->new(
74
    {
75
        itemtype       => 'type3',
76
        description    => 'description',
77
        rentalcharge   => '0.00',
78
        imageurl       => 'imageurl',
79
        summary        => 'summary',
80
        checkinmsg     => 'checkinmsg',
81
        checkinmsgtype => 'checkinmsgtype',
82
        processfee         => '0.00',
83
        defaultreplacecost => '0.00',
84
    }
85
)->store;
86
69
87
Koha::Localization->new(
70
Koha::Localization->new(
88
    {
71
    {
89
        entity      => 'itemtypes',
72
        entity      => 'itemtypes',
90
        code        => 'type1',
73
        code        => $child1->itemtype,
91
        lang        => 'en',
74
        lang        => 'en',
92
        translation => 'b translated itemtype desc'
75
        translation => 'b translated itemtype desc'
93
    }
76
    }
Lines 95-101 Koha::Localization->new( Link Here
95
Koha::Localization->new(
78
Koha::Localization->new(
96
    {
79
    {
97
        entity      => 'itemtypes',
80
        entity      => 'itemtypes',
98
        code        => 'type2',
81
        code        => $child2->itemtype,
99
        lang        => 'en',
82
        lang        => 'en',
100
        translation => 'a translated itemtype desc'
83
        translation => 'a translated itemtype desc'
101
    }
84
    }
Lines 103-138 Koha::Localization->new( Link Here
103
Koha::Localization->new(
86
Koha::Localization->new(
104
    {
87
    {
105
        entity      => 'something_else',
88
        entity      => 'something_else',
106
        code        => 'type2',
89
        code        => $child2->itemtype,
107
        lang        => 'en',
90
        lang        => 'en',
108
        translation => 'another thing'
91
        translation => 'another thing'
109
    }
92
    }
110
)->store;
93
)->store;
111
94
112
my $type = Koha::ItemTypes->find('type1');
95
my $type = Koha::ItemTypes->find($child1->itemtype);
113
ok( defined($type), 'first result' );
96
ok( defined($type), 'first result' );
114
is( $type->itemtype,       'type1',          'itemtype/code' );
97
is_deeply( $type->unblessed, $child1->unblessed, "We got back the same object" );
115
is( $type->description,    'description',    'description' );
98
116
is( $type->rentalcharge+0, 0,                'rentalcharge' );
99
$type = Koha::ItemTypes->find($child2->itemtype);
117
is( $type->imageurl,       'imageurl',       'imageurl' );
118
is( $type->summary,        'summary',        'summary' );
119
is( $type->checkinmsg,     'checkinmsg',     'checkinmsg' );
120
is( $type->checkinmsgtype, 'checkinmsgtype', 'checkinmsgtype' );
121
122
$type = Koha::ItemTypes->find('type2');
123
ok( defined($type), 'second result' );
100
ok( defined($type), 'second result' );
124
is( $type->itemtype,       'type2',          'itemtype/code' );
101
is_deeply( $type->unblessed, $child2->unblessed, "We got back the same object" );
125
is( $type->description,    'description',    'description' );
126
is( $type->rentalcharge+0, 0,                'rentalcharge' );
127
is( $type->imageurl,       'imageurl',       'imageurl' );
128
is( $type->summary,        'summary',        'summary' );
129
is( $type->checkinmsg,     'checkinmsg',     'checkinmsg' );
130
is( $type->checkinmsgtype, 'checkinmsgtype', 'checkinmsgtype' );
131
102
132
t::lib::Mocks::mock_preference('language', 'en');
103
t::lib::Mocks::mock_preference('language', 'en');
133
t::lib::Mocks::mock_preference('opaclanguages', 'en');
104
t::lib::Mocks::mock_preference('opaclanguages', 'en');
134
my $itemtypes = Koha::ItemTypes->search_with_localization;
105
my $itemtypes = Koha::ItemTypes->search_with_localization;
135
is( $itemtypes->count, 3, 'There are 3 item types' );
106
is( $itemtypes->count, $initial_count + 4, 'We added 4 item types' );
136
my $first_itemtype = $itemtypes->next;
107
my $first_itemtype = $itemtypes->next;
137
is(
108
is(
138
    $first_itemtype->translated_description,
109
    $first_itemtype->translated_description,
Lines 140-146 is( Link Here
140
    'item types should be sorted by translated description'
111
    'item types should be sorted by translated description'
141
);
112
);
142
113
143
my $builder = t::lib::TestBuilder->new;
114
my $children = $parent1->children_with_localization;
115
my $first_child = $children->next;
116
is(
117
    $first_child->translated_description,
118
    'a translated itemtype desc',
119
    'item types should be sorted by translated description'
120
);
121
144
my $item_type = $builder->build_object({ class => 'Koha::ItemTypes' });
122
my $item_type = $builder->build_object({ class => 'Koha::ItemTypes' });
145
123
146
is( $item_type->can_be_deleted, 1, 'An item type that is not used can be deleted');
124
is( $item_type->can_be_deleted, 1, 'An item type that is not used can be deleted');
147
- 

Return to bug 21946