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

(-)a/Koha/CirculationRules.pm (-27 / +35 lines)
Lines 51-57 our $RULE_KINDS = { Link Here
51
    },
51
    },
52
52
53
    patron_maxissueqty => {
53
    patron_maxissueqty => {
54
        scope => [ 'branchcode', 'categorycode' ],
54
        scope => [ 'branchcode', 'categorycode', 'checkout_type' ],
55
    },
55
    },
56
    patron_maxonsiteissueqty => {
56
    patron_maxonsiteissueqty => {
57
        scope => [ 'branchcode', 'categorycode' ],
57
        scope => [ 'branchcode', 'categorycode' ],
Lines 74-104 our $RULE_KINDS = { Link Here
74
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
74
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
75
    },
75
    },
76
    auto_renew => {
76
    auto_renew => {
77
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
77
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
78
    },
78
    },
79
    cap_fine_to_replacement_price => {
79
    cap_fine_to_replacement_price => {
80
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
80
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
81
    },
81
    },
82
    chargeperiod => {
82
    chargeperiod => {
83
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
83
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
84
    },
84
    },
85
    chargeperiod_charge_at => {
85
    chargeperiod_charge_at => {
86
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
86
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
87
    },
87
    },
88
    fine => {
88
    fine => {
89
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
89
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
90
    },
90
    },
91
    finedays => {
91
    finedays => {
92
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
92
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
93
    },
93
    },
94
    firstremind => {
94
    firstremind => {
95
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
95
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
96
    },
96
    },
97
    hardduedate => {
97
    hardduedate => {
98
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
98
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
99
    },
99
    },
100
    hardduedatecompare => {
100
    hardduedatecompare => {
101
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
101
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
102
    },
102
    },
103
    holds_per_day => {
103
    holds_per_day => {
104
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
104
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
Lines 107-134 our $RULE_KINDS = { Link Here
107
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
107
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
108
    },
108
    },
109
    issuelength => {
109
    issuelength => {
110
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
110
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
111
    },
111
    },
112
    lengthunit => {
112
    lengthunit => {
113
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
113
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
114
    },
114
    },
115
    maxissueqty => {
115
    maxissueqty => {
116
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
116
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
117
    },
117
    },
118
    maxonsiteissueqty => {
118
    maxonsiteissueqty => {
119
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
119
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
120
    },
120
    },
121
    maxsuspensiondays => {
121
    maxsuspensiondays => {
122
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
122
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
123
    },
123
    },
124
    no_auto_renewal_after => {
124
    no_auto_renewal_after => {
125
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
125
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
126
    },
126
    },
127
    no_auto_renewal_after_hard_limit => {
127
    no_auto_renewal_after_hard_limit => {
128
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
128
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
129
    },
129
    },
130
    norenewalbefore => {
130
    norenewalbefore => {
131
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
131
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
132
    },
132
    },
133
    onshelfholds => {
133
    onshelfholds => {
134
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
134
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
Lines 137-161 our $RULE_KINDS = { Link Here
137
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
137
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
138
    },
138
    },
139
    overduefinescap => {
139
    overduefinescap => {
140
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
140
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
141
    },
141
    },
142
    renewalperiod => {
142
    renewalperiod => {
143
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
143
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
144
    },
144
    },
145
    renewalsallowed => {
145
    renewalsallowed => {
146
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
146
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
147
    },
147
    },
148
    rentaldiscount => {
148
    rentaldiscount => {
149
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
149
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
150
    },
150
    },
151
    reservesallowed => {
151
    reservesallowed => {
152
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
152
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
153
    },
153
    },
154
    suspension_chargeperiod => {
154
    suspension_chargeperiod => {
155
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
155
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
156
    },
156
    },
157
    note => { # This is not really a rule. Maybe we will want to separate this later.
157
    note => { # This is not really a rule. Maybe we will want to separate this later.
158
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
158
        scope => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ],
159
    },
159
    },
160
    # Not included (deprecated?):
160
    # Not included (deprecated?):
161
    #   * accountsent
161
    #   * accountsent
Lines 177-198 sub get_effective_rule { Link Here
177
    $params->{categorycode} //= undef;
177
    $params->{categorycode} //= undef;
178
    $params->{branchcode}   //= undef;
178
    $params->{branchcode}   //= undef;
179
    $params->{itemtype}     //= undef;
179
    $params->{itemtype}     //= undef;
180
    $params->{checkout_type} //= undef;
180
181
181
    my $rule_name    = $params->{rule_name};
182
    my $rule_name    = $params->{rule_name};
182
    my $categorycode = $params->{categorycode};
183
    my $categorycode = $params->{categorycode};
183
    my $itemtype     = $params->{itemtype};
184
    my $itemtype     = $params->{itemtype};
184
    my $branchcode   = $params->{branchcode};
185
    my $branchcode   = $params->{branchcode};
186
    my $checkout_type = $params->{checkout_type};
185
187
186
    Koha::Exceptions::MissingParameter->throw(
188
    Koha::Exceptions::MissingParameter->throw(
187
        "Required parameter 'rule_name' missing")
189
        "Required parameter 'rule_name' missing")
188
      unless $rule_name;
190
      unless $rule_name;
189
191
190
    for my $v ( $branchcode, $categorycode, $itemtype ) {
192
    for my $v ( $branchcode, $categorycode, $itemtype, $checkout_type ) {
191
        $v = undef if $v and $v eq '*';
193
        $v = undef if $v and $v eq '*';
192
    }
194
    }
193
195
194
    my $order_by = $params->{order_by}
196
    my $order_by = $params->{order_by}
195
      // { -desc => [ 'branchcode', 'categorycode', 'itemtype' ] };
197
      // { -desc => [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ] };
196
198
197
    my $search_params;
199
    my $search_params;
198
    $search_params->{rule_name} = $rule_name;
200
    $search_params->{rule_name} = $rule_name;
Lines 200-205 sub get_effective_rule { Link Here
200
    $search_params->{categorycode} = defined $categorycode ? [ $categorycode, undef ] : undef;
202
    $search_params->{categorycode} = defined $categorycode ? [ $categorycode, undef ] : undef;
201
    $search_params->{itemtype}     = defined $itemtype     ? [ $itemtype, undef ] : undef;
203
    $search_params->{itemtype}     = defined $itemtype     ? [ $itemtype, undef ] : undef;
202
    $search_params->{branchcode}   = defined $branchcode   ? [ $branchcode,   undef ] : undef;
204
    $search_params->{branchcode}   = defined $branchcode   ? [ $branchcode,   undef ] : undef;
205
    $search_params->{checkout_type} = defined $checkout_type ? [ $checkout_type, undef ] : undef;
203
206
204
    my $rule = $self->search(
207
    my $rule = $self->search(
205
        $search_params,
208
        $search_params,
Lines 222-227 sub get_effective_rules { Link Here
222
    my $rules        = $params->{rules};
225
    my $rules        = $params->{rules};
223
    my $categorycode = $params->{categorycode};
226
    my $categorycode = $params->{categorycode};
224
    my $itemtype     = $params->{itemtype};
227
    my $itemtype     = $params->{itemtype};
228
    my $checkout_type = $params->{checkout_type};
225
    my $branchcode   = $params->{branchcode};
229
    my $branchcode   = $params->{branchcode};
226
230
227
    my $r;
231
    my $r;
Lines 231-236 sub get_effective_rules { Link Here
231
                rule_name    => $rule,
235
                rule_name    => $rule,
232
                categorycode => $categorycode,
236
                categorycode => $categorycode,
233
                itemtype     => $itemtype,
237
                itemtype     => $itemtype,
238
                checkout_type => $checkout_type,
234
                branchcode   => $branchcode,
239
                branchcode   => $branchcode,
235
            }
240
            }
236
        );
241
        );
Lines 260-266 sub set_rule { Link Here
260
        unless defined $kind_info;
265
        unless defined $kind_info;
261
266
262
    # Enforce scope; a rule should be set for its defined scope, no more, no less.
267
    # Enforce scope; a rule should be set for its defined scope, no more, no less.
263
    foreach my $scope_level ( qw( branchcode categorycode itemtype ) ) {
268
    foreach my $scope_level ( qw( branchcode categorycode itemtype checkout_type ) ) {
264
        if ( grep /$scope_level/, @{ $kind_info->{scope} } ) {
269
        if ( grep /$scope_level/, @{ $kind_info->{scope} } ) {
265
            croak "set_rule needs '$scope_level' to set '$params->{rule_name}'!"
270
            croak "set_rule needs '$scope_level' to set '$params->{rule_name}'!"
266
                unless exists $params->{$scope_level};
271
                unless exists $params->{$scope_level};
Lines 273-282 sub set_rule { Link Here
273
    my $branchcode   = $params->{branchcode};
278
    my $branchcode   = $params->{branchcode};
274
    my $categorycode = $params->{categorycode};
279
    my $categorycode = $params->{categorycode};
275
    my $itemtype     = $params->{itemtype};
280
    my $itemtype     = $params->{itemtype};
281
    my $checkout_type = $params->{checkout_type};
276
    my $rule_name    = $params->{rule_name};
282
    my $rule_name    = $params->{rule_name};
277
    my $rule_value   = $params->{rule_value};
283
    my $rule_value   = $params->{rule_value};
278
284
279
    for my $v ( $branchcode, $categorycode, $itemtype ) {
285
    for my $v ( $branchcode, $categorycode, $itemtype, $checkout_type ) {
280
        $v = undef if $v and $v eq '*';
286
        $v = undef if $v and $v eq '*';
281
    }
287
    }
282
    my $rule = $self->search(
288
    my $rule = $self->search(
Lines 285-290 sub set_rule { Link Here
285
            branchcode   => $branchcode,
291
            branchcode   => $branchcode,
286
            categorycode => $categorycode,
292
            categorycode => $categorycode,
287
            itemtype     => $itemtype,
293
            itemtype     => $itemtype,
294
            checkout_type => $checkout_type,
288
        }
295
        }
289
    )->next();
296
    )->next();
290
297
Lines 304-309 sub set_rule { Link Here
304
                    branchcode   => $branchcode,
311
                    branchcode   => $branchcode,
305
                    categorycode => $categorycode,
312
                    categorycode => $categorycode,
306
                    itemtype     => $itemtype,
313
                    itemtype     => $itemtype,
314
                    checkout_type => $checkout_type,
307
                    rule_name    => $rule_name,
315
                    rule_name    => $rule_name,
308
                    rule_value   => $rule_value,
316
                    rule_value   => $rule_value,
309
                }
317
                }
(-)a/t/db_dependent/Koha/CirculationRules.t (-6 / +26 lines)
Lines 22-27 use Modern::Perl; Link Here
22
use Test::More tests => 3;
22
use Test::More tests => 3;
23
use Test::Exception;
23
use Test::Exception;
24
24
25
use Koha::Checkouts;
25
use Koha::CirculationRules;
26
use Koha::CirculationRules;
26
use Koha::Database;
27
use Koha::Database;
27
28
Lines 35-40 subtest 'set_rule + get_effective_rule' => sub { Link Here
35
36
36
    $schema->storage->txn_begin;
37
    $schema->storage->txn_begin;
37
38
39
    my $checkout_type = $Koha::Checkouts::type->{checkout};
38
    my $categorycode = $builder->build_object( { class => 'Koha::Patron::Categories' } )->categorycode;
40
    my $categorycode = $builder->build_object( { class => 'Koha::Patron::Categories' } )->categorycode;
39
    my $itemtype     = $builder->build_object( { class => 'Koha::ItemTypes' } )->itemtype;
41
    my $itemtype     = $builder->build_object( { class => 'Koha::ItemTypes' } )->itemtype;
40
    my $branchcode   = $builder->build_object( { class => 'Koha::Libraries' } )->branchcode;
42
    my $branchcode   = $builder->build_object( { class => 'Koha::Libraries' } )->branchcode;
Lines 54-59 subtest 'set_rule + get_effective_rule' => sub { Link Here
54
            branchcode   => $branchcode,
56
            branchcode   => $branchcode,
55
            categorycode => $categorycode,
57
            categorycode => $categorycode,
56
            itemtype     => $itemtype,
58
            itemtype     => $itemtype,
59
            checkout_type => $checkout_type,
57
            rule_name    => $rule_name,
60
            rule_name    => $rule_name,
58
        }
61
        }
59
    );
62
    );
Lines 64-69 subtest 'set_rule + get_effective_rule' => sub { Link Here
64
            branchcode   => '*',
67
            branchcode   => '*',
65
            categorycode => '*',
68
            categorycode => '*',
66
            itemtype     => '*',
69
            itemtype     => '*',
70
            checkout_type => '*',
67
            rule_name    => $rule_name,
71
            rule_name    => $rule_name,
68
            rule_value   => $default_rule_value,
72
            rule_value   => $default_rule_value,
69
        }
73
        }
Lines 74-79 subtest 'set_rule + get_effective_rule' => sub { Link Here
74
            branchcode   => undef,
78
            branchcode   => undef,
75
            categorycode => undef,
79
            categorycode => undef,
76
            itemtype     => undef,
80
            itemtype     => undef,
81
            checkout_type => undef,
77
            rule_name    => $rule_name,
82
            rule_name    => $rule_name,
78
        }
83
        }
79
    );
84
    );
Lines 83-88 subtest 'set_rule + get_effective_rule' => sub { Link Here
83
            branchcode   => '*',
88
            branchcode   => '*',
84
            categorycode => '*',
89
            categorycode => '*',
85
            itemtype     => '*',
90
            itemtype     => '*',
91
            checkout_type => '*',
86
            rule_name    => $rule_name,
92
            rule_name    => $rule_name,
87
        }
93
        }
88
    );
