[Koha-patches] [PATCH 1/3] bug 3435: SIP Checkin extension for 3M SmartChute - partial
Galen Charlton
galen.charlton at liblime.com
Thu Jul 30 02:56:06 CEST 2009
From: Joe Atzberger <joe.atzberger at liblime.com>
Signed-off-by: Galen Charlton <galen.charlton at liblime.com>
---
C4/Reserves.pm | 81 +++++++++-------------
C4/SIP/ILS.pm | 2 +-
C4/SIP/ILS/Item.pm | 137 ++++++++++++++++++++++++++----------
C4/SIP/ILS/Item.pod | 52 +++++++-------
C4/SIP/ILS/Transaction/Checkin.pm | 10 ++--
C4/SIP/Sip/MsgType.pm | 25 +++----
6 files changed, 176 insertions(+), 131 deletions(-)
diff --git a/C4/Reserves.pm b/C4/Reserves.pm
index fca00f6..11846e7 100644
--- a/C4/Reserves.pm
+++ b/C4/Reserves.pm
@@ -559,6 +559,7 @@ sub GetReservesForBranch {
=item CheckReserves
($status, $reserve) = &CheckReserves($itemnumber);
+ ($status, $reserve) = &CheckReserves(undef, $barcode);
Find a book in the reserves.
@@ -586,65 +587,50 @@ sub CheckReserves {
my ( $item, $barcode ) = @_;
my $dbh = C4::Context->dbh;
my $sth;
+ my $select = "
+ SELECT items.biblionumber,
+ items.biblioitemnumber,
+ itemtypes.notforloan,
+ items.notforloan AS itemnotforloan,
+ items.itemnumber
+ FROM items
+ LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
+ LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
+ ";
+
if ($item) {
- my $qitem = $dbh->quote($item);
- # Look up the item by itemnumber
- my $query = "
- SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan, items.notforloan AS itemnotforloan
- FROM items
- LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
- LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
- WHERE itemnumber=$qitem
- ";
- $sth = $dbh->prepare($query);
+ $sth = $dbh->prepare("$select WHERE itemnumber = ?");
+ $sth->execute($item);
}
else {
- my $qbc = $dbh->quote($barcode);
- # Look up the item by barcode
- my $query = "
- SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan, items.notforloan AS itemnotforloan
- FROM items
- LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber
- LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
- WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
- AND biblioitems.itemtype = itemtypes.itemtype
- AND barcode=$qbc
- ";
- $sth = $dbh->prepare($query);
-
- # FIXME - This function uses $item later on. Ought to set it here.
+ $sth = $dbh->prepare("$select WHERE barcode = ?");
+ $sth->execute($barcode);
}
- $sth->execute;
- my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item ) = $sth->fetchrow_array;
- $sth->finish;
+ # note: we get the itemnumber because we might have started w/ just the barcode. Now we know for sure we have it.
+ my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item, $itemnumber ) = $sth->fetchrow_array;
+
+ return ( 0, 0 ) unless $itemnumber; # bail if we got nothing.
+
# if item is not for loan it cannot be reserved either.....
- # execption to notforloan is where items.notforloan < 0 : This indicates the item is holdable.
+ # execpt where items.notforloan < 0 : This indicates the item is holdable.
return ( 0, 0 ) if ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype;
- # get the reserves...
# Find this item in the reserves
- my @reserves = _Findgroupreserve( $bibitem, $biblio, $item );
- my $count = scalar @reserves;
+ my @reserves = _Findgroupreserve( $bibitem, $biblio, $itemnumber );
# $priority and $highest are used to find the most important item
# in the list returned by &_Findgroupreserve. (The lower $priority,
# the more important the item.)
# $highest is the most important item we've seen so far.
- my $priority = 10000000;
my $highest;
- if ($count) {
+ if (scalar @reserves) {
+ my $priority = 10000000;
foreach my $res (@reserves) {
- # FIXME - $item might be undefined or empty: the caller
- # might be searching by barcode.
- if ( $res->{'itemnumber'} == $item && $res->{'priority'} == 0) {
- # Found it
- return ( "Waiting", $res );
- }
- else {
- # See if this item is more important than what we've got
- # so far.
- if ( $res->{'priority'} != 0 && $res->{'priority'} < $priority )
- {
+ if ( $res->{'itemnumber'} == $itemnumber && $res->{'priority'} == 0) {
+ return ( "Waiting", $res ); # Found it
+ } else {
+ # See if this item is more important than what we've got so far
+ if ( $res->{'priority'} && $res->{'priority'} < $priority ) {
$priority = $res->{'priority'};
$highest = $res;
}
@@ -652,10 +638,9 @@ sub CheckReserves {
}
}
- # If we get this far, then no exact match was found. Print the
- # most important item on the list. I think this tells us who's
- # next in line to get this book.
- if ($highest) { # FIXME - $highest might be undefined
+ # If we get this far, then no exact match was found.
+ # We return the most important (i.e. next) reservation.
+ if ($highest) {
$highest->{'itemnumber'} = $item;
return ( "Reserved", $highest );
}
diff --git a/C4/SIP/ILS.pm b/C4/SIP/ILS.pm
index 09c454f..b1e516a 100644
--- a/C4/SIP/ILS.pm
+++ b/C4/SIP/ILS.pm
@@ -157,7 +157,7 @@ sub checkout {
$item->{patron} = $patron_id;
$item->{due_date} = $circ->{due};
push(@{$patron->{items}}, $item_id);
- $circ->desensitize(!$item->magnetic);
+ $circ->desensitize(!$item->magnetic_media);
syslog("LOG_DEBUG", "ILS::Checkout: patron %s has checked out %s",
$patron_id, join(', ', @{$patron->{items}}));
diff --git a/C4/SIP/ILS/Item.pm b/C4/SIP/ILS/Item.pm
index b32ea92..28cd4bb 100644
--- a/C4/SIP/ILS/Item.pm
+++ b/C4/SIP/ILS/Item.pm
@@ -1,8 +1,7 @@
#
# ILS::Item.pm
#
-# A Class for hiding the ILS's concept of the item from the OpenSIP
-# system
+# A Class for hiding the ILS's concept of the item from OpenSIP
#
package ILS::Item;
@@ -11,6 +10,7 @@ use strict;
use warnings;
use Sys::Syslog qw(syslog);
+use Carp;
use ILS::Transaction;
@@ -25,7 +25,7 @@ use C4::Reserves;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
BEGIN {
- $VERSION = 2.10;
+ $VERSION = 2.11;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw();
@@ -82,22 +82,27 @@ sub new {
my $type = ref($class) || $class;
my $self;
my $itemnumber = GetItemnumberFromBarcode($item_id);
- my $item = GetBiblioFromItemNumber($itemnumber);
+ my $item = GetBiblioFromItemNumber($itemnumber); # actually biblio.*, biblioitems.* AND items.* (overkill)
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'};
+ $item->{ 'itemnumber' } = $itemnumber;
+ $item->{ 'id' } = $item->{barcode}; # to SIP, the barcode IS the id.
+ $item->{permanent_location}= $item->{homebranch};
+ $item->{'collection_code'} = $item->{ccode};
+ $item->{ 'call_number' } = $item->{itemcallnumber};
+ # $item->{'destination_loc'} = ?
+
# check if its on issue and if so get the borrower
my $issue = GetItemIssue($item->{'itemnumber'});
my $borrower = GetMember($issue->{'borrowernumber'},'borrowernumber');
$item->{patron} = $borrower->{'cardnumber'};
- my @reserves = (@{ GetReservesFromBiblionumber($item->{biblionumber}) });
- $item->{hold_queue} = [ sort priority_sort @reserves ];
+ my ($whatever, $arrayref) = GetReservesFromBiblionumber($item->{biblionumber});
+ $item->{hold_queue} = [ sort priority_sort @$arrayref ];
$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}} )];
+ $item->{pending_queue} = [( grep {(! defined $_->{found}) or $_->{found} ne 'W' } @{$item->{hold_queue}} )];
$self = $item;
bless $self, $type;
@@ -107,17 +112,93 @@ sub new {
return $self;
}
-sub magnetic {
- my $self = shift;
- return $self->{magnetic_media};
+# 0 means read-only
+# 1 means read/write
+
+my %fields = (
+ id => 0,
+ sip_media_type => 0,
+ sip_item_properties => 0,
+ magnetic_media => 0,
+ permanent_location => 0,
+ current_location => 0,
+ print_line => 1,
+ screen_msg => 1,
+ itemnumber => 0,
+ biblionumber => 0,
+ barcode => 0,
+ onloan => 0,
+ collection_code => 0,
+ call_number => 0,
+ enumchron => 0,
+ location => 0,
+ author => 0,
+ title => 0,
+);
+
+sub next_hold {
+ my $self = shift or return;
+ foreach (@$self->{hold_shelf}) { # If this item was taken from the hold shelf, then that reserve still governs
+ next unless ($_->{itemnumber} and $_->{itemnumber} == $self->{itemnumber});
+ return $_;
+ }
+ if (scalar @$self->{pending_queue}) { # Otherwise, if there is at least one hold, the first (best priority) gets it
+ return $self->{pending_queue}->[0];
+ }
+ return;
}
-sub sip_media_type {
- my $self = shift;
- return $self->{sip_media_type};
+
+sub hold_patron_id {
+ my $self = shift or return;
+ my $hold = $self->next_hold() or return;
+ return $hold->{borrowernumber};
+}
+sub hold_patron_name {
+ my $self = shift or return;
+ # return $self->{hold_patron_name} if $self->{hold_patron_name}; TODO: consider caching
+ my $borrowernumber = (@_ ? shift: $self->hold_patron_id()) or return;
+ my $holder = GetMember($borrowernumber, 'borrowernumber');
+ unless ($holder) {
+ syslog("LOG_ERR", "While checking hold, GetMember failed for borrowernumber '$borrowernumber'");
+ return;
+ }
+ my $email = $holder{email} || '';
+ my $phone = $holder{phone} || '';
+ my $extra = ($email and $phone) ? " ($email, $phone)" : # both populated, employ comma
+ ($email or $phone) ? " ($email$phone)" : # only 1 populated, we don't care which: no comma
+ "" ; # niether populated, empty string
+ my $name = $holder->{firstname} ? $holder->{firstname} . ' ' : '';
+ $name .= $holder->{surname} . $extra;
+ # $self->{hold_patron_name} = $name; # TODO: consider caching
+ return $name;
+}
+sub destination_loc {
+ my $self = shift or return;
+ my $hold = $self->next_hold();
+ return ($hold ? $hold->{branchcode}
}
-sub sip_item_properties {
+
+our $AUTOLOAD;
+
+sub DESTROY { } # keeps AUTOLOAD from catching inherent DESTROY calls
+
+sub AUTOLOAD {
my $self = shift;
- return $self->{sip_item_properties};
+ my $class = ref($self) or croak "$self is not an object";
+ my $name = $AUTOLOAD;
+
+ $name =~ s/.*://;
+
+ unless (exists $fields{$name}) {
+ croak "Cannot access '$name' field of class '$class'";
+ }
+
+ if (@_) {
+ $fields{$name} or croak "Field '$name' of class '$class' is READ ONLY.";
+ return $self->{$name} = shift;
+ } else {
+ return $self->{$name};
+ }
}
sub status_update { # FIXME: this looks unimplemented
@@ -128,22 +209,10 @@ sub status_update { # FIXME: this looks unimplemented
return $status;
}
-sub id {
- my $self = shift;
- return $self->{id};
-}
sub title_id {
my $self = shift;
return $self->{title};
}
-sub permanent_location {
- my $self = shift;
- return $self->{permanent_location} || '';
-}
-sub current_location {
- my $self = shift;
- return $self->{current_location} || '';
-}
sub sip_circulation_status {
my $self = shift;
@@ -173,7 +242,7 @@ sub fee_currency {
}
sub owner {
my $self = shift;
- return 'CPL'; # FIXME: UWOLS was hardcoded
+ return $self->{homebranch};
}
sub hold_queue {
my $self = shift;
@@ -217,14 +286,6 @@ sub hold_pickup_date {
my $self = shift;
return $self->{hold_pickup_date} || 0;
}
-sub screen_msg {
- my $self = shift;
- return $self->{screen_msg} || '';
-}
-sub print_line {
- my $self = shift;
- return $self->{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:
diff --git a/C4/SIP/ILS/Item.pod b/C4/SIP/ILS/Item.pod
index e4ba8c1..29f6761 100644
--- a/C4/SIP/ILS/Item.pod
+++ b/C4/SIP/ILS/Item.pod
@@ -11,30 +11,30 @@ ILS::Item - Portable Item status object class for SIP
my $item = new ILS::Item $item_id;
# Basic object access methods
- $item_id = $item->id;
- $title = $item->title_id;
- $media_type = $item->sip_media_type;
- $bool = $item->magnetic;
- $locn = $item->permanent_location;
- $locn = $item->current_location;
- $props = $item->sip_item_props;
- $owner = $item->owner;
- $str = $item->sip_circulation_status;
- $bool = $item->available;
- @hold_queue = $item->hold_queue;
- $pos = $item->hold_queue_position($patron_id);
- $due = $item->due_date;
- $pickup = $item->hold_pickup_date;
- $recall = $item->recall_date;
- $fee = $item->fee;
- $currency = $item->fee_currency;
- $type = $item->sip_fee_type;
- $mark = $item->sip_security_marker;
- $msg = $item->screen_msg;
- $msg = $item->print_line;
-
- # Operations on items
- $status = $item->status_update($item_props);
+ $item_id = $item->id;
+ $title = $item->title_id;
+ $media_type = $item->sip_media_type;
+ $bool = $item->magnetic_media;
+ $locn = $item->permanent_location;
+ $locn = $item->current_location;
+ $props = $item->sip_item_props;
+ $owner = $item->owner;
+ $str = $item->sip_circulation_status;
+ $bool = $item->available;
+ @hold_queue = $item->hold_queue;
+ $pos = $item->hold_queue_position($patron_id);
+ $due = $item->due_date;
+ $pickup = $item->hold_pickup_date;
+ $recall = $item->recall_date;
+ $fee = $item->fee;
+ $currency = $item->fee_currency;
+ $type = $item->sip_fee_type;
+ $mark = $item->sip_security_marker;
+ $msg = $item->screen_msg;
+ $msg = $item->print_line;
+
+ # Operations on items
+ $status = $item->status_update($item_props);
=head1 DESCRIPTION
@@ -93,9 +93,9 @@ behavior at all; it merely passes it through to the self-service
terminal. In particular, it does not set indicators related to
whether an item is magnetic, or whether it should be
desensitized, based on this return type. The
-C<$item-E<gt>magnetic> method will be used for that purpose.
+C<$item-E<gt>magnetic_media> method will be used for that purpose.
-=item C<magnetic>
+=item C<magnetic_media>
Is the item some form of magnetic media (eg, a video or a book
with an accompanying floppy)? This method will not be called
diff --git a/C4/SIP/ILS/Transaction/Checkin.pm b/C4/SIP/ILS/Transaction/Checkin.pm
index 6c4f360..fd5f861 100644
--- a/C4/SIP/ILS/Transaction/Checkin.pm
+++ b/C4/SIP/ILS/Transaction/Checkin.pm
@@ -7,7 +7,7 @@ package ILS::Transaction::Checkin;
use warnings;
use strict;
-use POSIX qw(strftime);
+# use POSIX qw(strftime);
use ILS;
use ILS::Transaction;
@@ -31,7 +31,7 @@ my %fields = (
sub new {
my $class = shift;
- my $self = $class->SUPER::new();
+ my $self = $class->SUPER::new(); # start with an ILS::Transaction object
foreach (keys %fields) {
$self->{_permitted}->{$_} = $fields{$_}; # overlaying _permitted
@@ -59,7 +59,7 @@ sub do_checkin {
$self->alert_type('99');
}
}
- defined $self->alert_type and $self->alert(1); # alert_type could be "00"
+ $self->alert(1) if defined $self->alert_type; # alert_type could be "00"
$self->ok($return);
}
@@ -69,7 +69,7 @@ sub resensitize {
warn "no item found in object to resensitize";
return;
}
- return !$self->{item}->magnetic;
+ return !$self->{item}->magnetic_media;
}
sub patron_id {
@@ -78,7 +78,7 @@ sub patron_id {
warn "no patron found in object";
return;
}
- return !$self->{patron}->id;
+ return $self->{patron}->id;
}
1;
diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm
index 16b1506..01e094f 100644
--- a/C4/SIP/Sip/MsgType.pm
+++ b/C4/SIP/Sip/MsgType.pm
@@ -531,7 +531,7 @@ sub handle_checkout {
$resp = CHECKOUT_RESP . '1';
$resp .= sipbool($status->renew_ok);
if ($ils->supports('magnetic media')) {
- $resp .= sipbool($item->magnetic);
+ $resp .= sipbool($item->magnetic_media);
} else {
$resp .= 'U';
}
@@ -634,10 +634,9 @@ sub handle_checkin {
$resp .= $status->ok ? '1' : '0';
$resp .= $status->resensitize ? 'Y' : 'N';
if ($item && $ils->supports('magnetic media')) {
- $resp .= sipbool($item->magnetic);
+ $resp .= sipbool($item->magnetic_media);
} else {
- # The item barcode was invalid or the system doesn't support
- # the 'magnetic media' indicator
+ # item barcode is invalid or system doesn't support 'magnetic media' indicator
$resp .= 'U';
}
$resp .= $status->alert ? 'Y' : 'N';
@@ -656,17 +655,17 @@ sub handle_checkin {
$resp .= add_field(FID_PATRON_ID, $patron->id);
}
if ($item) {
- $resp .= maybe_add(FID_MEDIA_TYPE, $item->sip_media_type );
- $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
- # $resp .= maybe_add(FID_COLLECTION_CODE, $item->collection_code );
- # $resp .= maybe_add(FID_CALL_NUMBER, $item->call_number );
- # $resp .= maybe_add(FID_DESTINATION, $item->destination_loc );
- # $resp .= maybe_add(FID_ALERT_TYPE, $item->alert_type );
- # $resp .= maybe_add(FID_PATRON_ID, $item->hold_patron_id );
- # $resp .= maybe_add(FID_PATRON_NAME, $item->hold_patron_name );
+ $resp .= maybe_add(FID_MEDIA_TYPE, $item->sip_media_type );
+ $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
+ $resp .= maybe_add(FID_COLLECTION_CODE, $item->collection_code );
+ $resp .= maybe_add(FID_CALL_NUMBER, $item->call_number );
+ $resp .= maybe_add(FID_DESTINATION_LOCATION, $item->destination_loc );
+ $resp .= maybe_add(FID_HOLD_PATRON_ID, $item->hold_patron_id );
+ $resp .= maybe_add(FID_HOLD_PATRON_NAME, $item->hold_patron_name );
}
}
+ $resp .= maybe_add(FID_ALERT_TYPE, $status->alert_type) if $status->alert;
$resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
$resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
@@ -1328,7 +1327,7 @@ sub handle_renew {
$resp .= '1';
$resp .= $status->renewal_ok ? 'Y' : 'N';
if ($ils->supports('magnetic media')) {
- $resp .= sipbool($item->magnetic);
+ $resp .= sipbool($item->magnetic_media);
} else {
$resp .= 'U';
}
--
1.5.6.5
More information about the Koha-patches
mailing list