File Coverage

File:C4/ILSDI/Services.pm
Coverage:15.2%

linestmtbrancondsubtimecode
1package C4::ILSDI::Services;
2
3# Copyright 2009 SARL Biblibre
4#
5# This file is part of Koha.
6#
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.
11#
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.
15#
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.
19
20
2
2
2
578
4
54
use strict;
21
2
2
2
10
3
99
use warnings;
22
23
2
2
2
206
24
1144
use C4::Members;
24
2
2
2
30
22
545
use C4::Items;
25
2
2
2
28
19
727
use C4::Circulation;
26
2
2
2
45
17
343
use C4::Branch;
27
2
2
2
22
14
343
use C4::Accounts;
28
2
2
2
21
12
951
use C4::Biblio;
29
2
2
2
18
11
209
use C4::Reserves qw(AddReserve CancelReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber);
30
2
2
2
17
11
41
use C4::Context;
31
2
2
2
285
27
589
use C4::AuthoritiesMarc;
32
2
2
2
356
3
187
use C4::ILSDI::Utility;
33
2
2
2
10
4
26
use XML::Simple;
34
2
2
2
90427
8965
150
use HTML::Entities;
35
2
2
2
216
14528
65
use CGI;
36
2
2
2
151
27
7205
use DateTime;
37
38 - 67
=head1 NAME

C4::ILS-DI::Services - ILS-DI Services

=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

=head1 SYNOPSIS

	use C4::ILSDI::Services;
	use XML::Simple;
	use CGI;

	my $cgi = new 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);

=cut
68
69 - 103
=head1 FUNCTIONS

=head2 GetAvailability

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
104
105sub GetAvailability {
106
0
    my ($cgi) = @_;
107
108
0
    my $out = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
109
0
    $out .= "<dlf:collection\n";
110
0
    $out .= " xmlns:dlf=\"http://diglib.org/ilsdi/1.1\"\n";
111
0
    $out .= " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
112
0
    $out .= " xsi:schemaLocation=\"http://diglib.org/ilsdi/1.1\n";
113
0
    $out .= " http://diglib.org/architectures/ilsdi/schemas/1.1/dlfexpanded.xsd\">\n";
114
115
0
    foreach my $id ( split( / /, $cgi->param('id') ) ) {
116
0
        if ( $cgi->param('id_type') eq "item" ) {
117
0
            my ( $biblionumber, $status, $msg, $location ) = Availability($id);
118
119
0
            $out .= " <dlf:record>\n";
120
0
            $out .= " <dlf:bibliographic id=\"" . ( $biblionumber || $id ) . "\" />\n";
121
0
            $out .= " <dlf:items>\n";
122
0
            $out .= " <dlf:item id=\"" . $id . "\">\n";
123
0
            $out .= " <dlf:simpleavailability>\n";
124
0
            $out .= " <dlf:identifier>" . $id . "</dlf:identifier>\n";
125
0
            $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
126
0
0
            if ($msg) { $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n"; }
127
0
0
            if ($location) { $out .= " <dlf:location>" . $location . "</dlf:location>\n"; }
128
0
            $out .= " </dlf:simpleavailability>\n";
129
0
            $out .= " </dlf:item>\n";
130
0
            $out .= " </dlf:items>\n";
131
0
            $out .= " </dlf:record>\n";
132        } else {
133
0
            my $status;
134
0
            my $msg;
135
0
            my $biblioitem = ( GetBiblioItemByBiblioNumber( $id, undef ) )[0];
136
0
            if ($biblioitem) {
137
138            } else {
139
0
                $status = "unknown";
140
0
                $msg = "Error: could not retrieve availability for this ID";
141            }
142
0
            $out .= " <dlf:record>\n";
143
0
            $out .= " <dlf:bibliographic id=\"" . $id . "\" />\n";
144
0
            $out .= " <dlf:simpleavailability>\n";
145
0
            $out .= " <dlf:identifier>" . $id . "</dlf:identifier>\n";
146
0
            $out .= " <dlf:availabilitystatus>" . $status . "</dlf:availabilitystatus>\n";
147
0
            $out .= " <dlf:availabilitymsg>" . $msg . "</dlf:availabilitymsg>\n";
148
0
            $out .= " </dlf:simpleavailability>\n";
149
0
            $out .= " </dlf:record>\n";
150        }
151    }
152
0
    $out .= "</dlf:collection>\n";
153
154
0
    return $out;
155}
156
157 - 179
=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

=cut
180
181sub GetRecords {
182
0
    my ($cgi) = @_;
183
184    # Check if the schema is supported. For now, GetRecords only supports MARCXML
185
0
    if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
186
0
        return { code => 'UnsupportedSchema' };
187    }
188
189
0
    my @records;
190
191    # Loop over biblionumbers
192
0
    foreach my $biblionumber ( split( / /, $cgi->param('id') ) ) {
193
194        # Get the biblioitem from the biblionumber
195
0
        my $biblioitem = ( GetBiblioItemByBiblioNumber( $biblionumber, undef ) )[0];
196
0
        if ( not $biblioitem->{'biblionumber'} ) {
197
0
            $biblioitem->{code} = "RecordNotFound";
198        }
199
200        # We don't want MARC to be displayed
201
0
        delete $biblioitem->{'marc'};
202
203        # Get most of the needed data
204
0
        my $biblioitemnumber = $biblioitem->{'biblioitemnumber'};
205
0
        my @reserves = GetReservesFromBiblionumber( $biblionumber, undef, undef );
206
0
        my $issues = GetBiblioIssues($biblionumber);
207
0
        my $items = GetItemsByBiblioitemnumber($biblioitemnumber);
208
209        # We loop over the items to clean them
210
0
        foreach my $item (@$items) {
211
212            # This hides additionnal XML subfields, we don't need these info
213
0
            delete $item->{'more_subfields_xml'};
214
215            # Display branch names instead of branch codes
216
0
            $item->{'homebranchname'} = GetBranchName( $item->{'homebranch'} );
217
0
            $item->{'holdingbranchname'} = GetBranchName( $item->{'holdingbranch'} );
218        }
219
220        # Hashref building...
221
0
        $biblioitem->{'items'}->{'item'} = $items;
222
0
        $biblioitem->{'reserves'}->{'reserve'} = $reserves[1];
223
0
        $biblioitem->{'issues'}->{'issue'} = $issues;
224
225
0
        push @records, $biblioitem;
226    }
227
228
0
    return { record => \@records };
229}
230
231 - 245
=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:

  - id (Required)
    list of authority record identifiers
  - schema (Optional)
    specifies the metadata schema of records to be returned, possible values:
      - MARCXML

