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