Fix for bug 1689
[koha.git] / C4 / Circulation.pm
index 983c9dc..1694444 100644 (file)
@@ -26,7 +26,7 @@ use C4::Reserves;
 use C4::Koha;
 use C4::Biblio;
 use C4::Members;
-# use C4::Date;        # apparently no dependency.
+use C4::Dates;
 use Date::Calc qw(
   Today
   Today_and_Now
@@ -40,6 +40,8 @@ use POSIX qw(strftime);
 use C4::Branch; # GetBranches
 use C4::Log; # logaction
 
+use Data::Dumper;
+
 our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,%EXPORT_TAGS);
 
 # set the version for version checking
@@ -376,28 +378,26 @@ sub TooMany {
     my $branch_borrower = $borrower->{'branchcode'};
     my $dbh             = C4::Context->dbh;
 
- my $branch_issuer = C4::Context->userenv->{'branchcode'};
-#TODO : specify issuer or borrower for circrule.
-  my $type = (C4::Context->preference('item-level_itypes')) 
      my $branch_issuer = C4::Context->userenv->{'branchcode'};
+    # TODO : specify issuer or borrower for circrule.
+       my $type = (C4::Context->preference('item-level_itypes')) 
                        ? $item->{'itype'}         # item-level
                        : $item->{'itemtype'};     # biblio-level
   
-  my $sth =
+       my $sth =
       $dbh->prepare(
                 'SELECT * FROM issuingrules 
                         WHERE categorycode = ? 
-                            AND branchcode = ?
-                            AND itemtype = ? '
+                            AND itemtype = ? 
+                            AND branchcode = ?'
       );
 
     my $query2 = "SELECT  COUNT(*) FROM issues i, biblioitems s1, items s2 
                 WHERE i.borrowernumber = ? 
                     AND i.returndate IS NULL 
                     AND i.itemnumber = s2.itemnumber 
-                    AND s1.biblioitemnumber = s2.biblioitemnumber"
-                               . (C4::Context->preference('item-level_itypes'))
-                               ? " AND s2.itype=? "
-                : " AND s1.itemtype= ? ";
+                    AND s1.biblioitemnumber = s2.biblioitemnumber";
+   (C4::Context->preference('item-level_itypes')) ? $query2.=" AND s2.itype=? " : $query2.=" AND s1.itemtype= ? ";
     my $sth2=  $dbh->prepare($query2);
     my $sth3 =
       $dbh->prepare(
@@ -646,6 +646,8 @@ sub CanBookBeIssued {
     my %issuingimpossible;    # filled with problems that causes the issue to be IMPOSSIBLE
     my $item = GetItem(GetItemnumberFromBarcode( $barcode ));
     my $issue = GetItemIssue($item->{itemnumber});
+       my $biblioitem = GetBiblioItemData($item->{biblioitemnumber});
+       $item->{'itemtype'}=$biblioitem->{'itemtype'};
     my $dbh             = C4::Context->dbh;
 
     #
@@ -699,7 +701,6 @@ sub CanBookBeIssued {
     #
     # JB34 CHECKS IF BORROWERS DONT HAVE ISSUE TOO MANY BOOKS
     #
-    
        my $toomany = TooMany( $borrower, $item->{biblionumber}, $item );
     $needsconfirmation{TOO_MANY} = $toomany if $toomany;
 
@@ -856,7 +857,9 @@ sub AddIssue {
                if ( $actualissue->{borrowernumber} eq $borrower->{'borrowernumber'} ) {
                        AddRenewal(
                                $borrower->{'borrowernumber'},
-                               $item->{'itemnumber'}
+                               $item->{'itemnumber'},
+                               C4::Context->userenv->{'branch'},
+                               $date
                        );
 
                }
@@ -959,8 +962,8 @@ sub AddIssue {
                        $dateduef=CheckValidDatedue($dateduef,$item->{'itemnumber'},C4::Context->userenv->{'branch'});
                
                # if ReturnBeforeExpiry ON the datedue can't be after borrower expirydate
-               if ( C4::Context->preference('ReturnBeforeExpiry') && $dateduef gt $borrower->{dateexpiry} ) {
-                   $dateduef = $borrower->{dateexpiry};
+               if ( C4::Context->preference('ReturnBeforeExpiry') && $dateduef->output('iso') gt $borrower->{dateexpiry} ) {
+                   $dateduef = C4::Dates->new($borrower->{dateexpiry},'iso');
                }
         };
                $sth->execute(
@@ -1027,7 +1030,7 @@ sub GetLoanLength {
       $dbh->prepare(
 "select issuelength from issuingrules where categorycode=? and itemtype=? and branchcode=? and issuelength is not null"
       );
-
+# warn "in get loan lenght $borrowertype $itemtype $branchcode ";
 # try to find issuelength & return the 1st available.
 # check with borrowertype, itemtype and branchcode, then without one of those parameters
     $sth->execute( $borrowertype, $itemtype, $branchcode );
@@ -1077,12 +1080,13 @@ sub GetLoanLength {
 =head2 AddReturn
 
 ($doreturn, $messages, $iteminformation, $borrower) =
-    &AddReturn($barcode, $branch);
+    &AddReturn($barcode, $branch, $exemptfine);
 
 Returns a book.
 
 C<$barcode> is the bar code of the book being returned. C<$branch> is
-the code of the branch where the book is being returned.
+the code of the branch where the book is being returned.  C<$exemptfine>
+indicates that overdue charges for the item will not be applied.
 
 C<&AddReturn> returns a list of four items:
 
@@ -1125,7 +1129,7 @@ patron who last borrowed the book.
 =cut
 
 sub AddReturn {
-    my ( $barcode, $branch ) = @_;
+    my ( $barcode, $branch, $exemptfine ) = @_;
     my $dbh      = C4::Context->dbh;
     my $messages;
     my $doreturn = 1;
@@ -1135,6 +1139,7 @@ sub AddReturn {
     
     # get information on item
     my $iteminformation = GetItemIssue( GetItemnumberFromBarcode($barcode));
+    my $biblio = GetBiblioFromItemNumber($iteminformation->{'itemnumber'});
     unless ($iteminformation->{'itemnumber'} ) {
         $messages->{'BadBarcode'} = $barcode;
         $doreturn = 0;
@@ -1151,7 +1156,13 @@ sub AddReturn {
         if ( $hbr && $branches->{$hbr}->{'PE'} ) {
             $messages->{'IsPermanent'} = $hbr;
         }
-    
+               
+               # if independent branches are on and returning to different branch, refuse the return
+        if ($hbr ne C4::Context->userenv->{'branch'} && C4::Context->preference("IndependantBranches")){
+                       $messages->{'Wrongbranch'} = 1;
+                       $doreturn=0;
+               }
+                       
         # check that the book has been cancelled
         if ( $iteminformation->{'wthdrawn'} ) {
             $messages->{'wthdrawn'} = 1;
@@ -1184,16 +1195,16 @@ sub AddReturn {
                $iteminformation->{'holdingbranch'} = C4::Context->userenv->{'branch'};
        }
         ModDateLastSeen( $iteminformation->{'itemnumber'} );
+               my $sth = $dbh->prepare("UPDATE items SET onloan = NULL where itemnumber = ?");
+               $sth->execute($iteminformation->{'itemnumber'});
+               $sth->finish();
+               my $record = GetMarcItem( $biblio->{'biblionumber'}, $iteminformation->{'itemnumber'} );
+               my $frameworkcode = GetFrameworkCode( $biblio->{'biblionumber'} );
+               ModItemInMarc( $record, $biblio->{'biblionumber'}, $iteminformation->{'itemnumber'}, $frameworkcode );
+               
                if ($iteminformation->{borrowernumber}){
-                       my $sth = $dbh->prepare("UPDATE items SET onloan = NULL where itemnumber = ?");
-                       $sth->execute($iteminformation->{'itemnumber'});
-                       $sth->finish();
-                       my $record = GetMarcItem( $iteminformation->{'biblionumber'}, $iteminformation->{'itemnumber'} );
-                       my $frameworkcode = GetFrameworkCode( $iteminformation->{'biblionumber'} );
-                       ModItemInMarc( $record, $iteminformation->{'biblionumber'}, $iteminformation->{'itemnumber'}, $frameworkcode );
-               }
-        ($borrower) = C4::Members::GetMemberDetails( $iteminformation->{borrowernumber}, 0 );
-        
+                       ($borrower) = C4::Members::GetMemberDetails( $iteminformation->{borrowernumber}, 0 );
+               }       
         # fix up the accounts.....
         if ( $iteminformation->{'itemlost'} ) {
             $messages->{'WasLost'} = 1;
@@ -1230,7 +1241,7 @@ sub AddReturn {
         }
         # fix up the overdues in accounts...
         FixOverduesOnReturn( $borrower->{'borrowernumber'},
-            $iteminformation->{'itemnumber'} );
+            $iteminformation->{'itemnumber'}, $exemptfine );
     
     # find reserves.....
     #     if we don't have a reserve with the status W, we launch the Checkreserves routine
@@ -1258,11 +1269,13 @@ sub AddReturn {
         #we check, if we don't have reserv or transfert for this document, if not, return it to homebranch .
         
         if ( ($iteminformation->{'holdingbranch'} ne $iteminformation->{'homebranch'}) and not $messages->{'WrongTransfer'} and ($validTransfert ne 1) and ($reserveDone ne 1) ){
-                    if (C4::Context->preference("AutomaticItemReturn") == 1) {
-                    ModItemTransfer($iteminformation->{'itemnumber'}, C4::Context->userenv->{'branch'}, $iteminformation->{'homebranch'});
-                    $messages->{'WasTransfered'} = 1;
-                    warn "was transfered";
-                    }
+                       if (C4::Context->preference("AutomaticItemReturn") == 1) {
+                               ModItemTransfer($iteminformation->{'itemnumber'}, C4::Context->userenv->{'branch'}, $iteminformation->{'homebranch'});
+                               $messages->{'WasTransfered'} = 1;
+                       }
+                       else {
+                               $messages->{'NeedsTransfer'} = 1;
+                       }
         }
     }
     return ( $doreturn, $messages, $iteminformation, $borrower );
@@ -1270,7 +1283,7 @@ sub AddReturn {
 
 =head2 FixOverduesOnReturn
 
-    &FixOverduesOnReturn($brn,$itm);
+    &FixOverduesOnReturn($brn,$itm, $exemptfine);
 
 C<$brn> borrowernumber
 
@@ -1281,7 +1294,7 @@ internal function, called only by AddReturn
 =cut
 
 sub FixOverduesOnReturn {
-    my ( $borrowernumber, $item ) = @_;
+    my ( $borrowernumber, $item, $exemptfine ) = @_;
     my $dbh = C4::Context->dbh;
 
     # check for overdue fine
@@ -1292,14 +1305,15 @@ sub FixOverduesOnReturn {
     $sth->execute( $borrowernumber, $item );
 
     # alter fine to show that the book has been returned
-    if ( my $data = $sth->fetchrow_hashref ) {
-        my $usth =
-          $dbh->prepare(
-"UPDATE accountlines SET accounttype='F' WHERE (borrowernumber = ?) AND (itemnumber = ?) AND (accountno = ?)"
-          );
-        $usth->execute( $borrowernumber, $item, $data->{'accountno'} );
+   my $data; 
+       if ($data = $sth->fetchrow_hashref) {
+        my $uquery =($exemptfine)? "update accountlines set accounttype='FFOR', amountoutstanding=0":"update accountlines set accounttype='F' ";
+               $uquery .= " where (borrowernumber = ?) and (itemnumber = ?) and (accountno = ?)";
+        my $usth = $dbh->prepare($uquery);
+        $usth->execute($borrowernumber,$item ,$data->{'accountno'});
         $usth->finish();
     }
+
     $sth->finish();
     return;
 }
@@ -1382,7 +1396,7 @@ sub FixAccountForLostAndReturned {
                if ($amountleft > 0){
                        $amountleft*=-1;
                }
-               my $desc="Book Returned ".$iteminfo->{'barcode'};
+               my $desc="Item Returned ".$iteminfo->{'barcode'};
                $usth = $dbh->prepare("INSERT INTO accountlines
                        (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
                        VALUES (?,?,now(),?,?,'CR',?)");
@@ -1610,12 +1624,13 @@ sub AddRenewal {
 
     my ( $borrowernumber, $itemnumber, $branch ,$datedue ) = @_;
     my $dbh = C4::Context->dbh;
-
+       
+       my $biblio = GetBiblioFromItemNumber($itemnumber);
     # If the due date wasn't specified, calculate it by adding the
     # book's loan length to today's date.
     unless ( $datedue ) {
 
-        my $biblio = GetBiblioFromItemNumber($itemnumber);
+
         my $borrower = C4::Members::GetMemberDetails( $borrowernumber, 0 );
         my $loanlength = GetLoanLength(
             $borrower->{'categorycode'},
@@ -1624,10 +1639,13 @@ sub AddRenewal {
         );
                #FIXME --  choose issuer or borrower branch.
                #FIXME -- where's the calendar ?
-        my ( $due_year, $due_month, $due_day ) =
-          Add_Delta_DHMS( Today_and_Now(), $loanlength, 0, 0, 0 );
-        $datedue = C4::Dates->new( "$due_year-$due_month-$due_day",'iso');
-       $datedue=CheckValidDatedue($datedue,$itemnumber,$branch);
+               #FIXME -- $debug-ify the (0)
+        my @darray = Add_Delta_DHMS( Today_and_Now(), $loanlength, 0, 0, 0 );
+        $datedue = C4::Dates->new( sprintf("%04d-%02d-%02d",@darray[0..2]), 'iso');
+               (0) and print STDERR  "C4::Dates->new->output = " . C4::Dates->new()->output()
+                               . "\ndatedue->output = " . $datedue->output()
+                               . "\n(Y,M,D) = " . join ',', @darray;
+               $datedue=CheckValidDatedue($datedue,$itemnumber,$branch);
     }
 
     # Find the issues record for this book
@@ -1651,8 +1669,15 @@ sub AddRenewal {
     );
     $sth->execute( $datedue->output('iso'), $renews, $borrowernumber, $itemnumber );
     $sth->finish;
-    
-    # Log the renewal
+
+    # Update the renewal count on the item, and tell zebra to reindex
+    $renews = $biblio->{'renewals'} + 1;
+    $sth = $dbh->prepare("UPDATE items SET renewals = ? WHERE itemnumber = ?");
+    $sth->execute($renews,$itemnumber);
+    $sth->finish();
+    my $record = GetMarcItem( $biblio->{'biblionumber'}, $itemnumber );
+    my $frameworkcode = GetFrameworkCode( $biblio->{'biblionumber'} );
+    ModItemInMarc( $record, $biblio->{'biblionumber'}, $itemnumber, $frameworkcode );
 
     # Charge a new rental fee, if applicable?
     my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
@@ -1671,6 +1696,7 @@ sub AddRenewal {
             'Rent', $charge, $itemnumber );
         $sth->finish;
     }
+    # Log the renewal
     UpdateStats( $branch, 'renew', $charge, '', $itemnumber );
 }
 
@@ -1946,6 +1972,7 @@ my @datedue=split('-',$date_due->output('iso'));
 my $years=$datedue[0];
 my $month=$datedue[1];
 my $day=$datedue[2];
+# die "Item# $itemnumber ($branchcode) due: " . ${date_due}->output() . "\n(Y,M,D) = ($years,$month,$day)":
 my $dow;
 for (my $i=0;$i<2;$i++){
        $dow=Day_of_Week($years,$month,$day);
@@ -1958,7 +1985,7 @@ for (my $i=0;$i<2;$i++){
                (($years,$month,$day) = Add_Delta_Days($years,$month,$day, 1))if ($i ne '1');
                }
        }
-my $newdatedue=C4::Dates->new( $years."-".$month."-".$day,'iso');
+       my $newdatedue=C4::Dates->new(sprintf("%04d-%02d-%02d",$years,$month,$day),'iso');
 return $newdatedue;
 }
 =head2 CheckRepeatableHolidays