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 );
35 use C4::AuthoritiesMarc qw( GetAuthorityXML );
45 C4::ILS-DI::Services - ILS-DI Services
49 Each function in this module represents an ILS-DI service.
50 They all takes a CGI instance as argument and most of them return a
51 hashref that will be printed by XML::Simple in opac/ilsdi.pl
55 use C4::ILSDI::Services;
61 $out = LookupPatron($cgi);
63 print CGI::header('text/xml');
68 xmldecl => '<?xml version="1.0" encoding="UTF-8" ?>',
69 RootName => 'LookupPatron',
76 =head2 GetAvailability
78 Given a set of biblionumbers or itemnumbers, returns a list with
79 availability of the items associated with the identifiers.
85 list of either biblionumbers or itemnumbers
87 =head3 id_type (Required)
89 defines the type of record identifier being used in the request,
95 =head3 return_type (Optional)
97 requests a particular level of detail in reporting availability,
103 =head3 return_fmt (Optional)
105 requests a particular format or set of formats in reporting
110 sub GetAvailability {
113 my $out = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
114 $out .= "<dlf:collection\n";
115 $out .= " xmlns:dlf=\"http://diglib.org/ilsdi/1.1\"\n";
116 $out .= " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
117 $out .= " xsi:schemaLocation=\"http://diglib.org/ilsdi/1.1\n";
118 $out .= " http://diglib.org/architectures/ilsdi/schemas/1.1/dlfexpanded.xsd\">\n";
120 foreach my $id ( split( / /, $cgi->param('id') ) ) {
121 if ( $cgi->param('id_type') eq "item" ) {
122 my ( $biblionumber, $status, $msg, $location ) = _availability($id);
124 $out .= " <dlf:record>\n";
125 $out .= " <dlf:bibliographic id=\"" . ( $biblionumber || $id ) . "\" />\n";
126 $out .= " <dlf:items>\n";
127 $out .= " <dlf:item id=\"" . $id . "\">\n";
128 $out .= " <dlf:simpleavailability>\n";
129 $out .= " <dlf:identifier>" . $id . "</dlf:identifier>\n";
130 $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
131 if ($msg) { $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n"; }
132 if ($location) { $out .= " <dlf:location>" . $location . "</dlf:location>\n"; }
133 $out .= " </dlf:simpleavailability>\n";
134 $out .= " </dlf:item>\n";
135 $out .= " </dlf:items>\n";
136 $out .= " </dlf:record>\n";
140 my $items = Koha::Items->search({ biblionumber => $id });
143 $out .= " <dlf:record>\n";
144 $out .= " <dlf:bibliographic id=\"" .$id. "\" />\n";
145 $out .= " <dlf:items>\n";
146 # We loop over the items to clean them
147 while ( my $item = $items->next ) {
148 my $itemnumber = $item->itemnumber;
149 my ( $biblionumber, $status, $msg, $location ) = _availability($itemnumber);
150 $out .= " <dlf:item id=\"" . $itemnumber . "\">\n";
151 $out .= " <dlf:simpleavailability>\n";
152 $out .= " <dlf:identifier>" . $itemnumber . "</dlf:identifier>\n";
153 $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
154 if ($msg) { $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n"; }
155 if ($location) { $out .= " <dlf:location>" . $location . "</dlf:location>\n"; }
156 $out .= " </dlf:simpleavailability>\n";
157 $out .= " </dlf:item>\n";
160 $out .= " </dlf:items>\n";
161 $out .= " </dlf:record>\n";
164 $msg = "Error: could not retrieve availability for this ID";
168 $out .= "</dlf:collection>\n";
175 Given a list of biblionumbers, returns a list of record objects that
176 contain bibliographic information, as well as associated holdings and item
177 information. The caller may request a specific metadata schema for the
178 record objects to be returned.
180 This function behaves similarly to HarvestBibliographicRecords and
181 HarvestExpandedRecords in Data Aggregation, but allows quick, real time
182 lookup by bibliographic identifier.
184 You can use OAI-PMH ListRecords instead of this service.
189 list of system record identifiers
191 Defines the metadata schema in which the records are returned,
200 # Check if the schema is supported. For now, GetRecords only supports MARCXML
201 if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
202 return { code => 'UnsupportedSchema' };
207 # Loop over biblionumbers
208 foreach my $biblionumber ( split( / /, $cgi->param('id') ) ) {
210 # Get the biblioitem from the biblionumber
211 my $biblio = Koha::Biblios->find( $biblionumber );
213 push @records, { code => "RecordNotFound" };
217 my $biblioitem = $biblio->biblioitem->unblessed;
220 my $record = GetMarcBiblio({
221 biblionumber => $biblionumber,
222 embed_items => $embed_items });
224 $biblioitem->{marcxml} = $record->as_xml_record();
227 # Get most of the needed data
228 my $biblioitemnumber = $biblioitem->{'biblioitemnumber'};
229 my $checkouts = Koha::Checkouts->search(
230 { biblionumber => $biblionumber },
233 '+select' => ['item.barcode'],
234 '+as' => ['barcode'],
237 foreach my $checkout (@$checkouts) {
238 delete $checkout->{'borrowernumber'};
240 my @items = $biblio->items->as_list;
242 $biblioitem->{items}->{item} = [];
244 # We loop over the items to clean them
245 foreach my $item (@items) {
246 my %item = %{ $item->unblessed };
248 # This hides additionnal XML subfields, we don't need these info
249 delete $item{'more_subfields_xml'};
251 # Display branch names instead of branch codes
252 my $home_library = $item->home_branch;
253 my $holding_library = $item->holding_branch;
254 $item{'homebranchname'} = $home_library ? $home_library->branchname : '';
255 $item{'holdingbranchname'} = $holding_library ? $holding_library->branchname : '';
257 if ($item->location) {
258 my $authorised_value = Koha::AuthorisedValues->find_by_koha_field({ kohafield => 'items.location', authorised_value => $item->location });
259 if ($authorised_value) {
260 $item{location_description} = $authorised_value->opac_description;
265 my $itemtype = Koha::ItemTypes->find($item->itype);
267 $item{itype_description} = $itemtype->description;
271 my $transfer = $item->get_transfer;
274 datesent => $transfer->datesent,
275 frombranch => $transfer->frombranch,
276 tobranch => $transfer->tobranch,
280 push @{ $biblioitem->{items}->{item} }, \%item;
284 my $holds = $biblio->current_holds->unblessed;
285 foreach my $hold (@$holds) {
286 delete $hold->{'borrowernumber'};
289 # Hashref building...
290 $biblioitem->{'reserves'}->{'reserve'} = $holds;
291 $biblioitem->{'issues'}->{'issue'} = $checkouts;
293 push @records, $biblioitem;
296 return { record => \@records };
299 =head2 GetAuthorityRecords
301 Given a list of authority record identifiers, returns a list of record
302 objects that contain the authority records. The function user may request
303 a specific metadata schema for the record objects.
308 list of authority record identifiers
310 specifies the metadata schema of records to be returned, possible values:
315 sub GetAuthorityRecords {
318 # If the user asks for an unsupported schema, return an error code
319 if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
320 return { code => 'UnsupportedSchema' };
325 # Let's loop over the authority IDs
326 foreach my $authid ( split( / /, $cgi->param('id') ) ) {
328 # Get the record as XML string, or error code
329 push @records, GetAuthorityXML($authid) || { code => 'RecordNotFound' };
332 return { record => \@records };
337 Looks up a patron in the ILS by an identifier, and returns the borrowernumber.
342 an identifier used to look up the patron in Koha
344 the type of the identifier, possible values:
357 my $id = $cgi->param('id');
359 return { message => 'PatronNotFound' };
363 my $passed_id_type = $cgi->param('id_type');
364 if($passed_id_type) {
365 $patrons = Koha::Patrons->search( { $passed_id_type => $id } );
367 foreach my $id_type ('cardnumber', 'userid', 'email', 'borrowernumber',
368 'surname', 'firstname') {
369 $patrons = Koha::Patrons->search( { $id_type => $id } );
370 last if($patrons->count);
373 unless ( $patrons->count ) {
374 return { message => 'PatronNotFound' };
377 return { id => $patrons->next->borrowernumber };
380 =head2 AuthenticatePatron
382 Authenticates a user's login credentials and returns the identifier for
387 - username (Required)
388 user's login identifier (userid or cardnumber)
389 - password (Required)
394 sub AuthenticatePatron {
396 my $username = $cgi->param('username');
397 my $password = $cgi->param('password');
398 my ($status, $cardnumber, $userid) = C4::Auth::checkpw( C4::Context->dbh, $username, $password );
401 C4::Auth::track_login_daily( $userid );
403 my $patron = Koha::Patrons->find( { userid => $userid } );
404 return { id => $patron->borrowernumber };
407 return { code => 'PatronNotFound' };
413 Returns specified information about the patron, based on options in the
414 request. This function can optionally return patron's contact information,
415 fine information, hold request information, and loan information.
419 - patron_id (Required)
421 - show_contact (Optional, default 1)
422 whether or not to return patron's contact information in the response
423 - show_fines (Optional, default 0)
424 whether or not to return fine information in the response
425 - show_holds (Optional, default 0)
426 whether or not to return hold request information in the response
427 - show_loans (Optional, default 0)
428 whether or not to return loan information request information in the response
429 - show_attributes (Optional, default 0)
430 whether or not to return additional patron attributes, when enabled the attributes
431 are limited to those marked as opac visible only.
439 my $borrowernumber = $cgi->param('patron_id');
440 my $patron = Koha::Patrons->find( $borrowernumber );
441 return { code => 'PatronNotFound' } unless $patron;
443 # Cleaning the borrower hashref
444 my $borrower = $patron->unblessed;
445 $borrower->{charges} = sprintf "%.02f", $patron->account->non_issues_charges; # FIXME Formatting should not be done here
446 my $library = Koha::Libraries->find( $borrower->{branchcode} );
447 $borrower->{'branchname'} = $library ? $library->branchname : '';
448 delete $borrower->{'userid'};
449 delete $borrower->{'password'};
451 # Contact fields management
452 if ( defined $cgi->param('show_contact') && $cgi->param('show_contact') eq "0" ) {
454 # Define contact fields
455 my @contactfields = (
456 'email', 'emailpro', 'fax', 'mobile', 'phone', 'phonepro',
457 'streetnumber', 'zipcode', 'city', 'streettype', 'B_address', 'B_city',
458 'B_email', 'B_phone', 'B_zipcode', 'address', 'address2', 'altcontactaddress1',
459 'altcontactaddress2', 'altcontactaddress3', 'altcontactfirstname', 'altcontactphone', 'altcontactsurname', 'altcontactzipcode'
463 foreach my $field (@contactfields) {
464 delete $borrower->{$field};
469 if ( $cgi->param('show_fines') && $cgi->param('show_fines') eq "1" ) {
470 $borrower->{fines}{fine} = $patron->account->lines->unblessed;
473 # Reserves management
474 if ( $cgi->param('show_holds') && $cgi->param('show_holds') eq "1" ) {
476 # Get borrower's reserves
477 my $holds = $patron->holds;
478 while ( my $hold = $holds->next ) {
480 my ( $item, $biblio, $biblioitem ) = ( {}, {}, {} );
481 # Get additional informations
482 if ( $hold->itemnumber ) { # item level holds
483 $item = Koha::Items->find( $hold->itemnumber );
484 $biblio = $item->biblio;
485 $biblioitem = $biblio->biblioitem;
487 # Remove unwanted fields
488 $item = $item->unblessed;
489 delete $item->{more_subfields_xml};
490 $biblio = $biblio->unblessed;
491 $biblioitem = $biblioitem->unblessed;
494 # Add additional fields
495 my $unblessed_hold = $hold->unblessed;
496 $unblessed_hold->{item} = { %$item, %$biblio, %$biblioitem };
497 my $library = Koha::Libraries->find( $hold->branchcode );
498 my $branchname = $library ? $library->branchname : '';
499 $unblessed_hold->{branchname} = $branchname;
500 $biblio = Koha::Biblios->find( $hold->biblionumber ); # Should be $hold->get_biblio
501 $unblessed_hold->{title} = $biblio ? $biblio->title : ''; # Just in case, but should not be needed
503 push @{ $borrower->{holds}{hold} }, $unblessed_hold;
509 if ( $cgi->param('show_loans') && $cgi->param('show_loans') eq "1" ) {
510 my $per_page = $cgi->param('loans_per_page');
511 my $page = $cgi->param('loans_page');
513 my $pending_checkouts = $patron->pending_checkouts;
515 if ($page || $per_page) {
518 $borrower->{total_loans} = $pending_checkouts->count();
519 $pending_checkouts = $pending_checkouts->search(undef, {
526 while ( my $c = $pending_checkouts->next ) {
527 # FIXME We should only retrieve what is needed in the template
528 my $issue = $c->unblessed_all_relateds;
529 delete $issue->{'more_subfields_xml'};
530 push @checkouts, $issue
532 $borrower->{'loans'}->{'loan'} = \@checkouts;
535 my $show_attributes = $cgi->param('show_attributes');
536 if ( $show_attributes && $show_attributes eq "1" ) {
537 # FIXME Regression expected here, we do not retrieve the same field as previously
538 # Waiting for answer on bug 14257 comment 15
539 $borrower->{'attributes'} = [
541 $_->type->opac_display
544 %{ $_->type->unblessed },
545 value => $_->attribute, # Backward compatibility
546 value_description => $_->description, # Awkward retro-compability...
549 } $patron->extended_attributes->search
553 # Add is expired information
554 $borrower->{'is_expired'} = $patron->is_expired ? 1 : 0;
559 =head2 GetPatronStatus
561 Returns a patron's status information.
565 - patron_id (Required)
570 sub GetPatronStatus {
574 my $borrowernumber = $cgi->param('patron_id');
575 my $patron = Koha::Patrons->find( $borrowernumber );
576 return { code => 'PatronNotFound' } unless $patron;
580 type => $patron->categorycode,
582 expiry => $patron->dateexpiry,
588 Returns information about the services available on a particular item for
593 - patron_id (Required)
603 # Get the member, or return an error code if not found
604 my $borrowernumber = $cgi->param('patron_id');
605 my $patron = Koha::Patrons->find( $borrowernumber );
606 return { code => 'PatronNotFound' } unless $patron;
608 my $borrower = $patron->unblessed;
609 # Get the item, or return an error code if not found
610 my $itemnumber = $cgi->param('item_id');
611 my $item = Koha::Items->find($itemnumber);
612 return { code => 'RecordNotFound' } unless $item;
616 # Reserve level management
617 my $biblionumber = $item->biblionumber;
618 my $canbookbereserved = CanBookBeReserved( $borrower, $biblionumber );
619 if ($canbookbereserved->{status} eq 'OK') {
620 push @availablefor, 'title level hold';
621 my $canitembereserved = IsAvailableForItemLevelRequest($item, $patron);
622 if ($canitembereserved) {
623 push @availablefor, 'item level hold';
627 # Reserve cancellation management
628 my $holds = $patron->holds;
630 while ( my $hold = $holds->next ) { # FIXME This could be improved
631 push @reserveditems, $hold->itemnumber;
633 if ( grep { $itemnumber eq $_ } @reserveditems ) {
634 push @availablefor, 'hold cancellation';
638 my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
640 push @availablefor, 'loan renewal';
644 my $barcode = $item->barcode || '';
645 $barcode = barcodedecode($barcode) if $barcode;
647 my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $patron, $barcode );
649 # TODO push @availablefor, 'loan';
653 $out->{'AvailableFor'} = \@availablefor;
660 Extends the due date for a borrower's existing issue.
664 - patron_id (Required)
668 - desired_due_date (Required)
669 the date the patron would like the item returned by
676 # Get borrower infos or return an error code
677 my $borrowernumber = $cgi->param('patron_id');
678 my $patron = Koha::Patrons->find( $borrowernumber );
679 return { code => 'PatronNotFound' } unless $patron;
681 # Get the item, or return an error code
682 my $itemnumber = $cgi->param('item_id');
683 my $item = Koha::Items->find($itemnumber);
684 return { code => 'RecordNotFound' } unless $item;
686 # Add renewal if possible
687 my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
688 if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber, undef, undef, undef, undef, 0 ); }
690 my $issue = $item->checkout;
691 return unless $issue; # FIXME should be handled
695 $out->{'renewals'} = $issue->renewals;
696 $out->{date_due} = dt_from_string($issue->date_due)->strftime('%Y-%m-%d %H:%M');
697 $out->{'success'} = $renewal[0];
698 $out->{'error'} = $renewal[1];
705 Creates, for a borrower, a biblio-level hold reserve.
709 - patron_id (Required)
713 - request_location (Required)
714 IP address where the end user request is being placed
715 - pickup_location (Optional)
716 a branch code indicating the location to which to deliver the item for pickup
717 - start_date (Optional)
718 date after which hold request is no longer needed if the document has not been made available
719 - expiry_date (Optional)
720 date after which item returned to shelf if item is not picked up
727 # Get the borrower or return an error code
728 my $borrowernumber = $cgi->param('patron_id');
729 my $patron = Koha::Patrons->find( $borrowernumber );
730 return { code => 'PatronNotFound' } unless $patron;
733 # If borrower is restricted return an error code
734 return { code => 'PatronRestricted' } if $patron->is_debarred;
736 # Check for patron expired, category and syspref settings
737 return { code => 'PatronExpired' } if ($patron->category->effective_BlockExpiredPatronOpacActions && $patron->is_expired);
739 # Get the biblio record, or return an error code
740 my $biblionumber = $cgi->param('bib_id');
741 my $biblio = Koha::Biblios->find( $biblionumber );
742 return { code => 'RecordNotFound' } unless $biblio;
744 my @hostitems = get_hostitemnumbers_of($biblionumber);
747 push(@itemnumbers, @hostitems);
750 my $items = Koha::Items->search({ -or => { biblionumber => $biblionumber, itemnumber => { in => \@itemnumbers } } });
752 unless ( $items->count ) {
753 return { code => 'NoItems' };
756 my $title = $biblio ? $biblio->title : '';
758 # Check if the biblio can be reserved
759 my $code = CanBookBeReserved( $borrowernumber, $biblionumber )->{status};
760 return { code => $code } unless ( $code eq 'OK' );
764 # Pickup branch management
765 if ( $cgi->param('pickup_location') ) {
766 $branch = $cgi->param('pickup_location');
767 return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
768 } else { # if the request provide no branch, use the borrower's branch
769 $branch = $patron->branchcode;
772 my $destination = Koha::Libraries->find($branch);
773 return { code => 'libraryNotPickupLocation' } unless $destination->pickup_location;
774 return { code => 'cannotBeTransferred' } unless $biblio->can_be_transferred({ to => $destination });
777 if ( $cgi->param('start_date') ) {
778 $resdate = $cgi->param('start_date');
782 if ( $cgi->param('expiry_date') ) {
783 $expdate = $cgi->param('expiry_date');
787 # $branch, $borrowernumber, $biblionumber,
788 # $constraint, $bibitems, $priority, $resdate, $expdate, $notes,
789 # $title, $checkitem, $found
790 my $priority= C4::Reserves::CalculatePriority( $biblionumber );
793 branchcode => $branch,
794 borrowernumber => $borrowernumber,
795 biblionumber => $biblionumber,
796 priority => $priority,
797 reservation_date => $resdate,
798 expiration_date => $expdate,
805 $out->{'title'} = $title;
806 my $library = Koha::Libraries->find( $branch );
807 $out->{'pickup_location'} = $library ? $library->branchname : '';
809 # TODO $out->{'date_available'} = '';
816 Creates, for a borrower, an item-level hold request on a specific item of
817 a bibliographic record in Koha.
821 - patron_id (Required)
827 - pickup_location (Optional)
828 a branch code indicating the location to which to deliver the item for pickup
829 - start_date (Optional)
830 date after which hold request is no longer needed if the item has not been made available
831 - expiry_date (Optional)
832 date after which item returned to shelf if item is not picked up
839 # Get the borrower or return an error code
840 my $borrowernumber = $cgi->param('patron_id');
841 my $patron = Koha::Patrons->find( $borrowernumber );
842 return { code => 'PatronNotFound' } unless $patron;
844 # If borrower is restricted return an error code
845 return { code => 'PatronRestricted' } if $patron->is_debarred;
847 # Check for patron expired, category and syspref settings
848 return { code => 'PatronExpired' } if ($patron->category->effective_BlockExpiredPatronOpacActions && $patron->is_expired);
850 # Get the biblio or return an error code
851 my $biblionumber = $cgi->param('bib_id');
852 my $biblio = Koha::Biblios->find( $biblionumber );
853 return { code => 'RecordNotFound' } unless $biblio;
855 my $title = $biblio ? $biblio->title : '';
857 # Get the item or return an error code
858 my $itemnumber = $cgi->param('item_id');
859 my $item = Koha::Items->find($itemnumber);
860 return { code => 'RecordNotFound' } unless $item;
862 # If the biblio does not match the item, return an error code
863 return { code => 'RecordNotFound' } if $item->biblionumber ne $biblio->biblionumber;
865 # Pickup branch management
867 if ( $cgi->param('pickup_location') ) {
868 $branch = $cgi->param('pickup_location');
869 return { code => 'LocationNotFound' } unless Koha::Libraries->find($branch);
870 } else { # if the request provide no branch, use the borrower's branch
871 $branch = $patron->branchcode;
874 # Check for item disponibility
875 my $canitembereserved = C4::Reserves::CanItemBeReserved( $borrowernumber, $itemnumber, $branch )->{status};
876 return { code => $canitembereserved } unless $canitembereserved eq 'OK';
879 if ( $cgi->param('start_date') ) {
880 $resdate = $cgi->param('start_date');
884 if ( $cgi->param('expiry_date') ) {
885 $expdate = $cgi->param('expiry_date');
889 my $priority = C4::Reserves::CalculatePriority($biblionumber);
892 branchcode => $branch,
893 borrowernumber => $borrowernumber,
894 biblionumber => $biblionumber,
895 priority => $priority,
896 reservation_date => $resdate,
897 expiration_date => $expdate,
899 itemnumber => $itemnumber,
905 my $library = Koha::Libraries->find( $branch );
906 $out->{'pickup_location'} = $library ? $library->branchname : '';
908 # TODO $out->{'date_available'} = '';
915 Cancels an active reserve request for the borrower.
919 - patron_id (Required)
929 # Get the borrower or return an error code
930 my $borrowernumber = $cgi->param('patron_id');
931 my $patron = Koha::Patrons->find( $borrowernumber );
932 return { code => 'PatronNotFound' } unless $patron;
934 # Get the reserve or return an error code
935 my $reserve_id = $cgi->param('item_id');
936 my $hold = Koha::Holds->find( $reserve_id );
937 return { code => 'RecordNotFound' } unless $hold;
938 return { code => 'RecordNotFound' } unless ($hold->borrowernumber == $borrowernumber);
942 return { code => 'Canceled' };
947 Returns, for an itemnumber, an array containing availability information.
949 my ($biblionumber, $status, $msg, $location) = _availability($id);
954 my ($itemnumber) = @_;
955 my $item = Koha::Items->find($itemnumber);
958 return ( undef, 'unknown', 'Error: could not retrieve availability for this ID', undef );
961 my $biblionumber = $item->biblioitemnumber;
962 my $library = Koha::Libraries->find( $item->holdingbranch );
963 my $location = $library ? $library->branchname : '';
965 if ( $item->notforloan ) {
966 return ( $biblionumber, 'not available', 'Not for loan', $location );
967 } elsif ( $item->onloan ) {
968 return ( $biblionumber, 'not available', 'Checked out', $location );
969 } elsif ( $item->itemlost ) {
970 return ( $biblionumber, 'not available', 'Item lost', $location );
971 } elsif ( $item->withdrawn ) {
972 return ( $biblionumber, 'not available', 'Item withdrawn', $location );
973 } elsif ( $item->damaged ) {
974 return ( $biblionumber, 'not available', 'Item damaged', $location );
976 return ( $biblionumber, 'available', undef, $location );