Bug 17600: Standardize our EXPORT_OK
[srvgit] / C4 / Overdues.pm
index d97cde9..54a4264 100644 (file)
@@ -19,55 +19,39 @@ package C4::Overdues;
 # You should have received a copy of the GNU General Public License
 # along with Koha; if not, see <http://www.gnu.org/licenses>.
 
-use strict;
-#use warnings; FIXME - Bug 2505
-use Date::Calc qw/Today Date_to_Days/;
-use Date::Manip qw/UnixDate/;
+use Modern::Perl;
+use Date::Calc qw( Today );
+use Date::Manip qw( UnixDate );
 use List::MoreUtils qw( uniq );
-use POSIX qw( floor ceil );
-use Locale::Currency::Format 1.28;
-use Carp;
+use POSIX qw( ceil floor );
+use Locale::Currency::Format 1.28 qw( currency_format FMT_SYMBOL );
+use Carp qw( carp );
 
-use C4::Circulation;
 use C4::Context;
 use C4::Accounts;
-use C4::Log; # logaction
-use C4::Debug;
-use Koha::DateUtils;
+use Koha::Logger;
 use Koha::Account::Lines;
 use Koha::Account::Offsets;
-use Koha::IssuingRules;
 use Koha::Libraries;
 
-use vars qw(@ISA @EXPORT);
-
+our (@ISA, @EXPORT_OK);
 BEGIN {
     require Exporter;
     @ISA = qw(Exporter);
 
     # subs to rename (and maybe merge some...)
-    push @EXPORT, qw(
-      &CalcFine
-      &Getoverdues
-      &checkoverdues
-      &UpdateFine
-      &GetFine
-      &get_chargeable_units
-      &GetOverduesForBranch
-      &GetOverdueMessageTransportTypes
-      &parse_overdues_letter
-    );
-
-    # subs to remove
-    push @EXPORT, qw(
-      &BorType
-    );
-
-    # check that an equivalent don't exist already before moving
-
-    # subs to move to Circulation.pm
-    push @EXPORT, qw(
-      &GetIssuesIteminfo
+    @EXPORT_OK = qw(
+      CalcFine
+      Getoverdues
+      checkoverdues
+      UpdateFine
+      GetFine
+      GetBranchcodesWithOverdueRules
+      get_chargeable_units
+      GetOverduesForBranch
+      GetOverdueMessageTransportTypes
+      parse_overdues_letter
+      GetIssuesIteminfo
     );
 }
 
@@ -232,40 +216,58 @@ or "Final Notice".  But CalcFine never defined any value.
 
 sub CalcFine {
     my ( $item, $bortype, $branchcode, $due_dt, $end_date  ) = @_;
+
+    # Skip calculations if item is not overdue
+    return ( 0, 0, 0 ) unless (DateTime->compare( $due_dt, $end_date ) == -1);
+
     my $start_date = $due_dt->clone();
     # get issuingrules (fines part will be used)
     my $itemtype = $item->{itemtype} || $item->{itype};
-    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
+    my $issuing_rule = Koha::CirculationRules->get_effective_rules(
+        {
+            categorycode => $bortype,
+            itemtype     => $itemtype,
+            branchcode   => $branchcode,
+            rules => [
+                'lengthunit',
+                'firstremind',
+                'chargeperiod',
+                'chargeperiod_charge_at',
+                'fine',
+                'overduefinescap',
+                'cap_fine_to_replacement_price',
+            ]
+        }
+    );
 
     $itemtype = Koha::ItemTypes->find($itemtype);
 
     return unless $issuing_rule; # If not rule exist, there is no fine
 
-    my $fine_unit = $issuing_rule->lengthunit || 'days';
+    my $fine_unit = $issuing_rule->{lengthunit} || 'days';
 
     my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
-    my $units_minus_grace = $chargeable_units - $issuing_rule->firstremind;
+    my $units_minus_grace = $chargeable_units - ($issuing_rule->{firstremind} || 0);
     my $amount = 0;
-    if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
+    if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
         my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
-        my $charge_periods = $units / $issuing_rule->chargeperiod;
+        my $charge_periods = $units / $issuing_rule->{chargeperiod};
         # If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
         # if chargeperiod_charge_at = 0, we charge at the end of each charge period
-        $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
-        $amount = $charge_periods * $issuing_rule->fine;
+        $charge_periods = defined $issuing_rule->{chargeperiod_charge_at} && $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
+        $amount = $charge_periods * $issuing_rule->{fine};
     } # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
 
-    $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
+    $amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
 
     # This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
     $item->{replacementprice} ||= $itemtype->defaultreplacecost
       if $itemtype
-      && $item->{replacementprice} == 0
+      && ( ! defined $item->{replacementprice} || $item->{replacementprice} == 0 )
       && C4::Context->preference("useDefaultReplacementCost");
 
-    $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
+    $amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
 
-    $debug and warn sprintf("CalcFine returning (%s, %s, %s)", $amount, $units_minus_grace, $chargeable_units);
     return ($amount, $units_minus_grace, $chargeable_units);
 }
 
