Allow SIP checkout to pre-empt unfilled holds.
[koha.git] / C4 / SIP / ILS / Item.pm
index 2107458..b32ea92 100644 (file)
@@ -81,13 +81,14 @@ sub new {
        my ($class, $item_id) = @_;
        my $type = ref($class) || $class;
        my $self;
-       my $item = GetBiblioFromItemNumber( GetItemnumberFromBarcode($item_id) );
-       
+    my $itemnumber = GetItemnumberFromBarcode($item_id);
+       my $item = GetBiblioFromItemNumber($itemnumber);
        if (! $item) {
                syslog("LOG_DEBUG", "new ILS::Item('%s'): not found", $item_id);
                warn "new ILS::Item($item_id) : No item '$item_id'.";
                return undef;
        }
+    $item->{itemnumber} = $itemnumber;
     $item->{'id'} = $item->{'barcode'};
        # check if its on issue and if so get the borrower
        my $issue = GetItemIssue($item->{'itemnumber'});
@@ -95,7 +96,8 @@ sub new {
        $item->{patron} = $borrower->{'cardnumber'};
        my @reserves = (@{ GetReservesFromBiblionumber($item->{biblionumber}) });
        $item->{hold_queue} = [ sort priority_sort @reserves ];
-       # $item->{joetest} = 111;
+       $item->{hold_shelf}    = [( grep {   defined $_->{found}  and $_->{found} eq 'W' } @{$item->{hold_queue}} )];
+       $item->{pending_queue} = [( grep {(! defined $_->{found}) or ($_->{found} ne 'W')} @{$item->{hold_queue}} )];
        $self = $item;
        bless $self, $type;
 
@@ -178,6 +180,16 @@ sub hold_queue {
        (defined $self->{hold_queue}) or return [];
     return $self->{hold_queue};
 }
+sub pending_queue {
+    my $self = shift;
+       (defined $self->{pending_queue}) or return [];
+    return $self->{pending_queue};
+}
+sub hold_shelf {
+    my $self = shift;
+       (defined $self->{hold_shelf}) or return [];
+    return $self->{hold_shelf};
+}
 
 sub hold_queue_position {
        my ($self, $patron_id) = @_;
@@ -216,38 +228,55 @@ sub print_line {
 
 # This is a partial check of "availability".  It is not supposed to check everything here.
 # An item is available for a patron if it is:
-# 1) checked out to the same patron and there's no hold queue
+# 1) checked out to the same patron 
+#    AND no pending (i.e. non-W) hold queue
 # OR
-# 2) not checked out and (there's no hold queue OR patron
-#    is at the front of the queue)
+# 2) not checked out
+#    AND (not on hold_shelf OR is on hold_shelf for patron)
+#
+# What this means is we are consciously allowing the patron to checkout (but not renew) an item that DOES
+# have non-W holds on it, but has not been "picked" from the stacks.  That is to say, the
+# patron has retrieved the item before the librarian.
+#
+# We don't check if the patron is at the front of the pending queue in the first case, because
+# they should not be able to place a hold on an item they already have.
+
 sub available {
        my ($self, $for_patron) = @_;
-       my $count = (defined $self->{hold_queue}) ? scalar @{$self->{hold_queue}} : 0;
-       $debug and print STDERR "availability check: hold_queue size $count\n";
+       my $count  = (defined $self->{pending_queue}) ? scalar @{$self->{pending_queue}} : 0;
+       my $count2 = (defined $self->{hold_shelf}   ) ? scalar @{$self->{hold_shelf}   } : 0;
+       $debug and print STDERR "availability check: pending_queue size $count, hold_shelf size $count2\n";
     if (defined($self->{patron_id})) {
                ($self->{patron_id} eq $for_patron) or return 0;
                return ($count ? 0 : 1);
        } else {        # not checked out
-               ($count) or return 1;
-               ($self->barcode_is_borrowernumber($for_patron, $self->{hold_queue}[0]->{borrowernumber})) and return 1;
+        ($count2) and return $self->barcode_is_borrowernumber($for_patron, $self->{hold_shelf}[0]->{borrowernumber});
        }
        return 0;
 }
 
-sub barcode_to_borrowernumber ($) {
+sub _barcode_to_borrowernumber ($) {
     my $known = shift;
     (defined($known)) or return undef;
-    my $member = GetMember($known) or return undef; # borrowernumber is default type for GetMember lookup
-    return $member->{cardnumber};
+    my $member = GetMember($known,'cardnumber') or return undef;
+    return $member->{borrowernumber};
 }
 sub barcode_is_borrowernumber ($$$) {    # because hold_queue only has borrowernumber...
     my $self = shift;   # not really used
     my $barcode = shift;
     my $number  = shift or return undef;    # can't be zero
     (defined($barcode)) or return undef;    # might be 0 or 000 or 000000
-    my $converted = barcode_to_borrowernumber($barcode) or return undef;
+    my $converted = _barcode_to_borrowernumber($barcode) or return undef;
     return ($number eq $converted); # even though both *should* be numbers, eq is safer.
 }
+sub fill_reserve ($$) {
+    my $self = shift;
+    my $hold = shift or return undef;
+    foreach (qw(biblionumber borrowernumber reservedate)) {
+        $hold->{$_} or return undef;
+    }
+    return ModReserveFill($hold);
+}
 1;
 __END__