Bug 18887: Port max_holds rules to new CirculationRules system
[koha-equinox.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     $maxissueqty =~ s/\s//g;
228     $maxissueqty = undef if $maxissueqty !~ /^\d+/;
229     $maxonsiteissueqty =~ s/\s//g;
230     $maxonsiteissueqty = undef if $maxonsiteissueqty !~ /^\d+/;
231     $holdallowed =~ s/\s//g;
232     $holdallowed = undef if $holdallowed !~ /^\d+/;
233
234     if ($branch eq "*") {
235         my $sth_search = $dbh->prepare("SELECT count(*) AS total
236                                         FROM default_circ_rules");
237         my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
238                                         (maxissueqty, maxonsiteissueqty, holdallowed, hold_fulfillment_policy, returnbranch)
239                                         VALUES (?, ?, ?, ?, ?)");
240         my $sth_update = $dbh->prepare("UPDATE default_circ_rules
241                                         SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?");
242
243         $sth_search->execute();
244         my $res = $sth_search->fetchrow_hashref();
245         if ($res->{total}) {
246             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
247         } else {
248             $sth_insert->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
249         }
250     } else {
251         my $sth_search = $dbh->prepare("SELECT count(*) AS total
252                                         FROM default_branch_circ_rules
253                                         WHERE branchcode = ?");
254         my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
255                                         (branchcode, maxissueqty, maxonsiteissueqty, holdallowed, hold_fulfillment_policy, returnbranch)
256                                         VALUES (?, ?, ?, ?, ?, ?)");
257         my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
258                                         SET maxissueqty = ?, maxonsiteissueqty = ?, holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
259                                         WHERE branchcode = ?");
260         $sth_search->execute($branch);
261         my $res = $sth_search->fetchrow_hashref();
262         if ($res->{total}) {
263             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch, $branch);
264         } else {
265             $sth_insert->execute($branch, $maxissueqty, $maxonsiteissueqty, $holdallowed, $hold_fulfillment_policy, $returnbranch);
266         }
267     }
268 }
269 elsif ($op eq "add-branch-cat") {
270     my $categorycode  = $input->param('categorycode');
271     my $maxissueqty   = $input->param('maxissueqty');
272     my $maxonsiteissueqty = $input->param('maxonsiteissueqty');
273     my $max_holds = $input->param('max_holds');
274     $maxissueqty =~ s/\s//g;
275     $maxissueqty = undef if $maxissueqty !~ /^\d+/;
276     $maxonsiteissueqty =~ s/\s//g;
277     $maxonsiteissueqty = undef if $maxonsiteissueqty !~ /^\d+/;
278     $max_holds =~ s/\s//g;
279     $max_holds = undef if $max_holds !~ /^\d+/;
280
281     if ($branch eq "*") {
282         if ($categorycode eq "*") {
283             my $sth_search = $dbh->prepare("SELECT count(*) AS total
284                                             FROM default_circ_rules");
285             my $sth_insert = $dbh->prepare(q|
286                 INSERT INTO default_circ_rules
287                     (maxissueqty, maxonsiteissueqty, max_holds)
288                     VALUES (?, ?, ?)
289             |);
290             my $sth_update = $dbh->prepare(q|
291                 UPDATE default_circ_rules
292                 SET maxissueqty = ?,
293                     maxonsiteissueqty = ?,
294                     max_holds = ?
295             |);
296
297             $sth_search->execute();
298             my $res = $sth_search->fetchrow_hashref();
299             if ($res->{total}) {
300                 $sth_update->execute( $maxissueqty, $maxonsiteissueqty );
301             } else {
302                 $sth_insert->execute( $maxissueqty, $maxonsiteissueqty );
303             }
304
305             Koha::CirculationRules->set_rule(
306                 {
307                     branchcode   => undef,
308                     categorycode => undef,
309                     itemtype     => undef,
310                     rule_name    => 'max_holds',
311                     rule_value   => $max_holds,
312                 }
313             );
314         } else {
315             my $sth_search = $dbh->prepare("SELECT count(*) AS total
316                                             FROM default_borrower_circ_rules
317                                             WHERE categorycode = ?");
318             my $sth_insert = $dbh->prepare(q|
319                 INSERT INTO default_borrower_circ_rules
320                     (categorycode, maxissueqty, maxonsiteissueqty, max_holds)
321                     VALUES (?, ?, ?, ?)
322             |);
323             my $sth_update = $dbh->prepare(q|
324                 UPDATE default_borrower_circ_rules
325                 SET maxissueqty = ?,
326                     maxonsiteissueqty = ?,
327                     max_holds = ?
328                 WHERE categorycode = ?
329             |);
330             $sth_search->execute($categorycode);
331             my $res = $sth_search->fetchrow_hashref();
332             if ($res->{total}) {
333                 $sth_update->execute( $maxissueqty, $maxonsiteissueqty, $categorycode );
334             } else {
335                 $sth_insert->execute( $categorycode, $maxissueqty, $maxonsiteissueqty );
336             }
337
338             Koha::CirculationRules->set_rule(
339                 {
340                     branchcode   => undef,
341                     categorycode => $categorycode,
342                     itemtype     => undef,
343                     rule_name    => 'max_holds',
344                     rule_value   => $max_holds,
345                 }
346             );
347         }
348     } elsif ($categorycode eq "*") {
349         my $sth_search = $dbh->prepare("SELECT count(*) AS total
350                                         FROM default_branch_circ_rules
351                                         WHERE branchcode = ?");
352         my $sth_insert = $dbh->prepare(q|
353             INSERT INTO default_branch_circ_rules
354             (branchcode, maxissueqty, maxonsiteissueqty)
355             VALUES (?, ?, ?)
356         |);
357         my $sth_update = $dbh->prepare(q|
358             UPDATE default_branch_circ_rules
359             SET maxissueqty = ?,
360                 maxonsiteissueqty = ?
361             WHERE branchcode = ?
362         |);
363         $sth_search->execute($branch);
364         my $res = $sth_search->fetchrow_hashref();
365         if ($res->{total}) {
366             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $branch);
367         } else {
368             $sth_insert->execute($branch, $maxissueqty, $maxonsiteissueqty);
369         }
370     } else {
371         my $sth_search = $dbh->prepare("SELECT count(*) AS total
372                                         FROM branch_borrower_circ_rules
373                                         WHERE branchcode = ?
374                                         AND   categorycode = ?");
375         my $sth_insert = $dbh->prepare(q|
376             INSERT INTO branch_borrower_circ_rules
377             (branchcode, categorycode, maxissueqty, maxonsiteissueqty, max_holds)
378             VALUES (?, ?, ?, ?, ?)
379         |);
380         my $sth_update = $dbh->prepare(q|
381             UPDATE branch_borrower_circ_rules
382             SET maxissueqty = ?,
383                 maxonsiteissueqty = ?
384                 max_holds = ?
385             WHERE branchcode = ?
386             AND categorycode = ?
387         |);
388
389         $sth_search->execute($branch, $categorycode);
390         my $res = $sth_search->fetchrow_hashref();
391         if ($res->{total}) {
392             $sth_update->execute($maxissueqty, $maxonsiteissueqty, $max_holds, $branch, $categorycode);
393         } else {
394             $sth_insert->execute($branch, $categorycode, $maxissueqty, $maxonsiteissueqty, $max_holds);
395         }
396
397         Koha::CirculationRules->set_rule(
398             {
399                 branchcode   => $branch,
400                 categorycode => $categorycode,
401                 itemtype     => undef,
402                 rule_name    => 'max_holds',
403                 rule_value   => $max_holds,
404             }
405         );
406     }
407 }
408 elsif ($op eq "add-branch-item") {
409     my $itemtype                = $input->param('itemtype');
410     my $holdallowed             = $input->param('holdallowed');
411     my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy');
412     my $returnbranch            = $input->param('returnbranch');
413
414     $holdallowed =~ s/\s//g;
415     $holdallowed = undef if $holdallowed !~ /^\d+/;
416
417     if ($branch eq "*") {
418         if ($itemtype eq "*") {
419             my $sth_search = $dbh->prepare("SELECT count(*) AS total
420                                             FROM default_circ_rules");
421             my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
422                                             (holdallowed, hold_fulfillment_policy, returnbranch)
423                                             VALUES (?, ?, ?)");
424             my $sth_update = $dbh->prepare("UPDATE default_circ_rules
425                                             SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?");
426
427             $sth_search->execute();
428             my $res = $sth_search->fetchrow_hashref();
429             if ($res->{total}) {
430                 $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch);
431             } else {
432                 $sth_insert->execute($holdallowed, $hold_fulfillment_policy, $returnbranch);
433             }
434         } else {
435             my $sth_search = $dbh->prepare("SELECT count(*) AS total
436                                             FROM default_branch_item_rules
437                                             WHERE itemtype = ?");
438             my $sth_insert = $dbh->prepare("INSERT INTO default_branch_item_rules
439                                             (itemtype, holdallowed, hold_fulfillment_policy, returnbranch)
440                                             VALUES (?, ?, ?, ?)");
441             my $sth_update = $dbh->prepare("UPDATE default_branch_item_rules
442                                             SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
443                                             WHERE itemtype = ?");
444             $sth_search->execute($itemtype);
445             my $res = $sth_search->fetchrow_hashref();
446             if ($res->{total}) {
447                 $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $itemtype);
448             } else {
449                 $sth_insert->execute($itemtype, $holdallowed, $hold_fulfillment_policy, $returnbranch);
450             }
451         }
452     } elsif ($itemtype eq "*") {
453         my $sth_search = $dbh->prepare("SELECT count(*) AS total
454                                         FROM default_branch_circ_rules
455                                         WHERE branchcode = ?");
456         my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
457                                         (branchcode, holdallowed, hold_fulfillment_policy, returnbranch)
458                                         VALUES (?, ?, ?, ?)");
459         my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
460                                         SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
461                                         WHERE branchcode = ?");
462         $sth_search->execute($branch);
463         my $res = $sth_search->fetchrow_hashref();
464         if ($res->{total}) {
465             $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $branch);
466         } else {
467             $sth_insert->execute($branch, $holdallowed, $hold_fulfillment_policy, $returnbranch);
468         }
469     } else {
470         my $sth_search = $dbh->prepare("SELECT count(*) AS total
471                                         FROM branch_item_rules
472                                         WHERE branchcode = ?
473                                         AND   itemtype = ?");
474         my $sth_insert = $dbh->prepare("INSERT INTO branch_item_rules
475                                         (branchcode, itemtype, holdallowed, hold_fulfillment_policy, returnbranch)
476                                         VALUES (?, ?, ?, ?, ?)");
477         my $sth_update = $dbh->prepare("UPDATE branch_item_rules
478                                         SET holdallowed = ?, hold_fulfillment_policy = ?, returnbranch = ?
479                                         WHERE branchcode = ?
480                                         AND itemtype = ?");
481
482         $sth_search->execute($branch, $itemtype);
483         my $res = $sth_search->fetchrow_hashref();
484         if ($res->{total}) {
485             $sth_update->execute($holdallowed, $hold_fulfillment_policy, $returnbranch, $branch, $itemtype);
486         } else {
487             $sth_insert->execute($branch, $itemtype, $holdallowed, $hold_fulfillment_policy, $returnbranch);
488         }
489     }
490 }
491 elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) {
492
493     my $refund = $input->param('refund');
494
495     if ( $refund eq '*' ) {
496         if ( $branch ne '*' ) {
497             # only do something for $refund eq '*' if branch-specific
498             eval {
499                 # Delete it so it picks the default
500                 Koha::RefundLostItemFeeRules->find({
501                     branchcode => $branch
502                 })->delete;
503             };
504         }
505     } else {
506         my $refundRule =
507                 Koha::RefundLostItemFeeRules->find({
508                     branchcode => $branch
509                 }) // Koha::RefundLostItemFeeRule->new;
510         $refundRule->set({
511             branchcode => $branch,
512                 refund => $refund
513         })->store;
514     }
515 }
516
517 my $refundLostItemFeeRule = Koha::RefundLostItemFeeRules->find({ branchcode => $branch });
518 $template->param(
519     refundLostItemFeeRule => $refundLostItemFeeRule,
520     defaultRefundRule     => Koha::RefundLostItemFeeRules->_default_rule
521 );
522
523 my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] });
524
525 my @row_loop;
526 my $itemtypes = Koha::ItemTypes->search_with_localization;
527
528 my $sth2 = $dbh->prepare("
529     SELECT  issuingrules.*,
530             itemtypes.description AS humanitemtype,
531             categories.description AS humancategorycode,
532             COALESCE( localization.translation, itemtypes.description ) AS translated_description
533     FROM issuingrules
534     LEFT JOIN itemtypes
535         ON (itemtypes.itemtype = issuingrules.itemtype)
536     LEFT JOIN categories
537         ON (categories.categorycode = issuingrules.categorycode)
538     LEFT JOIN localization ON issuingrules.itemtype = localization.code
539         AND localization.entity = 'itemtypes'
540         AND localization.lang = ?
541     WHERE issuingrules.branchcode = ?
542 ");
543 $sth2->execute($language, $branch);
544
545 while (my $row = $sth2->fetchrow_hashref) {
546     $row->{'current_branch'} ||= $row->{'branchcode'};
547     $row->{humanitemtype} ||= $row->{itemtype};
548     $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
549     $row->{'humancategorycode'} ||= $row->{'categorycode'};
550     $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
551     $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
552     if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
553        my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
554        $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
555        $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
556        $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
557        $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
558     } else {
559        $row->{'hardduedate'} = 0;
560     }
561     if ($row->{no_auto_renewal_after_hard_limit}) {
562        my $dt = eval { dt_from_string( $row->{no_auto_renewal_after_hard_limit} ) };
563        $row->{no_auto_renewal_after_hard_limit} = eval { output_pref( { dt => $dt, dateonly => 1 } ) } if $dt;
564     }
565
566     push @row_loop, $row;
567 }
568
569 my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
570
571 my $sth_branch_cat;
572 if ($branch eq "*") {
573     $sth_branch_cat = $dbh->prepare("
574         SELECT default_borrower_circ_rules.*, categories.description AS humancategorycode
575         FROM default_borrower_circ_rules
576         JOIN categories USING (categorycode)
577
578     ");
579     $sth_branch_cat->execute();
580 } else {
581     $sth_branch_cat = $dbh->prepare("
582         SELECT branch_borrower_circ_rules.*, categories.description AS humancategorycode
583         FROM branch_borrower_circ_rules
584         JOIN categories USING (categorycode)
585         WHERE branch_borrower_circ_rules.branchcode = ?
586     ");
587     $sth_branch_cat->execute($branch);
588 }
589
590 my @branch_cat_rules = ();
591 while (my $row = $sth_branch_cat->fetchrow_hashref) {
592     push @branch_cat_rules, $row;
593 }
594 my @sorted_branch_cat_rules = sort { $a->{'humancategorycode'} cmp $b->{'humancategorycode'} } @branch_cat_rules;
595
596 # note undef maxissueqty so that template can deal with them
597 foreach my $entry (@sorted_branch_cat_rules, @sorted_row_loop) {
598     $entry->{unlimited_maxissueqty} = 1 unless defined($entry->{maxissueqty});
599     $entry->{unlimited_maxonsiteissueqty} = 1 unless defined($entry->{maxonsiteissueqty});
600     $entry->{unlimited_max_holds} = 1 unless defined($entry->{max_holds});
601 }
602
603 @sorted_row_loop = sort by_category_and_itemtype @row_loop;
604
605 my $sth_branch_item;
606 if ($branch eq "*") {
607     $sth_branch_item = $dbh->prepare("
608         SELECT default_branch_item_rules.*,
609             COALESCE( localization.translation, itemtypes.description ) AS translated_description
610         FROM default_branch_item_rules
611         JOIN itemtypes USING (itemtype)
612         LEFT JOIN localization ON itemtypes.itemtype = localization.code
613             AND localization.entity = 'itemtypes'
614             AND localization.lang = ?
615     ");
616     $sth_branch_item->execute($language);
617 } else {
618     $sth_branch_item = $dbh->prepare("
619         SELECT branch_item_rules.*,
620             COALESCE( localization.translation, itemtypes.description ) AS translated_description
621         FROM 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         WHERE branch_item_rules.branchcode = ?
627     ");
628     $sth_branch_item->execute($language, $branch);
629 }
630
631 my @branch_item_rules = ();
632 while (my $row = $sth_branch_item->fetchrow_hashref) {
633     push @branch_item_rules, $row;
634 }
635 my @sorted_branch_item_rules = sort { lc $a->{translated_description} cmp lc $b->{translated_description} } @branch_item_rules;
636
637 # note undef holdallowed so that template can deal with them
638 foreach my $entry (@sorted_branch_item_rules) {
639     $entry->{holdallowed_any}  = 1 if ( $entry->{holdallowed} == 2 );
640     $entry->{holdallowed_same} = 1 if ( $entry->{holdallowed} == 1 );
641 }
642
643 $template->param(show_branch_cat_rule_form => 1);
644 $template->param(branch_item_rule_loop => \@sorted_branch_item_rules);
645 $template->param(branch_cat_rule_loop => \@sorted_branch_cat_rules);
646
647 my $sth_defaults;
648 if ($branch eq "*") {
649     $sth_defaults = $dbh->prepare("
650         SELECT *
651         FROM default_circ_rules
652     ");
653     $sth_defaults->execute();
654 } else {
655     $sth_defaults = $dbh->prepare("
656         SELECT *
657         FROM default_branch_circ_rules
658         WHERE branchcode = ?
659     ");
660     $sth_defaults->execute($branch);
661 }
662
663 my $defaults = $sth_defaults->fetchrow_hashref;
664
665 if ($defaults) {
666     $template->param( default_holdallowed_none => 1 ) if ( $defaults->{holdallowed} == 0 );
667     $template->param( default_holdallowed_same => 1 ) if ( $defaults->{holdallowed} == 1 );
668     $template->param( default_holdallowed_any  => 1 ) if ( $defaults->{holdallowed} == 2 );
669     $template->param( default_hold_fulfillment_policy => $defaults->{hold_fulfillment_policy} );
670     $template->param( default_maxissueqty      => $defaults->{maxissueqty} );
671     $template->param( default_maxonsiteissueqty => $defaults->{maxonsiteissueqty} );
672     $template->param( default_returnbranch      => $defaults->{returnbranch} );
673 }
674
675 $template->param(default_rules => ($defaults ? 1 : 0));
676
677 $template->param(
678     patron_categories => $patron_categories,
679                         itemtypeloop => $itemtypes,
680                         rules => \@sorted_row_loop,
681                         humanbranch => ($branch ne '*' ? $branch : ''),
682                         current_branch => $branch,
683                         definedbranch => scalar(@sorted_row_loop)>0
684                         );
685 output_html_with_http_headers $input, $cookie, $template->output;
686
687 exit 0;
688
689 # sort by patron category, then item type, putting
690 # default entries at the bottom
691 sub by_category_and_itemtype {
692     unless (by_category($a, $b)) {
693         return by_itemtype($a, $b);
694     }
695 }
696
697 sub by_category {
698     my ($a, $b) = @_;
699     if ($a->{'default_humancategorycode'}) {
700         return ($b->{'default_humancategorycode'} ? 0 : 1);
701     } elsif ($b->{'default_humancategorycode'}) {
702         return -1;
703     } else {
704         return $a->{'humancategorycode'} cmp $b->{'humancategorycode'};
705     }
706 }
707
708 sub by_itemtype {
709     my ($a, $b) = @_;
710     if ($a->{default_translated_description}) {
711         return ($b->{'default_translated_description'} ? 0 : 1);
712     } elsif ($b->{'default_translated_description'}) {
713         return -1;
714     } else {
715         return lc $a->{'translated_description'} cmp lc $b->{'translated_description'};
716     }
717 }