94
    );
Lines 94-99 subtest 'set_rule + get_effective_rule' => sub { Link Here
94
            branchcode   => $branchcode_2,
100
            branchcode   => $branchcode_2,
95
            categorycode => '*',
101
            categorycode => '*',
96
            itemtype     => '*',
102
            itemtype     => '*',
103
            checkout_type => '*',
97
            rule_name    => $rule_name,
104
            rule_name    => $rule_name,
98
        }
105
        }
99
    );
106
    );
Lines 106-111 subtest 'set_rule + get_effective_rule' => sub { Link Here
106
            branchcode => $branchcode,
113
            branchcode => $branchcode,
107
            categorycode => $categorycode,
114
            categorycode => $categorycode,
108
            itemtype => $itemtype,
115
            itemtype => $itemtype,
116
            checkout_type => $checkout_type,
109
        }, 'maxissueqty' );
117
        }, 'maxissueqty' );
110
118
111
        plan tests => 2**scalar @$order;
119
        plan tests => 2**scalar @$order;
Lines 121-126 subtest 'set_rule + get_effective_rule' => sub { Link Here
121
                branchcode => $branchcode,
129
                branchcode => $branchcode,
122
                categorycode => $categorycode,
130
                categorycode => $categorycode,
123
                itemtype => $itemtype,
131
                itemtype => $itemtype,
132
                checkout_type => $checkout_type,
124
                rule_name => $rule_name,
133
                rule_name => $rule_name,
125
            } );