=cut
246
247sub GetAuthorityRecords {
248
0
    my ($cgi) = @_;
249
250    # If the user asks for an unsupported schema, return an error code
251
0
    if ( $cgi->param('schema') and $cgi->param('schema') ne "MARCXML" ) {
252
0
        return { code => 'UnsupportedSchema' };
253    }
254
255
0
    my @records;
256
257    # Let's loop over the authority IDs
258
0
    foreach my $authid ( split( / /, $cgi->param('id') ) ) {
259
260        # Get the record as XML string, or error code
261
0
        push @records, GetAuthorityXML($authid) || { code => 'RecordNotFound' };
262    }
263
264
0
    return { record => \@records };
265}
266
267 - 282
=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

=cut
283
284sub LookupPatron {
285
0
    my ($cgi) = @_;
286
287    # Get the borrower...
288
0
    my $borrower = GetMember($cgi->param('id_type') => $cgi->param('id'));
289
0
    if ( not $borrower->{'borrowernumber'} ) {
290
0
        return { message => 'PatronNotFound' };
291    }
292
293    # Build the hashref
294
0
    my $patron->{'id'} = $borrower->{'borrowernumber'};
295
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
296
297    # ...and return his ID
298
0
    return $patron;
299}
300
301 - 313
=head2 AuthenticatePatron

Authenticates a user's login credentials and returns the identifier for 
the patron.

Parameters:

  - username (Required)
	user's login identifier
  - password (Required)
	user's password

=cut
314
315sub AuthenticatePatron {
316
0
    my ($cgi) = @_;
317
318    # Check if borrower exists, using a C4::Auth function...
319
0
    unless( C4::Auth::checkpw( C4::Context->dbh, $cgi->param('username'), $cgi->param('password') ) ) {
320
0
        return { code => 'PatronNotFound' };
321    }
322
323    # Get the borrower
324
0
    my $borrower = GetMember( userid => $cgi->param('username') );
325
326    # Build the hashref
327
0
    my $patron->{'id'} = $borrower->{'borrowernumber'};
328
329    # ... and return his ID
330
0
    return $patron;
331}
332
333 - 352
=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 

