#!/usr/bin/perl # Copyright 2000-2002 Katipo Communications # copyright 2010 BibLibre # # This file is part of Koha. # # Koha is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # Koha is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Koha; if not, see . use Modern::Perl; use CGI qw ( -utf8 ); use C4::Context; use C4::Output; use C4::Auth; use C4::Koha; use C4::Debug; use Koha::DateUtils; use Koha::Database; use Koha::Logger; use Koha::RefundLostItemFeeRules; use Koha::Libraries; use Koha::CirculationRules; use Koha::Patron::Categories; use Koha::Caches; use Koha::Patrons; my $input = CGI->new; my $dbh = C4::Context->dbh; # my $flagsrequired; # $flagsrequired->{circulation}=1; my ($template, $loggedinuser, $cookie) = get_template_and_user({template_name => "admin/smart-rules.tt", query => $input, type => "intranet", authnotrequired => 0, flagsrequired => {parameters => 'manage_circ_rules'}, debug => 1, }); my $type=$input->param('type'); my $branch = $input->param('branch'); unless ( $branch ) { if ( C4::Context->preference('DefaultToLoggedInLibraryCircRules') ) { $branch = Koha::Libraries->search->count() == 1 ? undef : C4::Context::mybranch(); } else { $branch = C4::Context::only_my_library() ? ( C4::Context::mybranch() || '*' ) : '*'; } } my $logged_in_patron = Koha::Patrons->find( $loggedinuser ); my $can_edit_from_any_library = $logged_in_patron->has_permission( {parameters => 'manage_circ_rules_from_any_libraries' } ); $template->param( restricted_to_own_library => not $can_edit_from_any_library ); $branch = C4::Context::mybranch() unless $can_edit_from_any_library; my $op = $input->param('op') || q{}; my $language = C4::Languages::getlanguage(); my $cache = Koha::Caches->get_instance; $cache->clear_from_cache( Koha::CirculationRules::GUESSED_ITEMTYPES_KEY ); if ($op eq 'delete') { my $itemtype = $input->param('itemtype'); my $categorycode = $input->param('categorycode'); $debug and warn "deleting $1 $2 $branch"; Koha::CirculationRules->set_rules( { categorycode => $categorycode eq '*' ? undef : $categorycode, branchcode => $branch eq '*' ? undef : $branch, itemtype => $itemtype eq '*' ? undef : $itemtype, rules => { maxissueqty => undef, maxonsiteissueqty => undef, rentaldiscount => undef, fine => undef, finedays => undef, maxsuspensiondays => undef, suspension_chargeperiod => undef, firstremind => undef, chargeperiod => undef, chargeperiod_charge_at => undef, issuelength => undef, lengthunit => undef, hardduedate => undef, hardduedatecompare => undef, renewalsallowed => undef, renewalperiod => undef, norenewalbefore => undef, auto_renew => undef, no_auto_renewal_after => undef, no_auto_renewal_after_hard_limit => undef, reservesallowed => undef, holds_per_record => undef, holds_per_day => undef, onshelfholds => undef, opacitemholds => undef, overduefinescap => undef, cap_fine_to_replacement_price => undef, article_requests => undef, note => undef, } } ); } elsif ($op eq 'delete-branch-cat') { my $categorycode = $input->param('categorycode'); if ($branch eq "*") { if ($categorycode eq "*") { Koha::CirculationRules->set_rules( { branchcode => undef, categorycode => undef, rules => { max_holds => undef, patron_maxissueqty => undef, patron_maxonsiteissueqty => undef, } } ); Koha::CirculationRules->set_rules( { branchcode => undef, itemtype => undef, rules => { holdallowed => undef, hold_fulfillment_policy => undef, returnbranch => undef, } } ); } else { Koha::CirculationRules->set_rules( { categorycode => $categorycode, branchcode => undef, rules => { max_holds => undef, patron_maxissueqty => undef, patron_maxonsiteissueqty => undef, } } ); } } elsif ($categorycode eq "*") { Koha::CirculationRules->set_rules( { branchcode => $branch, categorycode => undef, rules => { patron_maxissueqty => undef, patron_maxonsiteissueqty => undef, } } ); Koha::CirculationRules->set_rules( { branchcode => $branch, rules => { holdallowed => undef, hold_fulfillment_policy => undef, returnbranch => undef, max_holds => undef, } } ); } else { Koha::CirculationRules->set_rules( { categorycode => $categorycode, branchcode => $branch, rules => { max_holds => undef, patron_maxissueqty => undef, patron_maxonsiteissueqty => undef, } } ); } } elsif ($op eq 'delete-branch-item') { my $itemtype = $input->param('itemtype'); if ($branch eq "*") { if ($itemtype eq "*") { Koha::CirculationRules->set_rules( { branchcode => undef, itemtype => undef, rules => { holdallowed => undef, hold_fulfillment_policy => undef, returnbranch => undef, } } ); } else { Koha::CirculationRules->set_rules( { branchcode => undef, itemtype => $itemtype, rules => { holdallowed => undef, hold_fulfillment_policy => undef, returnbranch => undef, } } ); } } elsif ($itemtype eq "*") { Koha::CirculationRules->set_rules( { branchcode => $branch, itemtype => undef, rules => { holdallowed => undef, hold_fulfillment_policy => undef, returnbranch => undef, } } ); } else { Koha::CirculationRules->set_rules( { branchcode => $branch, itemtype => $itemtype, rules => { holdallowed => undef, hold_fulfillment_policy => undef, returnbranch => undef, } } ); } } # save the values entered elsif ($op eq 'add') { my $br = $branch; # branch my $bor = $input->param('categorycode'); # borrower category my $itemtype = $input->param('itemtype'); # item type my $fine = $input->param('fine'); my $finedays = $input->param('finedays'); my $maxsuspensiondays = $input->param('maxsuspensiondays'); $maxsuspensiondays = undef if $maxsuspensiondays eq q||; $maxsuspensiondays = '' if $maxsuspensiondays eq q||; my $suspension_chargeperiod = $input->param('suspension_chargeperiod') || 1; my $firstremind = $input->param('firstremind'); my $chargeperiod = $input->param('chargeperiod'); my $chargeperiod_charge_at = $input->param('chargeperiod_charge_at'); my $maxissueqty = strip_non_numeric($input->param('maxissueqty')); my $maxonsiteissueqty = strip_non_numeric($input->param('maxonsiteissueqty')); my $renewalsallowed = $input->param('renewalsallowed'); my $renewalperiod = $input->param('renewalperiod'); my $norenewalbefore = $input->param('norenewalbefore'); $norenewalbefore = '' if $norenewalbefore =~ /^\s*$/; my $auto_renew = $input->param('auto_renew') eq 'yes' ? 1 : 0; my $no_auto_renewal_after = $input->param('no_auto_renewal_after'); $no_auto_renewal_after = '' if $no_auto_renewal_after =~ /^\s*$/; my $no_auto_renewal_after_hard_limit = $input->param('no_auto_renewal_after_hard_limit') || ''; $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 ); $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 ); my $reservesallowed = strip_non_numeric($input->param('reservesallowed')); my $holds_per_record = strip_non_numeric($input->param('holds_per_record')); my $holds_per_day = strip_non_numeric($input->param('holds_per_day')); my $onshelfholds = $input->param('onshelfholds') || 0; my $issuelength = $input->param('issuelength'); $issuelength = $issuelength eq q{} ? undef : $issuelength; my $lengthunit = $input->param('lengthunit'); my $hardduedate = $input->param('hardduedate') || undef; $hardduedate = eval { dt_from_string( $input->param('hardduedate') ) } if ( $hardduedate ); $hardduedate = output_pref( { dt => $hardduedate, dateonly => 1, dateformat => 'iso' } ) if ( $hardduedate ); my $hardduedatecompare = $input->param('hardduedatecompare'); my $rentaldiscount = $input->param('rentaldiscount'); my $opacitemholds = $input->param('opacitemholds') || 0; my $article_requests = $input->param('article_requests') || 'no'; my $overduefinescap = $input->param('overduefinescap') || ''; my $cap_fine_to_replacement_price = $input->param('cap_fine_to_replacement_price') eq 'on'; my $note = $input->param('note'); $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price"; my $rules = { maxissueqty => $maxissueqty, maxonsiteissueqty => $maxonsiteissueqty, rentaldiscount => $rentaldiscount, fine => $fine, finedays => $finedays, maxsuspensiondays => $maxsuspensiondays, suspension_chargeperiod => $suspension_chargeperiod, firstremind => $firstremind, chargeperiod => $chargeperiod, chargeperiod_charge_at => $chargeperiod_charge_at, issuelength => $issuelength, lengthunit => $lengthunit, hardduedate => $hardduedate, hardduedatecompare => $hardduedatecompare, renewalsallowed => $renewalsallowed, renewalperiod => $renewalperiod, norenewalbefore => $norenewalbefore, auto_renew => $auto_renew, no_auto_renewal_after => $no_auto_renewal_after, no_auto_renewal_after_hard_limit => $no_auto_renewal_after_hard_limit, reservesallowed => $reservesallowed, holds_per_record => $holds_per_record, holds_per_day => $holds_per_day, onshelfholds => $onshelfholds, opacitemholds => $opacitemholds, overduefinescap => $overduefinescap, cap_fine_to_replacement_price => $cap_fine_to_replacement_price, article_requests => $article_requests, note => $note, }; Koha::CirculationRules->set_rules( { categorycode => $bor eq '*' ? undef : $bor, itemtype => $itemtype eq '*' ? undef : $itemtype, branchcode => $br eq '*' ? undef : $br, rules => $rules, } ); } elsif ($op eq "set-branch-defaults") { my $categorycode = $input->param('categorycode'); my $patron_maxissueqty = strip_non_numeric($input->param('patron_maxissueqty')); my $patron_maxonsiteissueqty = $input->param('patron_maxonsiteissueqty'); $patron_maxonsiteissueqty = strip_non_numeric($patron_maxonsiteissueqty); my $holdallowed = $input->param('holdallowed'); my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy'); my $returnbranch = $input->param('returnbranch'); my $max_holds = strip_non_numeric($input->param('max_holds')); $holdallowed =~ s/\s//g; $holdallowed = undef if $holdallowed !~ /^\d+/; if ($branch eq "*") { Koha::CirculationRules->set_rules( { itemtype => undef, branchcode => undef, rules => { holdallowed => $holdallowed, hold_fulfillment_policy => $hold_fulfillment_policy, returnbranch => $returnbranch, } } ); Koha::CirculationRules->set_rules( { categorycode => undef, branchcode => undef, rules => { patron_maxissueqty => $patron_maxissueqty, patron_maxonsiteissueqty => $patron_maxonsiteissueqty, } } ); } else { Koha::CirculationRules->set_rules( { itemtype => undef, branchcode => $branch, rules => { holdallowed => $holdallowed, hold_fulfillment_policy => $hold_fulfillment_policy, returnbranch => $returnbranch, } } ); Koha::CirculationRules->set_rules( { categorycode => undef, branchcode => $branch, rules => { patron_maxissueqty => $patron_maxissueqty, patron_maxonsiteissueqty => $patron_maxonsiteissueqty, } } ); } Koha::CirculationRules->set_rule( { branchcode => $branch, categorycode => undef, rule_name => 'max_holds', rule_value => $max_holds, } ); } elsif ($op eq "add-branch-cat") { my $categorycode = $input->param('categorycode'); my $patron_maxissueqty = strip_non_numeric($input->param('patron_maxissueqty')); my $patron_maxonsiteissueqty = $input->param('patron_maxonsiteissueqty'); $patron_maxonsiteissueqty = strip_non_numeric($patron_maxonsiteissueqty); my $max_holds = $input->param('max_holds'); $max_holds =~ s/\s//g; $max_holds = undef if $max_holds !~ /^\d+/; if ($branch eq "*") { if ($categorycode eq "*") { Koha::CirculationRules->set_rules( { categorycode => undef, branchcode => undef, rules => { max_holds => $max_holds, patron_maxissueqty => $patron_maxissueqty, patron_maxonsiteissueqty => $patron_maxonsiteissueqty, } } ); } else { Koha::CirculationRules->set_rules( { categorycode => $categorycode, branchcode => undef, rules => { max_holds => $max_holds, patron_maxissueqty => $patron_maxissueqty, patron_maxonsiteissueqty => $patron_maxonsiteissueqty, } } ); } } elsif ($categorycode eq "*") { Koha::CirculationRules->set_rules( { categorycode => undef, branchcode => $branch, rules => { max_holds => $max_holds, patron_maxissueqty => $patron_maxissueqty, patron_maxonsiteissueqty => $patron_maxonsiteissueqty, } } ); } else { Koha::CirculationRules->set_rules( { categorycode => $categorycode, branchcode => $branch, rules => { max_holds => $max_holds, patron_maxissueqty => $patron_maxissueqty, patron_maxonsiteissueqty => $patron_maxonsiteissueqty, } } ); } } elsif ($op eq "add-branch-item") { my $itemtype = $input->param('itemtype'); my $holdallowed = $input->param('holdallowed'); my $hold_fulfillment_policy = $input->param('hold_fulfillment_policy'); my $returnbranch = $input->param('returnbranch'); $holdallowed =~ s/\s//g; $holdallowed = undef if $holdallowed !~ /^\d+/; if ($branch eq "*") { if ($itemtype eq "*") { Koha::CirculationRules->set_rules( { itemtype => undef, branchcode => undef, rules => { holdallowed => $holdallowed, hold_fulfillment_policy => $hold_fulfillment_policy, returnbranch => $returnbranch, } } ); } else { Koha::CirculationRules->set_rules( { itemtype => $itemtype, branchcode => undef, rules => { holdallowed => $holdallowed, hold_fulfillment_policy => $hold_fulfillment_policy, returnbranch => $returnbranch, } } ); } } elsif ($itemtype eq "*") { Koha::CirculationRules->set_rules( { itemtype => undef, branchcode => $branch, rules => { holdallowed => $holdallowed, hold_fulfillment_policy => $hold_fulfillment_policy, returnbranch => $returnbranch, } } ); } else { Koha::CirculationRules->set_rules( { itemtype => $itemtype, branchcode => $branch, rules => { holdallowed => $holdallowed, hold_fulfillment_policy => $hold_fulfillment_policy, returnbranch => $returnbranch, } } ); } } elsif ( $op eq 'mod-refund-lost-item-fee-rule' ) { my $refund = $input->param('refund'); if ( $refund eq '*' ) { if ( $branch ne '*' ) { # only do something for $refund eq '*' if branch-specific Koha::CirculationRules->set_rules( { branchcode => $branch, rules => { refund => undef } } ); } } else { Koha::CirculationRules->set_rules( { branchcode => $branch, rules => { refund => $refund } } ); } } my $refundLostItemFeeRule = Koha::RefundLostItemFeeRules->find({ branchcode => ($branch eq '*') ? undef : $branch }); $template->param( refundLostItemFeeRule => $refundLostItemFeeRule, defaultRefundRule => Koha::RefundLostItemFeeRules->_default_rule ); my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] }); my $itemtypes = Koha::ItemTypes->search_with_localization; my $humanbranch = ( $branch ne '*' ? $branch : undef ); my $all_rules = Koha::CirculationRules->search({ branchcode => $humanbranch }); my $definedbranch = $all_rules->count ? 1 : 0; my $rules = {}; while ( my $r = $all_rules->next ) { $r = $r->unblessed; $rules->{ $r->{categorycode} }->{ $r->{itemtype} }->{ $r->{rule_name} } = $r->{rule_value}; } $template->param(show_branch_cat_rule_form => 1); $template->param( patron_categories => $patron_categories, itemtypeloop => $itemtypes, humanbranch => $humanbranch, current_branch => $branch, definedbranch => $definedbranch, all_rules => $rules, ); output_html_with_http_headers $input, $cookie, $template->output; exit 0; # sort by patron category, then item type, putting # default entries at the bottom sub by_category_and_itemtype { unless (by_category($a, $b)) { return by_itemtype($a, $b); } } sub by_category { my ($a, $b) = @_; if ($a->{'default_humancategorycode'}) { return ($b->{'default_humancategorycode'} ? 0 : 1); } elsif ($b->{'default_humancategorycode'}) { return -1; } else { return $a->{'humancategorycode'} cmp $b->{'humancategorycode'}; } } sub by_itemtype { my ($a, $b) = @_; if ($a->{default_translated_description}) { return ($b->{'default_translated_description'} ? 0 : 1); } elsif ($b->{'default_translated_description'}) { return -1; } else { return lc $a->{'translated_description'} cmp lc $b->{'translated_description'}; } } sub strip_non_numeric { my $string = shift; $string =~ s/\s//g; $string = '' if $string !~ /^\d+/; return $string; }