@@ -510,9 +512,7 @@ sub UpdateFine {
     my $itemnum        = $params->{itemnumber};
     my $borrowernumber = $params->{borrowernumber};
     my $amount         = $params->{amount};
-    my $due            = $params->{due};
-
-    $debug and warn "UpdateFine({ itemnumber => $itemnum, borrowernumber => $borrowernumber, due => $due, issue_id => $issue_id})";
+    my $due            = $params->{due} // q{};
 
     unless ( $issue_id ) {
         carp("No issue_id passed in!");
@@ -523,8 +523,7 @@ sub UpdateFine {
     my $overdues = Koha::Account::Lines->search(
         {
             borrowernumber    => $borrowernumber,
-            debit_type_code   => [ 'OVERDUE', 'M' ],
-            amountoutstanding => { '<>' => 0 }
+            debit_type_code   => 'OVERDUE'
         }
     );
 
@@ -536,31 +535,36 @@ sub UpdateFine {
     # - accumulate fines for other items
     # so we can update $itemnum fine taking in account fine caps
     while (my $overdue = $overdues->next) {
-        if ( $overdue->issue_id == $issue_id && $overdue->status eq 'UNRETURNED' ) {
+        if ( defined $overdue->issue_id && $overdue->issue_id == $issue_id && $overdue->status eq 'UNRETURNED' ) {
             if ($accountline) {
-                $debug and warn "Not a unique accountlines record for issue_id $issue_id";
+                Koha::Logger->get->debug("Not a unique accountlines record for issue_id $issue_id"); # FIXME Do we really need to log that?
                 #FIXME Should we still count this one in total_amount ??
             }
             else {
                 $accountline = $overdue;
-                next;
             }
         }
         $total_amount_other += $overdue->amountoutstanding;
     }
 
-    if (my $maxfine = C4::Context->preference('MaxFine')) {
-        if ($total_amount_other + $amount > $maxfine) {
-            my $new_amount = $maxfine - $total_amount_other;
-            return if $new_amount <= 0.00;
-            $debug and warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
-            $amount = $new_amount;
+    if ( my $maxfine = C4::Context->preference('MaxFine') ) {
+        my $maxIncrease = $maxfine - $total_amount_other;
+        return if Koha::Number::Price->new($maxIncrease)->round <= 0.00;
+        if ($accountline) {
+            if ( ( $amount - $accountline->amount ) > $maxIncrease ) {
+                my $new_amount = $accountline->amount + $maxIncrease;
+                Koha::Logger->get->debug("Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached");
+                $amount = $new_amount;
+            }
+        }
+        elsif ( $amount > $maxIncrease ) {
+            Koha::Logger->get->debug("Reducing fine for item $itemnum borrower $borrowernumber from $amount to $maxIncrease - MaxFine reached");
+            $amount = $maxIncrease;
         }
     }
 
-
     if ( $accountline ) {
-        if ( $accountline->amount != $amount ) {
+        if ( Koha::Number::Price->new($accountline->amount)->round != Koha::Number::Price->new($amount)->round ) {
             $accountline->adjust(
                 {
                     amount    => $amount,
@@ -587,7 +591,7 @@ sub UpdateFine {
                     user_id     => undef,
                     interface   => C4::Context->interface,
                     library_id  => undef, #FIXME: Should we grab the checkout or circ-control branch here perhaps?
-                    type        => 'overdue',
+                    type        => 'OVERDUE',
                     item_id     => $itemnum,
                     issue_id    => $issue_id,
                 }
@@ -596,31 +600,6 @@ sub UpdateFine {
     }
 }
 
-=head2 BorType
-
-    $borrower = &BorType($borrowernumber);
-
-Looks up a patron by borrower number.
-
-C<$borrower> is a reference-to-hash whose keys are all of the fields
-from the borrowers and categories tables of the Koha database. Thus,
-C<$borrower> contains all information about both the borrower and
-category they belong to.
-
-=cut
-
-sub BorType {
-    my ($borrowernumber) = @_;
-    my $dbh              = C4::Context->dbh;
-    my $sth              = $dbh->prepare(
-        "SELECT * from borrowers
-      LEFT JOIN categories ON borrowers.categorycode=categories.categorycode 
-      WHERE borrowernumber=?"
-    );
-    $sth->execute($borrowernumber);
-    return $sth->fetchrow_hashref;
-}
-
 =head2 GetFine
 
     $data->{'sum(amountoutstanding)'} = &GetFine($itemnum,$borrowernumber);
@@ -637,7 +616,7 @@ sub GetFine {
     my ( $itemnum, $borrowernumber ) = @_;
     my $dbh   = C4::Context->dbh();
     my $query = q|SELECT sum(amountoutstanding) as fineamount FROM accountlines
-    WHERE debit_type_code LIKE 'OVERDUE'
+    WHERE debit_type_code = 'OVERDUE'
   AND amountoutstanding > 0 AND borrowernumber=?|;
     my @query_param;
     push @query_param, $borrowernumber;
@@ -770,7 +749,7 @@ sub GetOverdueMessageTransportTypes {
     # Put 'print' in first if exists
     # It avoid to sent a print notice with an email or sms template is no email or sms is defined
     @mtts = uniq( 'print', @mtts )
-        if grep {/^print$/} @mtts;
+        if grep { $_ eq 'print' } @mtts;
 
     return \@mtts;
 }