bdeee64e01b3ad673b22e1f796bf0c73ddbdfce7
[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;
24 use C4::Auth;
25 use C4::Koha;
26 use C4::Debug;
27 use Koha::DateUtils;
28 use Koha::Database;
29 use Koha::IssuingRule;
30 use Koha::IssuingRules;
31 use Koha::Logger;
32 use Koha::RefundLostItemFeeRule;
33 use Koha::RefundLostItemFeeRules;
34 use Koha::Libraries;
35 use Koha::CirculationRules;
36 use Koha::Patron::Categories;
37 use Koha::Caches;
38
39 my $input = CGI->new;
40 my $dbh = C4::Context->dbh;
41
42 # my $flagsrequired;
43 # $flagsrequired->{circulation}=1;
44 my ($template, $loggedinuser, $cookie)
45     = get_template_and_user({template_name => "admin/smart-rules.tt",
46                             query => $input,
47                             type => "intranet",
48                             authnotrequired => 0,
49                             flagsrequired => {parameters => 'manage_circ_rules'},
50                             debug => 1,
51                             });
52
53 my $type=$input->param('type');
54
55 my $branch = $input->param('branch');
56 unless ( $branch ) {
57     if ( C4::Context->preference('DefaultToLoggedInLibraryCircRules') ) {
58         $branch = Koha::Libraries->search->count() == 1 ? undef : C4::Context::mybranch();
59     }
60     else {
61         $branch = C4::Context::only_my_library() ? ( C4::Context::mybranch() || '*' ) : '*';
62     }
63 }
64 $branch = '*' if $branch eq 'NO_LIBRARY_SET';
65
66 my $op = $input->param('op') || q{};
67 my $language = C4::Languages::getlanguage();
68
69 my $cache = Koha::Caches->get_instance;
70 $cache->clear_from_cache( Koha::IssuingRules::GUESSED_ITEMTYPES_KEY );
71
72 if ($op eq 'delete') {
73     my $itemtype     = $input->param('itemtype');
74     my $categorycode = $input->param('categorycode');
75     $debug and warn "deleting $1 $2 $branch";
76
77     my $sth_Idelete = $dbh->prepare("delete from issuingrules where branchcode=? and categorycode=? and itemtype=?");
78     $sth_Idelete->execute($branch, $categorycode, $itemtype);
79 }
80 elsif ($op eq 'delete-branch-cat') {
81     my $categorycode  = $input->param('categorycode');
82     if ($branch eq "*") {
83         if ($categorycode eq "*") {
84             my $sth_delete = $dbh->prepare("DELETE FROM default_circ_rules");
85             $sth_delete->execute();
86         } else {
87             my $sth_delete = $dbh->prepare("DELETE FROM default_borrower_circ_rules
88                                             WHERE categorycode = ?");
89             $sth_delete->execute($categorycode);
90         }
91     } elsif ($categorycode eq "*") {
92         my $sth_delete = $dbh->prepare("DELETE FROM default_branch_circ_rules
93                                         WHERE branchcode = ?");
94         $sth_delete->execute($branch);
95     } else {
96         my $sth_delete = $dbh->prepare("DELETE FROM branch_borrower_circ_rules
97                                         WHERE branchcode = ?
98                                         AND categorycode = ?");
99         $sth_delete->execute($branch, $categorycode);
100     }
101     Koha::CirculationRules->set_rule(
102         {
103             branchcode   => $branch,
104             categorycode => $categorycode,
105             itemtype     => undef,
106             rule_name    => 'max_holds',
107             rule_value   => undef,
108         }
109     );
110 }
111 elsif ($op eq 'delete-branch-item') {
112     my $itemtype  = $input->param('itemtype');
113     if ($branch eq "*") {
114         if ($itemtype eq "*") {
115             my $sth_delete = $dbh->prepare("DELETE FROM default_circ_rules");
116             $sth_delete->execute();
117         } else {
118             my $sth_delete = $dbh->prepare("DELETE FROM default_branch_item_rules
119                                             WHERE itemtype = ?");
120             $sth_delete->execute($itemtype);
121         }
122     } elsif ($itemtype eq "*") {
123         my $sth_delete = $dbh->prepare("DELETE FROM default_branch_circ_rules
124                                         WHERE branchcode = ?");
125         $sth_delete->execute($branch);
126     } else {
127         my $sth_delete = $dbh->prepare("DELETE FROM branch_item_rules
128                                         WHERE branchcode = ?
129                                         AND itemtype = ?");
130         $sth_delete->execute($branch, $itemtype);
131     }
132 }
133 # save the values entered
134 elsif ($op eq 'add') {
135     my $br = $branch; # branch
136     my $bor  = $input->param('categorycode'); # borrower category
137     my $itemtype  = $input->param('itemtype');     # item type
138     my $fine = $input->param('fine');
139     my $finedays     = $input->param('finedays');
140     my $maxsuspensiondays = $input->param('maxsuspensiondays');
141     $maxsuspensiondays = undef if $maxsuspensiondays eq q||;
142     my $suspension_chargeperiod = $input->param('suspension_chargeperiod') || 1;
143     my $firstremind  = $input->param('firstremind');
144     my $chargeperiod = $input->param('chargeperiod');
145     my $chargeperiod_charge_at = $input->param('chargeperiod_charge_at');
146     my $maxissueqty  = $input->param('maxissueqty');
147     my $maxonsiteissueqty  = $input->param('maxonsiteissueqty');
148     my $renewalsallowed  = $input->param('renewalsallowed');
149     my $renewalperiod    = $input->param('renewalperiod');
150     my $norenewalbefore  = $input->param('norenewalbefore');
151     $norenewalbefore = undef if $norenewalbefore =~ /^\s*$/;
152     my $auto_renew = $input->param('auto_renew') eq 'yes' ? 1 : 0;
153     my $no_auto_renewal_after = $input->param('no_auto_renewal_after');
154     $no_auto_renewal_after = undef if $no_auto_renewal_after =~ /^\s*$/;
155     my $no_auto_renewal_after_hard_limit = $input->param('no_auto_renewal_after_hard_limit') || undef;
156     $no_auto_renewal_after_hard_limit = eval { dt_from_string( $input->param('no_auto_renewal_after_hard_limit') ) } if ( $no_auto_renewal_after_hard_limit );
157     $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 );
158     my $reservesallowed  = $input->param('reservesallowed');
159     my $holds_per_record  = $input->param('holds_per_record');
160     my $onshelfholds     = $input->param('onshelfholds') || 0;
161     $maxissueqty =~ s/\s//g;
162     $maxissueqty = undef if $maxissueqty !~ /^\d+/;
163     $maxonsiteissueqty =~ s/\s//g;
164     $maxonsiteissueqty = undef if $maxonsiteissueqty !~ /^\d+/;
165     my $issuelength  = $input->param('issuelength');
166     $issuelength = $issuelength eq q{} ? undef : $issuelength;
167     my $lengthunit  = $input->param('lengthunit');
168     my $hardduedate = $input->param('hardduedate') || undef;
169     $hardduedate = eval { dt_from_string( $input->param('hardduedate') ) } if ( $hardduedate );
170     $hardduedate = output_pref( { dt => $hardduedate, dateonly => 1, dateformat => 'iso' } ) if ( $hardduedate );
171     my $hardduedatecompare = $input->param('hardduedatecompare');
172     my $rentaldiscount = $input->param('rentaldiscount');
173     my $opacitemholds = $input->param('opacitemholds') || 0;
174     my $article_requests = $input->param('article_requests') || 'no';
175     my $overduefinescap = $input->param('overduefinescap') || undef;
176     my $cap_fine_to_replacement_price = $input->param('cap_fine_to_replacement_price') eq 'on';
177     $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
178
179     my $params = {
180         branchcode                    => $br,
181         categorycode                  => $bor,
182         itemtype                      => $itemtype,
183         fine                          => $fine,
184         finedays                      => $finedays,
185         maxsuspensiondays             => $maxsuspensiondays,
186         suspension_chargeperiod       => $suspension_chargeperiod,
187         firstremind                   => $firstremind,
188         chargeperiod                  => $chargeperiod,
189         chargeperiod_charge_at        => $chargeperiod_charge_at,
190         maxissueqty                   => $maxissueqty,
191         maxonsiteissueqty             => $maxonsiteissueqty,
192         renewalsallowed               => $renewalsallowed,
193         renewalperiod                 => $renewalperiod,
194         norenewalbefore               => $norenewalbefore,
195         auto_renew                    => $auto_renew,
196         no_auto_renewal_after         => $no_auto_renewal_after,
197         no_auto_renewal_after_hard_limit => $no_auto_renewal_after_hard_limit,
198         reservesallowed               => $reservesallowed,
199         holds_per_record              => $holds_per_record,
200         issuelength                   => $issuelength,
201         lengthunit                    => $lengthunit,
202         hardduedate                   => $hardduedate,
203         hardduedatecompare            => $hardduedatecompare,
204         rentaldiscount                => $rentaldiscount,
205         onshelfholds                  => $onshelfholds,
206         opacitemholds                 => $opacitemholds,
207         overduefinescap               => $overduefinescap,
208         cap_fine_to_replacement_price => $cap_fine_to_replacement_price,
209         article_requests              => $article_requests,
210     };
211
212     my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br});
213     if ($issuingrule) {
214         $issuingrule->set($params)->store();
215     } else {
216         Koha::IssuingRule->new()->set($params)->store();
217     }
218
219 }
220 elsif ($op eq "set-branch-defaults") {
221     my $categorycode  = $input->param('categorycode');
222     my $maxissueqty   = $input->param('maxissueqty');
223     my $maxonsiteissueqty = $input->param('maxonsiteissueqty');
224     my $holdallowed   = $input->param('holdallowed');
225     my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy');
226     my $returnbranch  = $input->param('returnbranch');
227     my $max_holds = $input->param('max_holds');
228     $maxissueqty =~ s/\s//g;
229     $maxissueqty = undef if $maxissueqty !~ /^\d+/;
230     $maxonsiteissueqty =~ s/\s//g;
231     $maxonsiteissueqty = undef if $maxonsiteissueqty !~ /^\d+/;
232     $holdallowed =~ s/\s//g;
233     $holdallowed = undef if $holdallowed !~ /^\d+/;
234     $max_holds =~ s/\s//g;
235     $max_holds = '' if $max_holds !~ /^\d+/;
236
237     if ($branch eq "*") {
238         my $sth_search = $dbh->prepare("SELECT count(*) AS total
239                                         FROM default_circ_rules");
240         my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
241                                         (maxissueqty, maxonsiteissueqty, holdallowed, hold_fulfillment_policy, returnbranch)
242                                         VALUES (?, ?, ?, ?, ?)");
243         my $sth_update = $dbh->prepare("UPDATE default_circ_rules
244                                         SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?");
245
246         $sth_search->execute();
247         my $res = $sth_search->fetchrow_hashref();
248         if ($res->{total}) {
249             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
250         } else {
251             $sth_insert->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
252         }
253     } else {
254         my $sth_search = $dbh->prepare("SELECT count(*) AS total
255                                         FROM default_branch_circ_rules
256                                         WHERE branchcode = ?");
257         my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
258                                         (branchcode, maxissueqty, maxonsiteissueqty, holdallowed, hold_fulfillment_policy, returnbranch)
259                                         VALUES (?, ?, ?, ?, ?, ?)");
260         my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
261                                         SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
262                                         WHERE branchcode = ?");
263         $sth_search->execute($branch);
264         my $res = $sth_search->fetchrow_hashref();
265         if ($res->{total}) {
266             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch, $branch);
267         } else {
268             $sth_insert->execute($branch, $maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
269         }
270     }
271     Koha::CirculationRules->set_rule(
272         {
273             branchcode   => $branch,
274             categorycode => undef,
275             itemtype     => undef,
276             rule_name    => 'max_holds',
277             rule_value   => $max_holds,
278         }
279     );
280 }
281 elsif ($op eq "add-branch-cat") {
282     my $categorycode  = $input->param('categorycode');
283     my $maxissueqty   = $input->param('maxissueqty');
284     my $maxonsiteissueqty = $input->param('maxonsiteissueqty');
285     my $max_holds = $input->param('max_holds');
286     $maxissueqty =~ s/\s//g;
287     $maxissueqty = undef if $maxissueqty !~ /^\d+/;
288     $maxonsiteissueqty =~ s/\s//g;
289     $maxonsiteissueqty = undef if $maxonsiteissueqty !~ /^\d+/;
290     $max_holds =~ s/\s//g;
291     $max_holds = undef if $max_holds !~ /^\d+/;
292
293     if ($branch eq "*") {
294         if ($categorycode eq "*") {
295             my $sth_search = $dbh->prepare("SELECT count(*) AS total
296                                             FROM default_circ_rules");
297             my $sth_insert = $dbh->prepare(q|
298                 INSERT INTO default_circ_rules
299                     (maxissueqty, maxonsiteissueqty, max_holds)
300                     VALUES (?, ?, ?)
301             |);
302             my $sth_update = $dbh->prepare(q|
303                 UPDATE default_circ_rules
304                 SET maxissueqty = ?,
305                     maxonsiteissueqty = ?,
306                     max_holds = ?
307             |);
308
309             $sth_search->execute();
310             my $res = $sth_search->fetchrow_hashref();
311             if ($res->{total}) {
312                 $sth_update->execute( $maxissueqty, $maxonsiteissueqty );
313             } else {
314                 $sth_insert->execute( $maxissueqty, $maxonsiteissueqty );
315             }
316
317             Koha::CirculationRules->set_rule(
318                 {
319                     branchcode   => undef,
320                     categorycode => undef,
321                     itemtype     => undef,
322                     rule_name    => 'max_holds',
323                     rule_value   => $max_holds,
324                 }
325             );
326         } else {
327             my $sth_search = $dbh->prepare("SELECT count(*) AS total
328                                             FROM default_borrower_circ_rules
329                                             WHERE categorycode = ?");
330             my $sth_insert = $dbh->prepare(q|
331                 INSERT INTO default_borrower_circ_rules
332                     (categorycode, maxissueqty, maxonsiteissueqty)
333                     VALUES ( ?, ?, ?)
334             |);
335             my $sth_update = $dbh->prepare(q|
336                 UPDATE default_borrower_circ_rules
337                 SET maxissueqty = ?,
338                     maxonsiteissueqty = ?,
339                 WHERE categorycode = ?
340             |);
341             $sth_search->execute($categorycode);
342             my $res = $sth_search->fetchrow_hashref();
343             if ($res->{total}) {
344                 $sth_update->execute( $maxissueqty, $maxonsiteissueqty, $categorycode );
345             } else {
346                 $sth_insert->execute( $categorycode, $maxissueqty, $maxonsiteissueqty );
347             }
348
349             Koha::CirculationRules->set_rule(
350                 {
351                     branchcode   => undef,
352                     categorycode => $categorycode,
353                     itemtype     => undef,
354                     rule_name    => 'max_holds',
355                     rule_value   => $max_holds,
356                 }
357             );
358         }
359     } elsif ($categorycode eq "*") {
360         my $sth_search = $dbh->prepare("SELECT count(*) AS total
361                                         FROM default_branch_circ_rules
362                                         WHERE branchcode = ?");
363         my $sth_insert = $dbh->prepare(q|
364             INSERT INTO default_branch_circ_rules
365             (branchcode, maxissueqty, maxonsiteissueqty)
366             VALUES (?, ?, ?)
367         |);
368         my $sth_update = $dbh->prepare(q|
369             UPDATE default_branch_circ_rules
370             SET maxissueqty = ?,
371                 maxonsiteissueqty = ?
372             WHERE branchcode = ?
373         |);
374         $sth_search->execute($branch);
375         my $res = $sth_search->fetchrow_hashref();
376         if ($res->{total}) {
377             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $branch);
378         } else {
379             $sth_insert->execute($branch, $maxissueqty, $maxonsiteissueqty);
380         }
381     } else {
382         my $sth_search = $dbh->prepare("SELECT count(*) AS total
383                                         FROM branch_borrower_circ_rules
384                                         WHERE branchcode = ?
385                                         AND   categorycode = ?");
386         my $sth_insert = $dbh->prepare(q|
387             INSERT INTO branch_borrower_circ_rules
388             (branchcode, categorycode, maxissueqty, maxonsiteissueqty, max_holds)
389             VALUES (?, ?, ?, ?, ?)
390         |);
391         my $sth_update = $dbh->prepare(q|
392             UPDATE branch_borrower_circ_rules
393             SET maxissueqty = ?,
394                 maxonsiteissueqty = ?
395                 max_holds = ?
396             WHERE branchcode = ?
397             AND categorycode = ?
398         |);
399
400         $sth_search->execute($branch, $categorycode);
401         my $res = $sth_search->fetchrow_hashref();
402         if ($res->{total}) {
403             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $max_holds, $branch, $categorycode);
404         } else {
405             $sth_insert->execute($branch, $categorycode, $maxissueqty, $maxonsiteissueqty, $max_holds);
406         }
407
408         Koha::CirculationRules->set_rule(
409             {
410                 branchcode   => $branch,
411                 categorycode => $categorycode,
412                 itemtype     => undef,
413                 rule_name    => 'max_holds',
414                 rule_value   => $max_holds,
415             }
416         );
417     }
418 }
419 elsif ($op eq "add-branch-item") {
420     my $itemtype                = $input->param('itemtype');
421     my $holdallowed             = $input->param('holdallowed');
422     my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy');
423     my $returnbranch            = $input->param('returnbranch');
424
425     $holdallowed =~ s/\s//g;
426     $holdallowed = undef if $holdallowed !~ /^\d+/;
427
428     if ($branch eq "*") {
429         if ($itemtype eq "*") {
430             my $sth_search = $dbh->prepare("SELECT count(*) AS total
431                                             FROM default_circ_rules");
432             my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
433                                             (holdallowed, hold_fulfillment_policy, returnbranch)
434                                             VALUES (?, ?, ?)");
435             my $sth_update = $dbh->prepare("UPDATE default_circ_rules
436                                             SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?");
437
438             $sth_search->execute();
439             my $res = $sth_search->fetchrow_hashref();
440             if ($res->{total}) {
441                 $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch);
442             } else {
443                 $sth_insert->execute($holdallowed, $hold_fulfillment_policy, $returnbranch);
444             }
445         } else {
446             my $sth_search = $dbh->prepare("SELECT count(*) AS total
447                                             FROM default_branch_item_rules
448                                             WHERE itemtype = ?");
449             my $sth_insert = $dbh->prepare("INSERT INTO default_branch_item_rules
450                                             (itemtype, holdallowed, hold_fulfillment_policy, returnbranch)
451                                             VALUES (?, ?, ?, ?)");
452             my $sth_update = $dbh->prepare("UPDATE default_branch_item_rules
453                                             SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
454                                             WHERE itemtype = ?");
455             $sth_search->execute($itemtype);
456             my $res = $sth_search->fetchrow_hashref();
457             if ($res->{total}) {
458                 $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $itemtype);
459             } else {
460                 $sth_insert->execute($itemtype, $holdallowed, $hold_fulfillment_policy, $returnbranch);
461             }
462         }
463     } elsif ($itemtype eq "*") {
464         my $sth_search = $dbh->prepare("SELECT count(*) AS total
465                                         FROM default_branch_circ_rules
466                                         WHERE branchcode = ?");
467         my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
468                                         (branchcode, holdallowed, hold_fulfillment_policy, returnbranch)
469                                         VALUES (?, ?, ?, ?)");
470         my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
471                                         SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
472                                         WHERE branchcode = ?");
473         $sth_search->execute($branch);
474         my $res = $sth_search->fetchrow_hashref();
475         if ($res->{total}) {
476             $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $branch);
477         } else {
478             $sth_insert->execute($branch, $holdallowed, $hold_fulfillment_policy, $returnbranch);
479         }
480     } else {
481         my $sth_search = $dbh->prepare("SELECT count(*) AS total
482                                         FROM branch_item_rules
483                                         WHERE branchcode = ?
484                                         AND   itemtype = ?");
485         my $sth_insert = $dbh->prepare("INSERT INTO branch_item_rules
486                                         (branchcode, itemtype, holdallowed, hold_fulfillment_policy, returnbranch)
487                                         VALUES (?, ?, ?, ?, ?)");
488         my $sth_update = $dbh->prepare("UPDATE branch_item_rules
489                                         SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
490                                         WHERE branchcode = ?
491                                         AND itemtype = ?");
492
493         $sth_search->execute($branch, $itemtype);
494         my $res = $sth_search->fetchrow_hashref();
495         if ($res->{total}) {
496             $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $branch, $itemtype);
497         } else {
498             $sth_insert->execute($branch, $itemtype, $holdallowed, $hold_fulfillment_policy, $returnbranch);
499         }
500     }
501 }
502 elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
503
504     my $refund = $input->param('refund');
505
506     if ( $refund eq '*' ) {
507         if ( $branch ne '*' ) {
508             # only do something for $refund eq '*' if branch-specific
509             eval {
510                 # Delete it so it picks the default
511                 Koha::RefundLostItemFeeRules->find({
512                     branchcode => $branch
513                 })->delete;
514             };
515         }
516     } else {
517         my $refundRule =
518                 Koha::RefundLostItemFeeRules->find({
519                     branchcode => $branch
520                 }) // Koha::RefundLostItemFeeRule->new;
521         $refundRule->set({
522             branchcode => $branch,
523                 refund => $refund
524         })->store;
525     }
526 }
527
528 my $refundLostItemFeeRule = Koha::RefundLostItemFeeRules->find({ branchcode => $branch });
529 $template->param(
530     refundLostItemFeeRule => $refundLostItemFeeRule,
531     defaultRefundRule     => Koha::RefundLostItemFeeRules->_default_rule
532 );
533
534 my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
535
536 my @row_loop;
537 my $itemtypes = Koha::ItemTypes->search_with_localization;
538
539 my $sth2 = $dbh->prepare("
540     SELECT  issuingrules.*,
541             itemtypes.description AS humanitemtype,
542             categories.description AS humancategorycode,
543             COALESCE( localization.translation, itemtypes.description ) AS translated_description
544     FROM issuingrules
545     LEFT JOIN itemtypes
546         ON (itemtypes.itemtype = issuingrules.itemtype)
547     LEFT JOIN categories
548         ON (categories.categorycode = issuingrules.categorycode)
549     LEFT JOIN localization ON issuingrules.itemtype = localization.code
550         AND localization.entity = 'itemtypes'
551         AND localization.lang = ?
552     WHERE issuingrules.branchcode = ?
553 ");
554 $sth2->execute($language, $branch);
555
556 while (my $row = $sth2->fetchrow_hashref) {
557     $row->{'current_branch'} ||= $row->{'branchcode'};
558     $row->{humanitemtype} ||= $row->{itemtype};
559     $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
560     $row->{'humancategorycode'} ||= $row->{'categorycode'};
561     $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
562     $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
563     if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
564        my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
565        $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
566        $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
567        $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
568        $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
569     } else {
570        $row->{'hardduedate'} = 0;
571     }
572     if ($row->{no_auto_renewal_after_hard_limit}) {
573        my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
574        $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
575     }
576
577     push @row_loop, $row;
578 }
579
580 my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
581
582 my $sth_branch_cat;
583 if ($branch eq "*") {
584     $sth_branch_cat = $dbh->prepare("
585         SELECT default_borrower_circ_rules.*, categories.description AS humancategorycode
586         FROM default_borrower_circ_rules
587         JOIN categories USING (categorycode)
588
589     ");
590     $sth_branch_cat->execute();
591 } else {
592     $sth_branch_cat = $dbh->prepare("
593         SELECT branch_borrower_circ_rules.*, categories.description AS humancategorycode
594         FROM branch_borrower_circ_rules
595         JOIN categories USING (categorycode)
596         WHERE branch_borrower_circ_rules.branchcode = ?
597     ");
598     $sth_branch_cat->execute($branch);
599 }
600
601 my @branch_cat_rules = ();
602 while (my $row = $sth_branch_cat->fetchrow_hashref) {
603     push @branch_cat_rules, $row;
604 }
605 my @sorted_branch_cat_rules = sort { $a->{'humancategorycode'} cmp $b->{'humancategorycode'} } @branch_cat_rules;
606
607 # note undef maxissueqty so that template can deal with them
608 foreach my $entry (@sorted_branch_cat_rules, @sorted_row_loop) {
609     $entry->{unlimited_maxissueqty} = 1 unless defined($entry->{maxissueqty});
610     $entry->{unlimited_maxonsiteissueqty} = 1 unless defined($entry->{maxonsiteissueqty});
611     $entry->{unlimited_max_holds} = 1 unless defined($entry->{max_holds});
612 }
613
614 @sorted_row_loop = sort by_category_and_itemtype @row_loop;
615
616 my $sth_branch_item;
617 if ($branch eq "*") {
618     $sth_branch_item = $dbh->prepare("
619         SELECT default_branch_item_rules.*,
620             COALESCE( localization.translation, itemtypes.description ) AS translated_description
621         FROM default_branch_item_rules
622         JOIN itemtypes USING (itemtype)
623         LEFT JOIN localization ON itemtypes.itemtype = localization.code
624             AND localization.entity = 'itemtypes'
625             AND localization.lang = ?
626     ");
627     $sth_branch_item->execute($language);
628 } else {
629     $sth_branch_item = $dbh->prepare("
630         SELECT branch_item_rules.*,
631             COALESCE( localization.translation, itemtypes.description ) AS translated_description
632         FROM branch_item_rules
633         JOIN itemtypes USING (itemtype)
634         LEFT JOIN localization ON itemtypes.itemtype = localization.code
635             AND localization.entity = 'itemtypes'
636             AND localization.lang = ?
637         WHERE branch_item_rules.branchcode = ?
638     ");
639     $sth_branch_item->execute($language, $branch);
640 }
641
642 my @branch_item_rules = ();
643 while (my $row = $sth_branch_item->fetchrow_hashref) {
644     push @branch_item_rules, $row;
645 }
646 my @sorted_branch_item_rules = sort { lc $a->{translated_description} cmp lc $b->{translated_description} } @branch_item_rules;
647
648 # note undef holdallowed so that template can deal with them
649 foreach my $entry (@sorted_branch_item_rules) {
650     $entry->{holdallowed_any}  = 1 if ( $entry->{holdallowed} == 2 );
651     $entry->{holdallowed_same} = 1 if ( $entry->{holdallowed} == 1 );
652 }
653
654 $template->param(show_branch_cat_rule_form => 1);
655 $template->param(branch_item_rule_loop => \@sorted_branch_item_rules);
656 $template->param(branch_cat_rule_loop => \@sorted_branch_cat_rules);
657
658 my $sth_defaults;
659 if ($branch eq "*") {
660     $sth_defaults = $dbh->prepare("
661         SELECT *
662         FROM default_circ_rules
663     ");
664     $sth_defaults->execute();
665 } else {
666     $sth_defaults = $dbh->prepare("
667         SELECT *
668         FROM default_branch_circ_rules
669         WHERE branchcode = ?
670     ");
671     $sth_defaults->execute($branch);
672 }
673
674 my $defaults = $sth_defaults->fetchrow_hashref;
675
676 if ($defaults) {
677     $template->param( default_holdallowed_none => 1 ) if ( $defaults->{holdallowed} == 0 );
678     $template->param( default_holdallowed_same => 1 ) if ( $defaults->{holdallowed} == 1 );
679     $template->param( default_holdallowed_any  => 1 ) if ( $defaults->{holdallowed} == 2 );
680     $template->param( default_hold_fulfillment_policy => $defaults->{hold_fulfillment_policy} );
681     $template->param( default_maxissueqty      => $defaults->{maxissueqty} );
682     $template->param( default_maxonsiteissueqty => $defaults->{maxonsiteissueqty} );
683     $template->param( default_returnbranch      => $defaults->{returnbranch} );
684 }
685
686 $template->param(default_rules => ($defaults ? 1 : 0));
687
688 $template->param(
689     patron_categories => $patron_categories,
690                         itemtypeloop => $itemtypes,
691                         rules => \@sorted_row_loop,
692                         humanbranch => ($branch ne '*' ? $branch : ''),
693                         current_branch => $branch,
694                         definedbranch => scalar(@sorted_row_loop)>0
695                         );
696 output_html_with_http_headers $input, $cookie, $template->output;
697
698 exit 0;
699
700 # sort by patron category, then item type, putting
701 # default entries at the bottom
702 sub by_category_and_itemtype {
703     unless (by_category($a, $b)) {
704         return by_itemtype($a, $b);
705     }
706 }
707
708 sub by_category {
709     my ($a, $b) = @_;
710     if ($a->{'default_humancategorycode'}) {
711         return ($b->{'default_humancategorycode'} ? 0 : 1);
712     } elsif ($b->{'default_humancategorycode'}) {
713         return -1;
714     } else {
715         return $a->{'humancategorycode'} cmp $b->{'humancategorycode'};
716     }
717 }
718
719 sub by_itemtype {
720     my ($a, $b) = @_;
721     if ($a->{default_translated_description}) {
722         return ($b->{'default_translated_description'} ? 0 : 1);
723     } elsif ($b->{'default_translated_description'}) {
724         return -1;
725     } else {
726         return lc $a->{'translated_description'} cmp lc $b->{'translated_description'};
727     }
728 }