1 package C4::ILSDI::Services;
3 # Copyright 2009 SARL Biblibre
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
24 use C4::Items qw( get_hostitemnumbers_of );
25 use C4::Circulation qw( CanBookBeRenewed barcodedecode CanBookBeIssued AddRenewal );
27 use C4::Biblio qw( GetMarcBiblio );
28 use C4::Reserves qw( CanBookBeReserved IsAvailableForItemLevelRequest CalculatePriority AddReserve CanItemBeReserved );
34 use Koha::DateUtils qw( dt_from_string );
44 C4::ILS-DI::Services - ILS-DI Services
48 Each function in this module represents an ILS-DI service.
49 They all takes a CGI instance as argument and most of them return a
50 hashref that will be printed by XML::Simple in opac/ilsdi.pl
54 use C4::ILSDI::Services;
60 $out = LookupPatron($cgi);
62 print CGI::header('text/xml');
67 xmldecl => '<?xml version="1.0" encoding="UTF-8" ?>',
68 RootName => 'LookupPatron',
75 =head2 GetAvailability
77 Given a set of biblionumbers or itemnumbers, returns a list with
78 availability of the items associated with the identifiers.
84 list of either biblionumbers or itemnumbers
86 =head3 id_type (Required)
88 defines the type of record identifier being used in the request,
94 =head3 return_type (Optional)
96 requests a particular level of detail in reporting availability,
102 =head3 return_fmt (Optional)
104 requests a particular format or set of formats in reporting
109 sub GetAvailability {
112 my $out = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
113 $out .= "<dlf:collection\n";
114 $out .= " xmlns:dlf=\"http://diglib.org/ilsdi/1.1\"\n";
115 $out .= " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
116 $out .= " xsi:schemaLocation=\"http://diglib.org/ilsdi/1.1\n";
117 $out .= " http://diglib.org/architectures/ilsdi/schemas/1.1/dlfexpanded.xsd\">\n";
119 foreach my $id ( split( / /, $cgi->param('id') ) ) {
120 if ( $cgi->param('id_type') eq "item" ) {
121 my ( $biblionumber, $status, $msg, $location ) = _availability($id);
123 $out .= " <dlf:record>\n";
124 $out .= " <dlf:bibliographic id=\"" . ( $biblionumber || $id ) . "\" />\n";
125 $out .= " <dlf:items>\n";
126 $out .= " <dlf:item id=\"" . $id . "\">\n";
127 $out .= " <dlf:simpleavailability>\n";
128 $out .= " <dlf:identifier>" . $id . "</dlf:identifier>\n";
129 $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
130 if ($msg) { $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n"; }
131 if ($location) { $out .= " <dlf:location>" . $location . "</dlf:location>\n"; }
132 $out .= " </dlf:simpleavailability>\n";
133 $out .= " </dlf:item>\n";
134 $out .= " </dlf:items>\n";
135 $out .= " </dlf:record>\n";
139 my $items = Koha::Items->search({ biblionumber => $id });
142 $out .= " <dlf:record>\n";
143 $out .= " <dlf:bibliographic id=\"" .$id. "\" />\n";
144 $out .= " <dlf:items>\n";
145 # We loop over the items to clean them
146 while ( my $item = $items->next ) {
147 my $itemnumber = $item->itemnumber;
148 my ( $biblionumber, $status, $msg, $location ) = _availability($itemnumber);
149 $out .= " <dlf:item id=\"" . $itemnumber . "\">\n";
150 $out .= " <dlf:simpleavailability>\n";
151 $out .= " <dlf:identifier>" . $itemnumber . "</dlf:identifier>\n";
152 $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
153 if ($msg) { $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n"; }
154 if ($location) { $out .= " <dlf:location>" . $location . "</dlf:location>\n"; }
155 $out .= " </dlf:simpleavailability>\n";
156 $out .= " </dlf:item>\n";
159 $out .= " </dlf:items>\n";
160 $out .= " </dlf:record>\n";
163 $msg = "Error: could not retrieve availability for this ID";
167 $out .= "</dlf:collection>\n";
174 Given a list of biblionumbers, returns a list of record objects that
175 contain bibliographic information, as well as associated holdings and item
176 information. The caller may request a specific metadata schema for the
177 record objects to be returned.
179 This function behaves similarly to HarvestBibliographicRecords and
180 HarvestExpandedRecords in Data Aggregation, but allows quick, real time
181 lookup by bibliographic identifier.
183 You can use OAI-PMH ListRecords instead of this service.
188 list of system record identifiers
190 Defines the metadata schema in which the records are returned,
199 # Check if the schema is supported. For now, GetRecords only supports MARCXML
200 if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
201 return { code => 'UnsupportedSchema' };
206 # Loop over biblionumbers
207 foreach my $biblionumber ( split( / /, $cgi->param('id') ) ) {
209 # Get the biblioitem from the biblionumber
210 my $biblio = Koha::Biblios->find( $biblionumber );
212 push @records, { code => "RecordNotFound" };
216 my $biblioitem = $biblio->biblioitem->unblessed;
219 my $record = GetMarcBiblio({
220 biblionumber => $biblionumber,
221 embed_items => $embed_items });
223 $biblioitem->{marcxml} = $record->as_xml_record();
226 # Get most of the needed data
227 my $biblioitemnumber = $biblioitem->{'biblioitemnumber'};
228 my $checkouts = Koha::Checkouts->search(
229 { biblionumber => $biblionumber },
232 '+select' => ['item.barcode'],
233 '+as' => ['barcode'],
236 foreach my $checkout (@$checkouts) {
237 delete $checkout->{'borrowernumber'};
239 my @items = $biblio->items->as_list;
241 $biblioitem->{items}->{item} = [];
243 # We loop over the items to clean them
244 foreach my $item (@items) {
245 my %item = %{ $item->unblessed };
247 # This hides additionnal XML subfields, we don't need these info
248 delete $item{'more_subfields_xml'};
250 # Display branch names instead of branch codes
251 my $home_library = $item->home_branch;
252 my $holding_library = $item->holding_branch;
253 $item{'homebranchname'} = $home_library ? $home_library->branchname : '';
254 $item{'holdingbranchname'} = $holding_library ? $holding_library->branchname : '';
256 if ($item->location) {
257 my $authorised_value = Koha::AuthorisedValues->find_by_koha_field({ kohafield => 'items.location', authorised_value => $item->location });
258 if ($authorised_value) {
259 $item{location_description} = $authorised_value->opac_description;
264 my $itemtype = Koha::ItemTypes->find($item->itype);
266 $item{itype_description} = $itemtype->description;
270 my $transfer = $item->get_transfer;
273 datesent => $transfer->datesent,
274 frombranch => $transfer->frombranch,
275 tobranch => $transfer->tobranch,
279 push @{ $biblioitem->{items}->{item} }, \%item;
283 my $holds = $biblio->current_holds->unblessed;
284 foreach my $hold (@$holds) {
285 delete $hold->{'borrowernumber'};
288 # Hashref building...
289 $biblioitem->{'reserves'}->{'reserve'} = $holds;
290 $biblioitem->{'issues'}->{'issue'} = $checkouts;
292 push @records, $biblioitem;
295 return { record => \@records };
298 =head2 GetAuthorityRecords
300 Given a list of authority record identifiers, returns a list of record
301 objects that contain the authority records. The function user may request
302 a specific metadata schema for the record objects.
307 list of authority record identifiers
309 specifies the metadata schema of records to be returned, possible values:
314 sub GetAuthorityRecords {
317 # If the user asks for an unsupported schema, return an error code
318 if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
319 return { code => 'UnsupportedSchema' };
324 # Let's loop over the authority IDs
325 foreach my $authid ( split( / /, $cgi->param('id') ) ) {
327 # Get the record as XML string, or error code
328 push @records, GetAuthorityXML($authid) || { code => 'RecordNotFound' };
331 return { record => \@records };
336 Looks up a patron in the ILS by an identifier, and returns the borrowernumber.
341 an identifier used to look up the patron in Koha
343 the type of the identifier, possible values:
356 my $id = $cgi->param('id');
358 return { message => 'PatronNotFound' };
362 my $passed_id_type = $cgi->param('id_type');
363 if($passed_id_type) {
364 $patrons = Koha::Patrons->search( { $passed_id_type => $id } );
366 foreach my $id_type ('cardnumber', 'userid', 'email', 'borrowernumber',
367 'surname', 'firstname') {
368 $patrons = Koha::Patrons->search( { $id_type => $id } );
369 last if($patrons->count);
372 unless ( $patrons->count ) {
373 return { message => 'PatronNotFound' };
376 return { id => $patrons->next->borrowernumber };
379 =head2 AuthenticatePatron
381 Authenticates a user's login credentials and returns the identifier for
386 - username (Required)
387 user's login identifier (userid or cardnumber)
388 - password (Required)
393 sub AuthenticatePatron {
395 my $username = $cgi->param('username');
396 my $password = $cgi->param('password');
397 my ($status, $cardnumber, $userid) = C4::Auth::checkpw( C4::Context->dbh, $username, $password );
400 my $patron = Koha::Patrons->find( { userid => $userid } );
401 return { id => $patron->borrowernumber };
404 return { code => 'PatronNotFound' };
410 Returns specified information about the patron, based on options in the
411 request. This function can optionally return patron's contact information,
412 fine information, hold request information, and loan information.
416 - patron_id (Required)
418 - show_contact (Optional, default 1)
419 whether or not to return patron's contact information in the response
420 - show_fines (Optional, default 0)
421 whether or not to return fine information in the response
422 - show_holds (Optional, default 0)
423 whether or not to return hold request information in the response
424 - show_loans (Optional, default 0)
425 whether or not to return loan information request information in the response
426 - show_attributes (Optional, default 0)
427 whether or not to return additional patron attributes, when enabled the attributes
428 are limited to those marked as opac visible only.
436 my $borrowernumber = $cgi->param('patron_id');
437 my $patron = Koha::Patrons->find( $borrowernumber );
438 return { code => 'PatronNotFound' } unless $patron;
440 # Cleaning the borrower hashref
441 my $borrower = $patron->unblessed;
442 $borrower->{charges} = sprintf "%.02f", $patron->account->non_issues_charges; # FIXME Formatting should not be done here
443 my $library = Koha::Libraries->find( $borrower->{branchcode} );
444 $borrower->{'branchname'} = $library ? $library->branchname : '';
445 delete $borrower->{'userid'};
446 delete $borrower->{'password'};
448 # Contact fields management
449 if ( defined $cgi->param('show_contact') && $cgi->param('show_contact') eq "0" ) {
451 # Define contact fields
452 my @contactfields = (
453 'email', 'emailpro', 'fax', 'mobile', 'phone', 'phonepro',
454 'streetnumber', 'zipcode', 'city', 'streettype', 'B_address', 'B_city',
455 'B_email', 'B_phone', 'B_zipcode', 'address', 'address2', 'altcontactaddress1',
456 'altcontactaddress2', 'altcontactaddress3', 'altcontactfirstname', 'altcontactphone', 'altcontactsurname', 'altcontactzipcode'
460 foreach my $field (@contactfields) {
461 delete $borrower->{$field};
466 if ( $cgi->param('show_fines') && $cgi->param('show_fines') eq "1" ) {
467 $borrower->{fines}{fine} = $patron->account->lines->unblessed;
470 # Reserves management
471 if ( $cgi->param('show_holds') && $cgi->param('show_holds') eq "1" ) {
473 # Get borrower's reserves
474 my $holds = $patron->holds;
475 while ( my $hold = $holds->next ) {
477 my ( $item, $biblio, $biblioitem ) = ( {}, {}, {} );
478 # Get additional informations
479 if ( $hold->itemnumber ) { # item level holds
480 $item = Koha::Items->find( $hold->itemnumber );
481 $biblio = $item->biblio;
482 $biblioitem = $biblio->biblioitem;
484 # Remove unwanted fields
485 $item = $item->unblessed;
486 delete $item->{more_subfields_xml};
487 $biblio = $biblio->unblessed;
488 $biblioitem = $biblioitem->unblessed;
491 # Add additional fields
492 my $unblessed_hold = $hold->unblessed;
493 $unblessed_hold->{item} = { %$item, %$biblio, %$biblioitem };
494 my $library = Koha::Libraries->find( $hold->branchcode );
495 my $branchname = $library ? $library->branchname : '';
496 $unblessed_hold->{branchname} = $branchname;
497 $biblio = Koha::Biblios->find( $hold->biblionumber ); # Should be $hold->get_biblio
498 $unblessed_hold->{title} = $biblio ? $biblio->title : ''; # Just in case, but should not be needed
500 push @{ $borrower->{holds}{hold} }, $unblessed_hold;
506 if ( $cgi->param('show_loans') && $cgi->param('show_loans') eq "1" ) {
507 my $per_page = $cgi->param('loans_per_page');
508 my $page = $cgi->param('loans_page');
510 my $pending_checkouts = $patron->pending_checkouts;
512 if ($page || $per_page) {
515 $borrower->{total_loans} = $pending_checkouts->count();
516 $pending_checkouts = $pending_checkouts->search(undef, {
523 while ( my $c = $pending_checkouts->next ) {
524 # FIXME We should only retrieve what is needed in the template
525 my $issue = $c->unblessed_all_relateds;
526 delete $issue->{'more_subfields_xml'};
527 push @checkouts, $issue
529 $borrower->{'loans'}->{'loan'} = \@checkouts;
532 my $show_attributes = $cgi->param('show_attributes');
533 if ( $show_attributes && $show_attributes eq "1" ) {
534 # FIXME Regression expected here, we do not retrieve the same field as previously
535 # Waiting for answer on bug 14257 comment 15
536 $borrower->{'attributes'} = [
538 $_->type->opac_display
541 %{ $_->type->unblessed },
542 value => $_->attribute, # Backward compatibility
543 value_description => $_->description, # Awkward retro-compability...
546 } $patron->extended_attributes->search
550 # Add is expired information
551 $borrower->{'is_expired'} = $patron->is_expired ? 1 : 0;
556 =head2 GetPatronStatus
558 Returns a patron's status information.
562 - patron_id (Required)
567 sub GetPatronStatus {
571 my $borrowernumber = $cgi->param('patron_id');
572 my $patron = Koha::Patrons->find( $borrowernumber );
573 return { code => 'PatronNotFound' } unless $patron;
577 type => $patron->categorycode,
579 expiry => $patron->dateexpiry,
585 Returns information about the services available on a particular item for
590 - patron_id (Required)
600 # Get the member, or return an error code if not found
601 my $borrowernumber = $cgi->param('patron_id');
602 my $patron = Koha::Patrons->find( $borrowernumber );
603 return { code => 'PatronNotFound' } unless $patron;
605 my $borrower = $patron->unblessed;
606 # Get the item, or return an error code if not found
607 my $itemnumber = $cgi->param('item_id');
608 my $item = Koha::Items->find($itemnumber);
609 return { code => 'RecordNotFound' } unless $item;
613 # Reserve level management
614 my $biblionumber = $item->biblionumber;
615 my $canbookbereserved = CanBookBeReserved( $borrower, $biblionumber );
616 if ($canbookbereserved->{status} eq 'OK') {
617 push @availablefor, 'title level hold';
618 my $canitembereserved = IsAvailableForItemLevelRequest($item, $patron);
619 if ($canitembereserved) {
620 push @availablefor, 'item level hold';
624 # Reserve cancellation management
625 my $holds = $patron->holds;
627 while ( my $hold = $holds->next ) { # FIXME This could be improved
628 push @reserveditems, $hold->itemnumber;
630 if ( grep { $itemnumber eq $_ } @reserveditems ) {
631 push @availablefor, 'hold cancellation';
635 my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
637 push @availablefor, 'loan renewal';
641 my $barcode = $item->barcode || '';
642 $barcode = barcodedecode($barcode) if ( $barcode && C4::Context->preference('itemBarcodeInputFilter') );
644 my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $patron, $barcode );
646 # TODO push @availablefor, 'loan';
650 $out->{'AvailableFor'} = \@availablefor;
657 Extends the due date for a borrower's existing issue.
661 - patron_id (Required)
665 - desired_due_date (Required)
666 the date the patron would like the item returned by
673 # Get borrower infos or return an error code
674 my $borrowernumber = $cgi->param('patron_id');
675 my $patron = Koha::Patrons->find( $borrowernumber );
676 return { code => 'PatronNotFound' } unless $patron;
678 # Get the item, or return an error code
679 my $itemnumber = $cgi->param('item_id');
680 my $item = Koha::Items->find($itemnumber);
681 return { code => 'RecordNotFound' } unless $item;
683 # Add renewal if possible
684 my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
685 if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber, undef, undef, undef, undef, 0 ); }
687 my $issue = $item->checkout;
688 return unless $issue; # FIXME should be handled
692 $out->{'renewals'} = $issue->renewals;
693 $out->{date_due} = dt_from_string($issue->date_due)->strftime('%Y-%m-%d %H:%M');
694 $out->{'success'} = $renewal[0];
695 $out->{'error'} = $renewal[1];
702 Creates, for a borrower, a biblio-level hold reserve.
706 - patron_id (Required)
710 - request_location (Required)
711 IP address where the end user request is being placed
712 - pickup_location (Optional)
713 a branch code indicating the location to which to deliver the item for pickup
714 - start_date (Optional)
715 date after which hold request is no longer needed if the document has not been made available
716 - expiry_date (Optional)
717 date after which item returned to shelf if item is not picked up
724 # Get the borrower or return an error code
725 my $borrowernumber = $cgi->param('patron_id');
726 my $patron = Koha::Patrons->find( $borrowernumber );
727 return { code => 'PatronNotFound' } unless $patron;
730 # If borrower is restricted return an error code
731 return { code => 'PatronRestricted' } if $patron->is_debarred;
733 # Check for patron expired, category and syspref settings
734 return { code => 'PatronExpired' } if ($patron->category->effective_BlockExpiredPatronOpacActions && $patron->is_expired);
736 # Get the biblio record, or return an error code
737 my $biblionumber = $cgi->param('bib_id');
738 my $biblio = Koha::Biblios->find( $biblionumber );
739 return { code => 'RecordNotFound' } unless $biblio;
741 my @hostitems = get_hostitemnumbers_of($biblionumber);
744 push(@itemnumbers, @hostitems);
747 my $items = Koha::Items->search({ -or => { biblionumber => $biblionumber, itemnumber => { in => \@itemnumbers } } });
749 unless ( $items->count ) {
750 return { code => 'NoItems' };
753 my $title = $biblio ? $biblio->title : '';
755 # Check if the biblio can be reserved
756 my $code = CanBookBeReserved( $borrowernumber, $biblionumber )->{status};
757 return { code => $code } unless ( $code eq 'OK' );
761 # Pickup branch management
762 if ( $cgi->param('pickup_location') ) {
763 $branch = $cgi->param('pickup_location');
764 return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
765 } else { # if the request provide no branch, use the borrower's branch
766 $branch = $patron->branchcode;
769 my $destination = Koha::Libraries->find($branch);
770 return { code => 'libraryNotPickupLocation' } unless $destination->pickup_location;
771 return { code => 'cannotBeTransferred' } unless $biblio->can_be_transferred({ to => $destination });
774 if ( $cgi->param('start_date') ) {
775 $resdate = $cgi->param('start_date');
779 if ( $cgi->param('expiry_date') ) {
780 $expdate = $cgi->param('expiry_date');
784 # $branch, $borrowernumber, $biblionumber,
785 # $constraint, $bibitems, $priority, $resdate, $expdate, $notes,
786 # $title, $checkitem, $found
787 my $priority= C4::Reserves::CalculatePriority( $biblionumber );
790 branchcode => $branch,
791 borrowernumber => $borrowernumber,
792 biblionumber => $biblionumber,
793 priority => $priority,
794 reservation_date => $resdate,
795 expiration_date => $expdate,
802 $out->{'title'} = $title;
803 my $library = Koha::Libraries->find( $branch );
804 $out->{'pickup_location'} = $library ? $library->branchname : '';
806 # TODO $out->{'date_available'} = '';
813 Creates, for a borrower, an item-level hold request on a specific item of
814 a bibliographic record in Koha.
818 - patron_id (Required)
824 - pickup_location (Optional)
825 a branch code indicating the location to which to deliver the item for pickup
826 - start_date (Optional)
827 date after which hold request is no longer needed if the item has not been made available
828 - expiry_date (Optional)
829 date after which item returned to shelf if item is not picked up
836 # Get the borrower or return an error code
837 my $borrowernumber = $cgi->param('patron_id');
838 my $patron = Koha::Patrons->find( $borrowernumber );
839 return { code => 'PatronNotFound' } unless $patron;
841 # If borrower is restricted return an error code
842 return { code => 'PatronRestricted' } if $patron->is_debarred;
844 # Check for patron expired, category and syspref settings
845 return { code => 'PatronExpired' } if ($patron->category->effective_BlockExpiredPatronOpacActions && $patron->is_expired);
847 # Get the biblio or return an error code
848 my $biblionumber = $cgi->param('bib_id');
849 my $biblio = Koha::Biblios->find( $biblionumber );
850 return { code => 'RecordNotFound' } unless $biblio;
852 my $title = $biblio ? $biblio->title : '';
854 # Get the item or return an error code
855 my $itemnumber = $cgi->param('item_id');
856 my $item = Koha::Items->find($itemnumber);
857 return { code => 'RecordNotFound' } unless $item;
859 # If the biblio does not match the item, return an error code
860 return { code => 'RecordNotFound' } if $item->biblionumber ne $biblio->biblionumber;
862 # Pickup branch management
864 if ( $cgi->param('pickup_location') ) {
865 $branch = $cgi->param('pickup_location');
866 return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
867 } else { # if the request provide no branch, use the borrower's branch
868 $branch = $patron->branchcode;
871 # Check for item disponibility
872 my $canitembereserved = C4::Reserves::CanItemBeReserved( $borrowernumber, $itemnumber, $branch )->{status};
873 return { code => $canitembereserved } unless $canitembereserved eq 'OK';
876 if ( $cgi->param('start_date') ) {
877 $resdate = $cgi->param('start_date');
881 if ( $cgi->param('expiry_date') ) {
882 $expdate = $cgi->param('expiry_date');
886 my $priority = C4::Reserves::CalculatePriority($biblionumber);
889 branchcode => $branch,
890 borrowernumber => $borrowernumber,
891 biblionumber => $biblionumber,
892 priority => $priority,
893 reservation_date => $resdate,
894 expiration_date => $expdate,
896 itemnumber => $itemnumber,
902 my $library = Koha::Libraries->find( $branch );
903 $out->{'pickup_location'} = $library ? $library->branchname : '';
905 # TODO $out->{'date_available'} = '';
912 Cancels an active reserve request for the borrower.
916 - patron_id (Required)
926 # Get the borrower or return an error code
927 my $borrowernumber = $cgi->param('patron_id');
928 my $patron = Koha::Patrons->find( $borrowernumber );
929 return { code => 'PatronNotFound' } unless $patron;
931 # Get the reserve or return an error code
932 my $reserve_id = $cgi->param('item_id');
933 my $hold = Koha::Holds->find( $reserve_id );
934 return { code => 'RecordNotFound' } unless $hold;
935 return { code => 'RecordNotFound' } unless ($hold->borrowernumber == $borrowernumber);
939 return { code => 'Canceled' };
944 Returns, for an itemnumber, an array containing availability information.
946 my ($biblionumber, $status, $msg, $location) = _availability($id);
951 my ($itemnumber) = @_;
952 my $item = Koha::Items->find($itemnumber);
955 return ( undef, 'unknown', 'Error: could not retrieve availability for this ID', undef );
958 my $biblionumber = $item->biblioitemnumber;
959 my $library = Koha::Libraries->find( $item->holdingbranch );
960 my $location = $library ? $library->branchname : '';
962 if ( $item->notforloan ) {
963 return ( $biblionumber, 'not available', 'Not for loan', $location );
964 } elsif ( $item->onloan ) {
965 return ( $biblionumber, 'not available', 'Checked out', $location );
966 } elsif ( $item->itemlost ) {
967 return ( $biblionumber, 'not available', 'Item lost', $location );
968 } elsif ( $item->withdrawn ) {
969 return ( $biblionumber, 'not available', 'Item withdrawn', $location );
970 } elsif ( $item->damaged ) {
971 return ( $biblionumber, 'not available', 'Item damaged', $location );
973 return ( $biblionumber, 'available', undef, $location );