134
            } );
126
135
Lines 136-144 subtest 'set_rule + get_effective_rule' => sub { Link Here
136
    };
145
    };
137
146
138
    my $our_branch_rules = Koha::CirculationRules->search({branchcode => $branchcode});
147
    my $our_branch_rules = Koha::CirculationRules->search({branchcode => $branchcode});
139
    is( $our_branch_rules->count, 4, "We added 8 rules");
148
    is( $our_branch_rules->count, 8, "We added 16 rules");
140
    $our_branch_rules->delete;
149
    $our_branch_rules->delete;
141
    is( $our_branch_rules->count, 0, "We deleted 8 rules");
150
    is( $our_branch_rules->count, 0, "We deleted 16 rules");
142
151
143
    $schema->storage->txn_rollback;
152
    $schema->storage->txn_rollback;
144
};
153
};
Lines 177-183 subtest 'set_rules() tests' => sub { Link Here
177
    plan tests => 1;
186
    plan tests => 1;
178
187
179
    subtest 'scope validation' => sub {
188
    subtest 'scope validation' => sub {
180
        plan tests => 6;
189
        plan tests => 7;
181
190
182
        $schema->storage->txn_begin;
191
        $schema->storage->txn_begin;
183
192
Lines 187-192 subtest 'set_rules() tests' => sub { Link Here
187
            class => 'Koha::ItemTypes' } )->itemtype;
196
            class => 'Koha::ItemTypes' } )->itemtype;