=cut
353
354sub GetPatronInfo {
355
0
    my ($cgi) = @_;
356
357    # Get Member details
358
0
    my $borrowernumber = $cgi->param('patron_id');
359
0
    my $borrower = GetMemberDetails( $borrowernumber );
360
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
361
362    # Cleaning the borrower hashref
363
0
    $borrower->{'charges'} = $borrower->{'flags'}->{'CHARGES'}->{'amount'};
364
0
    $borrower->{'branchname'} = GetBranchName( $borrower->{'branchcode'} );
365
0
    delete $borrower->{'flags'};
366
0
    delete $borrower->{'userid'};
367
0
    delete $borrower->{'password'};
368
369    # Contact fields management
370
0
    if ( $cgi->param('show_contact') eq "0" ) {
371
372        # Define contact fields
373
0
        my @contactfields = (
374            'email', 'emailpro', 'fax', 'mobile', 'phone', 'phonepro',
375            'streetnumber', 'zipcode', 'city', 'streettype', 'B_address', 'B_city',
376            'B_email', 'B_phone', 'B_zipcode', 'address', 'address2', 'altcontactaddress1',
377            'altcontactaddress2', 'altcontactaddress3', 'altcontactfirstname', 'altcontactphone', 'altcontactsurname', 'altcontactzipcode'
378        );
379
380        # and delete them
381
0
        foreach my $field (@contactfields) {
382
0
            delete $borrower->{$field};
383        }
384    }
385
386    # Fines management
387
0
    if ( $cgi->param('show_fines') eq "1" ) {
388
0
        my @charges;
389        for ( my $i = 1 ; my @charge = getcharges( $borrowernumber, undef, $i ) ; $i++ ) {
390
0
            push( @charges, @charge );
391
0
        }
392
0
        $borrower->{'fines'}->{'fine'} = \@charges;
393    }
394
395    # Reserves management
396
0
    if ( $cgi->param('show_holds') eq "1" ) {
397
398        # Get borrower's reserves
399
0
        my @reserves = GetReservesFromBorrowernumber( $borrowernumber, undef );
400
0
        foreach my $reserve (@reserves) {
401
402            # Get additional informations
403
0
            my $item = GetBiblioFromItemNumber( $reserve->{'itemnumber'}, undef );
404
0
            my $branchname = GetBranchName( $reserve->{'branchcode'} );
405
406            # Remove unwanted fields
407
0
            delete $item->{'marc'};
408
0
            delete $item->{'marcxml'};
409
0
            delete $item->{'more_subfields_xml'};
410
411            # Add additional fields
412
0
            $reserve->{'item'} = $item;
413
0
            $reserve->{'branchname'} = $branchname;
414
0
            $reserve->{'title'} = ( GetBiblio( $reserve->{'biblionumber'} ) )[1]->{'title'};
415        }
416
0
        $borrower->{'holds'}->{'hold'} = \@reserves;
417    }
418
419    # Issues management
420
0
    if ( $cgi->param('show_loans') eq "1" ) {
421
0
        my $issues = GetPendingIssues($borrowernumber);
422
0
        $borrower->{'loans'}->{'loan'} = $issues;
423    }
424
425
0
    return $borrower;
426}
427
428 - 437
=head2 GetPatronStatus

Returns a patron's status information.

Parameters:

  - patron_id (Required)
	the borrower ID

