Bug 17196: [QA Follow-up] Correct POD in ILSDI/Services.pm
[koha.git] / C4 / ILSDI / Services.pm
index 68cbdb3..1868204 100644 (file)
@@ -4,18 +4,18 @@ package C4::ILSDI::Services;
 #
 # 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 2 of the License, or (at your option) any later
-# version.
+# 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.
+# 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, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# 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;
@@ -23,17 +23,19 @@ use warnings;
 use C4::Members;
 use C4::Items;
 use C4::Circulation;
-use C4::Branch;
 use C4::Accounts;
 use C4::Biblio;
-use C4::Reserves qw(AddReserve CancelReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber CanBookBeReserved CanItemBeReserved);
+use C4::Reserves qw(AddReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber CanBookBeReserved CanItemBeReserved IsAvailableForItemLevelRequest);
 use C4::Context;
 use C4::AuthoritiesMarc;
-use C4::ILSDI::Utility;
 use XML::Simple;
 use HTML::Entities;
-use CGI;
+use CGI qw ( -utf8 );
 use DateTime;
+use C4::Auth;
+use C4::Members::Attributes qw(GetBorrowerAttributes);
+
+use Koha::Libraries;
 
 =head1 NAME
 
@@ -49,7 +51,7 @@ hashref that will be printed by XML::Simple in opac/ilsdi.pl
 
        use C4::ILSDI::Services;
        use XML::Simple;
-       use CGI;
+       use CGI qw ( -utf8 );
 
        my $cgi = new CGI;
 
@@ -60,7 +62,7 @@ hashref that will be printed by XML::Simple in opac/ilsdi.pl
                noattr => 1, 
                noescape => 1,
                nosort => 1,
-               xmldecl => '<?xml version="1.0" encoding="ISO-8859-1" ?>', 
+                xmldecl => '<?xml version="1.0" encoding="UTF-8" ?>',
                RootName => 'LookupPatron', 
                SuppressEmpty => 1);
 