188
        my $branchcode   = $builder->build_object( {
197
        my $branchcode   = $builder->build_object( {
189
            class => 'Koha::Libraries' } )->branchcode;
198
            class => 'Koha::Libraries' } )->branchcode;
199
        my $checkout_type = $Koha::Checkouts::type->{checkout};
190
200
191
        my $rule;
201
        my $rule;
192
        Koha::CirculationRules->delete;
202
        Koha::CirculationRules->delete;
Lines 195-208 subtest 'set_rules() tests' => sub { Link Here
195
            branchcode   => $branchcode,
205
            branchcode   => $branchcode,
196
            categorycode => $categorycode,
206
            categorycode => $categorycode,
197
            itemtype     => $itemtype,
207
            itemtype     => $itemtype,
208
            checkout_type => $checkout_type,
198
            rules        => {
209
            rules        => {
199
                refund              => 1,
210
                refund              => 1,
211
                max_holds           => 9001,
200
                patron_maxissueqty  => 2,
212
                patron_maxissueqty  => 2,
201
                holdallowed         => 3,
213
                holdallowed         => 3,
202
                article_requests    => 4,
214
                article_requests    => 4,
203
                maxissueqty         => 5,
215
                maxissueqty         => 5,
204
            }
216
            }
205
        } )}, 5, 'All rules added' );