=cut
438
439sub GetPatronStatus {
440
0
    my ($cgi) = @_;
441
442    # Get Member details
443
0
    my $borrowernumber = $cgi->param('patron_id');
444
0
    my $borrower = GetMemberDetails( $borrowernumber );
445
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
446
447    # Return the results
448    return {
449
0
        type => $$borrower{categorycode},
450        status => 0, # TODO
451        expiry => $$borrower{dateexpiry},
452    };
453}
454
455 - 466
=head2 GetServices

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
=cut
467
468sub GetServices {
469
0
    my ($cgi) = @_;
470
471    # Get the member, or return an error code if not found
472
0
    my $borrowernumber = $cgi->param('patron_id');
473
0
    my $borrower = GetMemberDetails( $borrowernumber );
474
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
475
476    # Get the item, or return an error code if not found
477
0
    my $itemnumber = $cgi->param('item_id');
478
0
    my $item = GetItem( $itemnumber );
479
0
    return { code => 'RecordNotFound' } unless $$item{itemnumber};
480
481
0
    my @availablefor;
482
483    # Reserve level management
484
0
    my $biblionumber = $item->{'biblionumber'};
485
0
    my $canbookbereserved = CanBookBeReserved( $borrower, $biblionumber );
486
0
    if ($canbookbereserved) {
487
0
        push @availablefor, 'title level hold';
488
0
        my $canitembereserved = IsAvailableForItemLevelRequest($itemnumber);
489
0
        if ($canitembereserved) {
490
0
            push @availablefor, 'item level hold';
491        }
492    }
493
494    # Reserve cancellation management
495
0
    my @reserves = GetReservesFromBorrowernumber( $borrowernumber, undef );
496
0
    my @reserveditems;
497
0
    foreach my $reserve (@reserves) {
498
0
        push @reserveditems, $reserve->{'itemnumber'};
499    }
500
0
0
    if ( grep { $itemnumber eq $_ } @reserveditems ) {
501
0
        push @availablefor, 'hold cancellation';
502    }
503
504    # Renewal management
505
0
    my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
506
0
    if ( $renewal[0] ) {
507
0
        push @availablefor, 'loan renewal';
508    }
509
510    # Issuing management
511
0
    my $barcode = $item->{'barcode'} || '';
512
0
    $barcode = barcodedecode($barcode) if ( $barcode && C4::Context->preference('itemBarcodeInputFilter') );
513
0
    if ($barcode) {
514
0
        my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $borrower, $barcode );
515
516        # TODO push @availablefor, 'loan';
517    }
518
519
0
    my $out;
520
0
    $out->{'AvailableFor'} = \@availablefor;
521
522
0
    return $out;
523}
524
525 - 538
=head2 RenewLoan

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 

=cut
539
540sub RenewLoan {
541
0
    my ($cgi) = @_;
542
543    # Get borrower infos or return an error code
544
0
    my $borrowernumber = $cgi->param('patron_id');
545
0
    my $borrower = GetMemberDetails( $borrowernumber );
546
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
547
548    # Get the item, or return an error code
549
0
    my $itemnumber = $cgi->param('item_id');
550
0
    my $item = GetItem( $itemnumber );
551
0
    return { code => 'RecordNotFound' } unless $$item{itemnumber};
552
553    # Add renewal if possible
554
0
    my @renewal = CanBookBeRenewed( $borrowernumber, $itemnumber );
555
0
0
    if ( $renewal[0] ) { AddRenewal( $borrowernumber, $itemnumber ); }
556
557
0
    my $issue = GetItemIssue($itemnumber);
558
559    # Hashref building
560
0
    my $out;
561
0
    $out->{'renewals'} = $issue->{'renewals'};
562
0
    $out->{date_due} = $issue->{date_due}->strftime('%Y-%m-%d %H:%S');
563
0
    $out->{'success'} = $renewal[0];
564
0
    $out->{'error'} = $renewal[1];
565
566
0
    return $out;
567}
568
569 - 588
=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 

=cut
589
590sub HoldTitle {
591
0
    my ($cgi) = @_;
592
593    # Get the borrower or return an error code
594
0
    my $borrowernumber = $cgi->param('patron_id');
595
0
    my $borrower = GetMemberDetails( $borrowernumber );
596
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
597
598    # Get the biblio record, or return an error code
599
0
    my $biblionumber = $cgi->param('bib_id');
600
0
    my ( $count, $biblio ) = GetBiblio( $biblionumber );
601
0
    return { code => 'RecordNotFound' } unless $$biblio{biblionumber};
602
603
0
    my $title = $$biblio{title};
604
605    # Check if the biblio can be reserved
606
0
    return { code => 'NotHoldable' } unless CanBookBeReserved( $borrowernumber, $biblionumber );
607
608
0
    my $branch;
609
610    # Pickup branch management
611
0
    if ( $cgi->param('pickup_location') ) {
612
0
        $branch = $cgi->param('pickup_location');
613
0
        my $branches = GetBranches;
614
0
        return { code => 'LocationNotFound' } unless $$branches{$branch};
615    } else { # if the request provide no branch, use the borrower's branch
616
0
        $branch = $$borrower{branchcode};
617    }
618
619    # Add the reserve
620    # $branch, $borrowernumber, $biblionumber, $constraint, $bibitems, $priority, $notes, $title, $checkitem, $found
621
0
    AddReserve( $branch, $borrowernumber, $biblionumber, 'a', undef, 0, undef, $title, undef, undef );
622
623    # Hashref building
624
0
    my $out;
625
0
    $out->{'title'} = $title;
626
0
    $out->{'pickup_location'} = GetBranchName($branch);
627
628    # TODO $out->{'date_available'} = '';
629
630
0
    return $out;
631}
632
633 - 653
=head2 HoldItem

