Bug 13726: Make Koha::Acq::Bookseller using Koha::Object
[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 = @{ GetItemTypes( style => 'array' ) };
472 @itemtypes = sort { lc $a->{translated_description} cmp lc $b->{translated_description} } @itemtypes;
473
474 my $sth2 = $dbh->prepare("
475     SELECT  issuingrules.*,
476             itemtypes.description AS humanitemtype,
477             categories.description AS humancategorycode,
478             COALESCE( localization.translation, itemtypes.description ) AS translated_description
479     FROM issuingrules
480     LEFT JOIN itemtypes
481         ON (itemtypes.itemtype = issuingrules.itemtype)
482     LEFT JOIN categories
483         ON (categories.categorycode = issuingrules.categorycode)
484     LEFT JOIN localization ON issuingrules.itemtype = localization.code
485         AND localization.entity = 'itemtypes'
486         AND localization.lang = ?
487     WHERE issuingrules.branchcode = ?
488 ");
489 $sth2->execute($language, $branch);
490
491 while (my $row = $sth2->fetchrow_hashref) {
492     $row->{'current_branch'} ||= $row->{'branchcode'};
493     $row->{humanitemtype} ||= $row->{itemtype};
494     $row->{default_translated_description} = 1 if $row->{humanitemtype} eq '*';
495     $row->{'humancategorycode'} ||= $row->{'categorycode'};
496     $row->{'default_humancategorycode'} = 1 if $row->{'humancategorycode'} eq '*';
497     $row->{'fine'} = sprintf('%.2f', $row->{'fine'});
498     if ($row->{'hardduedate'} && $row->{'hardduedate'} ne '0000-00-00') {
499        my $harddue_dt = eval { dt_from_string( $row->{'hardduedate'} ) };
500        $row->{'hardduedate'} = eval { output_pref( { dt => $harddue_dt, dateonly => 1 } ) } if ( $harddue_dt );
501        $row->{'hardduedatebefore'} = 1 if ($row->{'hardduedatecompare'} == -1);
502        $row->{'hardduedateexact'} = 1 if ($row->{'hardduedatecompare'} ==  0);
503        $row->{'hardduedateafter'} = 1 if ($row->{'hardduedatecompare'} ==  1);
504     } else {
505        $row->{'hardduedate'} = 0;
506     }
507     push @row_loop, $row;
508 }
509
510 my @sorted_row_loop = sort by_category_and_itemtype @row_loop;
511
512 my $sth_branch_cat;
513 if ($branch eq "*") {
514     $sth_branch_cat = $dbh->prepare("
515         SELECT default_borrower_circ_rules.*, categories.description AS humancategorycode
516         FROM default_borrower_circ_rules
517         JOIN categories USING (categorycode)
518
519     ");
520     $sth_branch_cat->execute();
521 } else {
522     $sth_branch_cat = $dbh->prepare("
523         SELECT branch_borrower_circ_rules.*, categories.description AS humancategorycode
524         FROM branch_borrower_circ_rules
525         JOIN categories USING (categorycode)
526         WHERE branch_borrower_circ_rules.branchcode = ?
527     ");
528     $sth_branch_cat->execute($branch);
529 }
530
531 my @branch_cat_rules = ();
532 while (my $row = $sth_branch_cat->fetchrow_hashref) {
533     push @branch_cat_rules, $row;
534 }
535 my @sorted_branch_cat_rules = sort { $a->{'humancategorycode'} cmp $b->{'humancategorycode'} } @branch_cat_rules;
536
537 # note undef maxissueqty so that template can deal with them
538 foreach my $entry (@sorted_branch_cat_rules, @sorted_row_loop) {
539     $entry->{unlimited_maxissueqty} = 1 unless defined($entry->{maxissueqty});
540     $entry->{unlimited_maxonsiteissueqty} = 1 unless defined($entry->{maxonsiteissueqty});
541 }
542
543 @sorted_row_loop = sort by_category_and_itemtype @row_loop;
544
545 my $sth_branch_item;
546 if ($branch eq "*") {
547     $sth_branch_item = $dbh->prepare("
548         SELECT default_branch_item_rules.*,
549             COALESCE( localization.translation, itemtypes.description ) AS translated_description
550         FROM default_branch_item_rules
551         JOIN itemtypes USING (itemtype)
552         LEFT JOIN localization ON itemtypes.itemtype = localization.code
553             AND localization.entity = 'itemtypes'
554             AND localization.lang = ?
555     ");
556     $sth_branch_item->execute($language);
557 } else {
558     $sth_branch_item = $dbh->prepare("
559         SELECT branch_item_rules.*,
560             COALESCE( localization.translation, itemtypes.description ) AS translated_description
561         FROM branch_item_rules
562         JOIN itemtypes USING (itemtype)
563         LEFT JOIN localization ON itemtypes.itemtype = localization.code
564             AND localization.entity = 'itemtypes'
565             AND localization.lang = ?
566         WHERE branch_item_rules.branchcode = ?
567     ");
568     $sth_branch_item->execute($language, $branch);
569 }
570
571 my @branch_item_rules = ();
572 while (my $row = $sth_branch_item->fetchrow_hashref) {
573     push @branch_item_rules, $row;
574 }
575 my @sorted_branch_item_rules = sort { lc $a->{translated_description} cmp lc $b->{translated_description} } @branch_item_rules;
576
577 # note undef holdallowed so that template can deal with them
578 foreach my $entry (@sorted_branch_item_rules) {
579     $entry->{holdallowed_any}  = 1 if ( $entry->{holdallowed} == 2 );
580     $entry->{holdallowed_same} = 1 if ( $entry->{holdallowed} == 1 );
581 }
582
583 $template->param(show_branch_cat_rule_form => 1);
584 $template->param(branch_item_rule_loop => \@sorted_branch_item_rules);
585 $template->param(branch_cat_rule_loop => \@sorted_branch_cat_rules);
586
587 my $sth_defaults;
588 if ($branch eq "*") {
589     $sth_defaults = $dbh->prepare("
590         SELECT *
591         FROM default_circ_rules
592     ");
593     $sth_defaults->execute();
594 } else {
595     $sth_defaults = $dbh->prepare("
596         SELECT *
597         FROM default_branch_circ_rules
598         WHERE branchcode = ?
599     ");
600     $sth_defaults->execute($branch);
601 }
602
603 my $defaults = $sth_defaults->fetchrow_hashref;
604
605 if ($defaults) {
606     $template->param( default_holdallowed_none => 1 ) if ( $defaults->{holdallowed} == 0 );
607     $template->param( default_holdallowed_same => 1 ) if ( $defaults->{holdallowed} == 1 );
608     $template->param( default_holdallowed_any  => 1 ) if ( $defaults->{holdallowed} == 2 );
609     $template->param( default_hold_fulfillment_policy => $defaults->{hold_fulfillment_policy} );
610     $template->param( default_maxissueqty      => $defaults->{maxissueqty} );
611     $template->param( default_maxonsiteissueqty => $defaults->{maxonsiteissueqty} );
612     $template->param( default_returnbranch      => $defaults->{returnbranch} );
613 }
614
615 $template->param(default_rules => ($defaults ? 1 : 0));
616
617 $template->param(
618     patron_categories => $patron_categories,
619                         itemtypeloop => \@itemtypes,
620                         rules => \@sorted_row_loop,
621                         humanbranch => ($branch ne '*' ? $branch : ''),
622                         current_branch => $branch,
623                         definedbranch => scalar(@sorted_row_loop)>0
624                         );
625 output_html_with_http_headers $input, $cookie, $template->output;
626
627 exit 0;
628
629 # sort by patron category, then item type, putting
630 # default entries at the bottom
631 sub by_category_and_itemtype {
632     unless (by_category($a, $b)) {
633         return by_itemtype($a, $b);
634     }
635 }
636
637 sub by_category {
638     my ($a, $b) = @_;
639     if ($a->{'default_humancategorycode'}) {
640         return ($b->{'default_humancategorycode'} ? 0 : 1);
641     } elsif ($b->{'default_humancategorycode'}) {
642         return -1;
643     } else {
644         return $a->{'humancategorycode'} cmp $b->{'humancategorycode'};
645     }
646 }
647
648 sub by_itemtype {
649     my ($a, $b) = @_;
650     if ($a->{default_translated_description}) {
651         return ($b->{'default_translated_description'} ? 0 : 1);
652     } elsif ($b->{'default_translated_description'}) {
653         return -1;
654     } else {
655         return lc $a->{'translated_description'} cmp lc $b->{'translated_description'};
656     }
657 }