Bug 8251 - Follow up, use 'day' instead of 'days' for Datetime::truncate
[koha.git] / C4 / Circulation.pm
index 6ca860d..a7e7389 100644 (file)
@@ -37,6 +37,7 @@ use C4::Debug;
 use C4::Branch; # GetBranches
 use C4::Log; # logaction
 use C4::Koha qw(GetAuthorisedValueByCode);
+use C4::Overdues qw(CalcFine UpdateFine);
 use Data::Dumper;
 use Koha::DateUtils;
 use Koha::Calendar;
@@ -46,7 +47,7 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
 
 BEGIN {
        require Exporter;
-       $VERSION = 3.02;        # for version checking
+    $VERSION = 3.07.00.049;    # for version checking
        @ISA    = qw(Exporter);
 
        # FIXME subs that should probably be elsewhere
@@ -667,6 +668,8 @@ sub CanBookBeIssued {
     my ( $borrower, $barcode, $duedate, $inprocess, $ignore_reserves ) = @_;
     my %needsconfirmation;    # filled with problems that needs confirmations
     my %issuingimpossible;    # filled with problems that causes the issue to be IMPOSSIBLE
+    my %alerts;               # filled with messages that shouldn't stop issuing, but the librarian should be aware of.
+
     my $item = GetItem(GetItemnumberFromBarcode( $barcode ));
     my $issue = GetItemIssue($item->{itemnumber});
        my $biblioitem = GetBiblioItemData($item->{biblioitemnumber});
@@ -698,7 +701,7 @@ sub CanBookBeIssued {
     }
     if ($duedate) {
         my $today = $now->clone();
-        $today->truncate( to => 'minutes');
+        $today->truncate( to => 'minute');
         if (DateTime->compare($duedate,$today) == -1 ) { # duedate cannot be before now
             $needsconfirmation{INVALID_DATE} = output_pref($duedate);
         }
@@ -735,8 +738,8 @@ sub CanBookBeIssued {
                 day   => $d,
                 time_zone => C4::Context->tz,
             );
-            $expiry_dt->truncate( to => 'days');
-            my $today = $now->clone()->truncate(to => 'days');
+            $expiry_dt->truncate( to => 'day');
+            my $today = $now->clone()->truncate(to => 'day');
             if (DateTime->compare($today, $expiry_dt) == 1) {
                 $issuingimpossible{EXPIRED} = 1;
             }
@@ -848,8 +851,10 @@ sub CanBookBeIssued {
     {
         $issuingimpossible{RESTRICTED} = 1;
     }
-    if ( $item->{'itemlost'} ) {
-        $needsconfirmation{ITEM_LOST} = GetAuthorisedValueByCode( 'LOST', $item->{'itemlost'} );
+    if ( $item->{'itemlost'} && C4::Context->preference("IssueLostItem") ne 'nothing' ) {
+        my $code = GetAuthorisedValueByCode( 'LOST', $item->{'itemlost'} );
+        $needsconfirmation{ITEM_LOST} = $code if ( C4::Context->preference("IssueLostItem") eq 'confirm' );
+        $alerts{ITEM_LOST} = $code if ( C4::Context->preference("IssueLostItem") eq 'alert' );
     }
     if ( C4::Context->preference("IndependantBranches") ) {
         my $userenv = C4::Context->userenv;
@@ -926,7 +931,7 @@ sub CanBookBeIssued {
             }
         }
     }
-    return ( \%issuingimpossible, \%needsconfirmation );
+    return ( \%issuingimpossible, \%needsconfirmation, \%alerts );
 }
 
 =head2 AddIssue
@@ -1046,7 +1051,7 @@ sub AddIssue {
             $datedue = CalcDateDue( $issuedate, $itype, $branch, $borrower );
 
         }
-        $datedue->truncate( to => 'minutes');
+        $datedue->truncate( to => 'minute');
         $sth->execute(
             $borrower->{'borrowernumber'},      # borrowernumber
             $item->{'itemnumber'},              # itemnumber
@@ -1524,6 +1529,7 @@ patron who last borrowed the book.
 
 sub AddReturn {
     my ( $barcode, $branch, $exemptfine, $dropbox ) = @_;
+
     if ($branch and not GetBranchDetail($branch)) {
         warn "AddReturn error: branch '$branch' not found.  Reverting to " . C4::Context->userenv->{'branch'};
         undef $branch;
@@ -1576,8 +1582,8 @@ sub AddReturn {
         $branches->{$hbr}->{PE} and $messages->{'IsPermanent'} = $hbr;
     }
 
-    # if indy branches and returning to different branch, refuse the return
-    if ($hbr ne $branch && C4::Context->preference("IndependantBranches")){
+    # if indy branches and returning to different branch, refuse the return unless canreservefromotherbranches is turned on
+    if ($hbr ne $branch && C4::Context->preference("IndependantBranches") && !(C4::Context->preference("canreservefromotherbranches"))){
         $messages->{'Wrongbranch'} = {
             Wrongbranch => $branch,
             Rightbranch => $hbr,
@@ -1598,6 +1604,8 @@ sub AddReturn {
 
     # case of a return of document (deal with issues and holdingbranch)
     if ($doreturn) {
+    my $today = DateTime->now( time_zone => C4::Context->tz() );
+    my $datedue = $issue->{date_due};
         $borrower or warn "AddReturn without current borrower";
                my $circControlBranch;
         if ($dropbox) {
@@ -1606,9 +1614,22 @@ sub AddReturn {
             # FIXME: check issuedate > returndate, factoring in holidays
             #$circControlBranch = _GetCircControlBranch($item,$borrower) unless ( $item->{'issuedate'} eq C4::Dates->today('iso') );;
             $circControlBranch = _GetCircControlBranch($item,$borrower);
+        my $datedue = $issue->{date_due};
+        $issue->{'overdue'} = DateTime->compare($issue->{'date_due'}, $today ) == -1 ? 1 : 0;
         }
 
         if ($borrowernumber) {
+        if($issue->{'overdue'}){
+                my ( $amount, $type, $daycounttotal ) = C4::Overdues::CalcFine( $item, $borrower->{categorycode},$branch, $datedue, $today );
+                $type ||= q{};
+        if ( $amount > 0 && ( C4::Context->preference('finesMode') eq 'production' )) {
+          C4::Overdues::UpdateFine(
+              $issue->{itemnumber},
+              $issue->{borrowernumber},
+                      $amount, $type, output_pref($datedue)
+              );
+        }
+            }
             MarkIssueReturned($borrowernumber, $item->{'itemnumber'}, $circControlBranch, '', $borrower->{'privacy'});
             $messages->{'WasReturned'} = 1;    # FIXME is the "= 1" right?  This could be the borrower hash.
         }
@@ -1741,6 +1762,7 @@ routine in C<C4::Accounts>.
 
 sub MarkIssueReturned {
     my ( $borrowernumber, $itemnumber, $dropbox_branch, $returndate, $privacy ) = @_;
+
     my $dbh   = C4::Context->dbh;
     my $query = 'UPDATE issues SET returndate=';
     my @bind;
@@ -1810,10 +1832,16 @@ sub _FixFineDaysOnReturn {
     my $circcontrol = C4::Context::preference('CircControl');
     my $issuingrule = GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
     my $finedays    = $issuingrule->{finedays};
+    my $unit        = $issuingrule->{lengthunit};
 
     # exit if no finedays defined
     return unless $finedays;
-    my $grace = DateTime::Duration->new( days => $issuingrule->{firstremind} );
+    # finedays is in days, so hourly loans must multiply by 24
+    # thus 1 hour late equals 1 day suspension * finedays rate
+    $finedays       = $finedays * 24 if ($unit eq 'hours');
+
+    # grace period is measured in the same units as the loan
+    my $grace = DateTime::Duration->new( $unit => $issuingrule->{firstremind} );
 
     if ( ( $deltadays - $grace )->is_positive ) { # you can't compare DateTime::Durations with logical operators
         my $new_debar_dt = $dt_today->clone()->add_duration( $deltadays * $finedays );
@@ -2053,10 +2081,10 @@ sub GetItemIssue {
     my $data = $sth->fetchrow_hashref;
     return unless $data;
     $data->{issuedate} = dt_from_string($data->{issuedate}, 'sql');
-    $data->{issuedate}->truncate(to => 'minutes');
+    $data->{issuedate}->truncate(to => 'minute');
     $data->{date_due} = dt_from_string($data->{date_due}, 'sql');
-    $data->{date_due}->truncate(to => 'minutes');
-    my $dt = DateTime->now( time_zone => C4::Context->tz)->truncate( to => 'minutes');
+    $data->{date_due}->truncate(to => 'minute');
+    my $dt = DateTime->now( time_zone => C4::Context->tz)->truncate( to => 'minute');
     $data->{'overdue'} = DateTime->compare($data->{'date_due'}, $dt ) == -1 ? 1 : 0;
     return $data;
 }
@@ -2101,7 +2129,7 @@ sub GetItemIssues {
     my ( $itemnumber, $history ) = @_;
     
     my $today = DateTime->now( time_zome => C4::Context->tz);  # get today date
-    $today->truncate( to => 'minutes' );
+    $today->truncate( to => 'minute' );
     my $sql = "SELECT * FROM issues
               JOIN borrowers USING (borrowernumber)
               JOIN items     USING (itemnumber)
@@ -2123,7 +2151,7 @@ sub GetItemIssues {
     my $results = $sth->fetchall_arrayref({});
     foreach (@$results) {
         my $date_due = dt_from_string($_->{date_due},'sql');
-        $date_due->truncate( to => 'minutes' );
+        $date_due->truncate( to => 'minute' );
 
         $_->{overdue} = (DateTime->compare($date_due, $today) == -1) ? 1 : 0;
     }
@@ -2728,7 +2756,7 @@ sub SendCirculationAlert {
         }
     ) or return;
 
-    my @transports = @{ $borrower_preferences->{transports} };
+    my @transports = keys %{ $borrower_preferences->{transports} };
     # warn "no transports" unless @transports;
     for (@transports) {
         # warn "transport: $_";
@@ -3076,12 +3104,13 @@ sub LostItem{
 
     # if a borrower lost the item, add a replacement cost to the their record
     if ( my $borrowernumber = $issues->{borrowernumber} ){
+        my $borrower = C4::Members::GetMemberDetails( $borrowernumber );
 
         C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}")
           if $charge_fee;
         #FIXME : Should probably have a way to distinguish this from an item that really was returned.
         #warn " $issues->{'borrowernumber'}  /  $itemnumber ";
-        MarkIssueReturned($borrowernumber,$itemnumber) if $mark_returned;
+        MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned;
     }
 }