Bug 29012: (QA follow-up) Use q{} instead of '' in smart-rules.pl
[koha.git] / admin / smart-rules.pl
1 #!/usr/bin/perl
2 # Copyright 2000-2002 Katipo Communications
3 # copyright 2010 BibLibre
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21 use CGI qw ( -utf8 );
22 use C4::Context;
23 use C4::Output qw( output_html_with_http_headers );
24 use C4::Auth qw( get_template_and_user );
25 use Koha::Exception;
26 use Koha::DateUtils qw( dt_from_string output_pref );
27 use Koha::Database;
28 use Koha::Logger;
29 use Koha::Libraries;
30 use Koha::CirculationRules;
31 use Koha::Patron::Categories;
32 use Koha::Caches;
33 use Koha::Patrons;
34
35 my $input = CGI->new;
36 my $dbh = C4::Context->dbh;
37
38 # my $flagsrequired;
39 # $flagsrequired->{circulation}=1;
40 my ($template, $loggedinuser, $cookie)
41     = get_template_and_user({template_name => "admin/smart-rules.tt",
42                             query => $input,
43                             type => "intranet",
44                             flagsrequired => {parameters => 'manage_circ_rules'},
45                             });
46
47 my $type=$input->param('type');
48
49 my $branch = $input->param('branch');
50 unless ( $branch ) {
51     if ( C4::Context->preference('DefaultToLoggedInLibraryCircRules') ) {
52         $branch = Koha::Libraries->search->count() == 1 ? undef : C4::Context::mybranch();
53     }
54     else {
55         $branch = C4::Context::only_my_library() ? ( C4::Context::mybranch() || '*' ) : '*';
56     }
57 }
58
59 my $logged_in_patron = Koha::Patrons->find( $loggedinuser );
60
61 my $can_edit_from_any_library = $logged_in_patron->has_permission( {parameters => 'manage_circ_rules_from_any_libraries' } );
62 $template->param( restricted_to_own_library => not $can_edit_from_any_library );
63 $branch = C4::Context::mybranch() unless $can_edit_from_any_library;
64
65 my $op = $input->param('op') || q{};
66 my $language = C4::Languages::getlanguage();
67
68 my $cache = Koha::Caches->get_instance;
69 $cache->clear_from_cache( Koha::CirculationRules::GUESSED_ITEMTYPES_KEY );
70
71 if ($op eq 'delete') {
72     my $itemtype     = $input->param('itemtype');
73     my $categorycode = $input->param('categorycode');
74
75     Koha::CirculationRules->set_rules(
76         {
77             categorycode => $categorycode eq '*' ? undef : $categorycode,
78             branchcode   => $branch eq '*' ? undef : $branch,
79             itemtype     => $itemtype eq '*' ? undef : $itemtype,
80             rules        => {
81                 maxissueqty                      => undef,
82                 maxonsiteissueqty                => undef,
83                 rentaldiscount                   => undef,
84                 fine                             => undef,
85                 finedays                         => undef,
86                 maxsuspensiondays                => undef,
87                 suspension_chargeperiod          => undef,
88                 firstremind                      => undef,
89                 chargeperiod                     => undef,
90                 chargeperiod_charge_at           => undef,
91                 issuelength                      => undef,
92                 daysmode                         => undef,
93                 lengthunit                       => undef,
94                 hardduedate                      => undef,
95                 hardduedatecompare               => undef,
96                 renewalsallowed                  => undef,
97                 unseen_renewals_allowed          => undef,
98                 renewalperiod                    => undef,
99                 norenewalbefore                  => undef,
100                 auto_renew                       => undef,
101                 no_auto_renewal_after            => undef,
102                 no_auto_renewal_after_hard_limit => undef,
103                 reservesallowed                  => undef,
104                 holds_per_record                 => undef,
105                 holds_per_day                    => undef,
106                 onshelfholds                     => undef,
107                 opacitemholds                    => undef,
108                 overduefinescap                  => undef,
109                 cap_fine_to_replacement_price    => undef,
110                 article_requests                 => undef,
111                 note                             => undef,
112                 recalls_allowed                  => undef,
113                 recalls_per_record               => undef,
114                 on_shelf_recalls                 => undef,
115                 recall_due_date_interval         => undef,
116                 recall_overdue_fine              => undef,
117                 recall_shelf_time                => undef,
118             }
119         }
120     );
121 }
122 elsif ($op eq 'delete-branch-cat') {
123     my $categorycode  = $input->param('categorycode');
124     if ($branch eq "*") {
125         if ($categorycode eq "*") {
126             Koha::CirculationRules->set_rules(
127                 {
128                     branchcode   => undef,
129                     categorycode => undef,
130                     rules        => {
131                         max_holds                      => undef,
132                         patron_maxissueqty             => undef,
133                         patron_maxonsiteissueqty       => undef,
134                     }
135                 }
136             );
137             Koha::CirculationRules->set_rules(
138                 {
139                     branchcode   => undef,
140                     itemtype     => undef,
141                     rules        => {
142                         holdallowed             => undef,
143                         hold_fulfillment_policy => undef,
144                         returnbranch            => undef,
145                     }
146                 }
147             );
148         } else {
149             Koha::CirculationRules->set_rules(
150                 {
151                     categorycode => $categorycode,
152                     branchcode   => undef,
153                     rules        => {
154                         max_holds                => undef,
155                         patron_maxissueqty       => undef,
156                         patron_maxonsiteissueqty => undef,
157                     }
158                 }
159             );
160         }
161     } elsif ($categorycode eq "*") {
162         Koha::CirculationRules->set_rules(
163             {
164                 branchcode   => $branch,
165                 categorycode => undef,
166                 rules        => {
167                     max_holds                => undef,
168                     patron_maxissueqty       => undef,
169                     patron_maxonsiteissueqty => undef,
170                 }
171             }
172         );
173         Koha::CirculationRules->set_rules(
174             {
175                 branchcode   => $branch,
176                 itemtype     => undef,
177                 rules        => {
178                     holdallowed             => undef,
179                     hold_fulfillment_policy => undef,
180                     returnbranch            => undef,
181                 }
182             }
183         );
184     } else {
185         Koha::CirculationRules->set_rules(
186             {
187                 categorycode => $categorycode,
188                 branchcode   => $branch,
189                 rules        => {
190                     max_holds         => undef,
191                     patron_maxissueqty       => undef,
192                     patron_maxonsiteissueqty => undef,
193                 }
194             }
195         );
196     }
197 }
198 elsif ($op eq 'delete-branch-item') {
199     my $itemtype  = $input->param('itemtype');
200     if ($branch eq "*") {
201         if ($itemtype eq "*") {
202             Koha::CirculationRules->set_rules(
203                 {
204                     branchcode   => undef,
205                     itemtype     => undef,
206                     rules        => {
207                         holdallowed             => undef,
208                         hold_fulfillment_policy => undef,
209                         returnbranch            => undef,
210                     }
211                 }
212             );
213         } else {
214             Koha::CirculationRules->set_rules(
215                 {
216                     branchcode   => undef,
217                     itemtype     => $itemtype,
218                     rules        => {
219                         holdallowed             => undef,
220                         hold_fulfillment_policy => undef,
221                         returnbranch            => undef,
222                     }
223                 }
224             );
225         }
226     } elsif ($itemtype eq "*") {
227         Koha::CirculationRules->set_rules(
228             {
229                 branchcode   => $branch,
230                 itemtype     => undef,
231                 rules        => {
232                     holdallowed             => undef,
233                     hold_fulfillment_policy => undef,
234                     returnbranch            => undef,
235                 }
236             }
237         );
238     } else {
239         Koha::CirculationRules->set_rules(
240             {
241                 branchcode   => $branch,
242                 itemtype     => $itemtype,
243                 rules        => {
244                     holdallowed             => undef,
245                     hold_fulfillment_policy => undef,
246                     returnbranch            => undef,
247                 }
248             }
249         );
250     }
251 }
252 # save the values entered
253 elsif ($op eq 'add') {
254     my $br = $branch; # branch
255     my $bor  = $input->param('categorycode'); # borrower category
256     my $itemtype  = $input->param('itemtype');     # item type
257     my $fine = $input->param('fine');
258     my $finedays     = $input->param('finedays');
259     my $maxsuspensiondays = $input->param('maxsuspensiondays') || q{};
260     my $suspension_chargeperiod = $input->param('suspension_chargeperiod') || 1;
261     my $firstremind  = $input->param('firstremind');
262     my $chargeperiod = $input->param('chargeperiod');
263     my $chargeperiod_charge_at = $input->param('chargeperiod_charge_at');
264     my $maxissueqty = strip_non_numeric( scalar $input->param('maxissueqty') );
265     my $maxonsiteissueqty = strip_non_numeric( scalar $input->param('maxonsiteissueqty') );
266     my $renewalsallowed  = $input->param('renewalsallowed');
267     my $unseen_renewals_allowed  = strip_non_numeric( scalar $input->param('unseen_renewals_allowed') ) // q{};
268     my $renewalperiod    = $input->param('renewalperiod');
269     my $norenewalbefore  = $input->param('norenewalbefore');
270     $norenewalbefore = q{} if $norenewalbefore =~ /^\s*$/;
271     my $auto_renew = $input->param('auto_renew') eq 'yes' ? 1 : 0;
272     my $no_auto_renewal_after = $input->param('no_auto_renewal_after');
273     $no_auto_renewal_after = q{} if $no_auto_renewal_after =~ /^\s*$/;
274     my $no_auto_renewal_after_hard_limit = $input->param('no_auto_renewal_after_hard_limit') || q{};
275     $no_auto_renewal_after_hard_limit = eval { dt_from_string( scalar $no_auto_renewal_after_hard_limit ) } if ( $no_auto_renewal_after_hard_limit );
276     $no_auto_renewal_after_hard_limit = output_pref( { dt => $no_auto_renewal_after_hard_limit, dateonly => 1, dateformat => 'iso' } ) if ( $no_auto_renewal_after_hard_limit );
277     my $reservesallowed  = strip_non_numeric( scalar $input->param('reservesallowed') );
278     my $holds_per_record = strip_non_numeric( scalar $input->param('holds_per_record') );
279     my $holds_per_day    = strip_non_numeric( scalar $input->param('holds_per_day') );
280     my $onshelfholds     = $input->param('onshelfholds') || 0;
281     my $issuelength  = $input->param('issuelength') || 0;
282     my $daysmode = $input->param('daysmode');
283     my $lengthunit  = $input->param('lengthunit');
284     my $hardduedate = $input->param('hardduedate') || q{};
285     $hardduedate = eval { dt_from_string( scalar $hardduedate ) } if ( $hardduedate );
286     $hardduedate = output_pref( { dt => $hardduedate, dateonly => 1, dateformat => 'iso' } ) if ( $hardduedate );
287     my $hardduedatecompare = $input->param('hardduedatecompare');
288     my $rentaldiscount = $input->param('rentaldiscount') || 0;
289     my $opacitemholds = $input->param('opacitemholds') || 0;
290     my $article_requests = $input->param('article_requests') || 'no';
291     my $overduefinescap = $input->param('overduefinescap') || q{};
292     my $cap_fine_to_replacement_price = ($input->param('cap_fine_to_replacement_price') || q{}) eq 'on';
293     my $note = $input->param('note');
294     my $decreaseloanholds = $input->param('decreaseloanholds') || q{};
295     my $recalls_allowed = $input->param('recalls_allowed');
296     my $recalls_per_record = $input->param('recalls_per_record');
297     my $on_shelf_recalls = $input->param('on_shelf_recalls');
298     my $recall_due_date_interval = $input->param('recall_due_date_interval');
299     my $recall_overdue_fine = $input->param('recall_overdue_fine');
300     my $recall_shelf_time = $input->param('recall_shelf_time');
301
302     my $rules = {
303         maxissueqty                   => $maxissueqty,
304         maxonsiteissueqty             => $maxonsiteissueqty,
305         rentaldiscount                => $rentaldiscount,
306         fine                          => $fine,
307         finedays                      => $finedays,
308         maxsuspensiondays             => $maxsuspensiondays,
309         suspension_chargeperiod       => $suspension_chargeperiod,
310         firstremind                   => $firstremind,
311         chargeperiod                  => $chargeperiod,
312         chargeperiod_charge_at        => $chargeperiod_charge_at,
313         issuelength                   => $issuelength,
314         daysmode                      => $daysmode,
315         lengthunit                    => $lengthunit,
316         hardduedate                   => $hardduedate,
317         hardduedatecompare            => $hardduedatecompare,
318         renewalsallowed               => $renewalsallowed,
319         unseen_renewals_allowed       => $unseen_renewals_allowed,
320         renewalperiod                 => $renewalperiod,
321         norenewalbefore               => $norenewalbefore,
322         auto_renew                    => $auto_renew,
323         no_auto_renewal_after         => $no_auto_renewal_after,
324         no_auto_renewal_after_hard_limit => $no_auto_renewal_after_hard_limit,
325         reservesallowed               => $reservesallowed,
326         holds_per_record              => $holds_per_record,
327         holds_per_day                 => $holds_per_day,
328         onshelfholds                  => $onshelfholds,
329         opacitemholds                 => $opacitemholds,
330         overduefinescap               => $overduefinescap,
331         cap_fine_to_replacement_price => $cap_fine_to_replacement_price,
332         article_requests              => $article_requests,
333         note                          => $note,
334         decreaseloanholds             => $decreaseloanholds,
335         recalls_allowed               => $recalls_allowed,
336         recalls_per_record            => $recalls_per_record,
337         on_shelf_recalls              => $on_shelf_recalls,
338         recall_due_date_interval      => $recall_due_date_interval,
339         recall_overdue_fine           => $recall_overdue_fine,
340         recall_shelf_time             => $recall_shelf_time,
341     };
342
343     Koha::CirculationRules->set_rules(
344         {
345             categorycode => $bor eq '*' ? undef : $bor,
346             itemtype     => $itemtype eq '*' ? undef : $itemtype,
347             branchcode   => $br eq '*' ? undef : $br,
348             rules        => $rules,
349         }
350     );
351
352 }
353 elsif ($op eq "set-branch-defaults") {
354     my $categorycode  = $input->param('categorycode');
355     my $patron_maxissueqty = strip_non_numeric( scalar $input->param('patron_maxissueqty') );
356     my $patron_maxonsiteissueqty = $input->param('patron_maxonsiteissueqty');
357     $patron_maxonsiteissueqty = strip_non_numeric($patron_maxonsiteissueqty);
358     my $holdallowed   = $input->param('holdallowed');
359     my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy');
360     my $returnbranch  = $input->param('returnbranch');
361     my $max_holds = strip_non_numeric( scalar $input->param('max_holds') );
362
363     if ($branch eq "*") {
364         Koha::CirculationRules->set_rules(
365             {
366                 itemtype     => undef,
367                 branchcode   => undef,
368                 rules        => {
369                     holdallowed             => $holdallowed,
370                     hold_fulfillment_policy => $hold_fulfillment_policy,
371                     returnbranch            => $returnbranch,
372                 }
373             }
374         );
375         Koha::CirculationRules->set_rules(
376             {
377                 categorycode => undef,
378                 branchcode   => undef,
379                 rules        => {
380                     patron_maxissueqty             => $patron_maxissueqty,
381                     patron_maxonsiteissueqty       => $patron_maxonsiteissueqty,
382                 }
383             }
384         );
385     } else {
386         Koha::CirculationRules->set_rules(
387             {
388                 itemtype     => undef,
389                 branchcode   => $branch,
390                 rules        => {
391                     holdallowed             => $holdallowed,
392                     hold_fulfillment_policy => $hold_fulfillment_policy,
393                     returnbranch            => $returnbranch,
394                 }
395             }
396         );
397         Koha::CirculationRules->set_rules(
398             {
399                 categorycode => undef,
400                 branchcode   => $branch,
401                 rules        => {
402                     patron_maxissueqty             => $patron_maxissueqty,
403                     patron_maxonsiteissueqty       => $patron_maxonsiteissueqty,
404                 }
405             }
406         );
407     }
408     Koha::CirculationRules->set_rule(
409         {
410             branchcode   => $branch,
411             categorycode => undef,
412             rule_name    => 'max_holds',
413             rule_value   => $max_holds,
414         }
415     );
416 }
417 elsif ($op eq "add-branch-cat") {
418     my $categorycode  = $input->param('categorycode');
419     my $patron_maxissueqty = strip_non_numeric( scalar $input->param('patron_maxissueqty') );
420     my $patron_maxonsiteissueqty = $input->param('patron_maxonsiteissueqty');
421     $patron_maxonsiteissueqty = strip_non_numeric($patron_maxonsiteissueqty);
422     my $max_holds = $input->param('max_holds');
423     $max_holds =~ s/\s//g;
424     $max_holds = undef if $max_holds !~ /^\d+/;
425
426     if ($branch eq "*") {
427         if ($categorycode eq "*") {
428             Koha::CirculationRules->set_rules(
429                 {
430                     categorycode => undef,
431                     branchcode   => undef,
432                     rules        => {
433                         max_holds         => $max_holds,
434                         patron_maxissueqty       => $patron_maxissueqty,
435                         patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
436                     }
437                 }
438             );
439         } else {
440             Koha::CirculationRules->set_rules(
441                 {
442                     categorycode => $categorycode,
443                     branchcode   => undef,
444                     rules        => {
445                         max_holds         => $max_holds,
446                         patron_maxissueqty       => $patron_maxissueqty,
447                         patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
448                     }
449                 }
450             );
451         }
452     } elsif ($categorycode eq "*") {
453         Koha::CirculationRules->set_rules(
454             {
455                 categorycode => undef,
456                 branchcode   => $branch,
457                 rules        => {
458                     max_holds         => $max_holds,
459                     patron_maxissueqty       => $patron_maxissueqty,
460                     patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
461                 }
462             }
463         );
464     } else {
465         Koha::CirculationRules->set_rules(
466             {
467                 categorycode => $categorycode,
468                 branchcode   => $branch,
469                 rules        => {
470                     max_holds         => $max_holds,
471                     patron_maxissueqty       => $patron_maxissueqty,
472                     patron_maxonsiteissueqty => $patron_maxonsiteissueqty,
473                 }
474             }
475         );
476     }
477 }
478 elsif ( $op eq "add-open-article-requests-limit" ) {
479     my $categorycode                = $input->param('categorycode');
480     my $open_article_requests_limit = strip_non_numeric( scalar $input->param('open_article_requests_limit') );
481
482     Koha::Exception->throw("No value passed for article request limit")
483       if not defined $open_article_requests_limit # There is a JS check for that
484       || $open_article_requests_limit eq q{};
485
486     if ( $branch eq "*" ) {
487         if ( $categorycode eq "*" ) {
488             Koha::CirculationRules->set_rules(
489                 {   categorycode => undef,
490                     branchcode   => undef,
491                     rules        => { open_article_requests_limit => $open_article_requests_limit, }
492                 }
493             );
494         } else {
495             Koha::CirculationRules->set_rules(
496                 {   categorycode => $categorycode,
497                     branchcode   => undef,
498                     rules        => { open_article_requests_limit => $open_article_requests_limit, }
499                 }
500             );
501         }
502     } elsif ( $categorycode eq "*" ) {
503         Koha::CirculationRules->set_rules(
504             {   categorycode => undef,
505                 branchcode   => $branch,
506                 rules        => { open_article_requests_limit => $open_article_requests_limit, }
507             }
508         );
509     } else {
510         Koha::CirculationRules->set_rules(
511             {   categorycode => $categorycode,
512                 branchcode   => $branch,
513                 rules        => { open_article_requests_limit => $open_article_requests_limit, }
514             }
515         );
516     }
517 } elsif ( $op eq 'del-open-article-requests-limit' ) {
518     my $categorycode = $input->param('categorycode');
519     if ( $branch eq "*" ) {
520         if ( $categorycode eq "*" ) {
521             Koha::CirculationRules->set_rules(
522                 {   branchcode   => undef,
523                     categorycode => undef,
524                     rules        => { open_article_requests_limit => undef, }
525                 }
526             );
527         } else {
528             Koha::CirculationRules->set_rules(
529                 {   categorycode => $categorycode,
530                     branchcode   => undef,
531                     rules        => { open_article_requests_limit => undef, }
532                 }
533             );
534         }
535     } elsif ( $categorycode eq "*" ) {
536         Koha::CirculationRules->set_rules(
537             {   branchcode   => $branch,
538                 categorycode => undef,
539                 rules        => { open_article_requests_limit => undef, }
540             }
541         );
542     } else {
543         Koha::CirculationRules->set_rules(
544             {   categorycode => $categorycode,
545                 branchcode   => $branch,
546                 rules        => { open_article_requests_limit => undef, }
547             }
548         );
549     }
550 }
551 elsif ( $op eq "set-article-request-fee" ) {
552
553     my $category = $input->param('article_request_fee_category');
554     my $fee      = strip_non_numeric( scalar $input->param('article_request_fee') );
555
556     Koha::Exception->throw("No value passed for article request fee")
557       if not defined $fee # There is a JS check for that
558       || $fee eq q{};
559
560     Koha::CirculationRules->set_rules(
561         {   categorycode => ( $category  eq '*' ) ? undef : $category,
562             branchcode   => ( $branch    eq '*' ) ? undef : $branch,
563             rules        => { article_request_fee => $fee },
564         }
565     );
566
567 } elsif ( $op eq 'del-article-request-fee' ) {
568
569     my $category  = $input->param('article_request_fee_category');
570
571     Koha::CirculationRules->set_rules(
572         {   categorycode => ( $category eq  '*' ) ? undef : $category,
573             branchcode   => ( $branch eq    '*' ) ? undef : $branch,
574             rules        => { article_request_fee => undef },
575         }
576     );
577 }
578 elsif ($op eq "add-branch-item") {
579     my $itemtype                = $input->param('itemtype');
580     my $holdallowed             = $input->param('holdallowed');
581     my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy');
582     my $returnbranch            = $input->param('returnbranch');
583
584     if ($branch eq "*") {
585         if ($itemtype eq "*") {
586             Koha::CirculationRules->set_rules(
587                 {
588                     itemtype     => undef,
589                     branchcode   => undef,
590                     rules        => {
591                         holdallowed             => $holdallowed,
592                         hold_fulfillment_policy => $hold_fulfillment_policy,
593                         returnbranch            => $returnbranch,
594                     }
595                 }
596             );
597         } else {
598             Koha::CirculationRules->set_rules(
599                 {
600                     itemtype     => $itemtype,
601                     branchcode   => undef,
602                     rules        => {
603                         holdallowed             => $holdallowed,
604                         hold_fulfillment_policy => $hold_fulfillment_policy,
605                         returnbranch            => $returnbranch,
606                     }
607                 }
608             );
609         }
610     } elsif ($itemtype eq "*") {
611             Koha::CirculationRules->set_rules(
612                 {
613                     itemtype     => undef,
614                     branchcode   => $branch,
615                     rules        => {
616                         holdallowed             => $holdallowed,
617                         hold_fulfillment_policy => $hold_fulfillment_policy,
618                         returnbranch            => $returnbranch,
619                     }
620                 }
621             );
622     } else {
623         Koha::CirculationRules->set_rules(
624             {
625                 itemtype     => $itemtype,
626                 branchcode   => $branch,
627                 rules        => {
628                     holdallowed             => $holdallowed,
629                     hold_fulfillment_policy => $hold_fulfillment_policy,
630                     returnbranch            => $returnbranch,
631                 }
632             }
633         );
634     }
635 }
636 elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
637
638     my $lostreturn = $input->param('lostreturn');
639
640     if ( $lostreturn eq '*' ) {
641         if ( $branch ne '*' ) {
642             # only do something for $lostreturn eq '*' if branch-specific
643             Koha::CirculationRules->set_rules(
644                 {
645                     branchcode   => $branch,
646                     rules        => {
647                         lostreturn => undef
648                     }
649                 }
650             );
651         }
652     } else {
653         Koha::CirculationRules->set_rules(
654             {
655                 branchcode   => $branch,
656                 rules        => {
657                     lostreturn => $lostreturn
658                 }
659             }
660         );
661     }
662 } elsif ( $op eq "set-waiting-hold-cancellation" ) {
663
664     my $category = $input->param('waiting_hold_cancellation_category');
665     my $itemtype = $input->param('waiting_hold_cancellation_itemtype');
666     my $policy   = strip_non_numeric( scalar $input->param('waiting_hold_cancellation_policy') )
667                     ? 1
668                     : 0;
669
670     Koha::Exception->throw("No value passed for waiting holds cancellation policy")
671       if not defined $policy # There is a JS check for that
672       || $policy eq '';
673
674     Koha::CirculationRules->set_rules(
675         {   categorycode => ( $category eq '*' ) ? undef : $category,
676             itemtype     => ( $itemtype eq '*' ) ? undef : $itemtype,
677             branchcode   => ( $branch   eq '*' ) ? undef : $branch,
678             rules        => { waiting_hold_cancellation => $policy },
679         }
680     );
681
682 } elsif ( $op eq 'del-waiting-hold-cancellation' ) {
683
684     my $category = $input->param('waiting_hold_cancellation_category');
685     my $itemtype = $input->param('waiting_hold_cancellation_itemtype');
686
687     Koha::CirculationRules->set_rules(
688         {   categorycode => ( $category eq '*' ) ? undef : $category,
689             itemtype     => ( $itemtype eq '*' ) ? undef : $itemtype,
690             branchcode   => ( $branch   eq '*' ) ? undef : $branch,
691             rules        => { waiting_hold_cancellation => undef },
692         }
693     );
694 }
695
696
697 my $refundLostItemFeeRule = Koha::CirculationRules->find({ branchcode => ($branch eq '*') ? undef : $branch, rule_name => 'lostreturn' });
698 my $defaultLostItemFeeRule = Koha::CirculationRules->find({ branchcode => undef, rule_name => 'lostreturn' });
699 $template->param(
700     refundLostItemFeeRule => $refundLostItemFeeRule,
701     defaultRefundRule     => $defaultLostItemFeeRule ? $defaultLostItemFeeRule->rule_value : 'refund'
702 );
703
704 my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
705
706 my $itemtypes = Koha::ItemTypes->search_with_localization;
707
708 my $humanbranch = ( $branch ne '*' ? $branch : undef );
709
710 my $all_rules = Koha::CirculationRules->search({ branchcode => $humanbranch });
711 my $definedbranch = $all_rules->count ? 1 : 0;
712
713 my $rules = {};
714 while ( my $r = $all_rules->next ) {
715     $r = $r->unblessed;
716     $rules->{ $r->{categorycode} // q{} }->{ $r->{itemtype} // q{} }->{ $r->{rule_name} } = $r->{rule_value};
717 }
718
719 $template->param(show_branch_cat_rule_form => 1);
720
721 $template->param(
722     patron_categories => $patron_categories,
723     itemtypeloop      => $itemtypes,
724     humanbranch       => $humanbranch,
725     current_branch    => $branch,
726     definedbranch     => $definedbranch,
727     all_rules         => $rules,
728 );
729 output_html_with_http_headers $input, $cookie, $template->output;
730
731 exit 0;
732
733 # sort by patron category, then item type, putting
734 # default entries at the bottom
735 sub by_category_and_itemtype {
736     unless (by_category($a, $b)) {
737         return by_itemtype($a, $b);
738     }
739 }
740
741 sub by_category {
742     my ($a, $b) = @_;
743     if ($a->{'default_humancategorycode'}) {
744         return ($b->{'default_humancategorycode'} ? 0 : 1);
745     } elsif ($b->{'default_humancategorycode'}) {
746         return -1;
747     } else {
748         return $a->{'humancategorycode'} cmp $b->{'humancategorycode'};
749     }
750 }
751
752 sub by_itemtype {
753     my ($a, $b) = @_;
754     if ($a->{default_translated_description}) {
755         return ($b->{'default_translated_description'} ? 0 : 1);
756     } elsif ($b->{'default_translated_description'}) {
757         return -1;
758     } else {
759         return lc $a->{'translated_description'} cmp lc $b->{'translated_description'};
760     }
761 }
762
763 sub strip_non_numeric {
764     my $string = shift;
765     $string =~ s/\s//g;
766     $string = q{} if $string !~ /^\d+/;
767     return $string;
768 }