From 8b8efeeb42547a0a2153a565c84aadfd0fe7f1ec Mon Sep 17 00:00:00 2001 From: Christophe Croullebois Date: Mon, 25 May 2015 15:41:21 +0200 Subject: [PATCH 1/1] Bug 20517: SIP bin sorting Robot handling --- C4/SIP/ILS.pm | 103 +++++++++++++++++++++++++++++++++++++++++++++ C4/SIP/ILS/Item.pm | 4 ++ C4/SIP/Sip/MsgType.pm | 11 ++--- etc/SIPconfig.xml | 11 +++-- etc/sortbin_reserves.yaml | 6 +++ etc/sortbin_transform.yaml | 40 ++++++++++++++++++ 6 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 etc/sortbin_reserves.yaml create mode 100644 etc/sortbin_transform.yaml diff --git a/C4/SIP/ILS.pm b/C4/SIP/ILS.pm index 1bd23c6..070eba4 100644 --- a/C4/SIP/ILS.pm +++ b/C4/SIP/ILS.pm @@ -7,6 +7,9 @@ package C4::SIP::ILS; use warnings; use strict; use Sys::Syslog qw(syslog); +use YAML qw(LoadFile Dump); +use MARC::Record; +use MARC::Transform; use Data::Dumper; use C4::SIP::ILS::Item; @@ -18,6 +21,7 @@ use C4::SIP::ILS::Transaction::FeePayment; use C4::SIP::ILS::Transaction::Hold; use C4::SIP::ILS::Transaction::Renew; use C4::SIP::ILS::Transaction::RenewAll; +use C4::Biblio qw(GetMarcBiblio); my $debug = 0; @@ -206,6 +210,7 @@ sub checkin { $circ->item( $item = C4::SIP::ILS::Item->new($item_id) ); if ($item) { + $self->_sortbin_checkin($item); # Call sorting robot handling $circ->do_checkin( $current_loc, $return_date ); } else { @@ -243,6 +248,104 @@ sub checkin { return $circ; } +# "SORTING ROBOT" HANDLING +sub _sortbin_checkin { + my ( $self, $item ) = @_; + return unless defined $item; + + # to activate this code, it is necessary to add a few parameters in SIPconfig.xml + # For the institution which will use the robot, add the following parameters + # in the "sortbin" tag: + # status="1" -> 1 to activate the module + # subfield="995z" -> subfield which contains the value of the destination bin + # transform="1" -> useful if the destination subfield has to be constructed + # by checking the values of other fields, this way you can create a virtual subfield + # which doesn't need to be configured in the MARC biblio framework. + # transform_config_file="/home/koha/etc/sortbin_transform.yaml" -> absolute path to the sortbin config file. + # reserve_config_file="/home/koha/etc/sortbin_reserves.yaml" -> absolute path to the reserve sortbin config file. + + my $sortbin_status; + my $sortbin_subfield; + my $sortbin_transform; + my $sortbin_transform_path; + my $sortbin_reserve_path; + + if ( defined $self->{institution}->{sortbin} ) { + $sortbin_status = $self->{institution}->{sortbin}->{status} + if ( defined $self->{institution}->{sortbin}->{status} ); + $sortbin_subfield = $self->{institution}->{sortbin}->{subfield} + if ( defined $self->{institution}->{sortbin}->{subfield} ); + $sortbin_transform = $self->{institution}->{sortbin}->{transform} + if ( defined $self->{institution}->{sortbin}->{transform} ); + $sortbin_transform_path = $self->{institution}->{sortbin}->{transform_config_file} + if ( defined $self->{institution}->{sortbin}->{transform_config_file} ); + $sortbin_reserve_path = $self->{institution}->{sortbin}->{reserve_config_file} + if ( defined $self->{institution}->{sortbin}->{reserve_config_file} ); + } + + # Test feature is turned on + unless ( $sortbin_status == 1 ) { + return; + } + + unless ( defined $sortbin_subfield ) { + syslog( "LOG_ERR", "sortbin subfield must be defined" ); + return; + } + my $marc_record_obj = C4::Biblio::GetMarcBiblio($item->{'biblionumber'}); + unless ( defined $marc_record_obj ) { + syslog( "LOG_ERR", "sortbin error calling GetMarcBiblio on biblionumber=%s", $item->{'biblionumber'} ); + return; + } + + # We add the 995 field related to the item, to run marctransform with only this one. + my @itemnumbers = ( $item->{'itemnumber'} ); + C4::Biblio::EmbedItemsInMarcBiblio($marc_record_obj, $item->{'biblionumber'}, \@itemnumbers); + + # We look for the sortbin number + $item->{'sort_bin'} = undef; + + # priority to holds + # if the document is reserved + # and if the yaml file dedicated to holds contains something else than 0 in "sortbin_reserves" + # then the document goes to the reserves bin + my @reserves = @{ $item->{'hold_queue'} }; + if ( scalar @reserves > 0 ) { + my $sortbin_reserves_config = LoadFile($sortbin_reserve_path); + if ( $sortbin_reserves_config->{'sortbin_reserves'} != 0 ) { + $item->{'sort_bin'} = $sortbin_reserves_config->{'sortbin_reserves'}; + } + } + + # if the item is not reserved, proceed to the standard sort + if ( !defined $item->{'sort_bin'} ) { + if ( $sortbin_transform == 1 ) { + + # In Transform mode, we create a virtuel MARC field, + # based on the values of other fields + # The conversion is defined in a yaml file, + # check the MARC::Transform doc for more information + # The goal is to obtain a single MARC subfield containing the + # value the bin where the document will have to be redirected, + # with MARC::Transform you can create this subfield by checking + # the values of several other MARC fields + MARC::Transform->new( $marc_record_obj, $sortbin_transform_path ); + } + + # obtained through Transform mode or already available in DB, + # the MARC subfield containing the destination bin value is now available + my $field = substr( $sortbin_subfield, 0, 3 ); + my $subfield = substr( $sortbin_subfield, 3, 1 ); + if ( defined $marc_record_obj->subfield( $field, $subfield ) ) { + $item->{'sort_bin'} = $marc_record_obj->subfield( $field, $subfield ); + } + else { + syslog( "LOG_ERR", "sortbin undefined value in subfield %s", $sortbin_subfield ); + return; + } + } +} + # If the ILS caches patron information, this lets it free # it up sub end_patron_session { diff --git a/C4/SIP/ILS/Item.pm b/C4/SIP/ILS/Item.pm index 240e199..7c90b2d 100644 --- a/C4/SIP/ILS/Item.pm +++ b/C4/SIP/ILS/Item.pm @@ -380,6 +380,10 @@ sub fill_reserve { } return ModReserveFill($hold); } +sub sort_bin { + my $self = shift; + return $self->{sort_bin} || ''; +} 1; __END__ diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm index 9ec126e..e22ed24 100644 --- a/C4/SIP/Sip/MsgType.pm +++ b/C4/SIP/Sip/MsgType.pm @@ -669,12 +669,13 @@ 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_SORT_BIN, $item->sort_bin ); + $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_bcode ); + $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_bcode ); $resp .= maybe_add( FID_HOLD_PATRON_NAME, $item->hold_patron_name( $server->{account}->{da_field_template} ) ); if ( $status->hold and $status->hold->{branchcode} ne $item->destination_loc ) { warn 'SIP hold mismatch: $status->hold->{branchcode}=' . $status->hold->{branchcode} . '; $item->destination_loc=' . $item->destination_loc; diff --git a/etc/SIPconfig.xml b/etc/SIPconfig.xml index 5d9ee98..9169f45 100644 --- a/etc/SIPconfig.xml +++ b/etc/SIPconfig.xml @@ -70,9 +70,14 @@ in our case "ILS". + status_update="false" offline="false" + timeout="100" + retries="5" /> +