Creates, for a borrower, an item-level hold request on a specific item of 
a bibliographic record in Koha.

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 

=cut
654
655sub HoldItem {
656
0
    my ($cgi) = @_;
657
658    # Get the borrower or return an error code
659
0
    my $borrowernumber = $cgi->param('patron_id');
660
0
    my $borrower = GetMemberDetails( $borrowernumber );
661
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
662
663    # Get the biblio or return an error code
664
0
    my $biblionumber = $cgi->param('bib_id');
665
0
    my ( $count, $biblio ) = GetBiblio($biblionumber);
666
0
    return { code => 'RecordNotFound' } unless $$biblio{biblionumber};
667
668
0
    my $title = $$biblio{title};
669
670    # Get the item or return an error code
671
0
    my $itemnumber = $cgi->param('item_id');
672
0
    my $item = GetItem( $itemnumber );
673
0
    return { code => 'RecordNotFound' } unless $$item{itemnumber};
674
675    # If the biblio does not match the item, return an error code
676
0
    return { code => 'RecordNotFound' } if $$item{biblionumber} ne $$biblio{biblionumber};
677
678    # Check for item disponibility
679
0
    my $canitembereserved = CanItemBeReserved( $borrowernumber, $itemnumber );
680
0
    my $canbookbereserved = CanBookBeReserved( $borrowernumber, $biblionumber );
681
0
    return { code => 'NotHoldable' } unless $canbookbereserved and $canitembereserved;
682
683
0
    my $branch;
684
685    # Pickup branch management
686
0
    if ( $cgi->param('pickup_location') ) {
687
0
        $branch = $cgi->param('pickup_location');
688
0
        my $branches = GetBranches();
689
0
        return { code => 'LocationNotFound' } unless $$branches{$branch};
690    } else { # if the request provide no branch, use the borrower's branch
691
0
        $branch = $$borrower{branchcode};
692    }
693
694
0
    my $rank;
695
0
    my $found;
696
697    # Get rank and found
698
0
    $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
699
0
    if ( $item->{'holdingbranch'} eq $branch ) {
700
0
        $found = 'W' unless C4::Context->preference('ReservesNeedReturns');
701    }
702
703    # Add the reserve
704    # $branch, $borrowernumber, $biblionumber, $constraint, $bibitems, $priority, $notes, $title, $checkitem, $found
705
0
    AddReserve( $branch, $borrowernumber, $biblionumber, 'a', undef, $rank, undef, $title, $itemnumber, $found );
706
707    # Hashref building
708
0
    my $out;
709
0
    $out->{'pickup_location'} = GetBranchName($branch);
710
711    # TODO $out->{'date_available'} = '';
712
713
0
    return $out;
714}
715
716 - 727
=head2 CancelHold

Cancels an active reserve request for the borrower.

Parameters:

  - patron_id (Required)
	a borrowernumber
  - item_id (Required)
	an itemnumber 

=cut
728
729sub CancelHold {
730
0
    my ($cgi) = @_;
731
732    # Get the borrower or return an error code
733
0
    my $borrowernumber = $cgi->param('patron_id');
734
0
    my $borrower = GetMemberDetails( $borrowernumber );
735
0
    return { code => 'PatronNotFound' } unless $$borrower{borrowernumber};
736
737    # Get the item or return an error code
738
0
    my $itemnumber = $cgi->param('item_id');
739
0
    my $item = GetItem( $itemnumber );
740
0
    return { code => 'RecordNotFound' } unless $$item{itemnumber};
741
742    # Get borrower's reserves
743
0
    my @reserves = GetReservesFromBorrowernumber( $borrowernumber, undef );
744
0
    my @reserveditems;
745
746    # ...and loop over it to build an array of reserved itemnumbers
747
0
    foreach my $reserve (@reserves) {
748
0
        push @reserveditems, $reserve->{'itemnumber'};
749    }
750
751    # if the item was not reserved by the borrower, returns an error code
752
0
0
    return { code => 'NotCanceled' } unless any { $itemnumber eq $_ } @reserveditems;
753
754    # Cancel the reserve
755
0
    CancelReserve( $itemnumber, undef, $borrowernumber );
756
757
0
    return { code => 'Canceled' };
758}
759
7601;