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