#
# 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., 59 Temple Place,
-# Suite 330, Boston, MA 02111-1307 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;
use C4::Members;
use C4::Items;
use C4::Circulation;
-use C4::Branch;
use C4::Accounts;
use C4::Biblio;
-use C4::Reserves;
+use C4::Reserves qw(AddReserve CanBookBeReserved CanItemBeReserved IsAvailableForItemLevelRequest);
use C4::Context;
use C4::AuthoritiesMarc;
-use C4::ILSDI::Utility;
use XML::Simple;
-use CGI;
+use HTML::Entities;
+use CGI qw ( -utf8 );
+use DateTime;
+use C4::Auth;
+use C4::Members::Attributes qw(GetBorrowerAttributes);
+use Koha::DateUtils;
+
+use Koha::Biblios;
+use Koha::Checkouts;
+use Koha::Items;
+use Koha::Libraries;
+use Koha::Patrons;
=head1 NAME
=head1 DESCRIPTION
- Each function in this module represents an ILS-DI service.
- They all takes a CGI instance as argument and most of them return a
- hashref that will be printed by XML::Simple in opac/ilsdi.pl
+Each function in this module represents an ILS-DI service.
+They all takes a CGI instance as argument and most of them return a
+hashref that will be printed by XML::Simple in opac/ilsdi.pl
=head1 SYNOPSIS
- use C4::ILSDI::Services;
- use XML::Simple;
- use CGI;
+ use C4::ILSDI::Services;
+ use XML::Simple;
+ use CGI qw ( -utf8 );
- my $cgi = new CGI;
+ my $cgi = new CGI;
- $out = LookupPatron($cgi);
+ $out = LookupPatron($cgi);
- print CGI::header('text/xml');
- print XMLout($out,
- noattr => 1,
- noescape => 1,
- nosort => 1,
- xmldecl => '<?xml version="1.0" encoding="ISO-8859-1" ?>',
- RootName => 'LookupPatron',
- SuppressEmpty => 1);
+ print CGI::header('text/xml');
+ print XMLout($out,
+ noattr => 1,
+ noescape => 1,
+ nosort => 1,
+ xmldecl => '<?xml version="1.0" encoding="UTF-8" ?>',
+ RootName => 'LookupPatron',
+ SuppressEmpty => 1);
=cut
+=head1 FUNCTIONS
+
=head2 GetAvailability
-
- Given a set of biblionumbers or itemnumbers, returns a list with
- availability of the items associated with the identifiers.
-
- Parameters :
-
- - id (Required)
- list of either biblionumbers or itemnumbers
- - id_type (Required)
- defines the type of record identifier being used in the request,
- possible values:
- - bib
- - item
- - return_type (Optional)
- requests a particular level of detail in reporting availability,
- possible values:
- - bib
- - item
- - return_fmt (Optional)
- requests a particular format or set of formats in reporting
- availability
+
+Given a set of biblionumbers or itemnumbers, returns a list with
+availability of the items associated with the identifiers.
+
+Parameters:
+
+=head3 id (Required)
+
+list of either biblionumbers or itemnumbers
+
+=head3 id_type (Required)
+
+defines the type of record identifier being used in the request,
+possible values:
+
+ - bib
+ - item
+
+=head3 return_type (Optional)
+
+requests a particular level of detail in reporting availability,
+possible values:
+
+ - bib
+ - item
+
+=head3 return_fmt (Optional)
+
+requests a particular format or set of formats in reporting
+availability
=cut
sub GetAvailability {
- my ( $cgi ) = @_;
-
- my $out = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\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";
- $out .= " xsi:schemaLocation=\"http://diglib.org/ilsdi/1.1\n";
- $out .= " http://diglib.org/architectures/ilsdi/schemas/1.1/dlfexpanded.xsd\">\n";
-
- foreach $id (split(/ /, $cgi->param('id')))
- {
- if ($cgi->param('id_type') eq "item")
- {
- my ($biblionumber, $status, $msg, $location) = Availability($id);
-
- $out .= " <dlf:record>\n";
- $out .= " <dlf:bibliographic id=\"" . ($biblionumber || $id) . "\" />\n";
- $out .= " <dlf:items>\n";
- $out .= " <dlf:item id=\"" . $id . "\">\n";
- $out .= " <dlf:simpleavailability>\n";
- $out .= " <dlf:identifier>" . $id . "</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";
- $out .= " </dlf:items>\n";
- $out .= " </dlf:record>\n";
- }
- else
- {
- my $status;
- my $msg;
- my $biblioitem = (GetBiblioItemByBiblioNumber($id, undef))[0];
- if ($biblioitem) {
-
- } 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";
-
- return $out;
+ my ($cgi) = @_;
+
+ 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";
+ $out .= " xsi:schemaLocation=\"http://diglib.org/ilsdi/1.1\n";
+ $out .= " http://diglib.org/architectures/ilsdi/schemas/1.1/dlfexpanded.xsd\">\n";
+
+ foreach my $id ( split( / /, $cgi->param('id') ) ) {
+ if ( $cgi->param('id_type') eq "item" ) {
+ my ( $biblionumber, $status, $msg, $location ) = _availability($id);
+
+ $out .= " <dlf:record>\n";
+ $out .= " <dlf:bibliographic id=\"" . ( $biblionumber || $id ) . "\" />\n";
+ $out .= " <dlf:items>\n";
+ $out .= " <dlf:item id=\"" . $id . "\">\n";
+ $out .= " <dlf:simpleavailability>\n";
+ $out .= " <dlf:identifier>" . $id . "</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";
+ $out .= " </dlf:items>\n";
+ $out .= " </dlf:record>\n";
+ } else {
+ my $status;
+ my $msg;
+ my $items = Koha::Items->search({ biblionumber => $id });
+ if ($items->count) {
+ # Open XML
+ $out .= " <dlf:record>\n";
+ $out .= " <dlf:bibliographic id=\"" .$id. "\" />\n";
+ $out .= " <dlf:items>\n";
+ # We loop over the items to clean them
+ while ( my $item = $items->next ) {
+ my $itemnumber = $item->itemnumber;
+ 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:collection>\n";
+
+ return $out;
}
=head2 GetRecords
-
- Given a list of biblionumbers, returns a list of record objects that
- contain bibliographic information, as well as associated holdings and item
- information. The caller may request a specific metadata schema for the
- record objects to be returned.
- This function behaves similarly to HarvestBibliographicRecords and
- HarvestExpandedRecords in Data Aggregation, but allows quick, real time
- lookup by bibliographic identifier.
-
- You can use OAI-PMH ListRecords instead of this service.
-
- Parameters:
-
- - id (Required)
- list of system record identifiers
- - id_type (Optional)
- Defines the metadata schema in which the records are returned,
- possible values:
- - MARCXML
+
+Given a list of biblionumbers, returns a list of record objects that
+contain bibliographic information, as well as associated holdings and item
+information. The caller may request a specific metadata schema for the
+record objects to be returned.
+
+This function behaves similarly to HarvestBibliographicRecords and
+HarvestExpandedRecords in Data Aggregation, but allows quick, real time
+lookup by bibliographic identifier.
+
+You can use OAI-PMH ListRecords instead of this service.
+
+Parameters:
+
+ - id (Required)
+ list of system record identifiers
+ - id_type (Optional)
+ Defines the metadata schema in which the records are returned,
+ possible values:
+ - MARCXML
=cut
sub GetRecords {
- my ( $cgi ) = @_;
-
- # Check if the schema is supported. For now, GetRecords only supports MARCXML
- if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML") {
- $out->{'message'} = "UnsupportedSchema";
- return $out;
- }
-
- my @records;
- # Loop over biblionumbers
- foreach $biblionumber (split(/ /, $cgi->param('id')))
- {
- # Get the biblioitem from the biblionumber
- my $biblioitem = (GetBiblioItemByBiblioNumber($biblionumber, undef))[0];
- if ( not $biblioitem->{'biblionumber'} ) {
- $biblioitem = "RecordNotFound";
- }
-
- # We don't want MARC to be displayed
- delete $biblioitem->{'marc'};
- # nor the XML declaration of MARCXML
- $biblioitem->{'marcxml'} =~ s/<\?xml version="1.0" encoding="UTF-8"\?>//go;
-
- # Get most of the needed data
- my $biblioitemnumber = $biblioitem->{'biblioitemnumber'};
- my @reserves = GetReservesFromBiblionumber($biblionumber, undef, undef);
- my $issues = GetBiblioIssues($biblionumber);
- my $items = GetItemsByBiblioitemnumber($biblioitemnumber);
-
- # We loop over the items to clean them
- foreach $item (@$items)
- {
- # This hides additionnal XML subfields, we don't need these info
- delete $item->{'more_subfields_xml'};
- # Display branch names instead of branch codes
- $item->{'homebranchname'} = GetBranchName($item->{'homebranch'});
- $item->{'holdingbranchname'} = GetBranchName($item->{'holdingbranch'});
- }
-
- # Hashref building...
- $biblioitem->{'items'}->{'item'} = $items;
- $biblioitem->{'reserves'}->{'reserve'} = @reserves[1];
- $biblioitem->{'issues'}->{'issue'} = $issues;
-
- push @records, $biblioitem;
- }
-
- $records->{'record'} = \@records;
-
- return $records;
+ my ($cgi) = @_;
+
+ # Check if the schema is supported. For now, GetRecords only supports MARCXML
+ if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
+ return { code => 'UnsupportedSchema' };
+ }
+
+ my @records;
+
+ # Loop over biblionumbers
+ foreach my $biblionumber ( split( / /, $cgi->param('id') ) ) {
+
+ # Get the biblioitem from the biblionumber
+ my $biblio = Koha::Biblios->find( $biblionumber );
+ unless ( $biblio ) {
+ push @records, { code => "RecordNotFound" };
+ next;
+ }
+
+ my $biblioitem = $biblio->biblioitem->unblessed;
+
+ my $embed_items = 1;
+ my $record = GetMarcBiblio({
+ biblionumber => $biblionumber,
+ embed_items => $embed_items });
+ if ($record) {
+ $biblioitem->{marcxml} = $record->as_xml_record();
+ }
+
+ # Get most of the needed data
+ my $biblioitemnumber = $biblioitem->{'biblioitemnumber'};
+ my $holds = $biblio->current_holds->unblessed;
+ my $issues = GetBiblioIssues($biblionumber);
+ my @items = $biblio->items->as_list;
+
+ $biblioitem->{items}->{item} = [];
+
+ # We loop over the items to clean them
+ foreach my $item (@items) {
+ my %item = %{ $item->unblessed };
+
+ # This hides additionnal XML subfields, we don't need these info
+ delete $item{'more_subfields_xml'};
+
+ # Display branch names instead of branch codes
+ my $home_library = $item->home_branch;
+ my $holding_library = $item->holding_branch;
+ $item{'homebranchname'} = $home_library ? $home_library->branchname : '';
+ $item{'holdingbranchname'} = $holding_library ? $holding_library->branchname : '';
+
+ my $transfer = $item->get_transfer;
+ if ($transfer) {
+ $item{transfer} = {
+ datesent => $transfer->datesent,
+ frombranch => $transfer->frombranch,
+ tobranch => $transfer->tobranch,
+ };
+ }
+
+ push @{ $biblioitem->{items}->{item} }, \%item;
+ }
+
+ # Hashref building...
+ $biblioitem->{'reserves'}->{'reserve'} = $holds;
+ $biblioitem->{'issues'}->{'issue'} = $issues;
+
+ push @records, $biblioitem;
+ }
+
+ return { record => \@records };
}
=head2 GetAuthorityRecords
-
- Given a list of authority record identifiers, returns a list of record
- objects that contain the authority records. The function user may request
- a specific metadata schema for the record objects.
- Parameters:
+Given a list of authority record identifiers, returns a list of record
+objects that contain the authority records. The function user may request
+a specific metadata schema for the record objects.
+
+Parameters:
- - id (Required)
- list of authority record identifiers
- - schema (Optional)
- specifies the metadata schema of records to be returned, possible values:
- - MARCXML
+ - id (Required)
+ list of authority record identifiers
+ - schema (Optional)
+ specifies the metadata schema of records to be returned, possible values:
+ - MARCXML
=cut
sub GetAuthorityRecords {
- my ( $cgi ) = @_;
-
- # If the user asks for an unsupported schema, return an error code
- if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML") {
- $out->{'message'} = "UnsupportedSchema";
- return $out;
- }
-
- my $records;
- # Let's loop over the authority IDs
- foreach $authid (split(/ /, $cgi->param('id')))
- {
- # Get the record as XML string, or error code
- my $record= GetAuthorityXML($authid) || "<record>RecordNotFound</record>";
- $record =~ s/<\?xml version="1.0" encoding="UTF-8"\?>//go;
- $records .= $record;
- }
-
- return $records;
+ my ($cgi) = @_;
+
+ # If the user asks for an unsupported schema, return an error code
+ if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
+ return { code => 'UnsupportedSchema' };
+ }
+
+ my @records;
+
+ # Let's loop over the authority IDs
+ foreach my $authid ( split( / /, $cgi->param('id') ) ) {
+
+ # Get the record as XML string, or error code
+ push @records, GetAuthorityXML($authid) || { code => 'RecordNotFound' };
+ }
+
+ return { record => \@records };
}
=head2 LookupPatron
-
- Looks up a patron in the ILS by an identifier, and returns the borrowernumber.
-
- Parameters:
-
- - id (Required)
- an identifier used to look up the patron in Koha
- - id_type (Optional)
- the type of the identifier, possible values:
- - cardnumber
- - firstname
- - userid
- - borrowernumber
+
+Looks up a patron in the ILS by an identifier, and returns the borrowernumber.
+
+Parameters:
+
+ - id (Required)
+ an identifier used to look up the patron in Koha
+ - id_type (Optional)
+ the type of the identifier, possible values:
+ - cardnumber
+ - userid
+ - email
+ - borrowernumber
+ - firstname
+ - surname
=cut
sub LookupPatron {
- my ( $cgi ) = @_;
-
- # Get the borrower...
- my $borrower = GetMember($cgi->param('id'), $cgi->param('id_type'));
- if ( not $borrower->{'borrowernumber'} ) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Build the hashref
- my $patron->{'id'} = $borrower->{'borrowernumber'};
-
- # ...and return his ID
- return $patron;
+ my ($cgi) = @_;
+
+ my $id = $cgi->param('id');
+ if(!$id) {
+ return { message => 'PatronNotFound' };
+ }
+
+ my $patrons;
+ my $passed_id_type = $cgi->param('id_type');
+ if($passed_id_type) {
+ $patrons = Koha::Patrons->search( { $passed_id_type => $id } );
+ } else {
+ foreach my $id_type ('cardnumber', 'userid', 'email', 'borrowernumber',
+ 'surname', 'firstname') {
+ $patrons = Koha::Patrons->search( { $id_type => $id } );
+ last if($patrons->count);
+ }
+ }
+ unless ( $patrons->count ) {
+ return { message => 'PatronNotFound' };
+ }
+
+ return { id => $patrons->next->borrowernumber };
}
=head2 AuthenticatePatron
- Authenticates a user's login credentials and returns the identifier for
- the patron.
-
- Parameters:
+Authenticates a user's login credentials and returns the identifier for
+the patron.
+
+Parameters:
+
+ - username (Required)
+ user's login identifier (userid or cardnumber)
+ - password (Required)
+ user's password
- - username (Required)
- user's login identifier
- - password (Required)
- user's password
-
=cut
sub AuthenticatePatron {
- my ( $cgi ) = @_;
-
- # Check if borrower exists, using a C4::ILSDI::Utility function...
- if ( not (BorrowerExists($cgi->param('username'), $cgi->param('password')))) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Get the borrower
- my $borrower = GetMember($cgi->param('username'), "userid");
-
- # Build the hashref
- my $patron->{'id'} = $borrower->{'borrowernumber'};
-
- # ... and return his ID
- return $patron;
+ my ($cgi) = @_;
+ 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 $patron = Koha::Patrons->find( { userid => $userid } );
+ return { id => $patron->borrowernumber };
+ }
+ else {
+ return { code => 'PatronNotFound' };
+ }
}
=head2 GetPatronInfo
- Returns specified information about the patron, based on options in the
- request. This function can optionally return patron's contact information,
- fine information, hold request information, and loan information.
-
- Parameters:
-
- - patron_id (Required)
- the borrowernumber
- - show_contact (Optional, default 1)
- whether or not to return patron's contact information in the response
- - show_fines (Optional, default 0)
- whether or not to return fine information in the response
- - show_holds (Optional, default 0)
- whether or not to return hold request information in the response
- - show_loans (Optional, default 0)
- whether or not to return loan information request information in the response
-
+Returns specified information about the patron, based on options in the
+request. This function can optionally return patron's contact information,
+fine information, hold request information, and loan information.
+
+Parameters:
+
+ - patron_id (Required)
+ the borrowernumber
+ - show_contact (Optional, default 1)
+ whether or not to return patron's contact information in the response
+ - show_fines (Optional, default 0)
+ whether or not to return fine information in the response
+ - show_holds (Optional, default 0)
+ whether or not to return hold request information in the response
+ - show_loans (Optional, default 0)
+ whether or not to return loan information request information in the response
+ - show_attributes (Optional, default 0)
+ whether or not to return additional patron attributes, when enabled the attributes
+ are limited to those marked as opac visible only.
+
=cut
sub GetPatronInfo {
- my ( $cgi ) = @_;
-
- # Get Member details
- my $borrowernumber = $cgi->param('patron_id');
- my $borrower = GetMemberDetails($borrowernumber, undef);
- if ( not $borrower->{'borrowernumber'}) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Cleaning the borrower hashref
- $borrower->{'charges'} = $borrower->{'flags'}->{'CHARGES'}->{'amount'};
- $borrower->{'branchname'} = GetBranchName($borrower->{'branchcode'});
- delete $borrower->{'flags'};
- delete $borrower->{'userid'};
- delete $borrower->{'password'};
-
- # Contact fields management
- if ($cgi->param('show_contact') eq "0") {
- # Define contact fields
- my @contactfields = ('email', 'emailpro', 'fax', 'mobile',
- 'phone', 'phonepro', 'streetnumber', 'zipcode', 'city',
- 'streettype', 'B_address', 'B_city', 'B_email', 'B_phone',
- 'B_zipcode', 'address', 'address2', 'altcontactaddress1',
- 'altcontactaddress2', 'altcontactaddress3', 'altcontactfirstname',
- 'altcontactphone', 'altcontactsurname', 'altcontactzipcode');
- # and delete them
- foreach my $field (@contactfields) {
- delete $borrower->{$field};
- }
- }
-
- # Fines management
- if ($cgi->param('show_fines') eq "1") {
- my @charges;
- for(my $i = 1; my @charge = getcharges($borrowernumber, undef, $i); $i++) {
- push(@charges, @charge);
- }
- $borrower->{'fines'}->{'fine'} = \@charges;
- }
-
- # Reserves management
- if ($cgi->param('show_holds') eq "1") {
- # Get borrower's reserves
- my @reserves = GetReservesFromBorrowernumber($borrowernumber, undef);
- foreach my $reserve (@reserves) {
- # Get additional informations
- my $item = GetBiblioFromItemNumber($reserve->{'itemnumber'}, undef);
- my $branchname = GetBranchName($reserve->{'branchcode'});
- # Remove unwanted fields
- delete $item->{'marc'};
- delete $item->{'marcxml'};
- delete $item->{'more_subfields_xml'};
- # Add additional fields
- $reserve->{'item'} = $item;
- $reserve->{'branchname'} = $branchname;
- $reserve->{'title'} = (GetBiblio($reserve->{'biblionumber'}))[1]->{'title'};
- }
- $borrower->{'holds'}->{'hold'} = \@reserves;
- }
-
- # Issues management
- if ($cgi->param('show_loans') eq "1") {
- my $issues = GetPendingIssues($borrowernumber);
- $borrower->{'loans'}->{'loan'} = $issues;
- }
-
- return $borrower;
+ my ($cgi) = @_;
+
+ # Get Member details
+ my $borrowernumber = $cgi->param('patron_id');
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ return { code => 'PatronNotFound' } unless $patron;
+
+ # Cleaning the borrower hashref
+ my $borrower = $patron->unblessed;
+ $borrower->{charges} = sprintf "%.02f", $patron->account->non_issues_charges; # FIXME Formatting should not be done here
+ my $library = Koha::Libraries->find( $borrower->{branchcode} );
+ $borrower->{'branchname'} = $library ? $library->branchname : '';
+ delete $borrower->{'userid'};
+ delete $borrower->{'password'};
+
+ # Contact fields management
+ if ( defined $cgi->param('show_contact') && $cgi->param('show_contact') eq "0" ) {
+
+ # Define contact fields
+ my @contactfields = (
+ 'email', 'emailpro', 'fax', 'mobile', 'phone', 'phonepro',
+ 'streetnumber', 'zipcode', 'city', 'streettype', 'B_address', 'B_city',
+ 'B_email', 'B_phone', 'B_zipcode', 'address', 'address2', 'altcontactaddress1',
+ 'altcontactaddress2', 'altcontactaddress3', 'altcontactfirstname', 'altcontactphone', 'altcontactsurname', 'altcontactzipcode'
+ );
+
+ # and delete them
+ foreach my $field (@contactfields) {
+ delete $borrower->{$field};
+ }
+ }
+
+ # Fines management
+ if ( $cgi->param('show_fines') && $cgi->param('show_fines') eq "1" ) {
+ $borrower->{fines}{fine} = $patron->account->lines->unblessed;
+ }
+
+ # Reserves management
+ if ( $cgi->param('show_holds') && $cgi->param('show_holds') eq "1" ) {
+
+ # Get borrower's reserves
+ my $holds = $patron->holds;
+ while ( my $hold = $holds->next ) {
+
+ my ( $item, $biblio, $biblioitem ) = ( {}, {}, {} );
+ # Get additional informations
+ if ( $hold->itemnumber ) { # item level holds
+ $item = Koha::Items->find( $hold->itemnumber );
+ $biblio = $item->biblio;
+ $biblioitem = $biblio->biblioitem;
+
+ # Remove unwanted fields
+ $item = $item->unblessed;
+ delete $item->{more_subfields_xml};
+ $biblio = $biblio->unblessed;
+ $biblioitem = $biblioitem->unblessed;
+ }
+
+ # Add additional fields
+ my $unblessed_hold = $hold->unblessed;
+ $unblessed_hold->{item} = { %$item, %$biblio, %$biblioitem };
+ my $library = Koha::Libraries->find( $hold->branchcode );
+ my $branchname = $library ? $library->branchname : '';
+ $unblessed_hold->{branchname} = $branchname;
+ $biblio = Koha::Biblios->find( $hold->biblionumber ); # Should be $hold->get_biblio
+ $unblessed_hold->{title} = $biblio ? $biblio->title : ''; # Just in case, but should not be needed
+
+ push @{ $borrower->{holds}{hold} }, $unblessed_hold;
+
+ }
+ }
+
+ # Issues management
+ if ( $cgi->param('show_loans') && $cgi->param('show_loans') eq "1" ) {
+ my $per_page = $cgi->param('loans_per_page');
+ my $page = $cgi->param('loans_page');
+
+ my $pending_checkouts = $patron->pending_checkouts;
+
+ if ($page || $per_page) {
+ $page ||= 1;
+ $per_page ||= 10;
+ $borrower->{total_loans} = $pending_checkouts->count();
+ $pending_checkouts = $pending_checkouts->search(undef, {
+ rows => $per_page,
+ page => $page,
+ });
+ }
+
+ my @checkouts;
+ while ( my $c = $pending_checkouts->next ) {
+ # FIXME We should only retrieve what is needed in the template
+ my $issue = $c->unblessed_all_relateds;
+ delete $issue->{'more_subfields_xml'};
+ push @checkouts, $issue
+ }
+ $borrower->{'loans'}->{'loan'} = \@checkouts;
+ }
+
+ my $show_attributes = $cgi->param('show_attributes');
+ if ( $show_attributes && $show_attributes eq "1" ) {
+ my $attrs = GetBorrowerAttributes( $borrowernumber, 1 );
+ $borrower->{'attributes'} = $attrs;
+ }
+
+ # Add is expired information
+ $borrower->{'is_expired'} = $patron->is_expired ? 1 : 0;
+
+ return $borrower;
}
=head2 GetPatronStatus
- Returns a patron's status information.
-
- Parameters:
+Returns a patron's status information.
+
+Parameters:
- - patron_id (Required)
- the borrower ID
+ - patron_id (Required)
+ the borrower ID
=cut
sub GetPatronStatus {
- my ( $cgi ) = @_;
-
- # Get Member details
- my $borrowernumber = $cgi->param('patron_id');
- my $borrower = GetMemberDetails($borrowernumber, undef);
- if ( not $borrower->{'borrowernumber'} ) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Hashref building
- $patron->{'type'} = $borrower->{'categorycode'};
- $patron->{'status'} = 0; #TODO
- $patron->{'expiry'} = $borrower->{'dateexpiry'};
-
- return $patron;
+ my ($cgi) = @_;
+
+ # Get Member details
+ my $borrowernumber = $cgi->param('patron_id');
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ return { code => 'PatronNotFound' } unless $patron;
+
+ # Return the results
+ return {
+ type => $patron->categorycode,
+ status => 0, # TODO
+ expiry => $patron->dateexpiry,
+ };
}
=head2 GetServices
- Returns information about the services available on a particular item for
- a particular patron.
-
- Parameters:
+Returns information about the services available on a particular item for
+a particular patron.
+
+Parameters:
+
+ - patron_id (Required)
+ a borrowernumber
+ - item_id (Required)
+ an itemnumber
- - patron_id (Required)
- a borrowernumber
- - item_id (Required)
- an itemnumber
=cut
sub GetServices {
- my ( $cgi ) = @_;
-
- # Get the member, or return an error code if not found
- my $borrowernumber = $cgi->param('patron_id');
- my $borrower = GetMemberDetails($borrowernumber, undef);
- if ( not $borrower->{'borrowernumber'} ) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Get the item, or return an error code if not found
- my $itemnumber = $cgi->param('item_id');
- my $item = GetItem($itemnumber, undef, undef);
- if ( not $item->{'itemnumber'} ) {
- $out->{'message'} = "RecordNotFound";
- return $out;
- }
-
- my @availablefor;
-
- # Reserve level management
- my $biblionumber = $item->{'biblionumber'};
- my $canbookbereserved = CanBookBeReserved($borrower, $biblionumber);
- if ( $canbookbereserved ) {
- push @availablefor, 'title level hold';
- my $canitembereserved = IsAvailableForItemLevelRequest($itemnumber);
- if ( $canitembereserved ) {
- push @availablefor, 'item level hold';
- }
- }
-
- # Reserve cancellation management
- my @reserves = GetReservesFromBorrowernumber($borrowernumber, undef);
- my @reserveditems;
- foreach my $reserve (@reserves) {
- push @reserveditems, $reserve->{'itemnumber'};
- }
- if ( grep {$itemnumber eq $_} @reserveditems) {
- push @availablefor, 'hold cancellation';
- }
-
- # Renewal management
- my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
- if ( @renewal[0] ) {
- push @availablefor, 'loan renewal';
- }
-
- # Issuing management
- my $barcode = $item->{'barcode'} || '';
- $barcode = barcodedecode($barcode) if( $barcode && C4::Context->preference('itemBarcodeInputFilter'));
- if ($barcode) {
- my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $borrower, $barcode );
- # TODO push @availablefor, 'loan';
- }
-
- $out->{'AvailableFor'} = \@availablefor;
-
- return $out;
+ my ($cgi) = @_;
+
+ # Get the member, or return an error code if not found
+ my $borrowernumber = $cgi->param('patron_id');
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ return { code => 'PatronNotFound' } unless $patron;
+
+ my $borrower = $patron->unblessed;
+ # Get the item, or return an error code if not found
+ my $itemnumber = $cgi->param('item_id');
+ my $item = Koha::Items->find($itemnumber);
+ return { code => 'RecordNotFound' } unless $item;
+
+ my @availablefor;
+
+ # Reserve level management
+ my $biblionumber = $item->biblionumber;
+ my $canbookbereserved = CanBookBeReserved( $borrower, $biblionumber );
+ if ($canbookbereserved->{status} eq 'OK') {
+ push @availablefor, 'title level hold';
+ my $canitembereserved = IsAvailableForItemLevelRequest($item, $patron);
+ if ($canitembereserved) {
+ push @availablefor, 'item level hold';
+ }
+ }
+
+ # Reserve cancellation management
+ my $holds = $patron->holds;
+ my @reserveditems;
+ while ( my $hold = $holds->next ) { # FIXME This could be improved
+ push @reserveditems, $hold->itemnumber;
+ }
+ if ( grep { $itemnumber eq $_ } @reserveditems ) {
+ push @availablefor, 'hold cancellation';
+ }
+
+ # Renewal management
+ my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
+ if ( $renewal[0] ) {
+ push @availablefor, 'loan renewal';
+ }
+
+ # Issuing management
+ my $barcode = $item->barcode || '';
+ $barcode = barcodedecode($barcode) if ( $barcode && C4::Context->preference('itemBarcodeInputFilter') );
+ if ($barcode) {
+ my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $patron, $barcode );
+
+ # TODO push @availablefor, 'loan';
+ }
+
+ my $out;
+ $out->{'AvailableFor'} = \@availablefor;
+
+ return $out;
}
=head2 RenewLoan
- Extends the due date for a borrower's existing issue.
-
- Parameters:
+Extends the due date for a borrower's existing issue.
+
+Parameters:
- - patron_id (Required)
- a borrowernumber
- - item_id (Required)
- an itemnumber
- - desired_due_date (Required)
- the date the patron would like the item returned by
+ - patron_id (Required)
+ a borrowernumber
+ - item_id (Required)
+ an itemnumber
+ - desired_due_date (Required)
+ the date the patron would like the item returned by
=cut
sub RenewLoan {
- my ( $cgi ) = @_;
-
- # Get borrower infos or return an error code
- my $borrowernumber = $cgi->param('patron_id');
- my $borrower = GetMemberDetails($borrowernumber, undef);
- if ( not $borrower->{'borrowernumber'} ) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Get the item, or return an error code
- my $itemnumber = $cgi->param('item_id');
- my $item = GetItem($itemnumber, undef, undef);
- if ( not $item->{'itemnumber'} ) {
- $out->{'message'} = "RecordNotFound";
- return $out;
- }
-
- # Add renewal if possible
- my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
- if (@renewal[0]) { AddRenewal( $borrowernumber, $itemnumber ); }
-
- my $issue = GetItemIssue($itemnumber);
-
- # Hashref building
- $out->{'renewals'} = $issue->{'renewals'};
- $out->{'date_due'} = $issue->{'date_due'};
- $out->{'success'} = @renewal[0];
- $out->{'error'} = @renewal[1];
-
- return $out;
+ my ($cgi) = @_;
+
+ # Get borrower infos or return an error code
+ my $borrowernumber = $cgi->param('patron_id');
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ return { code => 'PatronNotFound' } unless $patron;
+
+ # Get the item, or return an error code
+ my $itemnumber = $cgi->param('item_id');
+ my $item = Koha::Items->find($itemnumber);
+ return { code => 'RecordNotFound' } unless $item;
+
+ # Add renewal if possible
+ my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
+ if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber ); }
+
+ my $issue = $item->checkout;
+ return unless $issue; # FIXME should be handled
+
+ # Hashref building
+ my $out;
+ $out->{'renewals'} = $issue->renewals;
+ $out->{date_due} = dt_from_string($issue->date_due)->strftime('%Y-%m-%d %H:%M');
+ $out->{'success'} = $renewal[0];
+ $out->{'error'} = $renewal[1];
+
+ return $out;
}
=head2 HoldTitle
- Creates, for a borrower, a biblio-level hold reserve.
-
- Parameters:
-
- - patron_id (Required)
- a borrowernumber
- - bib_id (Required)
- a biblionumber
- - request_location (Required)
- IP address where the end user request is being placed
- - pickup_location (Optional)
- a branch code indicating the location to which to deliver the item for pickup
- - needed_before_date (Optional)
- date after which hold request is no longer needed
- - pickup_expiry_date (Optional)
- date after which item returned to shelf if item is not picked up
+Creates, for a borrower, a biblio-level hold reserve.
+
+Parameters:
+
+ - patron_id (Required)
+ a borrowernumber
+ - bib_id (Required)
+ a biblionumber
+ - request_location (Required)
+ IP address where the end user request is being placed
+ - pickup_location (Optional)
+ a branch code indicating the location to which to deliver the item for pickup
+ - needed_before_date (Optional)
+ date after which hold request is no longer needed
+ - pickup_expiry_date (Optional)
+ date after which item returned to shelf if item is not picked up
=cut
sub HoldTitle {
- my ( $cgi ) = @_;
-
- # Get the borrower or return an error code
- my $borrowernumber = $cgi->param('patron_id');
- my $borrower = GetMemberDetails($borrowernumber, undef);
- if ( not $borrower->{'borrowernumber'} ) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Get the biblio record, or return an error code
- my $biblionumber = $cgi->param('bib_id');
- my ($count, $biblio) = GetBiblio($biblionumber);
- if ( not $biblio->{'biblionumber'} ) {
- $out->{'message'} = "RecordNotFound";
- return $out;
- }
- my $title = $biblio->{'title'};
-
- # Check if the biblio can be reserved
- my $canbereserved = CanBookBeReserved($borrower, $biblionumber);
- if ( not $canbereserved ) {
- $out->{'message'} = "NotHoldable";
- return $out;
- }
-
- my $branch;
- # Pickup branch management
- if ($cgi->param('pickup_location')) {
- $branch = $cgi->param('pickup_location');
- my $branches = GetBranches();
- if ( not $branches->{$branch} ) {
- $out->{'message'} = "LocationNotFound";
- return $out;
- }
- } else { # if user provide no branch, use his own
- $branch = C4::Context->userenv->{'branch'};
- }
-
- # Add the reserve
- # $branch, $borrowernumber, $biblionumber, $constraint, $bibitems, $priority, $notes, $title, $checkitem, $found
- AddReserve($branch, $borrowernumber, $biblionumber, 'a', undef, 0, undef, $title, undef, undef);
-
- # Hashref building
- $out->{'title'} = $title;
- $out->{'pickup_location'} = GetBranchName($branch);
- # TODO $out->{'date_available'} = '';
-
- return $out;
+ my ($cgi) = @_;
+
+ # Get the borrower or return an error code
+ my $borrowernumber = $cgi->param('patron_id');
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ return { code => 'PatronNotFound' } unless $patron;
+
+ # Get the biblio record, or return an error code
+ my $biblionumber = $cgi->param('bib_id');
+ my $biblio = Koha::Biblios->find( $biblionumber );
+ return { code => 'RecordNotFound' } unless $biblio;
+
+ my @hostitems = get_hostitemnumbers_of($biblionumber);
+ my @itemnumbers;
+ if (@hostitems){
+ push(@itemnumbers, @hostitems);
+ }
+
+ my $items = Koha::Items->search({ -or => { biblionumber => $biblionumber, itemnumber => { in => \@itemnumbers } } });
+
+ unless ( $items->count ) {
+ return { code => 'NoItems' };
+ }
+
+ my $title = $biblio ? $biblio->title : '';
+
+ # Check if the biblio can be reserved
+ my $code = CanBookBeReserved( $borrowernumber, $biblionumber )->{status};
+ return { code => $code } unless ( $code eq 'OK' );
+
+ my $branch;
+
+ # Pickup branch management
+ if ( $cgi->param('pickup_location') ) {
+ $branch = $cgi->param('pickup_location');
+ return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
+ } else { # if the request provide no branch, use the borrower's branch
+ $branch = $patron->branchcode;
+ }
+
+ my $destination = Koha::Libraries->find($branch);
+ return { code => 'libraryNotPickupLocation' } unless $destination->pickup_location;
+ return { code => 'cannotBeTransferred' } unless $biblio->can_be_transferred({ to => $destination });
+
+ # Add the reserve
+ # $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;
+ my $library = Koha::Libraries->find( $branch );
+ $out->{'pickup_location'} = $library ? $library->branchname : '';
+
+ # TODO $out->{'date_available'} = '';
+
+ return $out;
}
=head2 HoldItem
- Creates, for a borrower, an item-level hold request on a specific item of
- a bibliographic record in Koha.
+Creates, for a borrower, an item-level hold request on a specific item of
+a bibliographic record in Koha.
- Parameters:
+Parameters:
- - patron_id (Required)
- a borrowernumber
- - bib_id (Required)
- a biblionumber
- - item_id (Required)
- an itemnumber
- - pickup_location (Optional)
- a branch code indicating the location to which to deliver the item for pickup
- - needed_before_date (Optional)
- date after which hold request is no longer needed
- - pickup_expiry_date (Optional)
- date after which item returned to shelf if item is not picked up
+ - patron_id (Required)
+ a borrowernumber
+ - bib_id (Required)
+ a biblionumber
+ - item_id (Required)
+ an itemnumber
+ - pickup_location (Optional)
+ a branch code indicating the location to which to deliver the item for pickup
+ - needed_before_date (Optional)
+ date after which hold request is no longer needed
+ - pickup_expiry_date (Optional)
+ date after which item returned to shelf if item is not picked up
=cut
sub HoldItem {
- my ( $cgi ) = @_;
-
- # Get the borrower or return an error code
- my $borrowernumber = $cgi->param('patron_id');
- my $borrower = GetMemberDetails($borrowernumber, undef);
- if ( not $borrower->{'borrowernumber'} ) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Get the biblio or return an error code
- my $biblionumber = $cgi->param('bib_id');
- my ($count, $biblio) = GetBiblio($biblionumber);
- if ( not $biblio->{'biblionumber'} ) {
- $out->{'message'} = "RecordNotFound";
- return $out;
- }
- my $title = $biblio->{'title'};
-
- # Get the item or return an error code
- my $itemnumber = $cgi->param('item_id');
- my $item = GetItem($itemnumber, undef, undef);
- if ( not $item->{'itemnumber'} ) {
- $out->{'message'} = "RecordNotFound";
- return $out;
- }
-
- # if the biblio does not match the item, return an error code
- if ( $item->{'biblionumber'} ne $biblio->{'biblionumber'} ) {
- $out->{'message'} = "RecordNotFound";
- return $out;
- }
-
- # Check for item disponibility
- my $canitembereserved = IsAvailableForItemLevelRequest($itemnumber);
- my $canbookbereserved = CanBookBeReserved($borrower, $biblionumber);
- if ( (not $canbookbereserved) or not ($canitembereserved) ) {
- $out->{'message'} = "NotHoldable";
- return $out;
- }
-
- my $branch;
- # Pickup branch management
- if ($cgi->param('pickup_location')) {
- $branch = $cgi->param('pickup_location');
- my $branches = GetBranches();
- if ( not $branches->{$branch} ) {
- $out->{'message'} = "LocationNotFound";
- return $out;
- }
- } else { # if user provide no branch, use his own
- $branch = C4::Context->userenv->{'branch'};
- }
-
- 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, $notes, $title, $checkitem, $found
- AddReserve($branch, $borrowernumber, $biblionumber, 'a', undef, $rank, undef, $title, $itemnumber, $found);
-
- # Hashref building
- $out->{'title'} = $title;
- $out->{'pickup_location'} = GetBranchName($branch);
- # TODO $out->{'date_available'} = '';
-
- return $out;
+ my ($cgi) = @_;
+
+ # Get the borrower or return an error code
+ my $borrowernumber = $cgi->param('patron_id');
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ return { code => 'PatronNotFound' } unless $patron;
+
+ # Get the biblio or return an error code
+ my $biblionumber = $cgi->param('bib_id');
+ my $biblio = Koha::Biblios->find( $biblionumber );
+ return { code => 'RecordNotFound' } unless $biblio;
+
+ my $title = $biblio ? $biblio->title : '';
+
+ # Get the item or return an error code
+ my $itemnumber = $cgi->param('item_id');
+ my $item = Koha::Items->find($itemnumber);
+ return { code => 'RecordNotFound' } unless $item;
+
+ # If the biblio does not match the item, return an error code
+ return { code => 'RecordNotFound' } if $item->biblionumber ne $biblio->biblionumber;
+
+ # Pickup branch management
+ my $branch;
+ if ( $cgi->param('pickup_location') ) {
+ $branch = $cgi->param('pickup_location');
+ return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
+ } else { # if the request provide no branch, use the borrower's branch
+ $branch = $patron->branchcode;
+ }
+
+ # Check for item disponibility
+ my $canitembereserved = C4::Reserves::CanItemBeReserved( $borrowernumber, $itemnumber, $branch )->{status};
+ return { code => $canitembereserved } unless $canitembereserved eq 'OK';
+
+ # Add the reserve
+ # $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;
+ my $library = Koha::Libraries->find( $branch );
+ $out->{'pickup_location'} = $library ? $library->branchname : '';
+
+ # TODO $out->{'date_available'} = '';
+
+ return $out;
}
=head2 CancelHold
- Cancels an active reserve request for the borrower.
-
- Parameters:
+Cancels an active reserve request for the borrower.
+
+Parameters:
- - patron_id (Required)
- a borrowernumber
- - item_id (Required)
- an itemnumber
+ - patron_id (Required)
+ a borrowernumber
+ - item_id (Required)
+ a reserve_id
=cut
sub CancelHold {
- my ( $cgi ) = @_;
-
- # Get the borrower or return an error code
- my $borrowernumber = $cgi->param('patron_id');
- my $borrower = GetMemberDetails($borrowernumber, undef);
- if ( not $borrower->{'borrowernumber'} ) {
- $out->{'message'} = "PatronNotFound";
- return $out;
- }
-
- # Get the item or return an error code
- my $itemnumber = $cgi->param('item_id');
- my $item = GetItem($itemnumber, undef, undef);
- if ( not $item->{'itemnumber'} ) {
- $out->{'message'} = "RecordNotFound";
- return $out;
- }
-
- # Get borrower's reserves
- my @reserves = GetReservesFromBorrowernumber($borrowernumber, undef);
- my @reserveditems;
- # ...and loop over it to build an array of reserved itemnumbers
- foreach my $reserve (@reserves) {
- push @reserveditems, $reserve->{'itemnumber'};
- }
- # if the item was not reserved by the borrower, returns an error code
- if ( not grep {$itemnumber eq $_} @reserveditems) {
- $out->{'message'} = "NotCanceled";
- return $out;
- }
-
- # Cancel the reserve
- CancelReserve($itemnumber, undef, $borrowernumber);
-
- $out->{'message'} = "Canceled";
-
- return $out;
+ my ($cgi) = @_;
+
+ # Get the borrower or return an error code
+ my $borrowernumber = $cgi->param('patron_id');
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ return { code => 'PatronNotFound' } unless $patron;
+
+ # Get the reserve or return an error code
+ my $reserve_id = $cgi->param('item_id');
+ my $hold = Koha::Holds->find( $reserve_id );
+ return { code => 'RecordNotFound' } unless $hold;
+ return { code => 'RecordNotFound' } unless ($hold->borrowernumber == $borrowernumber);
+
+ $hold->cancel;
+
+ return { code => 'Canceled' };
+}
+
+=head2 _availability
+
+Returns, for an itemnumber, an array containing availability information.
+
+ my ($biblionumber, $status, $msg, $location) = _availability($id);
+
+=cut
+
+sub _availability {
+ my ($itemnumber) = @_;
+ my $item = Koha::Items->find($itemnumber);
+
+ unless ( $item ) {
+ 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;