@@ -105,7 +107,7 @@ availability
 sub GetAvailability {
     my ($cgi) = @_;
 
-    my $out = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
+    my $out = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
     $out .= "<dlf:collection\n";
     $out .= "  xmlns:dlf=\"http://diglib.org/ilsdi/1.1\"\n";
     $out .= "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
@@ -114,7 +116,7 @@ sub GetAvailability {
 
     foreach my $id ( split( / /, $cgi->param('id') ) ) {
         if ( $cgi->param('id_type') eq "item" ) {
-            my ( $biblionumber, $status, $msg, $location ) = Availability($id);
+            my ( $biblionumber, $status, $msg, $location ) = _availability($id);
 
             $out .= "  <dlf:record>\n";
             $out .= "    <dlf:bibliographic id=\"" . ( $biblionumber || $id ) . "\" />\n";
@@ -132,21 +134,31 @@ sub GetAvailability {
         } else {
             my $status;
             my $msg;
-            my $biblioitem = ( GetBiblioItemByBiblioNumber( $id, undef ) )[0];
-            if ($biblioitem) {
-
+            my $items = GetItemnumbersForBiblio($id);
+            if ($items) {
+                # Open XML
+                $out .= "  <dlf:record>\n";
+                $out .= "    <dlf:bibliographic id=\"" .$id. "\" />\n";
+                $out .= "    <dlf:items>\n";
+                # We loop over the items to clean them
+                foreach my $itemnumber (@$items) {
+                    my ( $biblionumber, $status, $msg, $location ) = _availability($itemnumber);
+                    $out .= "      <dlf:item id=\"" . $itemnumber . "\">\n";
+                    $out .= "        <dlf:simpleavailability>\n";
+                    $out .= "          <dlf:identifier>" . $itemnumber . "</dlf:identifier>\n";
+                    $out .= "          <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
+                    if ($msg)      { $out .= "          <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n"; }
+                    if ($location) { $out .= "          <dlf:location>" . $location . "</dlf:location>\n"; }
+                    $out .= "        </dlf:simpleavailability>\n";
+                    $out .= "      </dlf:item>\n";
+                }
+                # Close XML
+                $out .= "    </dlf:items>\n";
+                $out .= "  </dlf:record>\n";
             } else {
                 $status = "unknown";
                 $msg    = "Error: could not retrieve availability for this ID";
             }
-            $out .= "  <dlf:record>\n";
-            $out .= "    <dlf:bibliographic id=\"" . $id . "\" />\n";
-            $out .= "    <dlf:simpleavailability>\n";
-            $out .= "      <dlf:identifier>" . $id . "</dlf:identifier>\n";
-            $out .= "      <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
-            $out .= "      <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n";
-            $out .= "    </dlf:simpleavailability>\n";
-            $out .= "  </dlf:record>\n";
         }
     }
     $out .= "</dlf:collection>\n";
@@ -203,12 +215,9 @@ sub GetRecords {
             $biblioitem->{marcxml} = $record->as_xml_record();
         }
 
-        # We don't want MARC to be displayed
-        delete $biblioitem->{'marc'};
-
         # Get most of the needed data
         my $biblioitemnumber = $biblioitem->{'biblioitemnumber'};
-        my @reserves         = GetReservesFromBiblionumber( $biblionumber, undef, undef );
+        my $reserves         = GetReservesFromBiblionumber({ biblionumber => $biblionumber });
         my $issues           = GetBiblioIssues($biblionumber);
         my $items            = GetItemsByBiblioitemnumber($biblioitemnumber);
 
@@ -219,13 +228,15 @@ sub GetRecords {
             delete $item->{'more_subfields_xml'};
 
             # Display branch names instead of branch codes
-            $item->{'homebranchname'}    = GetBranchName( $item->{'homebranch'} );
-            $item->{'holdingbranchname'} = GetBranchName( $item->{'holdingbranch'} );
+            my $home_library    = Koha::Libraries->find( $item->{homebranch} );
+            my $holding_library = Koha::Libraries->find( $item->{holdingbranch} );
+            $item->{'homebranchname'}    = $home_library    ? $home_library->branchname    : '';
+            $item->{'holdingbranchname'} = $holding_library ? $holding_library->branchname : '';
         }
 
         # Hashref building...
         $biblioitem->{'items'}->{'item'}       = $items;
-        $biblioitem->{'reserves'}->{'reserve'} = $reserves[1];
+        $biblioitem->{'reserves'}->{'reserve'} = $reserves;
         $biblioitem->{'issues'}->{'issue'}     = $issues;
 
         push @records, $biblioitem;
@@ -312,28 +323,26 @@ the patron.
 Parameters:
 
   - username (Required)
-       user's login identifier
+    user's login identifier (userid or cardnumber)
   - password (Required)
-       user's password
+    user's password
 
 =cut
 
 sub AuthenticatePatron {
     my ($cgi) = @_;
-
-    # Check if borrower exists, using a C4::Auth function...
-    unless( C4::Auth::checkpw( C4::Context->dbh, $cgi->param('username'), $cgi->param('password') ) ) {
+    my $username = $cgi->param('username');
+    my $password = $cgi->param('password');
+    my ($status, $cardnumber, $userid) = C4::Auth::checkpw( C4::Context->dbh, $username, $password );
+    if ( $status ) {
+        # Get the borrower
+        my $borrower = GetMember( cardnumber => $cardnumber );
+        my $patron->{'id'} = $borrower->{'borrowernumber'};
+        return $patron;
+    }
+    else {
         return { code => 'PatronNotFound' };
     }
-
-    # Get the borrower
-    my $borrower = GetMember( userid => $cgi->param('username') );
-
-    # Build the hashref
-    my $patron->{'id'} = $borrower->{'borrowernumber'};
-
-    # ... and return his ID
-    return $patron;
 }
 
 =head2 GetPatronInfo
@@ -362,18 +371,19 @@ sub GetPatronInfo {
 
     # Get Member details
     my $borrowernumber = $cgi->param('patron_id');
-    my $borrower = GetMemberDetails( $borrowernumber );
+    my $borrower = GetMember( borrowernumber => $borrowernumber );
     return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
 
     # Cleaning the borrower hashref
-    $borrower->{'charges'}    = $borrower->{'flags'}->{'CHARGES'}->{'amount'};
-    $borrower->{'branchname'} = GetBranchName( $borrower->{'branchcode'} );
-    delete $borrower->{'flags'};
+    my $flags = C4::Members::patronflags( $borrower );
+    $borrower->{'charges'}    = $flags>{'CHARGES'}->{'amount'};
+    my $library = Koha::Libraries->find( $borrower->{branchcode} );
+    $borrower->{'branchname'} = $library ? $library->branchname : '';
     delete $borrower->{'userid'};
     delete $borrower->{'password'};
 
     # Contact fields management
-    if ( $cgi->param('show_contact') eq "0" ) {
+    if ( defined $cgi->param('show_contact') && $cgi->param('show_contact') eq "0" ) {
 
         # Define contact fields
         my @contactfields = (
@@ -390,7 +400,7 @@ sub GetPatronInfo {
     }
 
     # Fines management
-    if ( $cgi->param('show_fines') eq "1" ) {
+    if ( $cgi->param('show_fines') && $cgi->param('show_fines') eq "1" ) {
         my @charges;
         for ( my $i = 1 ; my @charge = getcharges( $borrowernumber, undef, $i ) ; $i++ ) {
             push( @charges, @charge );
@@ -399,7 +409,7 @@ sub GetPatronInfo {
     }
 
     # Reserves management
-    if ( $cgi->param('show_holds') eq "1" ) {
+    if ( $cgi->param('show_holds') && $cgi->param('show_holds') eq "1" ) {
 
         # Get borrower's reserves
         my @reserves = GetReservesFromBorrowernumber( $borrowernumber, undef );
@@ -407,11 +417,10 @@ sub GetPatronInfo {
 
             # Get additional informations
             my $item = GetBiblioFromItemNumber( $reserve->{'itemnumber'}, undef );
-            my $branchname = GetBranchName( $reserve->{'branchcode'} );
+            my $library = Koha::Libraries->find( $reserve->{branchcode} );
+            my $branchname = $library ? $library->branchname : '';
 
             # Remove unwanted fields
-            delete $item->{'marc'};
-            delete $item->{'marcxml'};
             delete $item->{'more_subfields_xml'};
 
             # Add additional fields
@@ -423,7 +432,7 @@ sub GetPatronInfo {
     }
 
     # Issues management
-    if ( $cgi->param('show_loans') eq "1" ) {
+    if ( $cgi->param('show_loans') && $cgi->param('show_loans') eq "1" ) {
         my $issues = GetPendingIssues($borrowernumber);
         foreach my $issue ( @$issues ){
             $issue->{'issuedate'} = $issue->{'issuedate'}->strftime('%Y-%m-%d %H:%M');
@@ -432,6 +441,11 @@ sub GetPatronInfo {
         $borrower->{'loans'}->{'loan'} = $issues;
     }
 
+    if ( $cgi->param('show_attributes') eq "1" ) {
+        my $attrs = GetBorrowerAttributes( $borrowernumber, 0, 1 );
+        $borrower->{'attributes'} = $attrs;
+    }
+
     return $borrower;
 }
 
@@ -451,7 +465,7 @@ sub GetPatronStatus {
 
     # Get Member details
     my $borrowernumber = $cgi->param('patron_id');
-    my $borrower = GetMemberDetails( $borrowernumber );
+    my $borrower = GetMember( borrowernumber => $borrowernumber );
     return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
 
     # Return the results
@@ -473,6 +487,7 @@ Parameters:
        a borrowernumber
   - item_id (Required)
        an itemnumber
+
 =cut
 
 sub GetServices {
@@ -480,7 +495,7 @@ sub GetServices {
 
     # Get the member, or return an error code if not found
     my $borrowernumber = $cgi->param('patron_id');
-    my $borrower = GetMemberDetails( $borrowernumber );
+    my $borrower = GetMember( borrowernumber => $borrowernumber );
     return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
 
     # Get the item, or return an error code if not found
@@ -493,9 +508,9 @@ sub GetServices {
     # Reserve level management
     my $biblionumber = $item->{'biblionumber'};
     my $canbookbereserved = CanBookBeReserved( $borrower, $biblionumber );
-    if ($canbookbereserved) {
+    if ($canbookbereserved eq 'OK') {
         push @availablefor, 'title level hold';
-        my $canitembereserved = IsAvailableForItemLevelRequest($itemnumber);
+        my $canitembereserved = IsAvailableForItemLevelRequest($item, $borrower);
         if ($canitembereserved) {
             push @availablefor, 'item level hold';
         }
@@ -552,7 +567,7 @@ sub RenewLoan {
 
     # Get borrower infos or return an error code
     my $borrowernumber = $cgi->param('patron_id');
-    my $borrower = GetMemberDetails( $borrowernumber );
+    my $borrower = GetMember( borrowernumber => $borrowernumber );
     return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
 
     # Get the item, or return an error code
@@ -602,7 +617,7 @@ sub HoldTitle {
 
     # Get the borrower or return an error code
     my $borrowernumber = $cgi->param('patron_id');
-    my $borrower = GetMemberDetails( $borrowernumber );
+    my $borrower = GetMember( borrowernumber => $borrowernumber );
     return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
 
     # Get the biblio record, or return an error code
@@ -613,27 +628,30 @@ sub HoldTitle {
     my $title = $$biblio{title};
 
     # Check if the biblio can be reserved
-    return { code => 'NotHoldable' } unless CanBookBeReserved( $borrowernumber, $biblionumber );
+    return { code => 'NotHoldable' } unless CanBookBeReserved( $borrowernumber, $biblionumber ) eq 'OK';
 
     my $branch;
 
     # Pickup branch management
     if ( $cgi->param('pickup_location') ) {
         $branch = $cgi->param('pickup_location');
-        my $branches = GetBranches;
-        return { code => 'LocationNotFound' } unless $$branches{$branch};
+        return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
     } else { # if the request provide no branch, use the borrower's branch
         $branch = $$borrower{branchcode};
     }
 
     # Add the reserve
-    #          $branch, $borrowernumber, $biblionumber, $constraint, $bibitems,  $priority, $notes, $title, $checkitem,  $found
-    AddReserve( $branch, $borrowernumber, $biblionumber, 'a', undef, 0, undef, $title, undef, undef );
+    #    $branch,    $borrowernumber, $biblionumber,
+    #    $constraint, $bibitems,  $priority, $resdate, $expdate, $notes,
+    #    $title,      $checkitem, $found
+    my $priority= C4::Reserves::CalculatePriority( $biblionumber );
+    AddReserve( $branch, $borrowernumber, $biblionumber, undef, $priority, undef, undef, undef, $title, undef, undef );
 
     # Hashref building
     my $out;
     $out->{'title'}           = $title;
-    $out->{'pickup_location'} = GetBranchName($branch);
+    my $library = Koha::Libraries->find( $branch );
+    $out->{'pickup_location'} = $library ? $library->branchname : '';
 
     # TODO $out->{'date_available'}  = '';
 
@@ -667,7 +685,7 @@ sub HoldItem {
 
     # Get the borrower or return an error code
     my $borrowernumber = $cgi->param('patron_id');
-    my $borrower = GetMemberDetails( $borrowernumber );
+    my $borrower = GetMember( borrowernumber => $borrowernumber );
     return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
 
     # Get the biblio or return an error code
@@ -688,35 +706,28 @@ sub HoldItem {
     # Check for item disponibility
     my $canitembereserved = C4::Reserves::CanItemBeReserved( $borrowernumber, $itemnumber );
     my $canbookbereserved = C4::Reserves::CanBookBeReserved( $borrowernumber, $biblionumber );
-    return { code => 'NotHoldable' } unless $canbookbereserved and $canitembereserved;
-
-    my $branch;
+    return { code => 'NotHoldable' } unless $canbookbereserved eq 'OK' and $canitembereserved eq 'OK';
 
     # Pickup branch management
+    my $branch;
     if ( $cgi->param('pickup_location') ) {
         $branch = $cgi->param('pickup_location');
-        my $branches = GetBranches();
-        return { code => 'LocationNotFound' } unless $$branches{$branch};
+        return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
     } else { # if the request provide no branch, use the borrower's branch
         $branch = $$borrower{branchcode};
     }
 
-    my $rank;
-    my $found;
-
-    # Get rank and found
-    $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
-    if ( $item->{'holdingbranch'} eq $branch ) {
-        $found = 'W' unless C4::Context->preference('ReservesNeedReturns');
-    }
-
     # Add the reserve
-    # $branch,$borrowernumber,$biblionumber,$constraint,$bibitems,$priority,$resdate,$expdate,$notes,$title,$checkitem,$found
-    AddReserve( $branch, $borrowernumber, $biblionumber, 'a', undef, $rank, '', '', '', $title, $itemnumber, $found );
+    #    $branch,    $borrowernumber, $biblionumber,
+    #    $constraint, $bibitems,  $priority, $resdate, $expdate, $notes,
+    #    $title,      $checkitem, $found
+    my $priority= C4::Reserves::CalculatePriority( $biblionumber );
+    AddReserve( $branch, $borrowernumber, $biblionumber, undef, $priority, undef, undef, undef, $title, $itemnumber, undef );
 
     # Hashref building
     my $out;
-    $out->{'pickup_location'} = GetBranchName($branch);
+    my $library = Koha::Libraries->find( $branch );
+    $out->{'pickup_location'} = $library ? $library->branchname : '';
 
     # TODO $out->{'date_available'} = '';
 
@@ -730,9 +741,9 @@ Cancels an active reserve request for the borrower.
 Parameters:
 
   - patron_id (Required)
-       a borrowernumber
+        a borrowernumber
   - item_id (Required)
-       an itemnumber 
+        a reserve_id
 
 =cut
 
@@ -741,30 +752,53 @@ sub CancelHold {
 
     # Get the borrower or return an error code
     my $borrowernumber = $cgi->param('patron_id');
-    my $borrower = GetMemberDetails( $borrowernumber );
+    my $borrower = GetMember( borrowernumber => $borrowernumber );
     return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
 
-    # Get the item or return an error code
-    my $itemnumber = $cgi->param('item_id');
-    my $item = GetItem( $itemnumber );
-    return { code => 'RecordNotFound' } unless $$item{itemnumber};
+    # Get the reserve or return an error code
+    my $reserve_id = $cgi->param('item_id');
+    my $reserve = C4::Reserves::GetReserve($reserve_id);
+    return { code => 'RecordNotFound' } unless $reserve;
+    return { code => 'RecordNotFound' } unless ($reserve->{borrowernumber} == $borrowernumber);
 
-    # Get borrower's reserves
-    my @reserves = GetReservesFromBorrowernumber( $borrowernumber, undef );
-    my @reserveditems;
+    C4::Reserves::CancelReserve({reserve_id => $reserve_id});
 
-    # ...and loop over it to build an array of reserved itemnumbers
-    foreach my $reserve (@reserves) {
-        push @reserveditems, $reserve->{'itemnumber'};
-    }
+    return { code => 'Canceled' };
+}
 
-    # if the item was not reserved by the borrower, returns an error code
-    return { code => 'NotCanceled' } unless any { $itemnumber eq $_ } @reserveditems;
+=head2 _availability
 
-    # Cancel the reserve
-    CancelReserve( $itemnumber, undef, $borrowernumber );
+Returns, for an itemnumber, an array containing availability information.
 
-    return { code => 'Canceled' };
+ my ($biblionumber, $status, $msg, $location) = _availability($id);
+
+=cut
+
+sub _availability {
+    my ($itemnumber) = @_;
+    my $item = GetItem( $itemnumber, undef, undef );
+
+    if ( not $item->{'itemnumber'} ) {
+        return ( undef, 'unknown', 'Error: could not retrieve availability for this ID', undef );
+    }
+
+    my $biblionumber = $item->{'biblioitemnumber'};
+    my $library = Koha::Libraries->find( $item->{holdingbranch} );
+    my $location = $library ? $library->branchname : '';
+
+    if ( $item->{'notforloan'} ) {
+        return ( $biblionumber, 'not available', 'Not for loan', $location );
+    } elsif ( $item->{'onloan'} ) {
+        return ( $biblionumber, 'not available', 'Checked out', $location );
+    } elsif ( $item->{'itemlost'} ) {
+        return ( $biblionumber, 'not available', 'Item lost', $location );
+    } elsif ( $item->{'withdrawn'} ) {
+        return ( $biblionumber, 'not available', 'Item withdrawn', $location );
+    } elsif ( $item->{'damaged'} ) {
+        return ( $biblionumber, 'not available', 'Item damaged', $location );
+    } else {
+        return ( $biblionumber, 'available', undef, $location );
+    }
 }
 
 1;