Bug 12871 - wthdrawn instead of withdrawn in ILSDI
[koha.git] / C4 / ILSDI / Services.pm
blob45864ab3de1bf54fe6eb192b9353e2e98a639115
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 under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 use strict;
21 use warnings;
23 use C4::Members;
24 use C4::Items;
25 use C4::Circulation;
26 use C4::Branch;
27 use C4::Accounts;
28 use C4::Biblio;
29 use C4::Reserves qw(AddReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber CanBookBeReserved CanItemBeReserved);
30 use C4::Context;
31 use C4::AuthoritiesMarc;
32 use XML::Simple;
33 use HTML::Entities;
34 use CGI;
35 use DateTime;
36 use C4::Auth;
38 =head1 NAME
40 C4::ILS-DI::Services - ILS-DI Services
42 =head1 DESCRIPTION
44 Each function in this module represents an ILS-DI service.
45 They all takes a CGI instance as argument and most of them return a
46 hashref that will be printed by XML::Simple in opac/ilsdi.pl
48 =head1 SYNOPSIS
50 use C4::ILSDI::Services;
51 use XML::Simple;
52 use CGI;
54 my $cgi = new CGI;
56 $out = LookupPatron($cgi);
58 print CGI::header('text/xml');
59 print XMLout($out,
60 noattr => 1,
61 noescape => 1,
62 nosort => 1,
63 xmldecl => '<?xml version="1.0" encoding="UTF-8" ?>',
64 RootName => 'LookupPatron',
65 SuppressEmpty => 1);
67 =cut
69 =head1 FUNCTIONS
71 =head2 GetAvailability
73 Given a set of biblionumbers or itemnumbers, returns a list with
74 availability of the items associated with the identifiers.
76 Parameters:
78 =head3 id (Required)
80 list of either biblionumbers or itemnumbers
82 =head3 id_type (Required)
84 defines the type of record identifier being used in the request,
85 possible values:
87 - bib
88 - item
90 =head3 return_type (Optional)
92 requests a particular level of detail in reporting availability,
93 possible values:
95 - bib
96 - item
98 =head3 return_fmt (Optional)
100 requests a particular format or set of formats in reporting
101 availability
103 =cut
105 sub GetAvailability {
106 my ($cgi) = @_;
108 my $out = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
109 $out .= "<dlf:collection\n";
110 $out .= " xmlns:dlf=\"http://diglib.org/ilsdi/1.1\"\n";
111 $out .= " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
112 $out .= " xsi:schemaLocation=\"http://diglib.org/ilsdi/1.1\n";
113 $out .= " http://diglib.org/architectures/ilsdi/schemas/1.1/dlfexpanded.xsd\">\n";
115 foreach my $id ( split( / /, $cgi->param('id') ) ) {
116 if ( $cgi->param('id_type') eq "item" ) {
117 my ( $biblionumber, $status, $msg, $location ) = _availability($id);
119 $out .= " <dlf:record>\n";
120 $out .= " <dlf:bibliographic id=\"" . ( $biblionumber || $id ) . "\" />\n";
121 $out .= " <dlf:items>\n";
122 $out .= " <dlf:item id=\"" . $id . "\">\n";
123 $out .= " <dlf:simpleavailability>\n";
124 $out .= " <dlf:identifier>" . $id . "</dlf:identifier>\n";
125 $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
126 if ($msg) { $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n"; }
127 if ($location) { $out .= " <dlf:location>" . $location . "</dlf:location>\n"; }
128 $out .= " </dlf:simpleavailability>\n";
129 $out .= " </dlf:item>\n";
130 $out .= " </dlf:items>\n";
131 $out .= " </dlf:record>\n";
132 } else {
133 my $status;
134 my $msg;
135 my $biblioitem = ( GetBiblioItemByBiblioNumber( $id, undef ) )[0];
136 if ($biblioitem) {
138 } else {
139 $status = "unknown";
140 $msg = "Error: could not retrieve availability for this ID";
142 $out .= " <dlf:record>\n";
143 $out .= " <dlf:bibliographic id=\"" . $id . "\" />\n";
144 $out .= " <dlf:simpleavailability>\n";
145 $out .= " <dlf:identifier>" . $id . "</dlf:identifier>\n";
146 $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
147 $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n";
148 $out .= " </dlf:simpleavailability>\n";
149 $out .= " </dlf:record>\n";
152 $out .= "</dlf:collection>\n";
154 return $out;
157 =head2 GetRecords
159 Given a list of biblionumbers, returns a list of record objects that
160 contain bibliographic information, as well as associated holdings and item
161 information. The caller may request a specific metadata schema for the
162 record objects to be returned.
164 This function behaves similarly to HarvestBibliographicRecords and
165 HarvestExpandedRecords in Data Aggregation, but allows quick, real time
166 lookup by bibliographic identifier.
168 You can use OAI-PMH ListRecords instead of this service.
170 Parameters:
172 - id (Required)
173 list of system record identifiers
174 - id_type (Optional)
175 Defines the metadata schema in which the records are returned,
176 possible values:
177 - MARCXML
179 =cut
181 sub GetRecords {
182 my ($cgi) = @_;
184 # Check if the schema is supported. For now, GetRecords only supports MARCXML
185 if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
186 return { code => 'UnsupportedSchema' };
189 my @records;
191 # Loop over biblionumbers
192 foreach my $biblionumber ( split( / /, $cgi->param('id') ) ) {
194 # Get the biblioitem from the biblionumber
195 my $biblioitem = ( GetBiblioItemByBiblioNumber( $biblionumber, undef ) )[0];
196 if ( not $biblioitem->{'biblionumber'} ) {
197 $biblioitem->{code} = "RecordNotFound";
200 my $embed_items = 1;
201 my $record = GetMarcBiblio($biblionumber, $embed_items);
202 if ($record) {
203 $biblioitem->{marcxml} = $record->as_xml_record();
206 # We don't want MARC to be displayed
207 delete $biblioitem->{'marc'};
209 # Get most of the needed data
210 my $biblioitemnumber = $biblioitem->{'biblioitemnumber'};
211 my $reserves = GetReservesFromBiblionumber({ biblionumber => $biblionumber });
212 my $issues = GetBiblioIssues($biblionumber);
213 my $items = GetItemsByBiblioitemnumber($biblioitemnumber);
215 # We loop over the items to clean them
216 foreach my $item (@$items) {
218 # This hides additionnal XML subfields, we don't need these info
219 delete $item->{'more_subfields_xml'};
221 # Display branch names instead of branch codes
222 $item->{'homebranchname'} = GetBranchName( $item->{'homebranch'} );
223 $item->{'holdingbranchname'} = GetBranchName( $item->{'holdingbranch'} );
226 # Hashref building...
227 $biblioitem->{'items'}->{'item'} = $items;
228 $biblioitem->{'reserves'}->{'reserve'} = $reserves;
229 $biblioitem->{'issues'}->{'issue'} = $issues;
231 push @records, $biblioitem;
234 return { record => \@records };
237 =head2 GetAuthorityRecords
239 Given a list of authority record identifiers, returns a list of record
240 objects that contain the authority records. The function user may request
241 a specific metadata schema for the record objects.
243 Parameters:
245 - id (Required)
246 list of authority record identifiers
247 - schema (Optional)
248 specifies the metadata schema of records to be returned, possible values:
249 - MARCXML
251 =cut
253 sub GetAuthorityRecords {
254 my ($cgi) = @_;
256 # If the user asks for an unsupported schema, return an error code
257 if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
258 return { code => 'UnsupportedSchema' };
261 my @records;
263 # Let's loop over the authority IDs
264 foreach my $authid ( split( / /, $cgi->param('id') ) ) {
266 # Get the record as XML string, or error code
267 push @records, GetAuthorityXML($authid) || { code => 'RecordNotFound' };
270 return { record => \@records };
273 =head2 LookupPatron
275 Looks up a patron in the ILS by an identifier, and returns the borrowernumber.
277 Parameters:
279 - id (Required)
280 an identifier used to look up the patron in Koha
281 - id_type (Optional)
282 the type of the identifier, possible values:
283 - cardnumber
284 - firstname
285 - userid
286 - borrowernumber
288 =cut
290 sub LookupPatron {
291 my ($cgi) = @_;
293 # Get the borrower...
294 my $borrower = GetMember($cgi->param('id_type') => $cgi->param('id'));
295 if ( not $borrower->{'borrowernumber'} ) {
296 return { message => 'PatronNotFound' };
299 # Build the hashref
300 my $patron->{'id'} = $borrower->{'borrowernumber'};
301 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
303 # ...and return his ID
304 return $patron;
307 =head2 AuthenticatePatron
309 Authenticates a user's login credentials and returns the identifier for
310 the patron.
312 Parameters:
314 - username (Required)
315 user's login identifier (userid or cardnumber)
316 - password (Required)
317 user's password
319 =cut
321 sub AuthenticatePatron {
322 my ($cgi) = @_;
323 my ($status, $cardnumber, $userid) = C4::Auth::checkpw( C4::Context->dbh, $cgi->param('username'), $cgi->param('password') );
324 if ( $status ) {
325 # Get the borrower
326 my $borrower = GetMember( cardnumber => $cardnumber );
327 my $patron->{'id'} = $borrower->{'borrowernumber'};
328 return $patron;
330 else {
331 return { code => 'PatronNotFound' };
335 =head2 GetPatronInfo
337 Returns specified information about the patron, based on options in the
338 request. This function can optionally return patron's contact information,
339 fine information, hold request information, and loan information.
341 Parameters:
343 - patron_id (Required)
344 the borrowernumber
345 - show_contact (Optional, default 1)
346 whether or not to return patron's contact information in the response
347 - show_fines (Optional, default 0)
348 whether or not to return fine information in the response
349 - show_holds (Optional, default 0)
350 whether or not to return hold request information in the response
351 - show_loans (Optional, default 0)
352 whether or not to return loan information request information in the response
354 =cut
356 sub GetPatronInfo {
357 my ($cgi) = @_;
359 # Get Member details
360 my $borrowernumber = $cgi->param('patron_id');
361 my $borrower = GetMemberDetails( $borrowernumber );
362 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
364 # Cleaning the borrower hashref
365 $borrower->{'charges'} = $borrower->{'flags'}->{'CHARGES'}->{'amount'};
366 $borrower->{'branchname'} = GetBranchName( $borrower->{'branchcode'} );
367 delete $borrower->{'flags'};
368 delete $borrower->{'userid'};
369 delete $borrower->{'password'};
371 # Contact fields management
372 if ( $cgi->param('show_contact') eq "0" ) {
374 # Define contact fields
375 my @contactfields = (
376 'email', 'emailpro', 'fax', 'mobile', 'phone', 'phonepro',
377 'streetnumber', 'zipcode', 'city', 'streettype', 'B_address', 'B_city',
378 'B_email', 'B_phone', 'B_zipcode', 'address', 'address2', 'altcontactaddress1',
379 'altcontactaddress2', 'altcontactaddress3', 'altcontactfirstname', 'altcontactphone', 'altcontactsurname', 'altcontactzipcode'
382 # and delete them
383 foreach my $field (@contactfields) {
384 delete $borrower->{$field};
388 # Fines management
389 if ( $cgi->param('show_fines') eq "1" ) {
390 my @charges;
391 for ( my $i = 1 ; my @charge = getcharges( $borrowernumber, undef, $i ) ; $i++ ) {
392 push( @charges, @charge );
394 $borrower->{'fines'}->{'fine'} = \@charges;
397 # Reserves management
398 if ( $cgi->param('show_holds') eq "1" ) {
400 # Get borrower's reserves
401 my @reserves = GetReservesFromBorrowernumber( $borrowernumber, undef );
402 foreach my $reserve (@reserves) {
404 # Get additional informations
405 my $item = GetBiblioFromItemNumber( $reserve->{'itemnumber'}, undef );
406 my $branchname = GetBranchName( $reserve->{'branchcode'} );
408 # Remove unwanted fields
409 delete $item->{'marc'};
410 delete $item->{'marcxml'};
411 delete $item->{'more_subfields_xml'};
413 # Add additional fields
414 $reserve->{'item'} = $item;
415 $reserve->{'branchname'} = $branchname;
416 $reserve->{'title'} = GetBiblio( $reserve->{'biblionumber'} )->{'title'};
418 $borrower->{'holds'}->{'hold'} = \@reserves;
421 # Issues management
422 if ( $cgi->param('show_loans') eq "1" ) {
423 my $issues = GetPendingIssues($borrowernumber);
424 foreach my $issue ( @$issues ){
425 $issue->{'issuedate'} = $issue->{'issuedate'}->strftime('%Y-%m-%d %H:%M');
426 $issue->{'date_due'} = $issue->{'date_due'}->strftime('%Y-%m-%d %H:%M');
428 $borrower->{'loans'}->{'loan'} = $issues;
431 return $borrower;
434 =head2 GetPatronStatus
436 Returns a patron's status information.
438 Parameters:
440 - patron_id (Required)
441 the borrower ID
443 =cut
445 sub GetPatronStatus {
446 my ($cgi) = @_;
448 # Get Member details
449 my $borrowernumber = $cgi->param('patron_id');
450 my $borrower = GetMemberDetails( $borrowernumber );
451 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
453 # Return the results
454 return {
455 type => $$borrower{categorycode},
456 status => 0, # TODO
457 expiry => $$borrower{dateexpiry},
461 =head2 GetServices
463 Returns information about the services available on a particular item for
464 a particular patron.
466 Parameters:
468 - patron_id (Required)
469 a borrowernumber
470 - item_id (Required)
471 an itemnumber
472 =cut
474 sub GetServices {
475 my ($cgi) = @_;
477 # Get the member, or return an error code if not found
478 my $borrowernumber = $cgi->param('patron_id');
479 my $borrower = GetMemberDetails( $borrowernumber );
480 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
482 # Get the item, or return an error code if not found
483 my $itemnumber = $cgi->param('item_id');
484 my $item = GetItem( $itemnumber );
485 return { code => 'RecordNotFound' } unless $$item{itemnumber};
487 my @availablefor;
489 # Reserve level management
490 my $biblionumber = $item->{'biblionumber'};
491 my $canbookbereserved = CanBookBeReserved( $borrower, $biblionumber );
492 if ($canbookbereserved) {
493 push @availablefor, 'title level hold';
494 my $canitembereserved = IsAvailableForItemLevelRequest($itemnumber);
495 if ($canitembereserved) {
496 push @availablefor, 'item level hold';
500 # Reserve cancellation management
501 my @reserves = GetReservesFromBorrowernumber( $borrowernumber, undef );
502 my @reserveditems;
503 foreach my $reserve (@reserves) {
504 push @reserveditems, $reserve->{'itemnumber'};
506 if ( grep { $itemnumber eq $_ } @reserveditems ) {
507 push @availablefor, 'hold cancellation';
510 # Renewal management
511 my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
512 if ( $renewal[0] ) {
513 push @availablefor, 'loan renewal';
516 # Issuing management
517 my $barcode = $item->{'barcode'} || '';
518 $barcode = barcodedecode($barcode) if ( $barcode && C4::Context->preference('itemBarcodeInputFilter') );
519 if ($barcode) {
520 my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $borrower, $barcode );
522 # TODO push @availablefor, 'loan';
525 my $out;
526 $out->{'AvailableFor'} = \@availablefor;
528 return $out;
531 =head2 RenewLoan
533 Extends the due date for a borrower's existing issue.
535 Parameters:
537 - patron_id (Required)
538 a borrowernumber
539 - item_id (Required)
540 an itemnumber
541 - desired_due_date (Required)
542 the date the patron would like the item returned by
544 =cut
546 sub RenewLoan {
547 my ($cgi) = @_;
549 # Get borrower infos or return an error code
550 my $borrowernumber = $cgi->param('patron_id');
551 my $borrower = GetMemberDetails( $borrowernumber );
552 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
554 # Get the item, or return an error code
555 my $itemnumber = $cgi->param('item_id');
556 my $item = GetItem( $itemnumber );
557 return { code => 'RecordNotFound' } unless $$item{itemnumber};
559 # Add renewal if possible
560 my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
561 if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber ); }
563 my $issue = GetItemIssue($itemnumber);
565 # Hashref building
566 my $out;
567 $out->{'renewals'} = $issue->{'renewals'};
568 $out->{date_due} = $issue->{date_due}->strftime('%Y-%m-%d %H:%S');
569 $out->{'success'} = $renewal[0];
570 $out->{'error'} = $renewal[1];
572 return $out;
575 =head2 HoldTitle
577 Creates, for a borrower, a biblio-level hold reserve.
579 Parameters:
581 - patron_id (Required)
582 a borrowernumber
583 - bib_id (Required)
584 a biblionumber
585 - request_location (Required)
586 IP address where the end user request is being placed
587 - pickup_location (Optional)
588 a branch code indicating the location to which to deliver the item for pickup
589 - needed_before_date (Optional)
590 date after which hold request is no longer needed
591 - pickup_expiry_date (Optional)
592 date after which item returned to shelf if item is not picked up
594 =cut
596 sub HoldTitle {
597 my ($cgi) = @_;
599 # Get the borrower or return an error code
600 my $borrowernumber = $cgi->param('patron_id');
601 my $borrower = GetMemberDetails( $borrowernumber );
602 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
604 # Get the biblio record, or return an error code
605 my $biblionumber = $cgi->param('bib_id');
606 my $biblio = GetBiblio( $biblionumber );
607 return { code => 'RecordNotFound' } unless $$biblio{biblionumber};
609 my $title = $$biblio{title};
611 # Check if the biblio can be reserved
612 return { code => 'NotHoldable' } unless CanBookBeReserved( $borrowernumber, $biblionumber );
614 my $branch;
616 # Pickup branch management
617 if ( $cgi->param('pickup_location') ) {
618 $branch = $cgi->param('pickup_location');
619 my $branches = GetBranches;
620 return { code => 'LocationNotFound' } unless $$branches{$branch};
621 } else { # if the request provide no branch, use the borrower's branch
622 $branch = $$borrower{branchcode};
625 # Add the reserve
626 # $branch, $borrowernumber, $biblionumber,
627 # $constraint, $bibitems, $priority, $resdate, $expdate, $notes,
628 # $title, $checkitem, $found
629 my $priority= C4::Reserves::CalculatePriority( $biblionumber );
630 AddReserve( $branch, $borrowernumber, $biblionumber, 'a', undef, $priority, undef, undef, undef, $title, undef, undef );
632 # Hashref building
633 my $out;
634 $out->{'title'} = $title;
635 $out->{'pickup_location'} = GetBranchName($branch);
637 # TODO $out->{'date_available'} = '';
639 return $out;
642 =head2 HoldItem
644 Creates, for a borrower, an item-level hold request on a specific item of
645 a bibliographic record in Koha.
647 Parameters:
649 - patron_id (Required)
650 a borrowernumber
651 - bib_id (Required)
652 a biblionumber
653 - item_id (Required)
654 an itemnumber
655 - pickup_location (Optional)
656 a branch code indicating the location to which to deliver the item for pickup
657 - needed_before_date (Optional)
658 date after which hold request is no longer needed
659 - pickup_expiry_date (Optional)
660 date after which item returned to shelf if item is not picked up
662 =cut
664 sub HoldItem {
665 my ($cgi) = @_;
667 # Get the borrower or return an error code
668 my $borrowernumber = $cgi->param('patron_id');
669 my $borrower = GetMemberDetails( $borrowernumber );
670 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
672 # Get the biblio or return an error code
673 my $biblionumber = $cgi->param('bib_id');
674 my $biblio = GetBiblio($biblionumber);
675 return { code => 'RecordNotFound' } unless $$biblio{biblionumber};
677 my $title = $$biblio{title};
679 # Get the item or return an error code
680 my $itemnumber = $cgi->param('item_id');
681 my $item = GetItem( $itemnumber );
682 return { code => 'RecordNotFound' } unless $$item{itemnumber};
684 # If the biblio does not match the item, return an error code
685 return { code => 'RecordNotFound' } if $$item{biblionumber} ne $$biblio{biblionumber};
687 # Check for item disponibility
688 my $canitembereserved = C4::Reserves::CanItemBeReserved( $borrowernumber, $itemnumber );
689 my $canbookbereserved = C4::Reserves::CanBookBeReserved( $borrowernumber, $biblionumber );
690 return { code => 'NotHoldable' } unless $canbookbereserved and $canitembereserved;
692 # Pickup branch management
693 my $branch;
694 if ( $cgi->param('pickup_location') ) {
695 $branch = $cgi->param('pickup_location');
696 my $branches = GetBranches();
697 return { code => 'LocationNotFound' } unless $$branches{$branch};
698 } else { # if the request provide no branch, use the borrower's branch
699 $branch = $$borrower{branchcode};
702 # Add the reserve
703 # $branch, $borrowernumber, $biblionumber,
704 # $constraint, $bibitems, $priority, $resdate, $expdate, $notes,
705 # $title, $checkitem, $found
706 my $priority= C4::Reserves::CalculatePriority( $biblionumber );
707 AddReserve( $branch, $borrowernumber, $biblionumber, 'a', undef, $priority, undef, undef, undef, $title, $itemnumber, undef );
709 # Hashref building
710 my $out;
711 $out->{'pickup_location'} = GetBranchName($branch);
713 # TODO $out->{'date_available'} = '';
715 return $out;
718 =head2 CancelHold
720 Cancels an active reserve request for the borrower.
722 Parameters:
724 - patron_id (Required)
725 a borrowernumber
726 - item_id (Required)
727 a reserve_id
729 =cut
731 sub CancelHold {
732 my ($cgi) = @_;
734 # Get the borrower or return an error code
735 my $borrowernumber = $cgi->param('patron_id');
736 my $borrower = GetMemberDetails( $borrowernumber );
737 return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
739 # Get the reserve or return an error code
740 my $reserve_id = $cgi->param('item_id');
741 my $reserve = C4::Reserves::GetReserve($reserve_id);
742 return { code => 'RecordNotFound' } unless $reserve;
743 return { code => 'RecordNotFound' } unless ($reserve->{borrowernumber} == $borrowernumber);
745 C4::Reserves::CancelReserve({reserve_id => $reserve_id});
747 return { code => 'Canceled' };
750 =head2 _availability
752 Returns, for an itemnumber, an array containing availability information.
754 my ($biblionumber, $status, $msg, $location) = _availability($id);
756 =cut
758 sub _availability {
759 my ($itemnumber) = @_;
760 my $item = GetItem( $itemnumber, undef, undef );
762 if ( not $item->{'itemnumber'} ) {
763 return ( undef, 'unknown', 'Error: could not retrieve availability for this ID', undef );
766 my $biblionumber = $item->{'biblioitemnumber'};
767 my $location = GetBranchName( $item->{'holdingbranch'} );
769 if ( $item->{'notforloan'} ) {
770 return ( $biblionumber, 'not available', 'Not for loan', $location );
771 } elsif ( $item->{'onloan'} ) {
772 return ( $biblionumber, 'not available', 'Checked out', $location );
773 } elsif ( $item->{'itemlost'} ) {
774 return ( $biblionumber, 'not available', 'Item lost', $location );
775 } elsif ( $item->{'withdrawn'} ) {
776 return ( $biblionumber, 'not available', 'Item withdrawn', $location );
777 } elsif ( $item->{'damaged'} ) {
778 return ( $biblionumber, 'not available', 'Item damaged', $location );
779 } else {
780 return ( $biblionumber, 'available', undef, $location );