217
        } )}, 6, 'All rules added' );
206
218
207
        is( Koha::CirculationRules->get_effective_rule( {
219
        is( Koha::CirculationRules->get_effective_rule( {
208
            branchcode      => $branchcode,
220
            branchcode      => $branchcode,
Lines 212-217 subtest 'set_rules() tests' => sub { Link Here
212
        is( Koha::CirculationRules->get_effective_rule( {
224
        is( Koha::CirculationRules->get_effective_rule( {
213
            branchcode      => $branchcode,
225
            branchcode      => $branchcode,
214
            categorycode    => $categorycode,
226
            categorycode    => $categorycode,
227
            checkout_type   => $checkout_type,
228
            rule_name       => 'max_holds'
229
        } )->rule_value, 9001, 'Found rule patron_maxissueqty' );
230
231
        is( Koha::CirculationRules->get_effective_rule( {
232
            branchcode      => $branchcode,
233
            categorycode    => $categorycode,
234
            checkout_type   => $checkout_type,
215
            rule_name       => 'patron_maxissueqty'
235
            rule_name       => 'patron_maxissueqty'
216
        } )->rule_value, 2, 'Found rule patron_maxissueqty' );
236
        } )->rule_value, 2, 'Found rule patron_maxissueqty' );
217
237
Lines 232-237 subtest 'set_rules() tests' => sub { Link Here
232
            branchcode      => $branchcode,
252
            branchcode      => $branchcode,
233
            categorycode    => $categorycode,
253
            categorycode    => $categorycode,
234
            itemtype        => $itemtype,
254
            itemtype        => $itemtype,
255
            checkout_type   => $checkout_type,
235
            rule_name       => 'maxissueqty'
256
            rule_name       => 'maxissueqty'
236
        } )->rule_value, 5, 'Found rule maxissueqty' );
257
        } )->rule_value, 5, 'Found rule maxissueqty' );
237
258
Lines 267-273 sub prepare_tests_for_rule_scope_combinations { Link Here
267
    # We must maintain the order in order to keep the test valid. This should be
288
    # We must maintain the order in order to keep the test valid. This should be
268
    # equal to Koha/CirculationRules.pm "order_by" of C<get_effective_rule> sub.
289
    # equal to Koha/CirculationRules.pm "order_by" of C<get_effective_rule> sub.
269
    # Let's explicitly define the order and fail test if we are missing a scope:
290
    # Let's explicitly define the order and fail test if we are missing a scope:
270
    my $order = [ 'branchcode', 'categorycode', 'itemtype' ];
291
    my $order = [ 'branchcode', 'categorycode', 'itemtype', 'checkout_type' ];
271
    is( join(", ", sort keys %$scope),
292
    is( join(", ", sort keys %$scope),
272
       join(", ", sort @$order), 'Missing a scope!' ) if keys %$scope ne scalar @$order;
293
       join(", ", sort @$order), 'Missing a scope!' ) if keys %$scope ne scalar @$order;
273
294
274
- 

Return to bug 25089