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 162-167 Link Here
162
                        [% IF show_rule %]
168
                        [% IF show_rule %]
163
                            [% SET row_count = row_count + 1 %]
169
                            [% SET row_count = row_count + 1 %]
164
                            <tr row_countd="row_[% row_count | html %]">
170
                            <tr row_countd="row_[% row_count | html %]">
171
                                    <td>[% IF ( c == undef ) %]1[% ELSE %]0[% END %]</td>
165
                                    <td>
172
                                    <td>
166
                                        [% IF c == undef %]
173
                                        [% IF c == undef %]
167
                                            <em>All</em>
174
                                            <em>All</em>
Lines 169-179 Link Here
169
                                            [% Categories.GetName(c) | html %]
176
                                            [% Categories.GetName(c) | html %]
170
                                        [% END %]
177
                                        [% END %]
171
                                    </td>
178
                                    </td>
179
                                    <td>[% IF ( i == undef ) %]1[% ELSE %]0[% END %]</td>
172
                                    <td>
180
                                    <td>
173
                                        [% IF i == undef %]
181
                                        [% IF i == undef %]
174
                                            <em>All</em>
182
                                            <em>All</em>
175
                                        [% ELSE %]
183
                                        [% ELSE %]
176
                                            [% ItemTypes.GetDescription(i) | html %]
184
                                            [% ItemTypes.GetDescription(i,1) | html %]
177
                                        [% END %]
185
                                        [% END %]
178
                                    </td>
186
                                    </td>
179
                                    <td class="actions">
187
                                    <td class="actions">
Lines 321-326 Link Here
321
                    [% END %]
329
                    [% END %]
322
                [% END %]
330
                [% END %]
323
                <tr id="edit_row">
331
                <tr id="edit_row">
332
                    <td>2</td>
324
                    <td>
333
                    <td>
325
                        <select name="categorycode" id="categorycode">
334
                        <select name="categorycode" id="categorycode">
326
                            <option value="*">All</option>
335
                            <option value="*">All</option>
Lines 329-339 Link Here
329
                        [% END %]
338
                        [% END %]
330
                        </select>
339
                        </select>
331
                    </td>
340
                    </td>
341
                    <td>0</td>
332
                    <td>
342
                    <td>
333
                        <select name="itemtype" id="matrixitemtype" style="width:13em;">
343
                        <select name="itemtype" id="matrixitemtype" style="width:13em;">
334
                            <option value="*">All</option>
344
                            <option value="*">All</option>
335
                        [% FOREACH itemtypeloo IN itemtypeloop %]
345
                        [% FOREACH itemtypeloo IN itemtypeloop %]
346
                            [% NEXT IF itemtypeloo.parent_type %]
336
                            <option value="[% itemtypeloo.itemtype | html %]">[% itemtypeloo.translated_description | html %]</option>
347
                            <option value="[% itemtypeloo.itemtype | html %]">[% itemtypeloo.translated_description | html %]</option>
348
                            [% SET children = itemtypeloo.children_with_localization %]
349
                            [% IF children %]
350
                                <optgroup>
351
                                [% FOREACH child IN children %]
352
                                    <option value="[% child.itemtype | html %]">[% child.translated_description | html %]</option>
353
                                [% END %]
354
                                </optgroup>
355
                            [% END %]
337
                        [% END %]
356
                        [% END %]
338
                        </select>
357
                        </select>
339
                    </td>
358
                    </td>
Lines 432-438 Link Here
432
                </tr>
451
                </tr>
433
                <tfoot>
452
                <tfoot>
434
                    <tr>
453
                    <tr>
454
                      <th>&nbsp;</th>
435
                      <th>Patron category</th>
455
                      <th>Patron category</th>
456
                      <th>&nbsp;</th>
436
                      <th>Item type</th>
457
                      <th>Item type</th>
437
                      <th>&nbsp;</th>
458
                      <th>&nbsp;</th>
438
                      <th>Note</th>
459
                      <th>Note</th>
Lines 943-950 Link Here
943
964
944
[% MACRO jsinclude BLOCK %]
965
[% MACRO jsinclude BLOCK %]
945
    [% Asset.js("js/admin-menu.js") | $raw %]
966
    [% Asset.js("js/admin-menu.js") | $raw %]
967
    [% INCLUDE 'datatables.inc' %]
946
    [% INCLUDE 'calendar.inc' %]
968
    [% INCLUDE 'calendar.inc' %]
947
    <script>
969
    <script>
970
        $(document).ready(function() {
971
            $("#default-circulation-rules").dataTable($.extend(true,{},dataTablesDefaults, {
972
                "aoColumnDefs": [
973
                    { "bVisible": false, "aTargets": [ 0,2 ] },
974
                    { "bSortable": false, "aTargets": ["_all"] }
975
                ],
976
                "aaSortingFixed": [ [0,'asc'], [1,'asc'], [2,'asc'], [3,'asc'] ],
977
                "bPaginate": false,
978
                "bAutoWidth": false
979
            }));
980
        });
948
981
949
        function clear_edit(){
982
        function clear_edit(){
950
            var cancel = confirm(_("Are you sure you want to cancel your changes?"));
983
            var cancel = confirm(_("Are you sure you want to cancel your changes?"));
Lines 1030-1035 Link Here
1030
                        // select the corresponding option
1063
                        // select the corresponding option
1031
                        $(current_column).find("select option").each(function(){
1064
                        $(current_column).find("select option").each(function(){
1032
                            opt = $(this).text().toLowerCase();
1065
                            opt = $(this).text().toLowerCase();
1066
                            itm = itm.replace(/.*->(.*)/,"$1"); //If item type is part of a group we need to clear the parent description
1033
                            opt = opt.replace(/^\s*|\s*$/g,'');
1067
                            opt = opt.replace(/^\s*|\s*$/g,'');
1034
                            if ( opt == itm.toLowerCase() ) {
1068
                            if ( opt == itm.toLowerCase() ) {
1035
                                $(this).attr('selected', 'selected');
1069
                                $(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