Merge branch 'master' of git.evergreen-ils.org:Evergreen into template-toolkit-opac
authorMike Rylander <mrylander@gmail.com>
Tue, 2 Aug 2011 18:39:31 +0000 (14:39 -0400)
committerMike Rylander <mrylander@gmail.com>
Tue, 2 Aug 2011 18:39:31 +0000 (14:39 -0400)
81 files changed:
Open-ILS/examples/oils_sip.xml.example
Open-ILS/src/extras/Makefile.install
Open-ILS/src/extras/ils_events.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CopyLocations.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
Open-ILS/src/perlmods/lib/OpenILS/SIP/Transaction/Checkin.pm
Open-ILS/src/perlmods/lib/OpenILS/Utils/MFHD/test/mfhd.t
Open-ILS/src/sql/Pg/002.functions.config.sql
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/012.schema.vandelay.sql
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/0584.data.org-setting-ui.circ.billing.uncheck_bills_and_unfocus_payment_box.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/0585.checkout_fills_related_hold_exact_match.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/0586.data.persistent_login_default_perm.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/0587.maintain_control_numbers_with_OCLC_awareness.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/0588.schema.replace_field-default-value.sql [new file with mode: 0644]
Open-ILS/web/css/skin/default/acq.css
Open-ILS/web/js/dojo/openils/acq/nls/acq.js
Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
Open-ILS/web/js/ui/default/acq/common/li_table.js
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/web/opac/locale/en-US/vandelay.dtd
Open-ILS/web/opac/skin/default/js/holds.js
Open-ILS/web/opac/skin/default/xml/rdetail/rdetail_extras.xml
Open-ILS/web/opac/skin/default/xml/result/result_table.xml
Open-ILS/web/opac/theme/default/css/colors.css
Open-ILS/web/templates/default/acq/common/li_table.tt2
Open-ILS/web/templates/default/conify/global/config/record_attr_definition.tt2
Open-ILS/xul/staff_client/chrome/content/cat/opac.js
Open-ILS/xul/staff_client/chrome/content/main/constants.js
Open-ILS/xul/staff_client/chrome/content/main/menu.js
Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
Open-ILS/xul/staff_client/chrome/content/main/menu_frame_overlay.xul
Open-ILS/xul/staff_client/chrome/content/util/browser.js
Open-ILS/xul/staff_client/chrome/content/util/fancy_prompt.xul
Open-ILS/xul/staff_client/chrome/content/util/list.js
Open-ILS/xul/staff_client/chrome/content/util/print.js
Open-ILS/xul/staff_client/chrome/content/util/sound.js
Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
Open-ILS/xul/staff_client/server/admin/transit_list.js
Open-ILS/xul/staff_client/server/admin/work_log.js
Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.js
Open-ILS/xul/staff_client/server/cat/bibs_abreast.js
Open-ILS/xul/staff_client/server/cat/copy_browser.js
Open-ILS/xul/staff_client/server/cat/copy_buckets.js
Open-ILS/xul/staff_client/server/cat/copy_summary.xul
Open-ILS/xul/staff_client/server/cat/marc_new.xul
Open-ILS/xul/staff_client/server/cat/record_buckets.js
Open-ILS/xul/staff_client/server/cat/spine_labels.js
Open-ILS/xul/staff_client/server/cat/util.js
Open-ILS/xul/staff_client/server/cat/volume_copy_creator.js
Open-ILS/xul/staff_client/server/cat/z3950.js
Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.js
Open-ILS/xul/staff_client/server/circ/checkin.js
Open-ILS/xul/staff_client/server/circ/checkin_overlay.xul
Open-ILS/xul/staff_client/server/circ/checkout.js
Open-ILS/xul/staff_client/server/circ/copy_details.xul
Open-ILS/xul/staff_client/server/circ/copy_status.js
Open-ILS/xul/staff_client/server/circ/in_house_use.js
Open-ILS/xul/staff_client/server/circ/renew.js
Open-ILS/xul/staff_client/server/circ/util.js
Open-ILS/xul/staff_client/server/index.xhtml
Open-ILS/xul/staff_client/server/locale/en-US/cat.properties
Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
Open-ILS/xul/staff_client/server/patron/bill2.js
Open-ILS/xul/staff_client/server/patron/bill2.xul
Open-ILS/xul/staff_client/server/patron/display.js
Open-ILS/xul/staff_client/server/patron/hold_details.js
Open-ILS/xul/staff_client/server/patron/holds.js
Open-ILS/xul/staff_client/server/patron/items.js
Open-ILS/xul/staff_client/server/patron/standing_penalties.js
Open-ILS/xul/staff_client/server/patron/util.js
Open-ILS/xul/staff_client/server/serial/manage_dists.js
Open-ILS/xul/staff_client/server/serial/manage_items.js
Open-ILS/xul/staff_client/server/serial/manage_subs.js
Open-ILS/xul/staff_client/server/skin/circ.css
Open-ILS/xul/staff_client/server/skin/custom.js.example
README

index 8adecf8..fa1e19d 100644 (file)
                     <event>COPY_ALERT_MESSAGE</event>
                 </checkout_override>
 
+                <!-- If uncommented, SIP2 checkins will capture local holds as transits, instead of marking as ready for pickup. -->
+                <!--
+                <checkin_hold_as_transit>1</checkin_hold_as_transit>
+                -->
+
                 <!-- If uncommented, overrides the legacy_script_support value in opensrf.xml for SIP. -->
                 <!--
                 <legacy_script_support>false</legacy_script_support>
index 2a3afa7..f008ef3 100644 (file)
@@ -246,9 +246,12 @@ CPAN_MODULES_SAFE = \
 CPAN_MODULES_MARC = \
        Business::ISBN \
        Business::ISBN::Data \
-    MARC::Charset \
-    MARC::File::XML \
-    Net::Z3950::ZOOM
+       MARC::Charset \
+       MARC::File::XML \
+       Net::Z3950::ZOOM
+
+CPAN_MODULES_MARC_RECORD = \
+       MARC::Record
 
 CPAN_MODULES_FORCE = \
        Class::DBI::Frozen::301
@@ -273,7 +276,7 @@ squeeze: install_pgsql_client_debs_90  install_extra_debs_squeeze
 generic_debian:  install_debs test_for_libdbi_pkg install debian_sys_config install_cpan_force
 
 ubuntu-lucid: lucid generic_ubuntu
-lucid: install_pgsql_client_debs_90 install_extra_debs
+lucid: install_pgsql_client_debs_90 install_extra_debs install_cpan_marc_record
 generic_ubuntu: install_debs test_for_libdbi_pkg install debian_sys_config install_cpan_more install_cpan_safe install_cpan_force
 
 # - COMMON TARGETS ---------------------------------------------------------
@@ -286,9 +289,12 @@ install_cpan_more:
        for m in $(CPAN_MODULES_MORE); do perl -MCPAN -e "install \"$$m\";"; done
 
 # Install the CPAN modules for MARC functionality
-install_cpan_marc: 
+install_cpan_marc: install_cpan_marc_record
        for m in $(CPAN_MODULES_MARC); do perl -MCPAN -e "install \"$$m\";"; done
 
+install_cpan_marc_record:
+       for m in $(CPAN_MODULES_MARC_RECORD); do perl -MCPAN -e "install \"$$m\";"; done
+
 install_cpan_force:
        for m in $(CPAN_MODULES_FORCE); do \
                echo "force install $$m" | perl -MCPAN -e shell ;\
index 0eb3f8a..ee68f72 100644 (file)
        <event code='1234' textcode='ITEM_DEPOSIT_PAID'>
                <desc xml:lang="en-US"></desc>
        </event>
+       <event code='1235' textcode='INVALID_USER_XACT_ID'>
+        <desc xml:lang="en-US">While you were trying to make payments, this account's transaction history changed.  Please go back and try again.</desc>
+       </event>
 
 
 
index f5cc14c..fba805a 100644 (file)
@@ -1275,6 +1275,9 @@ sub handle_mark_damaged {
         my $ses = OpenSRF::AppSession->create('open-ils.trigger');
         $ses->request('open-ils.trigger.event.autocreate', 'checkout.damaged', $circ, $circ->circ_lib);
 
+        my $evt2 = OpenILS::Utils::Penalty->calculate_penalties($e, $circ->usr->id, $e->requestor->ws_ou);
+        return $evt2 if $evt2;
+
         return undef;
 
     } else {
index 793b7fd..b569ffd 100644 (file)
@@ -535,6 +535,9 @@ my @AUTOLOAD_FIELDS = qw/
     skip_rental_fee
     use_booking
     generate_lost_overdue
+    clear_expired
+    retarget_mode
+    hold_as_transit
 /;
 
 
@@ -1681,8 +1684,17 @@ sub handle_checkout_holds {
 # ------------------------------------------------------------------------------
 # If the circ.checkout_fill_related_hold setting is turned on and no hold for
 # the patron directly targets the checked out item, see if there is another hold 
-# (with hold_type T or V) for the patron that could be fulfilled by the checked 
-# out item.  Fulfill the oldest hold and only fulfill 1 of them.
+# for the patron that could be fulfilled by the checked out item.  Fulfill the
+# oldest hold and only fulfill 1 of them.
+# 
+# For "another hold":
+#
+# First, check for one that the copy matches via hold_copy_map, ensuring that
+# *any* hold type that this copy could fill may end up filled.
+#
+# Then, if circ.checkout_fill_related_hold_exact_match_only is not enabled, look
+# for a Title (T) or Volume (V) hold that matches the item. This allows items
+# that are non-requestable to count as capturing those hold types.
 # ------------------------------------------------------------------------------
 sub find_related_user_hold {
     my($self, $copy, $patron) = @_;
@@ -1698,6 +1710,40 @@ sub find_related_user_hold {
         select => {ahr => ['id']}, 
         from => {
             ahr => {
+                ahcm => {
+                    field => 'hold',
+                    fkey => 'id'
+                }
+            }
+        }, 
+        where => {
+            '+ahr' => {
+                usr => $patron->id,
+                fulfillment_time => undef,
+                cancel_time => undef,
+               '-or' => [
+                    {expire_time => undef},
+                    {expire_time => {'>' => 'now'}}
+                ]
+            },
+            '+ahcm' => {
+                target_copy => $self->copy->id
+            },
+        },
+        order_by => {ahr => {request_time => {direction => 'asc'}}},
+        limit => 1
+    };
+
+    my $hold_info = $e->json_query($args)->[0];
+    return $e->retrieve_action_hold_request($hold_info->{id}) if $hold_info;
+    return undef if $U->ou_ancestor_setting_value(        
+        $self->circ_lib, 'circ.checkout_fills_related_hold_exact_match_only', $e);
+
+    # find the oldest unfulfilled hold that has not yet hit the holds shelf.
+    $args = {
+        select => {ahr => ['id']}, 
+        from => {
+            ahr => {
                 acp => {
                     field => 'id', 
                     fkey => 'current_copy',
@@ -1740,7 +1786,7 @@ sub find_related_user_hold {
         limit => 1
     };
 
-    my $hold_info = $e->json_query($args)->[0];
+    $hold_info = $e->json_query($args)->[0];
     return $e->retrieve_action_hold_request($hold_info->{id}) if $hold_info;
     return undef;
 }
@@ -2241,6 +2287,9 @@ sub check_transit_checkin_interval {
         )->[0]
     ); 
 
+    # transit from X to X for whatever reason has no min interval
+    return if $self->transit->source == $self->transit->dest;
+
     my $seconds = OpenSRF::Utils->interval_to_seconds($interval);
     my $t_start = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($self->transit->source_send_time));
     my $horizon = $t_start->add(seconds => $seconds);
@@ -2250,6 +2299,73 @@ sub check_transit_checkin_interval {
         if $horizon > DateTime->now;
 }
 
+# Retarget local holds at checkin
+sub checkin_retarget {
+    my $self = shift;
+    return unless $self->retarget_mode =~ m/retarget/; # Retargeting?
+    return unless $self->is_checkin; # Renewals need not be checked
+    return if $self->capture eq 'nocapture'; # Not capturing holds anyway? Move on.
+    return if $self->is_precat; # No holds for precats
+    return unless $self->circ_lib == $self->copy->circ_lib; # Item isn't "home"? Don't check.
+    return unless $self->copy->holdable; # Not holdable, shouldn't capture holds.
+    # Specifically target items that are likely new (by status ID)
+    unless ($self->retarget_mode =~ m/\.all/) {
+        my $status = $U->copy_status($self->copy->status)->id;
+        return unless $status == OILS_COPY_STATUS_IN_PROCESS;
+    }
+
+    # Fetch holds for the bib
+    my ($result) = $holdcode->method_lookup('open-ils.circ.holds.retrieve_all_from_title')->run(
+                    $self->editor->authtoken,
+                    $self->title->id,
+                    {
+                        capture_time => undef, # No touching captured holds
+                        frozen => 'f', # Don't bother with frozen holds
+                        pickup_lib => $self->circ_lib # Only holds actually here
+                    }); 
+
+    # Error? Skip the step.
+    return if exists $result->{"ilsevent"};
+
+    # Assemble holds
+    my $holds = [];
+    foreach my $holdlist (keys %{$result}) {
+        push @$holds, @{$result->{$holdlist}};
+    }
+
+    return if scalar(@$holds) == 0; # No holds, no retargeting
+
+    # Loop over holds in request-ish order
+    # Stage 1: Get them into request-ish order
+    # Also grab type and target for skipping low hanging ones
+    $result = $self->editor->json_query({
+        "select" => { "ahr" => ["id", "hold_type", "target"] },
+        "from" => { "ahr" => { "au" => { "fkey" => "usr",  "join" => "pgt"} } },
+        "where" => { "id" => $holds },
+        "order_by" => [
+            { "class" => "pgt", "field" => "hold_priority"},
+            { "class" => "ahr", "field" => "cut_in_line", "direction" => "desc", "transform" => "coalesce", "params" => ['f']},
+            { "class" => "ahr", "field" => "selection_depth", "direction" => "desc"},
+            { "class" => "ahr", "field" => "request_time"}
+        ]
+    });
+
+    # Stage 2: Loop!
+    if (ref $result eq "ARRAY" and scalar @$result) {
+        foreach (@{$result}) {
+            # Copy level, but not this copy?
+            next if ($_->{hold_type} eq 'C' or $_->{hold_type} eq 'R' or $_->{hold_type} eq 'F'
+                and $_->{target} != $self->copy->id);
+            # Volume level, but not this volume?
+            next if ($_->{hold_type} eq 'V' and $_->{target} != $self->volume->id);
+            # So much for easy stuff, attempt a retarget!
+            my $tresult = $U->storagereq('open-ils.storage.action.hold_request.copy_targeter', undef, $_->{id}, $self->copy->id);
+            if(ref $tresult eq "ARRAY" and scalar @$tresult) {
+                last if(exists $tresult->[0]->{found_copy} and $tresult->[0]->{found_copy});
+            }
+        }
+    }
+}
 
 sub do_checkin {
     my $self = shift;
@@ -2260,6 +2376,7 @@ sub do_checkin {
         unless $self->copy;
 
     $self->check_transit_checkin_interval;
+    $self->checkin_retarget;
 
     # the renew code and mk_env should have already found our circulation object
     unless( $self->circ ) {
@@ -2426,7 +2543,7 @@ sub do_checkin {
     
             $logger->debug("circulator: circlib=$circ_lib, workstation=".$self->circ_lib);
     
-            if( $circ_lib == $self->circ_lib) {
+            if( $circ_lib == $self->circ_lib and not ($self->hold_as_transit and $self->remote_hold) ) {
                 # copy is where it needs to be, either for hold or reshelving
     
                 $self->checkin_handle_precat();
@@ -2563,6 +2680,10 @@ sub checkin_check_holds_shelf {
         $U->copy_status($self->copy->status)->id ==
             OILS_COPY_STATUS_ON_HOLDS_SHELF;
 
+    # Attempt to clear shelf expired holds for this copy
+    $holdcode->method_lookup('open-ils.circ.hold.clear_shelf.process')->run($self->editor->authtoken, $self->circ_lib, $self->copy->id)
+        if($self->clear_expired);
+
     # find the hold that put us on the holds shelf
     my $holds = $self->editor->search_action_hold_request(
         { 
@@ -2584,7 +2705,7 @@ sub checkin_check_holds_shelf {
     $logger->info("circulator: we found a captured, un-fulfilled hold [".
         $hold->id. "] for copy ".$self->copy->barcode);
 
-    if( $hold->pickup_lib == $self->circ_lib ) {
+    if( $hold->pickup_lib == $self->circ_lib and not $self->hold_as_transit ) {
         $logger->info("circulator: hold is for here .. we're done: ".$self->copy->barcode);
         return 1;
     }
@@ -2724,7 +2845,7 @@ sub attempt_checkin_hold_capture {
 
     return 0 if $self->bail_out;
 
-    if( $hold->pickup_lib == $self->circ_lib ) {
+    if( $hold->pickup_lib == $self->circ_lib && not $self->hold_as_transit ) {
 
         # This hold was captured in the correct location
         $copy->status(OILS_COPY_STATUS_ON_HOLDS_SHELF);
@@ -2892,8 +3013,9 @@ sub process_received_transit {
 
     my $transit = $self->transit;
 
-    if( $transit->dest != $self->circ_lib ) {
+    if( $transit->dest != $self->circ_lib or ($self->hold_as_transit && $transit->copy_status == OILS_COPY_STATUS_ON_HOLDS_SHELF) ) {
         # - this item is in-transit to a different location
+        # - Or we are capturing holds as transits, so why create a new transit?
 
         my $tid = $transit->id; 
         my $loc = $self->circ_lib;
index d7f0773..bc4f2c1 100644 (file)
@@ -33,6 +33,7 @@ sub cl_retrieve_all {
        }
 
     my $second_cstore_arg = {"no_i18n" => scalar($no_i18n)};
+       $second_cstore_arg->{"order_by"} = {"acpl" => "name"};
     if ($flesh_owning_lib) {
         $second_cstore_arg->{"flesh"} = 1;
         $second_cstore_arg->{"flesh_fields"} = {"acpl" => ["owning_lib"]};
index a2135b2..584b4c7 100644 (file)
@@ -3227,7 +3227,10 @@ __PACKAGE__->register_method(
 );
 
 sub clear_shelf_process {
-       my($self, $client, $auth, $org_id) = @_;
+       my($self, $client, $auth, $org_id, $match_copy) = @_;
+
+    my $current_copy = { '!=' => undef };
+    $current_copy = { '=' => $match_copy } if $match_copy;
 
        my $e = new_editor(authtoken=>$auth, xact => 1);
        $e->checkauth or return $e->die_event;
@@ -3246,7 +3249,7 @@ sub clear_shelf_process {
             fulfillment_time  => undef,
             shelf_time        => {'!=' => undef},
             capture_time      => {'!=' => undef},
-            current_copy      => {'!=' => undef},
+            current_copy      => $current_copy,
         },
         { idlist => 1 }
     );
@@ -3297,7 +3300,7 @@ sub clear_shelf_process {
             my $copy = $hold->current_copy;
             my ($alt_hold) = __PACKAGE__->find_nearest_permitted_hold($e, $copy, $e->requestor, 1);
 
-            if($alt_hold) {
+            if($alt_hold and !$match_copy) {
 
                 push(@{$cache_data{hold}}, $hold->id); # copy is needed for a hold
 
index 23717a7..d54575d 100644 (file)
@@ -1042,6 +1042,7 @@ sub new_hold_copy_targeter {
        my $client = shift;
        my $check_expire = shift;
        my $one_hold = shift;
+    my $find_copy = shift;
 
        local $OpenILS::Application::Storage::WRITE = 1;
 
@@ -1288,6 +1289,8 @@ sub new_hold_copy_targeter {
                        }
 
                        my $copy_count = @$all_copies;
+            my $found_copy = undef;
+            $found_copy = 1 if($find_copy and grep $_ == $find_copy, @$all_copies);
 
                        # map the potentials, so that we can pick up checkins
                        # XXX Loop-based targeting may require that /only/ copies from this loop should be added to
@@ -1489,7 +1492,8 @@ sub new_hold_copy_targeter {
                                { hold => $hold->id,
                                  old_target => ($old_best ? $old_best->id : undef),
                                  eligible_copies => $copy_count,
-                                 target => ($best ? $best->id : undef) };
+                                 target => ($best ? $best->id : undef),
+                  found_copy => $found_copy };
 
                } otherwise {
                        my $e = shift;
index 42a689c..cee4fc5 100644 (file)
@@ -29,6 +29,8 @@ my %fields = (
 #   hold             => undef,
 );
 
+my $hold_as_transit = 0;
+
 sub new {
     my $class = shift;;
     my $self = $class->SUPER::new(@_);              # start with an Transaction object
@@ -41,6 +43,8 @@ sub new {
 
     $self->load_override_events;
 
+    $hold_as_transit = OpenILS::SIP->config->{implementation_config}->{checkin_hold_as_transit};
+
     return bless $self, $class;
 }
 
@@ -77,6 +81,7 @@ sub do_checkin {
     my $phys_location = $sip_handler->{login_session}->ws_ou;
 
     my $args = {barcode => $self->{item}->id};
+    $args->{hold_as_transit} = 1 if $hold_as_transit;
 
     if($return_date) {
         # SIP date format is YYYYMMDD.  Translate to ISO8601
index d9ad34b..29ee865 100644 (file)
@@ -66,7 +66,8 @@ while ($rec = testlib::load_MARC_rec($testdata, $testno++)) {
 close $testdata;
 
 # test: passthru_open_ended
-open($testdata, "<mfhddata2.txt") or die("Cannot open 'mfhddata2.txt': $!");
+my $testfile2 = dirname(__FILE__) . "/mfhddata2.txt";
+open($testdata, "<", $testfile2) or die("Cannot open '$testfile2': $!");
 
 $rec = MFHD->new(testlib::load_MARC_rec($testdata, $testno));
 my $rec2 = MFHD->new(testlib::load_MARC_rec($testdata, $testno));
index 4574c83..353c7f2 100644 (file)
@@ -553,20 +553,27 @@ foreach my $id_field ('001', '003') {
     } else {
         # Delete the other fields, as with more than 1 001/003 we do not know which 003/001 to match
         foreach my $control (@controls) {
-            unless ($control->data() eq $spec_value) {
-                $record->delete_field($control);
-            }
+            $record->delete_field($control);
         }
         $record->insert_fields_ordered(MARC::Field->new($id_field, $spec_value));
         $create = 1;
     }
 }
 
+my $cn = $record->field('001')->data();
+# Special handling of OCLC numbers, often found in records that lack 003
+if ($cn =~ /^oc[nm]/) {
+    $cn =~ s/^oc[nm]0*(\d+)/$1/;
+    $record->field('003')->data('OCoLC');
+    $create = 0;
+}
+
 # Now, if we need to munge the 001, we will first push the existing 001/003
 # into the 035; but if the record did not have one (and one only) 001 and 003
 # to begin with, skip this process
 if ($munge and not $create) {
-    my $scn = "(" . $record->field('003')->data() . ")" . $record->field('001')->data();
+
+    my $scn = "(" . $record->field('003')->data() . ")" . $cn;
 
     # Do not create duplicate 035 fields
     unless (grep $_->subfield('a') eq $scn, @scns) {
index 175a63c..cbe63cf 100644 (file)
@@ -86,7 +86,7 @@ CREATE TRIGGER no_overlapping_deps
     BEFORE INSERT OR UPDATE ON config.db_patch_dependencies
     FOR EACH ROW EXECUTE PROCEDURE evergreen.array_overlap_check ('deprecates');
 
-INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0583', :eg_version); -- miker/gmcharlt
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0588', :eg_version); -- miker/berick
 
 CREATE TABLE config.bib_source (
        id              SERIAL  PRIMARY KEY,
index de3e24a..b2780a5 100644 (file)
@@ -1073,6 +1073,7 @@ DECLARE
 BEGIN
 
     parsed_target := vandelay.strip_field( target_xml, ''); -- this dance normalizes the format of the xml for the IF below
+    xml_output := parsed_target; -- if there are no replace rules, just return the input
 
     FOR curr_field IN SELECT UNNEST( STRING_TO_ARRAY(field, ',') ) LOOP -- naive split, but it's the same we use in the perl
 
index 9cf3bbc..e4e7607 100644 (file)
@@ -97,6 +97,10 @@ INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath )
     (27, 'identifier', 'bibid', oils_i18n_gettext(27, 'Internal ID', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='901']/marc:subfield[@code='c']$$ );
 INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, search_field, facet_field) VALUES
     (28, 'identifier', 'authority_id', oils_i18n_gettext(28, 'Authority Record ID', 'cmf', 'label'), 'marcxml', '//marc:datafield/marc:subfield[@code="0"]', FALSE, TRUE);
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath) VALUES
+    (29, 'identifier', 'scn', oils_i18n_gettext(29, 'System Control Number', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='035']/marc:subfield[@code="a"]$$);
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath) VALUES
+    (30, 'identifier', 'lccn', oils_i18n_gettext(30, 'LC Control Number', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='010']/marc:subfield[@code="a" or @code='z']$$);
 
 SELECT SETVAL('config.metabib_field_id_seq'::TEXT, (SELECT MAX(id) FROM config.metabib_field), TRUE);
 
@@ -1432,7 +1436,9 @@ INSERT INTO permission.perm_list ( id, code, description ) VALUES
  ( 509, 'TRANSIT_CHECKIN_INTERVAL_BLOCK.override', oils_i18n_gettext(509,
     'Allows a user to override the TRANSIT_CHECKIN_INTERVAL_BLOCK event', 'ppl', 'description')),
  ( 510, 'UPDATE_PATRON_COLLECTIONS_EXEMPT', oils_i18n_gettext(510,
-    'Allows a user to indicate that a patron is exempt from collections processing', 'ppl', 'description'));
+    'Allows a user to indicate that a patron is exempt from collections processing', 'ppl', 'description')),
+ ( 511, 'PERSISTENT_LOGIN', oils_i18n_gettext( 511,
+    'Allows a user to authenticate and get a long-lived session (length configured in opensrf.xml)', 'ppl', 'description' ));
 
 
 SELECT SETVAL('permission.perm_list_id_seq'::TEXT, 1000);
@@ -1502,6 +1508,7 @@ INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
                        'CREATE_PURCHASE_REQUEST',
                        'MR_HOLDS',
                        'OPAC_LOGIN',
+                       'PERSISTENT_LOGIN',
                        'RENEW_CIRC',
                        'TITLE_HOLDS',
                        'user_request.create'
@@ -2592,6 +2599,11 @@ INSERT into config.org_unit_setting_type
     oils_i18n_gettext('circ.checkout_fills_related_hold', 'When a patron checks out an item and they have no holds that directly target the item, the system will attempt to find a hold for the patron that could be fulfilled by the checked out item and fulfills it', 'coust', 'description'),
     'bool'),
 
+( 'circ.checkout_fills_related_hold_exact_match_only',
+    oils_i18n_gettext('circ.checkout_fills_related_hold_exact_match_only', 'Checkout Fills Related Hold On Valid Copy Only', 'coust', 'label'),
+    oils_i18n_gettext('circ.checkout_fills_related_hold_exact_match_only', 'When filling related holds on checkout only match on items that are valid for opportunistic capture for the hold. Without this set a Title or Volume hold could match when the item is not holdable. With this set only holdable items will match.', 'coust', 'description'),
+    'bool'),
+
 ( 'circ.selfcheck.auto_override_checkout_events',
     oils_i18n_gettext('circ.selfcheck.auto_override_checkout_events', 'Selfcheck override events list', 'coust', 'label'),
     oils_i18n_gettext('circ.selfcheck.auto_override_checkout_events', 'List of checkout/renewal events that the selfcheck interface should automatically override instead instead of alerting and stopping the transaction', 'coust', 'description'),
@@ -2751,7 +2763,24 @@ INSERT into config.org_unit_setting_type
     oils_i18n_gettext( 'org.patron_opt_default', 'Circ: Patron Opt-In Default', 'coust', 'label'),
     oils_i18n_gettext( 'org.patron_opt_default', 'This is the default depth at which a patron is opted in; it is calculated as an org unit relative to the current workstation.', 'coust', 'label'),
     'integer')
-
+,( 
+        'ui.circ.billing.uncheck_bills_and_unfocus_payment_box',
+        oils_i18n_gettext(
+            'ui.circ.billing.uncheck_bills_and_unfocus_payment_box',
+            'GUI: Uncheck bills by default in the patron billing interface',
+            'coust',
+            'label'
+        ),
+        oils_i18n_gettext(
+            'ui.circ.billing.uncheck_bills_and_unfocus_payment_box',
+            'Uncheck bills by default in the patron billing interface,'
+            || ' and focus on the Uncheck All button instead of the'
+            || ' Payment Received field.',
+            'coust',
+            'description'
+        ),
+        'bool'
+    )
 ;
 
 UPDATE config.org_unit_setting_type
diff --git a/Open-ILS/src/sql/Pg/upgrade/0584.data.org-setting-ui.circ.billing.uncheck_bills_and_unfocus_payment_box.sql b/Open-ILS/src/sql/Pg/upgrade/0584.data.org-setting-ui.circ.billing.uncheck_bills_and_unfocus_payment_box.sql
new file mode 100644 (file)
index 0000000..64dbce4
--- /dev/null
@@ -0,0 +1,30 @@
+-- Evergreen DB patch XXXX.data.org-setting-ui.circ.billing.uncheck_bills_and_unfocus_payment_box.sql
+--
+-- New org setting ui.circ.billing.uncheck_bills_and_unfocus_payment_box
+--
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('0584', :eg_version);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) 
+    VALUES ( 
+        'ui.circ.billing.uncheck_bills_and_unfocus_payment_box',
+        oils_i18n_gettext(
+            'ui.circ.billing.uncheck_bills_and_unfocus_payment_box',
+            'GUI: Uncheck bills by default in the patron billing interface',
+            'coust',
+            'label'
+        ),
+        oils_i18n_gettext(
+            'ui.circ.billing.uncheck_bills_and_unfocus_payment_box',
+            'Uncheck bills by default in the patron billing interface,'
+            || ' and focus on the Uncheck All button instead of the'
+            || ' Payment Received field.',
+            'coust',
+            'description'
+        ),
+        'bool'
+    );
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/0585.checkout_fills_related_hold_exact_match.sql b/Open-ILS/src/sql/Pg/upgrade/0585.checkout_fills_related_hold_exact_match.sql
new file mode 100644 (file)
index 0000000..611a2b0
--- /dev/null
@@ -0,0 +1,13 @@
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('0585', :eg_version);
+
+INSERT into config.org_unit_setting_type
+( name, label, description, datatype ) VALUES
+( 'circ.checkout_fills_related_hold_exact_match_only',
+    'Checkout Fills Related Hold On Valid Copy Only',
+    'When filling related holds on checkout only match on items that are valid for opportunistic capture for the hold. Without this set a Title or Volume hold could match when the item is not holdable. With this set only holdable items will match.',
+    'bool');
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/0586.data.persistent_login_default_perm.sql b/Open-ILS/src/sql/Pg/upgrade/0586.data.persistent_login_default_perm.sql
new file mode 100644 (file)
index 0000000..107026c
--- /dev/null
@@ -0,0 +1,35 @@
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('0586', :eg_version);
+
+INSERT INTO permission.perm_list (id, code, description) VALUES (
+    511,
+    'PERSISTENT_LOGIN',
+    oils_i18n_gettext(
+        511,
+        'Allows a user to authenticate and get a long-lived session (length configured in opensrf.xml)',
+        'ppl',
+        'description'
+    )
+);
+
+INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
+    SELECT
+        pgt.id, perm.id, aout.depth, FALSE
+    FROM
+        permission.grp_tree pgt,
+        permission.perm_list perm,
+        actor.org_unit_type aout
+    WHERE
+        pgt.name = 'Users' AND
+        aout.name = 'Consortium' AND
+        perm.code = 'PERSISTENT_LOGIN';
+
+\qecho 
+\qecho If this transaction succeeded, your users (staff and patrons) now have
+\qecho the PERSISTENT_LOGIN permission by default.
+\qecho 
+
+COMMIT;
+
diff --git a/Open-ILS/src/sql/Pg/upgrade/0587.maintain_control_numbers_with_OCLC_awareness.sql b/Open-ILS/src/sql/Pg/upgrade/0587.maintain_control_numbers_with_OCLC_awareness.sql
new file mode 100644 (file)
index 0000000..a583250
--- /dev/null
@@ -0,0 +1,145 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('0587', :eg_version);
+
+CREATE OR REPLACE FUNCTION maintain_control_numbers() RETURNS TRIGGER AS $func$
+use strict;
+use MARC::Record;
+use MARC::File::XML (BinaryEncoding => 'UTF-8');
+use MARC::Charset;
+use Encode;
+use Unicode::Normalize;
+
+MARC::Charset->assume_unicode(1);
+
+my $record = MARC::Record->new_from_xml($_TD->{new}{marc});
+my $schema = $_TD->{table_schema};
+my $rec_id = $_TD->{new}{id};
+
+# Short-circuit if maintaining control numbers per MARC21 spec is not enabled
+my $enable = spi_exec_query("SELECT enabled FROM config.global_flag WHERE name = 'cat.maintain_control_numbers'");
+if (!($enable->{processed}) or $enable->{rows}[0]->{enabled} eq 'f') {
+    return;
+}
+
+# Get the control number identifier from an OU setting based on $_TD->{new}{owner}
+my $ou_cni = 'EVRGRN';
+
+my $owner;
+if ($schema eq 'serial') {
+    $owner = $_TD->{new}{owning_lib};
+} else {
+    # are.owner and bre.owner can be null, so fall back to the consortial setting
+    $owner = $_TD->{new}{owner} || 1;
+}
+
+my $ous_rv = spi_exec_query("SELECT value FROM actor.org_unit_ancestor_setting('cat.marc_control_number_identifier', $owner)");
+if ($ous_rv->{processed}) {
+    $ou_cni = $ous_rv->{rows}[0]->{value};
+    $ou_cni =~ s/"//g; # Stupid VIM syntax highlighting"
+} else {
+    # Fall back to the shortname of the OU if there was no OU setting
+    $ous_rv = spi_exec_query("SELECT shortname FROM actor.org_unit WHERE id = $owner");
+    if ($ous_rv->{processed}) {
+        $ou_cni = $ous_rv->{rows}[0]->{shortname};
+    }
+}
+
+my ($create, $munge) = (0, 0);
+
+my @scns = $record->field('035');
+
+foreach my $id_field ('001', '003') {
+    my $spec_value;
+    my @controls = $record->field($id_field);
+
+    if ($id_field eq '001') {
+        $spec_value = $rec_id;
+    } else {
+        $spec_value = $ou_cni;
+    }
+
+    # Create the 001/003 if none exist
+    if (scalar(@controls) == 1) {
+        # Only one field; check to see if we need to munge it
+        unless (grep $_->data() eq $spec_value, @controls) {
+            $munge = 1;
+        }
+    } else {
+        # Delete the other fields, as with more than 1 001/003 we do not know which 003/001 to match
+        foreach my $control (@controls) {
+            $record->delete_field($control);
+        }
+        $record->insert_fields_ordered(MARC::Field->new($id_field, $spec_value));
+        $create = 1;
+    }
+}
+
+my $cn = $record->field('001')->data();
+# Special handling of OCLC numbers, often found in records that lack 003
+if ($cn =~ /^oc[nm]/) {
+    $cn =~ s/^oc[nm]0*(\d+)/$1/;
+    $record->field('003')->data('OCoLC');
+    $create = 0;
+}
+
+# Now, if we need to munge the 001, we will first push the existing 001/003
+# into the 035; but if the record did not have one (and one only) 001 and 003
+# to begin with, skip this process
+if ($munge and not $create) {
+
+    my $scn = "(" . $record->field('003')->data() . ")" . $cn;
+
+    # Do not create duplicate 035 fields
+    unless (grep $_->subfield('a') eq $scn, @scns) {
+        $record->insert_fields_ordered(MARC::Field->new('035', '', '', 'a' => $scn));
+    }
+}
+
+# Set the 001/003 and update the MARC
+if ($create or $munge) {
+    $record->field('001')->data($rec_id);
+    $record->field('003')->data($ou_cni);
+
+    my $xml = $record->as_xml_record();
+    $xml =~ s/\n//sgo;
+    $xml =~ s/^<\?xml.+\?\s*>//go;
+    $xml =~ s/>\s+</></go;
+    $xml =~ s/\p{Cc}//go;
+
+    # Embed a version of OpenILS::Application::AppUtils->entityize()
+    # to avoid having to set PERL5LIB for PostgreSQL as well
+
+    # If we are going to convert non-ASCII characters to XML entities,
+    # we had better be dealing with a UTF8 string to begin with
+    $xml = decode_utf8($xml);
+
+    $xml = NFC($xml);
+
+    # Convert raw ampersands to entities
+    $xml =~ s/&(?!\S+;)/&amp;/gso;
+
+    # Convert Unicode characters to entities
+    $xml =~ s/([\x{0080}-\x{fffd}])/sprintf('&#x%X;',ord($1))/sgoe;
+
+    $xml =~ s/[\x00-\x1f]//go;
+    $_TD->{new}{marc} = $xml;
+
+    return "MODIFY";
+}
+
+return;
+$func$ LANGUAGE PLPERLU;
+
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath) VALUES
+    (29, 'identifier', 'scn', oils_i18n_gettext(28, 'System Control Number', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='035']/marc:subfield[@code="a"]$$);
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath) VALUES
+    (30, 'identifier', 'lccn', oils_i18n_gettext(28, 'LC Control Number', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='010']/marc:subfield[@code="a" or @code='z']$$);
+
+-- Far from perfect, but much faster than reingesting every record
+INSERT INTO metabib.identifier_field_entry(source, field, value) 
+    SELECT record, 29, value FROM metabib.full_rec WHERE tag = '035' AND subfield = 'a';
+INSERT INTO metabib.identifier_field_entry(source, field, value) 
+    SELECT record, 30, value FROM metabib.full_rec WHERE tag = '010' AND subfield IN ('a', 'z');
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/0588.schema.replace_field-default-value.sql b/Open-ILS/src/sql/Pg/upgrade/0588.schema.replace_field-default-value.sql
new file mode 100644 (file)
index 0000000..aa01ca7
--- /dev/null
@@ -0,0 +1,41 @@
+-- Evergreen DB patch XXXX.schema.replace_field-default-value.sql
+--
+-- Return the input XML when no replace rule is provided
+--
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('0588', :eg_version);
+
+CREATE OR REPLACE FUNCTION vandelay.replace_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+DECLARE
+    xml_output TEXT;
+    parsed_target TEXT;
+    curr_field TEXT;
+BEGIN
+
+    parsed_target := vandelay.strip_field( target_xml, ''); -- this dance normalizes the format of the xml for the IF below
+    xml_output := parsed_target; -- if there are no replace rules, just return the input
+
+    FOR curr_field IN SELECT UNNEST( STRING_TO_ARRAY(field, ',') ) LOOP -- naive split, but it's the same we use in the perl
+
+        xml_output := vandelay.strip_field( parsed_target, curr_field);
+
+        IF xml_output <> parsed_target  AND curr_field ~ E'~' THEN
+            -- we removed something, and there was a regexp restriction in the curr_field definition, so proceed
+            xml_output := vandelay.add_field( xml_output, source_xml, curr_field, 1 );
+        ELSIF curr_field !~ E'~' THEN
+            -- No regexp restriction, add the curr_field
+            xml_output := vandelay.add_field( xml_output, source_xml, curr_field, 0 );
+        END IF;
+
+        parsed_target := xml_output; -- in prep for any following loop iterations
+
+    END LOOP;
+
+    RETURN xml_output;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+
+COMMIT;
index 7844e17..6d03933 100644 (file)
@@ -146,7 +146,8 @@ label[for="attr_search_type_scalar"] { vertical-align: top; }
 .acq-lit-po-heading td span a[attr="name"] { font-weight: bold; }
 #acq-lit-info-tbody td {padding:5px;}
 #acq-lit-info-related { margin-top: 10px; }
-#acq-lit-li-details-table {margin-top:20px;}
+#acq-lit-distrib-formula-table { margin-top: 10px; margin-bottom: 5px;}
+#acq-lit-li-details-table {margin-top:5px; border-top;}
 #acq-lit-li-details-table td {padding:0px 3px 1px 3px;}
 #acq-lit-li-details-table th {padding:0px 3px 1px 3px; font-weight:bold;}
 #acq-lit-li-details-table .dijit {width:130px;}
@@ -252,3 +253,8 @@ span[name="bib_origin"] img { vertical-align: middle; }
 #acq-litpager-controls[disabled="true"] { color: #ccc; }
 
 .acq-po-info th { text-align: right; }
+#acq-lit-copies-li-summary { 
+    border: 1px #666 dashed;
+    margin-bottom: 15px;
+    padding: 4px;
+}
index 040bec3..2d89f12 100644 (file)
@@ -77,5 +77,6 @@
     "NUM_CLAIMS_EXISTING" : "Claims (${0} existing)",
     "LOAD_TERMS_FIRST" : "You can't retrieve records until you've loaded a CSV file\nwith bibliographic IDs in the first column.",
     "SELECT_SEARCH_FIELD": "Select Search Field",
-    "LIBRARY_INITIATED": "Library Initiated"
+    "LIBRARY_INITIATED": "Library Initiated",
+    "DEL_LI_FROM_PO": "That item has already been ordered!  Deleting it now will not revoke or modify any order that has been placed with a vendor.  Deleting the item may put the system's idea of your purchase order in a state that is inconsistent with reality.  Are you sure you mean to do this?"
 }
index e171f30..858ae70 100644 (file)
@@ -534,14 +534,15 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
                         oncomplete(openils.Util.readResponse(r, false, true));
                     };
 
+                    this.searchOptions = dojo.mixin(
+                        {async : !this.forceSync, oncomplete : _cb},
+                        this.searchOptions
+                    );
+
                     if (this.searchFilter) {
-                        new openils.PermaCrud().search(linkClass, this.searchFilter, {
-                            async : !this.forceSync, oncomplete : _cb
-                        });
+                        new openils.PermaCrud().search(linkClass, this.searchFilter, this.searchOptions);
                     } else {
-                        new openils.PermaCrud().retrieveAll(linkClass, {
-                            async : !this.forceSync, oncomplete : _cb
-                        });
+                        new openils.PermaCrud().retrieveAll(linkClass, this.searchOptions);
                     }
                 }
             }
index 4068294..0b9b642 100644 (file)
@@ -921,6 +921,12 @@ function AcqLiTable() {
         if (typeof force_fetch == "undefined")
             force_fetch = false;
 
+        openils.acq.Lineitem.fetchAndRender(liId, {}, 
+            function(li, html) {
+                dojo.byId('acq-lit-copies-li-summary').innerHTML = html;
+            }
+        );
+
         this.show('copies');
         var self = this;
         this.copyCache = {};
@@ -1112,7 +1118,7 @@ function AcqLiTable() {
 
         if (!self.distribForms) {
             // no formulas, hide the form
-            openils.Util.hide('acq-lit-distrib-formula-tbody');
+            openils.Util.hide('acq-lit-distrib-formula-table');
             return;
         }
 
@@ -2313,7 +2319,34 @@ function AcqLiTable() {
     this._deleteLiList = function(list, idx) {
         if(idx == null) idx = 0;
         if(idx >= list.length) return;
-        var liId = list[idx].id();
+
+        var li = list[idx];
+        var liId = li.id();
+
+        if (this.isPO && (li.state() == "on-order" || li.state() == "received")) {
+            /* It makes little sense to delete a lineitem from a PO that has
+             * already been marked 'on-order'.  Especially if EDI is in use,
+             * such a purchase order will probably have already been shipped
+             * off to a vendor, and mucking with it at this point could leave
+             * your data in a bad state that doesn't jive with reality.
+             *
+             * I could see making this restriction even firmer.
+             *
+             * I could also see adjusting the li state comparisons, extending
+             * the comparison to the PO's state, and/or providing functions
+             * that house the logic for comparing states in a single location.
+             *
+             * Yes, this will be really annoying if you have selected a lot
+             * of lineitems to cancel that have been ordered. You'll get a
+             * confirm dialog for each one.
+             */
+
+            if (!confirm(localeStrings.DEL_LI_FROM_PO)) {
+                self._deleteLiList(list, ++idx); /* move on to next in list */
+                return;
+            }
+        }
+
         fieldmapper.standardRequest(
             ['open-ils.acq',
              this.isPO ? 'open-ils.acq.purchase_order.lineitem.delete' : 'open-ils.acq.picklist.lineitem.delete'],
index ce4252e..c76f3a9 100644 (file)
 <!ENTITY staff.au_label_active "Active">
 <!ENTITY staff.au_label_family_name "Family Name">
 <!ENTITY staff.au_label_first_given_name "First Name">
-<!ENTITY staff.au_label_id "Record ID">
+<!ENTITY staff.au_label_id "Database ID">
 <!ENTITY staff.au_label_prefix "Prefix">
 <!ENTITY staff.au_label_second_given_name "Middle Name">
 <!ENTITY staff.au_label_suffix "Suffix">
 <!ENTITY staff.main.menu.cat.retrieve_last_record.accesskey "L">
 <!ENTITY staff.main.menu.cat.retrieve_last_record.label "Retrieve Last Record">
 <!ENTITY staff.main.menu.cat.search_tcn.accesskey "T">
-<!ENTITY staff.main.menu.cat.search_tcn.label "Retrieve record by TCN">
+<!ENTITY staff.main.menu.cat.search_tcn.label "Retrieve title by TCN">
 <!ENTITY staff.main.menu.cat.search_bib_id.accesskey "D">
-<!ENTITY staff.main.menu.cat.search_bib_id.label "Retrieve record by Record ID">
+<!ENTITY staff.main.menu.cat.search_bib_id.label "Retrieve title via Database ID">
 <!ENTITY staff.main.menu.cat.volume_status.key "V">
 <!ENTITY staff.main.menu.cat.volume_status.label "Display Volume">
 <!ENTITY staff.main.menu.cat.vandelay.label "MARC Batch Import/Export">
 <!ENTITY staff.main.menu.search.patrons.label "Search for Patrons">
 <!ENTITY staff.main.menu.search.patrons_barcode.accesskey "n">
 <!ENTITY staff.main.menu.search.patrons_barcode.label "Search for patron by Barcode">
+<!ENTITY staff.main.menu.search.patron_db_id.accesskey "">
+<!ENTITY staff.main.menu.search.patron_db_id.label "Retrieve patron via Database ID">
 <!ENTITY staff.main.menu.search.record.accesskey "T">
 <!ENTITY staff.main.menu.search.record.label "Search for record by TCN">
 <!ENTITY staff.main.menu.search.record_via_id.accesskey "D">
-<!ENTITY staff.main.menu.search.record_via_id.label "Search for record by Record ID">
+<!ENTITY staff.main.menu.search.record_via_id.label "Retrieve title via Database ID">
 <!ENTITY staff.main.menu.serials.key "l">
 <!ENTITY staff.main.menu.serials.label "Serials">
 <!ENTITY staff.main.menu.tabs.close "Close All Tabs">
 <!ENTITY staff.circ.checkin_overlay.checkin_auto_print_slips.accesskey "P">
 <!ENTITY staff.circ.checkin_overlay.checkin_modifiers_btn.label "Checkin Modifiers">
 <!ENTITY staff.circ.checkin_overlay.checkin_modifiers_btn.accesskey "M">
+<!ENTITY staff.circ.checkin_overlay.checkin_clear_shelf_expired.label "Clear Shelf-Expired Holds">
+<!ENTITY staff.circ.checkin_overlay.checkin_clear_shelf_expired.accesskey "C">
+<!ENTITY staff.circ.checkin_overlay.checkin_auto_retarget.label "Retarget Local Holds">
+<!ENTITY staff.circ.checkin_overlay.checkin_auto_retarget.accesskey "R">
+<!ENTITY staff.circ.checkin_overlay.checkin_auto_retarget_all.label "Retarget All Statuses">
+<!ENTITY staff.circ.checkin_overlay.checkin_auto_retarget_all.accesskey "e">
+<!ENTITY staff.circ.checkin_overlay.checkin_auto_retarget_all_ind.label "Always Retarget Local Holds">
+<!ENTITY staff.circ.checkin_overlay.checkin_local_hold_as_transit.label "Capture Local Holds as Transits">
+<!ENTITY staff.circ.checkin_overlay.checkin_local_hold_as_transit.accesskey "L">
 <!ENTITY staff.circ.renew_overlay.background_text "Renew Item">
 <!ENTITY staff.circ.renew_overlay.sel_clip.label "Copy to Clipboard">
 <!ENTITY staff.circ.renew_overlay.sel_clip.accesskey "C">
 <!-- "TCN" is an abbreviation for "title control number" -->
 <!ENTITY staff.cat.bib_brief.title_control_number.label "TCN:">
 <!ENTITY staff.cat.bib_brief.title_control_number.accesskey "">
-<!ENTITY staff.cat.bib_brief.biblio_record_entry_id.label "Record ID:">
+<!ENTITY staff.cat.bib_brief.biblio_record_entry_id.label "Database ID:">
 <!ENTITY staff.cat.bib_brief.biblio_record_entry_id.accesskey "">
 <!ENTITY staff.cat.bib_brief.biblio_record_entry_owner.label "Record Owner:">
 <!ENTITY staff.cat.bib_brief.biblio_record_entry_owner.accesskey "">
index 68eb92e..aa9649a 100644 (file)
@@ -7,7 +7,7 @@
 <!ENTITY vandelay.auto.import.auto_overlay_1match "Merge On Single Match">
 <!ENTITY vandelay.auto.import.auto_overlay_best "Merge On Best Match">
 <!ENTITY vandelay.auto.import.auto_overlay_best_ratio "Best/Single Match Minimum Quality Ratio">
-<!ENTITY vandelay.auto.import.auto_overlay_best_ratio.desc "New Record Quaility / Quality of Best Match">
+<!ENTITY vandelay.auto.import.auto_overlay_best_ratio.desc "New Record Quality / Quality of Best Match">
 <!ENTITY vandelay.auto.import.merge_profile "Merge Profile">
 <!ENTITY vandelay.auto.width "Auto Width">
 <!ENTITY vandelay.back.to.import.queue "Back To Import Queue">
index 0ec83f7..0363e5b 100644 (file)
@@ -126,7 +126,7 @@ function holdsDrawEditor(args) {
        if(holdArgs.editHold) // flesh the args with the existing hold 
                holdArgsFromHold(holdArgs.editHold, holdArgs);
 
-    $('holds_parts_selector').style.border = 'auto';
+     removeCSSClass($('holds_parts_selector'), 'parts-warning');
     holdArgs.partsSuggestionMade = false;
 
        holdsDrawWindow();
@@ -1026,7 +1026,7 @@ function holdHandleCreateResponse(r, recurse) {
                         holdArgs.recordParts.length && holdArgs.type == 'T') {
                     // T holds on records that have parts are OK, but if the record has no non-part
                     // copies, the hold will ultimately fail.  Suggest selecting a part to the user.
-                    $('holds_parts_selector').style.border = '2px solid red';
+                    addCSSClass($('holds_parts_selector'), 'parts-warning');
                     holdArgs.partsSuggestionMade = true;
                     alert($('hold_has_parts').innerHTML);
                 } else {
index 4245824..47382b6 100644 (file)
         var chilifresh = '<!--#echo var="OILS_CHILIFRESH_ACCOUNT"-->';
         if (chilifresh == '(none)') { chilifresh = false; }
     </script>
-    <!--if expr="${OILS_CHILIFRESH_ACCOUNT} && ${OILS_CHILIFRESH_ACCOUNT}!='(none)'"-->
+    <!--#if expr="${OILS_CHILIFRESH_ACCOUNT} && ${OILS_CHILIFRESH_ACCOUNT}!='(none)'"-->
         <input type="hidden" id="chilifresh_account" name="chilifresh_account"
             value="<!--#echo var='OILS_CHILIFRESH_ACCOUNT'-->" />
         <input type="hidden" id="chilifresh_profile" name="chilifresh_profile"
         <input type="hidden" id="chilifresh_version" name="chilifresh_version" value="onsite_v1" />
         <input type="hidden" id="chilifresh_type" name="chilifresh_type" value="search" />
         <script language="javascript" type="text/javascript" src="<!--#echo var='OILS_CHILIFRESH_URL'-->"></script>
-    <!--endif-->
+    <!--#endif-->
 
     <!-- Novelist setup -->
-    <!--if expr="${OILS_NOVELIST_URL} && ${OILS_NOVELIST_URL}!='(none)'"-->
+    <!--#if expr="${OILS_NOVELIST_URL} && ${OILS_NOVELIST_URL}!='(none)'"-->
         <script type="text/javascript" id="EIT" src="<!--#echo var='OILS_NOVELIST_URL'-->"></script>
-    <!--endif-->
+    <!--#endif-->
     <script language='javascript' type='text/javascript'>
         var novelist = '<!--#echo var="OILS_NOVELIST_URL"-->';
         if (novelist == '(none)') { novelist = false; }
index 03345ef..d211867 100644 (file)
         var chilifresh = '<!--#echo var="OILS_CHILIFRESH_ACCOUNT"-->';
         if (chilifresh=='(none)') { chilifresh = false; }
     </script>
-    <!--if expr="${OILS_CHILIFRESH_ACCOUNT} && ${OILS_CHILIFRESH_ACCOUNT}!='(none)'"-->
+    <!--#if expr="${OILS_CHILIFRESH_ACCOUNT} && ${OILS_CHILIFRESH_ACCOUNT}!='(none)'"-->
         <input type="hidden" id="chilifresh_account" name="chilifresh_account"
             value="<!--#echo var='OILS_CHILIFRESH_ACCOUNT'-->" />
         <input type="hidden" id="chilifresh_profile" name="chilifresh_profile"
         <input type="hidden" id="chilifresh_version" name="chilifresh_version" value="onsite_v1" />
         <input type="hidden" id="chilifresh_type" name="chilifresh_type" value="search" />
         <script language="javascript" type="text/javascript" src="<!--#echo var='OILS_CHILIFRESH_URL'-->"></script>
-    <!--endif-->
+    <!--#endif-->
 </div>
 
 
index db6ba1d..7bd54cc 100644 (file)
@@ -135,3 +135,5 @@ a:focus { background: #E0F0E0; color: #000000;}
 .hold_expire_warning { color:red; }
 
 #result_low_hits { border-top: 2px solid #A7EA9D }
+
+.parts-warning { border: 2px solid red; }
index 645a0ae..28ef757 100644 (file)
 
     <!-- Copies table -->
     <div id='acq-lit-li-details' class='hidden'>
-        <h2>Copies</h2>
+
+        <div id='acq-lit-copies-li-summary'></div>
+
+        <h3>Add/Edit Items</h3>
+        <hr/>
 
         <div class='acq-lit-li-menu-bar'>
             <table style='width:100%'>
                                 constraints="{min:0,max:1000,places:0}" style='width:40px' value='0'></input> 
                             <div dojoType='dijit.form.Button' jsId='acqLitAddCopyCount' scrollOnFocus='false'>Go</div>
                         </span>
-                    </td>
-                    <td class="acq-lit-li-menu-right">
-                        <span>
+                        <span style='margin-left:10px;padding-left:10px;border-left:2px solid #aaa;'>
                             <div dojoType='dijit.form.Button' jsId='acqLitSaveCopies' scrollOnFocus='false'>Save Changes</div>
                         </span>
                         <span id='acq-lit-update-copies-progress' class='hidden'>
             </table>
         </div>
 
+        <hr/>
+        <table id='acq-lit-distrib-formula-table'>
+            <tbody id='acq-lit-distrib-formula-tbody'>
+                <tr id='acq-lit-distrib-form-row'>
+                    <td colspan='0'>
+                        <span>Distribution Formulas</span>
+                        <div name='selector'></div>
+                        <div name='set_button'></div>
+                        <div name="reset_button"></div>
+                    </td>
+                </tr>
+            </tbody>
+            <tbody id="acq-lit-distrib-applied-tbody" class="hidden">
+                <tr>
+                    <td colspan="5" id="acq-lit-distrib-applied-heading">
+                        Distribution formulas applied to this lineitem:
+                    </td>
+                </tr>
+                <tr id="acq-lit-distrib-applied-row" class="acq-lit-distrib-applied-row">
+                    <th></th>
+                    <td colspan="4"></td>
+                </tr>
+            </tbody>
+        <table>
+
         <table id='acq-lit-li-details-table'>
             <tbody><tr><td class='acq-lit-table-spacer' colspan='0'/></tr></tbody>
             <tbody style='font-weight:bold;'>
                 </tr>
             </tbody>
 
-            <tbody><tr><td class='acq-lit-table-spacer' colspan='0'/></tr></tbody>
-
-            <tbody id='acq-lit-distrib-formula-tbody'>
-                <tr id='acq-lit-distrib-form-row'>
-                    <td colspan='0'>
-                        <span>Distribution Formulas</span>
-                        <div name='selector'></div>
-                        <div name='set_button'></div>
-                        <div name="reset_button"></div>
-                    </td>
-                </tr>
-            </tbody>
-
-            <tbody><tr><td class='acq-lit-table-spacer' colspan='0'/></tr></tbody>
-            <tbody id="acq-lit-distrib-applied-tbody" class="hidden">
-                <tr>
-                    <td colspan="5" id="acq-lit-distrib-applied-heading">
-                        Distribution formulas applied to this lineitem:
-                    </td>
-                </tr>
-                <tr id="acq-lit-distrib-applied-row" class="acq-lit-distrib-applied-row">
-                    <th></th>
-                    <td colspan="4"></td>
-                </tr>
-            </tbody>
 
             <tbody><tr><td class='acq-lit-table-spacer' colspan='0'></td></tr></tbody>
             <tbody style='font-weight:bold;'>
index 627b713..4af3b48 100644 (file)
 <script type ="text/javascript">
     dojo.require('openils.widget.AutoGrid');
     openils.Util.addOnLoad(
-        function() { cradGrid.loadAll({order_by : {crad : 'name'}}) }
+        function() {
+            // avoid loading the entire config.xml_transform object
+            cradGrid.overrideWidgetArgs.format = {searchOptions : {"select":{"cxt":["name"]}}};
+            cradGrid.loadAll({order_by : {crad : 'name'}}) 
+        }
     );
 </script>
 
index 92a1ad5..f64883e 100644 (file)
@@ -521,7 +521,19 @@ function set_opac() {
         content_params.set_help_context = xulG.set_help_context;
         content_params.get_barcode = xulG.get_barcode;
 
-        if (opac_url) { content_params.url = opac_url; } else { content_params.url = xulG.url_prefix( urls.browser ); }
+        var secure_opac = true; // default to secure
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']);
+        if (prefs.prefHasUserValue('oils.secure_opac')) {
+            secure_opac = prefs.getBoolPref('oils.secure_opac');
+        }
+        dump('secure_opac = ' + secure_opac + '\n');
+
+        if (opac_url) {
+            content_params.url = xulG.url_prefix( opac_url, secure_opac );
+        } else {
+            content_params.url = xulG.url_prefix( urls.browser, secure_opac );
+        }
         browser_frame = bottom_pane.set_iframe( xulG.url_prefix(urls.XUL_BROWSER) + '?name=Catalog', {}, content_params);
         /* // Remember to use the REMOTE_BROWSER if we ever try to move this to remote xul again
         browser_frame = bottom_pane.set_iframe( xulG.url_prefix(urls.XUL_REMOTE_BROWSER) + '?name=Catalog', {}, content_params);
@@ -989,7 +1001,7 @@ function gen_statusbar_click_handler(data_key) {
         }
 
         if (ev.button == 0 /* left click, spawn opac */) {
-            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + g.data[data_key];
+            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + g.data[data_key];
             var content_params = {
                 'session' : ses(),
                 'authtime' : ses('authtime'),
index 4d61b10..9413809 100644 (file)
@@ -139,6 +139,7 @@ var api = {
     'FM_AHR_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.on_shelf.retrieve' },
     'FM_AHR_ID_LIST_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.id_list.on_shelf.retrieve', 'secure' : false },
     'FM_AHR_ID_LIST_EXPIRED_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.id_list.expired_on_shelf.retrieve', 'secure' : false },
+    'FM_AHR_COUNT_FOR_BRE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.bre.holds.count', 'secure' : false },
     'FM_AHR_COUNT_RETRIEVE' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.hold_requests.count', 'cacheable' : true, 'ttl' : 60000  },
     'FM_AHR_COUNT_RETRIEVE.authoritative' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.hold_requests.count.authoritative', 'cacheable' : true, 'ttl' : 60000  },
     'FM_AHR_CANCEL' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold.cancel' },
@@ -368,8 +369,9 @@ var api = {
 var urls = {
 
     'opac' : '/opac/' + LOCALE + '/skin/default/xml/advanced.xml?nps=1',
-    'opac_rdetail' : '/opac/' + LOCALE + '/skin/default/xml/rdetail.xml',
+    'opac_rdetail' : '/opac/' + LOCALE + '/skin/default/xml/rdetail.xml?r=',
     'opac_rresult' : '/opac/' + LOCALE + '/skin/default/xml/rresult.xml',
+    'opac_rresult_metarecord' : '/opac/' + LOCALE + '/skin/default/xml/rresult.xml?m=',
     'org_tree' : '/opac/common/js/' + LOCALE + '/OrgTree.js',
     'browser' : '/opac/' + LOCALE + '/skin/default/xml/advanced.xml?nps=1',
     'fieldmapper' : '/opac/common/js/fmall.js',
index 5420b7e..8d179c0 100644 (file)
@@ -38,9 +38,19 @@ main.menu.prototype = {
     'toolbar_mode' : 'both',
     'toolbar_labelpos' : 'side',
 
-    'url_prefix' : function(url) {
+    'url_prefix' : function(url,secure) {
+        // if host unspecified URL with leading /, prefix the remote hostname
         if (url.match(/^\//)) url = urls.remote + url;
-        if (! url.match(/^(http|chrome):\/\//) && ! url.match(/^data:/) ) url = 'http://' + url;
+        // if it starts with http:// and we want secure, convert to https://
+        if (secure && url.match(/^http:\/\//)) {
+            url = url.replace(/^http:\/\//, 'https://');
+        }
+        // if it doesn't start with a known protocol, add http(s)://
+        if (! url.match(/^(http|https|chrome):\/\//) && ! url.match(/^data:/) ) {
+            url = secure
+                ? 'https://' + url
+                : 'http://' + url;
+        }
         dump('url_prefix = ' + url + '\n');
         return url;
     },
@@ -368,6 +378,23 @@ main.menu.prototype = {
                     obj.set_patron_tab({},{},event);
                 }
             ],
+            'cmd_search_usr_id' : [
+                ['oncommand'],
+                function(event) {
+                    var usr_id = prompt(
+                        offlineStrings.getString('menu.cmd_search_usr_id.tab'),
+                        '',
+                        offlineStrings.getString('menu.cmd_search_usr_id.prompt')
+                    );
+                    if (usr_id != '' && ! isNaN(usr_id)) {
+                        obj.set_patron_tab(
+                            {},
+                            { 'id' : usr_id },
+                            event
+                        );
+                    }
+                }
+            ],
             'cmd_search_opac' : [
                 ['oncommand'],
                 function(event) {
@@ -384,7 +411,7 @@ main.menu.prototype = {
                     function spawn_tcn(r,event) {
                         for (var i = 0; i < r.count; i++) {
                             var id = r.ids[i];
-                            var opac_url = obj.url_prefix( urls.opac_rdetail ) + '?r=' + id;
+                            var opac_url = obj.url_prefix( urls.opac_rdetail ) + id;
                             obj.data.stash_retrieve();
                             var content_params = { 
                                 'session' : ses(), 
@@ -434,7 +461,7 @@ main.menu.prototype = {
                     var bib_id = prompt(offlineStrings.getString('menu.cmd_search_bib_id.tab'),'',offlineStrings.getString('menu.cmd_search_bib_id.prompt'));
                     if (!bib_id) return;
 
-                    var opac_url = obj.url_prefix( urls.opac_rdetail ) + '?r=' + bib_id;
+                    var opac_url = obj.url_prefix( urls.opac_rdetail ) + bib_id;
                     var content_params = { 
                         'session' : ses(), 
                         'authtime' : ses('authtime'),
@@ -1123,7 +1150,7 @@ main.menu.prototype = {
                         alert(offlineStrings.getString('menu.cmd_retrieve_last_record.session.error'));
                         return;
                     }
-                    var opac_url = obj.url_prefix( urls.opac_rdetail ) + '?r=' + obj.data.last_record;
+                    var opac_url = obj.url_prefix( urls.opac_rdetail ) + obj.data.last_record;
                     var content_params = {
                         'session' : ses(),
                         'authtime' : ses('authtime'),
@@ -2081,7 +2108,7 @@ commands:
         content_params.set_tab_name = function(name) { tab.label = tab.curindex + ' ' + name; tab.origlabel = name; };
         content_params.set_help_context = function(params) { return obj.set_help_context(params); };
         content_params.open_chrome_window = function(a,b,c) { return xulG.window.open(a,b,c); };
-        content_params.url_prefix = function(url) { return obj.url_prefix(url); };
+        content_params.url_prefix = function(url,secure) { return obj.url_prefix(url,secure); };
         content_params.network_meter = obj.network_meter;
         content_params.page_meter = obj.page_meter;
         content_params.get_barcode = obj.get_barcode;
index 2218ae8..480ac2b 100644 (file)
@@ -38,6 +38,7 @@
     <command id="cmd_public_opac" />
     <command id="cmd_search_tcn" />
     <command id="cmd_search_bib_id" />
+    <command id="cmd_search_usr_id" />
 <!-- Perhaps add group_application.user here as well? -->
     <command id="cmd_patron_register"
              perm="CREATE_USER" 
         <menuitem label="&staff.main.menu.search.record_via_id.label;" accesskey="&staff.main.menu.search.record_via_id.accesskey;" command="cmd_search_bib_id" />
         <menuitem label="&staff.main.menu.search.copies.label;" accesskey="&staff.main.menu.search.copies.accesskey;" command="cmd_copy_status"/>
         <menuitem label="&staff.main.menu.search.patrons_barcode.label;" accesskey="&staff.main.menu.search.patrons_barcode.accesskey;" command="cmd_circ_checkout"/>
+        <menuitem
+            command="cmd_search_usr_id"
+            label="&staff.main.menu.search.patron_db_id.label;"
+            accesskey="&staff.main.menu.search.patron_db_id.accesskey;"/>
     </menupopup>
 </menu>
 
index 48f8b5e..3d42d29 100644 (file)
             <menupopup tooltiptext="">
                 <menuitem label="&staff.main.menu.search.patrons.label;" accesskey="&staff.main.menu.search.patrons.accesskey;" command="cmd_patron_search" />
                 <menuitem label="&staff.main.menu.search.patrons_barcode.label;" accesskey="&staff.main.menu.search.patrons_barcode.accesskey;" command="cmd_circ_checkout"/>
+                <menuitem label="&staff.main.menu.search.patron_db_id.label;" accesskey="&staff.main.menu.search.patron_db_id.accesskey;" command="cmd_search_usr_id"/>
             </menupopup>
         </toolbarbutton>
         <toolbarbutton
index 5ae0eb1..f0b4cd9 100644 (file)
@@ -293,7 +293,7 @@ util.browser.prototype = {
             if (!cw.xulG.volume_item_creator) { cw.xulG.volume_item_creator = function(a) { return window.xulG.volume_item_creator(a); }; }
             if (!cw.xulG.get_new_session) { cw.xulG.get_new_session = function(a) { return window.xulG.get_new_session(a); }; }
             if (!cw.xulG.holdings_maintenance_tab) { cw.xulG.holdings_maintenance_tab = function(a,b,c) { return window.xulG.holdings_maintenance_tab(a,b,c); }; }
-            if (!cw.xulG.url_prefix) { cw.xulG.url_prefix = function(url) { return window.xulG.url_prefix(url); }; }
+            if (!cw.xulG.url_prefix) { cw.xulG.url_prefix = function(url,secure) { return window.xulG.url_prefix(url,secure); }; }
             if (!cw.xulG.urls) { cw.xulG.urls = window.urls; }
             try { s += ('******** cw = ' + cw + ' cw.xulG = ' + (cw.xulG) + '\n'); } catch(E) { s+=E + '\n'; }
             obj.error.sdump('D_BROWSER',s);
index 9bf0e6e..e66dded 100644 (file)
                 var snd_obj = xul_param('sound_object',{'modal_xulG':true});
                 if (snd) {
                     try {
-                        var params = { 'interval' : 500, 'sig' : 'fancy_prompt_my_init' };
+                        var params = { 'sig' : 'fancy_prompt_my_init' };
                         if (snd_obj) { params.reuse_queue_from_this_snd_obj = snd_obj; }
                         JSAN.use('util.sound'); var sound = new util.sound(params);
                         if (snd) { sound[ snd ](); }
index d0b0f26..85a34d0 100644 (file)
@@ -1002,6 +1002,7 @@ util.list.prototype = {
                 
                 if ( this.columns[i].editable == false ) { treecell.setAttribute('editable','false'); }
                 var label = '';
+                var sort_value = '';
 
                 // What skip columns is doing is rendering the treecells as blank/empty
                 if (params.skip_columns && (params.skip_columns.indexOf(i) != -1)) {
@@ -1030,15 +1031,27 @@ util.list.prototype = {
         } else if (typeof params.map_row_to_columns == 'function' || typeof this.map_row_to_columns == 'function') {
 
             var labels = [];
+            var sort_values = [];
 
             if (typeof params.map_row_to_columns == 'function') {
 
-                labels = params.map_row_to_columns(params.row,this.columns,this.scratch_data);
+                var values = params.map_row_to_columns(params.row,this.columns,this.scratch_data);
+                if (typeof values.values == 'undefined') {
+                    labels = values;
+                } else {
+                    labels = values.values;
+                    sort_values = values.sort_values;
+                }
 
             } else if (typeof this.map_row_to_columns == 'function') {
 
-                labels = this.map_row_to_columns(params.row,this.columns,this.scratch_data);
-
+                var values = this.map_row_to_columns(params.row,this.columns,this.scratch_data);
+                if (typeof values.values == 'undefined') {
+                    labels = values;
+                } else {
+                    labels = values.values;
+                    sort_values = values.sort_values;
+                }
             }
             for (var i = 0; i < labels.length; i++) {
                 var treecell;
@@ -1054,6 +1067,9 @@ util.list.prototype = {
                 } else {
                     treecell.setAttribute('label',typeof labels[i] == 'string' || typeof labels[i] == 'number' ? labels[i] : '');
                 }
+                if (sort_values[i]) {
+                    treecell.setAttribute('sort_value',js2JSON(sort_values[i]));
+                }
                 s += ('treecell = ' + treecell + ' with label = ' + labels[i] + '\n');
             }
 
@@ -1490,38 +1506,53 @@ util.list.prototype = {
                             var treeitem = treeitems[i];
                             var treerow = treeitem.firstChild;
                             var treecell = treerow.childNodes[ col_pos ];
-                            value = ( { 'value' : treecell ? treecell.getAttribute('label') : '', 'node' : treeitem } );
+                            value = ( {
+                                'value' : treecell
+                                    ? treecell.getAttribute('label')
+                                    : '',
+                                'sort_value' : treecell ? treecell.hasAttribute('sort_value')
+                                    ? JSON2js(
+                                        treecell.getAttribute('sort_value'))
+                                    : '' : '',
+                                'node' : treeitem
+                            } );
                             rows.push( value );
                         }
                         rows = rows.sort( function(a,b) { 
-                            a = a.value; b = b.value; 
-                            if (col.getAttribute('sort_type')) {
-                                switch(col.getAttribute('sort_type')) {
-                                    case 'date' :
-                                        JSAN.use('util.date'); // to pull in dojo.date.locale
-                                        a = dojo.date.locale.parse(a,{});
-                                        b = dojo.date.locale.parse(b,{});
-                                    break;
-                                    case 'number' :
-                                        a = Number(a); b = Number(b);
-                                    break;
-                                    case 'money' :
-                                        a = util.money.dollars_float_to_cents_integer(a);
-                                        b = util.money.dollars_float_to_cents_integer(b);
-                                    break;
-                                    case 'title' : /* special case for "a" and "the".  doesn't use marc 245 indicator */
-                                        a = String( a ).toUpperCase().replace( /^\s*(THE|A|AN)\s+/, '' );
-                                        b = String( b ).toUpperCase().replace( /^\s*(THE|A|AN)\s+/, '' );
-                                    break;
-                                    default:
+                            if (a.sort_value) {
+                                a = a.sort_value;
+                                b = b.sort_value;
+                            } else {
+                                a = a.value;
+                                b = b.value;
+                                if (col.getAttribute('sort_type')) {
+                                    switch(col.getAttribute('sort_type')) {
+                                        case 'date' :
+                                            JSAN.use('util.date'); // to pull in dojo.date.locale
+                                            a = dojo.date.locale.parse(a,{});
+                                            b = dojo.date.locale.parse(b,{});
+                                        break;
+                                        case 'number' :
+                                            a = Number(a); b = Number(b);
+                                        break;
+                                        case 'money' :
+                                            a = util.money.dollars_float_to_cents_integer(a);
+                                            b = util.money.dollars_float_to_cents_integer(b);
+                                        break;
+                                        case 'title' : /* special case for "a" and "the".  doesn't use marc 245 indicator */
+                                            a = String( a ).toUpperCase().replace( /^\s*(THE|A|AN)\s+/, '' );
+                                            b = String( b ).toUpperCase().replace( /^\s*(THE|A|AN)\s+/, '' );
+                                        break;
+                                        default:
+                                            a = String( a ).toUpperCase();
+                                            b = String( b ).toUpperCase();
+                                        break;
+                                    }
+                                } else {
+                                    if (typeof a == 'string' || typeof b == 'string') {
                                         a = String( a ).toUpperCase();
                                         b = String( b ).toUpperCase();
-                                    break;
-                                }
-                            } else {
-                                if (typeof a == 'string' || typeof b == 'string') {
-                                    a = String( a ).toUpperCase();
-                                    b = String( b ).toUpperCase();
+                                    }
                                 }
                             }
                             //dump('sorting: type = ' + col.getAttribute('sort_type') + ' a = ' + a + ' b = ' + b + ' a<b= ' + (a<b) + ' a>b= ' + (a>b) + '\n');
@@ -1801,6 +1832,9 @@ util.list.prototype = {
                     def.render = function(my) {
                         return util.date.formatted_date( my[dataobj][datafield](), '%{localized}' );
                     }
+                    def.sort_value = function(my) {
+                        return util.date.db_date2Date( my[dataobj][datafield]() ).getTime();
+                    }
                 }
                 if (my_field.datatype == 'org_unit') {
                     def.render = function(my) {
@@ -1812,6 +1846,9 @@ util.list.prototype = {
                     def.render = function(my) {
                         return util.money.sanitize( my[dataobj][datafield]() );
                     }
+                    def.sort_value = function(my) {
+                        return util.money.dollars_float_to_cents_integer( my[dataobj][datafield]() );
+                    }
                 }
                 if (column_extras) {
                     if (column_extras['*']) {
@@ -1880,6 +1917,7 @@ util.list.prototype = {
 
             var my = row.my;
             var values = [];
+            var sort_values = [];
             var cmd = '';
             try {
                 for (var i = 0; i < cols.length; i++) {
@@ -1888,13 +1926,34 @@ util.list.prototype = {
                         case 'string' : cmd += 'try { ' + cols[i].render + '; values['+i+'] = v; } catch(E) { values['+i+'] = error_value; }'; break;
                         default: cmd += 'values['+i+'] = "??? '+(typeof cols[i].render)+'"; ';
                     }
+                    switch (typeof cols[i].sort_value) {
+                        case 'function':
+                            try {
+                                sort_values[i] = cols[i].sort_value(my,scratch);
+                            } catch(E) {
+                                sort_values[i] = error_value;
+                                obj.error.sdump('D_COLUMN_RENDER_ERROR',E);
+                            }
+                        break;
+                        case 'string' :
+                            cmd += 'try { '
+                                + cols[i].sort_value
+                                + '; values['
+                                + i
+                                +'] = v; } catch(E) { sort_values['
+                                + i
+                                + '] = error_value; }';
+                        break;
+                        default:
+                            cmd += 'sort_values['+i+'] = values[' + i + '];';
+                    }
                 }
                 if (cmd) eval( cmd );
             } catch(E) {
                 obj.error.sdump('D_WARN','map_row_to_column: ' + E);
                 if (error_value) { value = error_value; } else { value = '   ' };
             }
-            return values;
+            return { 'values' : values, 'sort_values' : sort_values };
         }
     }
 }
index 34a7157..aba38e9 100644 (file)
@@ -220,35 +220,35 @@ util.print.prototype = {
             JSAN.use('util.date');
             var s = msg; var b;
 
-            try{b = s; s = s.replace(/%LINE_NO%/,Number(params.row_idx)+1);}
+            try{b = s; s = s.replace(/%LINE_NO%/g,Number(params.row_idx)+1);}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
 
-            try{b = s; s = s.replace(/%patron_barcode%/,params.patron_barcode);}
+            try{b = s; s = s.replace(/%patron_barcode%/g,params.patron_barcode);}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
 
-            try{b = s; s = s.replace(/%LIBRARY%/,params.lib.name());}
+            try{b = s; s = s.replace(/%LIBRARY%/g,params.lib.name());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%PINES_CODE%/,params.lib.shortname());}
+            try{b = s; s = s.replace(/%PINES_CODE%/g,params.lib.shortname());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%SHORTNAME%/,params.lib.shortname());}
+            try{b = s; s = s.replace(/%SHORTNAME%/g,params.lib.shortname());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%STAFF_FIRSTNAME%/,params.staff.first_given_name());}
+            try{b = s; s = s.replace(/%STAFF_FIRSTNAME%/g,params.staff.first_given_name());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%STAFF_LASTNAME%/,params.staff.family_name());}
+            try{b = s; s = s.replace(/%STAFF_LASTNAME%/g,params.staff.family_name());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%STAFF_BARCODE%/,params.staff.barcode); }
+            try{b = s; s = s.replace(/%STAFF_BARCODE%/g,params.staff.barcode); }
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%STAFF_PROFILE%/,obj.data.hash.pgt[ params.staff.profile() ].name() ); }
+            try{b = s; s = s.replace(/%STAFF_PROFILE%/g,obj.data.hash.pgt[ params.staff.profile() ].name() ); }
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%PATRON_ALIAS_OR_FIRSTNAME%/,(params.patron.alias() == '' || params.patron.alias() == null) ? params.patron.first_given_name() : params.patron.alias());}
+            try{b = s; s = s.replace(/%PATRON_ALIAS_OR_FIRSTNAME%/g,(params.patron.alias() == '' || params.patron.alias() == null) ? params.patron.first_given_name() : params.patron.alias());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%PATRON_ALIAS%/,(params.patron.alias() == '' || params.patron.alias() == null) ? '' : params.patron.alias());}
+            try{b = s; s = s.replace(/%PATRON_ALIAS%/g,(params.patron.alias() == '' || params.patron.alias() == null) ? '' : params.patron.alias());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%PATRON_FIRSTNAME%/,params.patron.first_given_name());}
+            try{b = s; s = s.replace(/%PATRON_FIRSTNAME%/g,params.patron.first_given_name());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%PATRON_LASTNAME%/,params.patron.family_name());}
+            try{b = s; s = s.replace(/%PATRON_LASTNAME%/g,params.patron.family_name());}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
-            try{b = s; s = s.replace(/%PATRON_BARCODE%/,typeof params.patron.card() == 'object' ? params.patron.card().barcode() : util.functional.find_id_object_in_list( params.patron.cards(), params.patron.card() ).barcode() ) ;}
+            try{b = s; s = s.replace(/%PATRON_BARCODE%/g,typeof params.patron.card() == 'object' ? params.patron.card().barcode() : util.functional.find_id_object_in_list( params.patron.cards(), params.patron.card() ).barcode() ) ;}
                 catch(E){s = b; this.error.sdump('D_WARN','string = <' + s + '> error = ' + js2JSON(E)+'\n');}
 
             try{b = s; s=s.replace(/%TODAY%/g,(new Date()));}
index 8d46653..0d57f84 100644 (file)
@@ -28,7 +28,12 @@ util.sound = function (params) {
             } else {
                 this._funcs = [];
             }
-            JSAN.use('util.exec'); this._exec = new util.exec(); var intervalId = this._exec.timer( this._funcs, params.interval || 500 );
+            JSAN.use('util.exec');
+            this._exec = new util.exec();
+            var delay = params.interval;
+            if (!delay) { delay = _sound_delay_interval; /* define this in server/skin/custom.js */ }
+            if (!delay) { delay = 2000; }
+            var intervalId = this._exec.timer( this._funcs, delay );
             dump('SOUND('+this.sig+'): starting timer with intervalId = ' + intervalId + '\n');
         }
 
@@ -102,6 +107,12 @@ util.sound.prototype = {
         this.play_url( urls[key] );
     },
 
+    'special' : function special(e) {
+        var key = 'AUDIO_' + arguments.callee.name + '_' + e;
+        dump('SOUND('+this.sig+'): key = ' + key + '\n');
+        this.play_url( urls[key] );
+    },
+
     'good' : function good(e){
         var key = 'AUDIO_' + arguments.callee.name;
         dump('SOUND('+this.sig+'): key = ' + key + '\n');
index 753da58..ca7eedf 100644 (file)
@@ -110,6 +110,8 @@ menu.cmd_replace_barcode.renaming.failure=The rename operation probably failed.
 menu.cmd_search_opac.tab=Catalog
 menu.cmd_search_bib_id.tab=What is the internal ID for the bibliographic record?
 menu.cmd_search_bib_id.prompt=Bib ID Lookup
+menu.cmd_search_usr_id.tab=What is the internal database ID for the patron account?
+menu.cmd_search_usr_id.prompt=Patron ID Lookup
 menu.cmd_search_tcn.tab=What is the TCN or accession ID for the record?
 menu.cmd_search_tcn.prompt=TCN Lookup
 menu.cmd_search_tcn.not_found.error="%1$s" not found
index 545a329..4024ec1 100644 (file)
@@ -216,7 +216,6 @@ admin.transit_list.prototype = {
         obj.list.init( 
             { 
                 'columns' : columns, 
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(), 
                 'retrieve_row' : function(params) {
                     var row = params.row;
                     try {
index 88daa1a..9a1eb75 100644 (file)
@@ -45,11 +45,10 @@ function init_lists() {
         list1 = new util.list('work_action_log');
         list2 = new util.list('work_patron_log');
 
-        JSAN.use('circ.util'); var columns = circ.util.work_log_columns({}); var column_mapper_func = circ.util.std_map_row_to_columns();
+        JSAN.use('circ.util'); var columns = circ.util.work_log_columns({});
 
         list1.init( {
             'columns' : columns,
-            'map_row_to_columns' : column_mapper_func,
             'on_select' : function(ev) {
                 JSAN.use('util.functional'); var sel = list1.retrieve_selection();
                 selected1 = util.functional.map_list( sel, function(o) { return JSON2js(o.getAttribute('retrieve_id')); });
index b7dc24a..bc6d784 100644 (file)
@@ -35,6 +35,10 @@ function bib_brief_overlay(params) {
         }
 
         JSAN.use('util.widgets');
+        function exists(name) {
+            var nodes = document.getElementsByAttribute('name',name);
+            return nodes.length > 0;
+        }
         function set(name,value) {
             if (params.print_data) {
                 params.print_data[name] = value;
@@ -90,28 +94,76 @@ function bib_brief_overlay(params) {
             }
         }
 
-        // Let's fetch a bib call number
-        JSAN.use('OpenILS.data');
-        var data = new OpenILS.data();
-        var label_class = data.hash.aous['cat.default_classification_scheme'];
-        if (!label_class) {
-            label_class = 1;
-        }
-        var cn_blob_array = net.simple_request('BLOB_MARC_CALLNUMBERS_RETRIEVE',[params.mvr_id, label_class]);
-        if (! cn_blob_array) { cn_blob_array = []; }
-        var tooltip_text = '';
-        for (var i = 0; i < cn_blob_array.length; i++) {
-            var cn_blob_obj = cn_blob_array[i];
-            for (var j in cn_blob_obj) {
-                tooltip_text += j + ' : ' + cn_blob_obj[j] + '\n';
+        // Let's fetch a bib call number, if the "bib_call_number" field exists
+        // in our display
+        if (exists('bib_call_number')) {
+            JSAN.use('OpenILS.data');
+            var data = new OpenILS.data();
+            var label_class = data.hash.aous[
+                'cat.default_classification_scheme'
+            ];
+            if (!label_class) {
+                label_class = 1;
             }
+            net.simple_request(
+                'BLOB_MARC_CALLNUMBERS_RETRIEVE',
+                [params.mvr_id, label_class],
+                function(req) {
+                    var cn_blob_array = req.getResultObject();
+                    if (! cn_blob_array) { cn_blob_array = []; }
+                    var tooltip_text = '';
+                    for (var i = 0; i < cn_blob_array.length; i++) {
+                        var cn_blob_obj = cn_blob_array[i];
+                        for (var j in cn_blob_obj) {
+                            tooltip_text += j + ' : ' + cn_blob_obj[j] + '\n';
+                        }
+                    }
+                    if (tooltip_text) {
+                        var cn_blob_obj = cn_blob_array[0];
+                        for (var j in cn_blob_obj) {
+                            set('bib_call_number',cn_blob_obj[j]);
+                        }
+                        set_tooltip('bib_call_number',tooltip_text);
+                    }
+                }
+            );
         }
-        if (tooltip_text) {
-            var cn_blob_obj = cn_blob_array[0];
-            for (var j in cn_blob_obj) {
-                set('bib_call_number',cn_blob_obj[j]);
-            }
-            set_tooltip('bib_call_number',tooltip_text);
+
+        // Let's fetch the hold count for the bib, if the "holds" field exists
+        // in our display
+        if (exists('holds')) {
+            net.simple_request(
+                'FM_AHR_COUNT_FOR_BRE',
+                [params.mvr_id],
+                function(req) {
+                    var hold_count = req.getResultObject();
+                    set('holds',hold_count);
+                }
+            );
+        }
+
+        // Let's fetch the item count for the bib, if the "items" field exists
+        // in our display
+        if (exists('items')) {
+            JSAN.use('OpenILS.data');
+            var data = new OpenILS.data();
+            net.simple_request(
+                'FM_ACP_COUNT.authoritative',
+                [ data.tree.aou.id(), params.mvr_id ],
+                function(req){
+                    var count_blob = req.getResultObject()[0];
+                    set('items',count_blob.count);
+                    set_tooltip(
+                        'items',
+                        $('catStrings')
+                        ? $('catStrings').getFormattedString(
+                            'staff.cat.bib_brief.items.available.tooltip',
+                            [count_blob.available]
+                        )
+                        : count_blob.available
+                    );
+                }
+            );
         }
 
     } catch(E) {
index 3b3d088..81efb52 100644 (file)
@@ -192,7 +192,7 @@ function merge_records() {
         if (typeof xulG.on_merge == 'function') {
             xulG.on_merge(robj);
         }
-        var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + lead_record;
+        var opac_url = xulG.url_prefix( urls.opac_rdetail ) + lead_record;
         var content_params = {
             'session' : ses(),
             'authtime' : ses('authtime'),
index 855d023..bb9b632 100644 (file)
@@ -1708,7 +1708,6 @@ cat.copy_browser.prototype = {
                 {
                     'no_auto_select' : true,
                     'columns' : columns,
-                    'map_row_to_columns' : circ.util.std_map_row_to_columns(' '),
                     'retrieve_row' : function(params) {
 
                         var row = params.row;
index cc7b5a9..9dc89df 100644 (file)
@@ -79,7 +79,6 @@ cat.copy_buckets.prototype = {
         obj.list1.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : retrieve_row,
                 'on_select' : function(ev) {
                     try {
@@ -109,7 +108,6 @@ cat.copy_buckets.prototype = {
         obj.list2.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : retrieve_row,
                 'on_select' : function(ev) {
                     try {
index 3a459a2..9ab9a04 100644 (file)
@@ -82,7 +82,6 @@
                 g.list.init(
                     {
                         'columns' : columns,
-                        'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                     }
                 );
                 $('list_actions').appendChild( g.list.render_list_actions() );
index 7debf35..633d047 100644 (file)
 
                                             /* Replace tab with OPAC-view of record */
 
-                                            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + robj.id();
+                                            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + robj.id();
                                             var content_params = {
                                                 'session' : ses(),
                                                 'authtime' : ses('authtime'),
index 07a0aad..e4a0038 100644 (file)
@@ -151,7 +151,6 @@ cat.record_buckets.prototype = {
         obj.list0.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : retrieve_row,
                 'on_select' : function(ev) {
                     try {
@@ -180,7 +179,6 @@ cat.record_buckets.prototype = {
         obj.list1.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : retrieve_row,
                 'on_select' : function(ev) {
                     try {
@@ -211,7 +209,6 @@ cat.record_buckets.prototype = {
         obj.list2.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : retrieve_row,
                 'on_select' : function(ev) {
                     try {
@@ -784,7 +781,7 @@ cat.record_buckets.prototype = {
                                 for (var i = 0; i < docids.length; i++) {
                                     var doc_id = docids[i];
                                     if (seen[doc_id]) continue; seen[doc_id] = true;
-                                    var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + doc_id;
+                                    var opac_url = xulG.url_prefix( urls.opac_rdetail ) + doc_id;
                                     var content_params = { 
                                         'session' : ses(),
                                         'authtime' : ses('authtime'),
index f993615..ce28eac 100644 (file)
                     if (!lm) {
                         lm = g.data.hash.aous['cat.spine.line.margin'] || 0;
                     }
-                    var mm = Number($('mm').value); if (mm == NaN) mm = 2; /* middle margin */
+                    var mm = Number($('mm').value); if (isNaN(mm)) mm = 2; /* middle margin */
                     var lw = Number($('lw').value); /* spine label width */
                     if (!lw) {
                         lw = g.data.hash.aous['cat.spine.line.width'] || 8;
             var w = win.open( loc, 'spine_preview', 'chrome,resizable,width=750,height=550');
             w.xulG = { 
                 'url' : 'about:blank',
-                'url_prefix' : function (u) { return xulG.url_prefix(u); },
+                'url_prefix' : function (u,s) { return xulG.url_prefix(u,s); },
                 'show_print_button' : 1,
                 'printer_context' : 'label',
                 'alternate_print' : 1,
index 600f360..98a6dd4 100644 (file)
@@ -257,7 +257,7 @@ cat.util.show_in_opac = function(selection_list) {
                 continue;
             }
             seen[doc_id] = true;
-            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + doc_id;
+            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + doc_id;
             var content_params = { 
                 'session' : ses(),
                 'authtime' : ses('authtime'),
@@ -1163,7 +1163,7 @@ cat.util.mark_for_overlay = function(doc_id,doc_mvr) {
 
                 if (ev.button == 0 /* left click, spawn opac */) {
                     var opac_url = xulG.url_prefix( urls.opac_rdetail )
-                        + '?r=' + data[data_key];
+                        + data[data_key];
                     var content_params = {
                         'session' : ses(),
                         'authtime' : ses('authtime'),
index 5e204c4..5246e9c 100644 (file)
@@ -1175,7 +1175,7 @@ g.stash_and_close = function(param) {
         }
 
         if (xul_param('load_opac_when_done')) {
-            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + g.doc_id;
+            var opac_url = xulG.url_prefix( urls.opac_rdetail ) + g.doc_id;
             var content_params = {
                 'session' : ses(),
                 'authtime' : ses('authtime'),
index dc600e8..ac3e712 100644 (file)
@@ -53,7 +53,6 @@ cat.z3950.prototype = {
             obj.list.init(
                 {
                     'columns' : columns,
-                    'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                     'on_select' : function(ev) {
                         try {
                             JSAN.use('util.functional');
@@ -742,7 +741,7 @@ cat.z3950.prototype = {
     },
 
     'replace_tab_with_opac' : function(doc_id) {
-        var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + doc_id;
+        var opac_url = xulG.url_prefix( urls.opac_rdetail ) + doc_id;
         var content_params = { 
             'session' : ses(),
             'authtime' : ses('authtime'),
index b7b2207..d88e7a3 100644 (file)
@@ -46,10 +46,10 @@ function my_init() {
 
         var columns = circ.util.transit_columns({});
         transit_list = new util.list('transit');
-        transit_list.init( { 'columns' : columns, 'map_row_to_columns' : circ.util.std_map_row_to_columns(), });
+        transit_list.init( { 'columns' : columns });
 
         hold_list = new util.list('hold');
-        hold_list.init( { 'columns' : columns, 'map_row_to_columns' : circ.util.std_map_row_to_columns(), });
+        hold_list.init( { 'columns' : columns });
 
         // timeout so xulG gets a chance to get pushed in
         setTimeout(
index 24276ac..d967d5a 100644 (file)
@@ -46,7 +46,6 @@ circ.checkin.prototype = {
         obj.list.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : obj.gen_list_retrieve_row_func(),
                 'on_select' : function(ev) {
                     try {
@@ -408,6 +407,59 @@ circ.checkin.prototype = {
                         ind.hidden = cb.getAttribute('checked') != 'true'; 
                         document.getElementById('checkin_barcode_entry_textbox').focus();
                         return true;
+                    } ],
+                    'cmd_checkin_clear_shelf_expired' : [ ['command'], function(ev) {
+                        dump('in cmd_checkin_clear_shelf_expired\n');
+                        var bg = document.getElementById('background');
+                        var cb = document.getElementById('checkin_clear_shelf_expired');
+                        var ind = document.getElementById('checkin_clear_shelf_expired_indicator');
+                        var cn = 'checkin_screen_checkin_clear_shelf_expired';
+                        if (cb.getAttribute('checked') == 'true') { addCSSClass(bg,cn); } else { removeCSSClass(bg,cn); }
+                        ind.hidden = cb.getAttribute('checked') != 'true'; 
+                        document.getElementById('checkin_barcode_entry_textbox').focus();
+                        return true;
+                    } ],
+                    'cmd_checkin_auto_retarget' : [ ['command'], function(ev) {
+                        dump('in cmd_checkin_auto_retarget\n');
+                        var bg = document.getElementById('background');
+                        var cb = document.getElementById('checkin_auto_retarget');
+                        var cb2 = document.getElementById('checkin_auto_retarget_all');
+                        var ind = document.getElementById('checkin_auto_retarget_indicator');
+                        var ind2 = document.getElementById('checkin_auto_retarget_all_indicator');
+                        var cn = 'checkin_screen_checkin_auto_retarget';
+                        var cn2 = 'checkin_screen_checkin_auto_retarget_all';
+                        if (cb.getAttribute('checked') == 'true') {
+                            if(cb2.getAttribute('checked') == 'true') {
+                                removeCSSClass(bg,cn);
+                                addCSSClass(bg,cn2);
+                                ind.hidden = true;
+                                ind2.hidden = false;
+                            } else {
+                                addCSSClass(bg,cn);
+                                removeCSSClass(bg,cn2);
+                                ind.hidden = false;
+                                ind2.hidden = true;
+                            }
+                        } else {
+                            removeCSSClass(bg,cn);
+                            removeCSSClass(bg,cn2);
+                            ind.hidden = true;
+                            ind2.hidden = true;
+                        }
+                        document.getElementById('checkin_barcode_entry_textbox').focus();
+                        return true;
+                    } ],
+                    'cmd_checkin_local_hold_as_transit' : [ ['command'], function(ev) {
+                        dump('in cmd_checkin_local_hold_as_transit\n');
+                        var bg = document.getElementById('background');
+                        var cb = document.getElementById('checkin_local_hold_as_transit');
+                        var ind = document.getElementById('checkin_local_hold_as_transit_indicator');
+                        var cn = 'checkin_screen_checkin_local_hold_as_transit';
+                        if (cb.getAttribute('checked') == 'true') { addCSSClass(bg,cn); } else { removeCSSClass(bg,cn); }
+                        ind.hidden = cb.getAttribute('checked') != 'true'; 
+                        document.getElementById('checkin_barcode_entry_textbox').focus();
+                        return true;
+
                     } ]
                 }
             }
@@ -567,6 +619,20 @@ circ.checkin.prototype = {
             var amnesty_mode = document.getElementById('amnesty_mode');
             if (amnesty_mode) amnesty_mode = amnesty_mode.getAttribute('checked') == 'true';
             if (amnesty_mode) params.void_overdues = 1;
+            var clear_shelf_expired_holds = document.getElementById('checkin_clear_shelf_expired');
+            if (clear_shelf_expired_holds) clear_shelf_expired_holds = clear_shelf_expired_holds.getAttribute('checked') == 'true';
+            if (clear_shelf_expired_holds) params.clear_expired = 1;
+            var auto_retarget = document.getElementById('checkin_auto_retarget');
+            if (auto_retarget) auto_retarget = auto_retarget.getAttribute('checked') == 'true';
+            if (auto_retarget) {
+                var retarget_all = document.getElementById('checkin_auto_retarget_all');
+                if (retarget_all) retarget_all = retarget_all.getAttribute('checked') == 'true';
+                if (retarget_all) params.retarget_mode = 'retarget.all';
+                else params.retarget_mode = 'retarget';
+            }
+            var hold_as_transit = document.getElementById('checkin_local_hold_as_transit');
+            if (hold_as_transit) hold_as_transit = hold_as_transit.getAttribute('checked') == 'true';
+            if (hold_as_transit) params.hold_as_transit = 1;
             circ.util.checkin_via_barcode(
                 ses(), 
                 params,
index 522a740..f72fcff 100644 (file)
@@ -35,6 +35,9 @@
     <command id="cmd_suppress_holds_and_transits" />
     <command id="cmd_amnesty_mode" />
     <command id="cmd_checkin_auto_print_slips" />
+    <command id="cmd_checkin_clear_shelf_expired" />
+    <command id="cmd_checkin_auto_retarget" />
+    <command id="cmd_checkin_local_hold_as_transit" />
 </commandset>
 
 
                 <description id="suppress_holds_and_transits_indicator" hidden="true">&staff.circ.checkin_overlay.suppress_holds_and_transits.label;</description>
                 <description id="amnesty_mode_indicator" hidden="true">&staff.circ.checkin_overlay.amnesty_mode.label;</description>
                 <description id="checkin_auto_print_slips_indicator" hidden="true">&staff.circ.checkin_overlay.checkin_auto_print_slips.label;</description>
+                <description id="checkin_clear_shelf_expired_indicator" hidden="true">&staff.circ.checkin_overlay.checkin_clear_shelf_expired.label;</description>
+                <description id="checkin_auto_retarget_indicator" hidden="true">&staff.circ.checkin_overlay.checkin_auto_retarget.label;</description>
+                <description id="checkin_auto_retarget_all_indicator" hidden="true">&staff.circ.checkin_overlay.checkin_auto_retarget_all_ind.label;</description>
+                <description id="checkin_local_hold_as_transit_indicator" hidden="true">&staff.circ.checkin_overlay.checkin_local_hold_as_transit.label;</description>
             </vbox>
         </vbox>
         <spacer flex="1"/>
                 label="&staff.circ.checkin_overlay.amnesty_mode.label;" accesskey="&staff.circ.checkin_overlay.amnesty_mode.accesskey;"/>
             <menuitem type="checkbox" id="checkin_auto_print_slips" oils_persist="checked" command="cmd_checkin_auto_print_slips"
                 label="&staff.circ.checkin_overlay.checkin_auto_print_slips.label;" accesskey="&staff.circ.checkin_overlay.checkin_auto_print_slips.accesskey;"/>
+            <menuitem type="checkbox" id="checkin_clear_shelf_expired" oils_persist="checked" command="cmd_checkin_clear_shelf_expired"
+                label="&staff.circ.checkin_overlay.checkin_clear_shelf_expired.label;" accesskey="&staff.circ.checkin_overlay.checkin_clear_shelf_expired.accesskey;"/>
+            <menuitem type="checkbox" id="checkin_auto_retarget" oils_persist="checked" command="cmd_checkin_auto_retarget"
+                label="&staff.circ.checkin_overlay.checkin_auto_retarget.label;" accesskey="&staff.circ.checkin_overlay.checkin_auto_retarget.accesskey;"/>
+            <menuitem type="checkbox" id="checkin_auto_retarget_all" oils_persist="checked" command="cmd_checkin_auto_retarget"
+                label="&staff.circ.checkin_overlay.checkin_auto_retarget_all.label;" accesskey="&staff.circ.checkin_overlay.checkin_auto_retarget_all.accesskey;"/>
+            <menuitem type="checkbox" id="checkin_local_hold_as_transit" oils_persist="checked" command="cmd_checkin_local_hold_as_transit"
+                label="&staff.circ.checkin_overlay.checkin_local_hold_as_transit.label;" accesskey="&staff.circ.checkin_overlay.checkin_local_hold_as_transit;"/>
         </menupopup>
     </button>
 </hbox>
index 11f5373..53a4b0d 100644 (file)
@@ -31,7 +31,6 @@ circ.checkout.prototype = {
         obj.list.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'on_select' : function() {
                     var sel = obj.list.retrieve_selection();
                     document.getElementById('clip_button').disabled = sel.length < 1;
index 3fcd465..9046ef5 100644 (file)
                     JSAN.use('circ.util'); var columns = circ.util.transit_columns({});
 
                     JSAN.use('util.list'); g.list = new util.list('transit');
-                    g.list.init( { 'columns' : columns, 'map_row_to_columns' : circ.util.std_map_row_to_columns(), });
+                    g.list.init( { 'columns' : columns });
                     g.list.append( { 'row' : { 'my' : { 'atc' : g.transit, } } });
     
                 } else {
                     );
 
                     JSAN.use('util.list'); g.list = new util.list('hold');
-                    g.list.init( { 'columns' : columns, 'map_row_to_columns' : circ.util.std_map_row_to_columns(), });
+                    g.list.init( { 'columns' : columns });
                     g.list.append( { 'row' : { 'my' : { 'ahr' : better_fleshed_hold_blob.hold, 'acp' : g.copy, 'status' : status_robj, } } });
     
                     JSAN.use('patron.util'); 
index f7ac6dd..510d13c 100644 (file)
@@ -45,7 +45,6 @@ circ.copy_status.prototype = {
         obj.list.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'on_select' : function(ev) {
                     try {
                         JSAN.use('util.functional');
index d6d6355..e3d7be5 100644 (file)
@@ -37,7 +37,6 @@ circ.in_house_use.prototype = {
         obj.list.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'on_select' : function() {
                     var sel = obj.list.retrieve_selection();
                     obj.controller.view.sel_clip.setAttribute('disabled', sel.length < 1);
index 8dbe7c2..3264c84 100644 (file)
@@ -47,7 +47,6 @@ circ.renew.prototype = {
         obj.list.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'on_select' : function(ev) {
                     try {
                         JSAN.use('util.functional');
index c94c2ca..7c8003a 100644 (file)
@@ -1103,6 +1103,7 @@ circ.util.columns = function(modify,params) {
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.acp.status_changed_time(), '%{localized}' ); },
             'persist' : 'hidden width ordinal'
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.acp.status_changed_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1136,6 +1137,7 @@ circ.util.columns = function(modify,params) {
                     return "";
                 }
             }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.circ.xact_start() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1153,6 +1155,7 @@ circ.util.columns = function(modify,params) {
                     return "";
                 }
             }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.circ.checkin_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1164,6 +1167,7 @@ circ.util.columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.circ ? util.date.formatted_date( my.circ.xact_finish(), '%{localized}' ) : ""; },
+            'sort_value' : function(my) { return util.date.db_date2Date( my.circ.xact_finish() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1181,6 +1185,7 @@ circ.util.columns = function(modify,params) {
                     return "";
                 }
             }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.circ.due_date() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1192,6 +1197,7 @@ circ.util.columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.acp.create_date(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.acp.create_date() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1203,6 +1209,7 @@ circ.util.columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.acp.edit_date(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.acp.edit_date() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1354,6 +1361,7 @@ circ.util.columns = function(modify,params) {
                     return "";
                 }
             }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.circ.stop_fines_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1449,6 +1457,7 @@ circ.util.columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.circ ? util.date.formatted_date( my.circ.checkin_scan_time(), '%{localized}' ) : ""; },
+            'sort_value' : function(my) { return util.date.db_date2Date( my.circ.checkin_scan_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1490,6 +1499,7 @@ circ.util.columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.bre ? util.date.formatted_date( my.bre.create_date(), '%{localized}' ) : ''; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.bre.create_date() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1501,6 +1511,7 @@ circ.util.columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.bre ? util.date.formatted_date( my.bre.edit_date(), '%{localized}' ) : ''; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.bre.edit_date() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1690,6 +1701,7 @@ circ.util.transit_columns = function(modify,params) {
             'primary' : false,
             'hidden' : false,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.atc.source_send_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.atc.source_send_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1715,6 +1727,7 @@ circ.util.transit_columns = function(modify,params) {
             'primary' : false,
             'hidden' : false,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.atc.dest_recv_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.atc.dest_recv_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1779,6 +1792,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.ahr.cancel_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.cancel_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1837,6 +1851,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.ahr.request_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.request_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1847,6 +1862,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.ahr.shelf_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.shelf_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1857,6 +1873,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.ahr.shelf_expire_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.shelf_expire_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1875,6 +1892,16 @@ circ.util.hold_columns = function(modify,params) {
                 }
                 return "";
             }
+            ,'sort_value' : function(my) {
+                return util.date.db_date2Date( my.acp.create_date() ).getTime();
+                if (my.ahr.transit() && my.ahr.transit().dest_recv_time()) {
+                    return util.date.db_date2Date( my.ahr.transit().dest_recv_time() ).getTime();
+                }
+                if (!my.ahr.transit() && my.ahr.capture_time()) {
+                    return util.date.db_date2Date( my.ahr.capture_time() ).getTime();
+                }
+                return 0;
+            }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1885,6 +1912,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.ahr.capture_time() ? util.date.formatted_date( my.ahr.capture_time(), '%{localized}' ) : ""; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.capture_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -1973,6 +2001,7 @@ circ.util.hold_columns = function(modify,params) {
                     return util.date.formatted_date( my.ahr.thaw_date(), '%{localized}' );
                 }
             }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.thaw_date() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -2054,6 +2083,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.ahr.expire_time() ? util.date.formatted_date( my.ahr.expire_time(), '%{localized}' ) : ''; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.expire_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -2064,6 +2094,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.ahr.fulfillment_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.fulfillment_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -2119,6 +2150,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.ahr.prev_check_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.prev_check_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -2250,6 +2282,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.ahr.notify_time(), '%{localized}' ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.notify_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -2284,6 +2317,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.ahr.transit() ?  util.date.formatted_date( my.ahr.transit().source_send_time(), '%{localized}' ) : ""; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.transit().source_send_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -2303,6 +2337,7 @@ circ.util.hold_columns = function(modify,params) {
             'primary' : false,
             'hidden' : true,
             'editable' : false, 'render' : function(my) { return my.ahr.transit() ?  util.date.formatted_date( my.ahr.transit().dest_recv_time(), '%{localized}' ) : ""; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ahr.transit().dest_recv_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal',
@@ -2432,6 +2467,7 @@ circ.util.hold_columns = function(modify,params) {
                 {
             'persist' : 'hidden width ordinal',
             'id' : 'queue_position',
+            'sort_type' : 'number',
             'label' : document.getElementById('circStrings').getString('staff.circ.utils.queue_position'),
             'flex' : 1,
             'primary' : false,
@@ -2528,63 +2564,6 @@ circ.util.hold_columns = function(modify,params) {
     }
     return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
 };
-/*
-circ.util.std_map_row_to_column = function(error_value) {
-    return function(row,col) {
-        // row contains { 'my' : { 'acp' : {}, 'circ' : {}, 'mvr' : {} } }
-        // col contains one of the objects listed above in columns
-
-        // mimicking some of the obj in circ.checkin and circ.checkout where map_row_to_column is usually defined
-        var obj = {};
-        JSAN.use('util.error'); obj.error = new util.error();
-        JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
-        JSAN.use('util.network'); obj.network = new util.network();
-        JSAN.use('util.money');
-
-        var my = row.my;
-        var value;
-        try {
-            value = eval( col.render );
-        } catch(E) {
-            obj.error.sdump('D_WARN','map_row_to_column: ' + E);
-            if (error_value) value = error_value; else value = '   ';
-        }
-        return value;
-    }
-};
-*/
-circ.util.std_map_row_to_columns = function(error_value) {
-    return function(row,cols,scratch) {
-        // row contains { 'my' : { 'acp' : {}, 'circ' : {}, 'mvr' : {} } }
-        // cols contains all of the objects listed above in columns
-        // scratch is a temporary space shared by all cells/rows (or just per row if not explicitly passed in)
-        if (!scratch) { scratch = {}; }
-
-        var obj = {};
-        JSAN.use('util.error'); obj.error = new util.error();
-        JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
-        JSAN.use('util.network'); obj.network = new util.network();
-        JSAN.use('util.money');
-
-        var my = row.my;
-        var values = [];
-        var cmd = '';
-        try {
-            for (var i = 0; i < cols.length; i++) {
-                switch (typeof cols[i].render) {
-                    case 'function': try { values[i] = cols[i].render(my,scratch); } catch(E) { values[i] = error_value; obj.error.sdump('D_COLUMN_RENDER_ERROR',E); } break;
-                    case 'string' : cmd += 'try { ' + cols[i].render + '; values['+i+'] = v; } catch(E) { values['+i+'] = error_value; }'; break;
-                    default: cmd += 'values['+i+'] = "??? '+(typeof cols[i].render)+'"; ';
-                }
-            }
-            if (cmd) eval( cmd );
-        } catch(E) {
-            obj.error.sdump('D_WARN','map_row_to_column: ' + E);
-            if (error_value) { value = error_value; } else { value = '   ' };
-        }
-        return values;
-    }
-};
 
 circ.util.checkin_via_barcode = function(session,params,backdate,auto_print,async) {
     try {
@@ -2802,6 +2781,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
             if (check.ilsevent == 3 /* NO_CHANGE */) {
                 //msg = 'This item is already checked in.\n';
                 check.what_happened = 'no_change';
+                sound.special('checkin.no_change');
                 if (no_change_label) {
                     var m = no_change_label.getAttribute('value');
                     var text = document.getElementById('circStrings').getFormattedString('staff.circ.utils.item_checked_in', [params.barcode]);
@@ -2817,6 +2797,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
             }
             if (check.ilsevent == 1202 /* ITEM_NOT_CATALOGED */ && check.copy.status() != 11) {
                 check.what_happened = 'error';
+                sound.special('checkin.error');
                 var copy_status = (data.hash.ccs[ check.copy.status() ] ? data.hash.ccs[ check.copy.status() ].name() : check.copy.status().name() );
                 var err_msg = document.getElementById('commonStrings').getString('common.error');
                 err_msg += '\nFIXME --';
@@ -2829,6 +2810,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                 case 0: /* AVAILABLE */
                 case 7: /* RESHELVING */
                     check.what_happened = 'success';
+                    sound.special('checkin.success');
                     if (msg) {
                         print_data.route_to_msg = document.getElementById('circStrings').getFormattedString('staff.circ.utils.route_to.msg', [check.route_to]);
                         print_data.route_to = check.route_to;
@@ -2838,10 +2820,12 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                 break;
                 case 8: /* ON HOLDS SHELF */
                     check.what_happened = 'hold_shelf';
+                    sound.special('checkin.hold_shelf');
                     check.route_to = document.getElementById('circStrings').getString('staff.circ.route_to.hold_shelf');
                     if (check.payload.hold) {
                         if (check.payload.hold.pickup_lib() != data.list.au[0].ws_ou()) {
                             check.what_happened = 'error';
+                            sound.special('checkin.error');
                             var err_msg = document.getElementById('commonStrings').getString('common.error');
                             err_msg += '\nFIXME: ';
                             err_msg += document.getElementById('circStrings').getString('staff.circ.utils.route_item_error');
@@ -2878,6 +2862,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                         }
                     } else {
                         check.what_happened = 'error';
+                        sound.special('checkin.error');
                         var err_msg = document.getElementById('commonStrings').getString('common.error');
                         err_msg += '\nFIXME: ';
                         err_msg += document.getElementById('circStrings').getString('staff.circ.utils.route_item_status_error');
@@ -3062,6 +3047,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                 break;
                 case 6: /* IN TRANSIT */
                     check.what_happened = 'error';
+                    sound.special('checkin.error');
                     check.route_to = 'TRANSIT SHELF??';
                     print_data.route_to;
                     var err_msg = document.getElementById('commonStrings').getString('common.error');
@@ -3071,6 +3057,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                 break;
                 case 11: /* CATALOGING */
                     check.what_happened = 'cataloging';
+                    sound.special('checkin.cataloging');
                     check.route_to = 'CATALOGING';
                     print_data.route_to;
                     var suppress_popups = data.hash.aous['ui.circ.suppress_checkin_popups'];
@@ -3101,6 +3088,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                 case 15: // ON_RESERVATION_SHELF
                     check.route_to = 'RESERVATION SHELF';
                     check.what_happened = "reservation_shelf";
+                    sound.special('checkin.reservation_shelf');
                     if (check.payload.reservation) {
                         if (check.payload.reservation.pickup_lib() != data.list.au[0].ws_ou()) {
                             msg += document.getElementById('commonStrings').getString('common.error');
@@ -3188,6 +3176,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
                 break;
                 default:
                     check.what_happened = 'error';
+                    sound.special('checkin.error');
                     msg += document.getElementById('commonStrings').getString('common.error');
                     var copy_status = data.hash.ccs[check.copy.status()] ? data.hash.ccs[check.copy.status()].name() : check.copy.status().name();
                     msg += '\n';
@@ -3212,6 +3201,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
         } else /* ROUTE_ITEM */ if (check.ilsevent == 7000) {
 
             check.what_happened = 'transit';
+            sound.special('checkin.transit');
             var lib = data.hash.aou[ check.org ];
             check.route_to = lib.shortname();
             print_data.route_to = check.route_to;
@@ -3269,6 +3259,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
             JSAN.use('util.date');
             if (check.payload.hold) {
                 check.what_happened = 'transit_for_hold';
+                sound.special('checkin.transit_for_hold');
                 JSAN.use('patron.util');
                 var au_obj = patron.util.retrieve_fleshed_au_via_id( session, check.payload.hold.usr() );
                 print_data.user = au_obj;
@@ -3454,6 +3445,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
         } else /* ASSET_COPY_NOT_FOUND */ if (check.ilsevent == 1502) {
 
             check.what_happened = 'not_found';
+            sound.special('checkin.not_found');
             check.route_to = 'CATALOGING';
             var mis_scan_msg = document.getElementById('circStrings').getFormattedString('staff.circ.copy_status.status.copy_not_found', [params.barcode]);
             var suppress_popups = data.hash.aous['ui.circ.suppress_checkin_popups'];
@@ -3485,6 +3477,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
         } else /* HOLD_CAPTURE_DELAYED */ if (check.ilsevent == 7019) {
 
             check.what_happened = 'hold_capture_delayed';
+            sound.special('checkin.hold_capture_delayed');
             var rv = 0;
             msg += document.getElementById('circStrings').getString('staff.circ.utils.hold_capture_delayed.description');
             var suppress_popups = data.hash.aous['ui.circ.suppress_checkin_popupst'];
@@ -3508,6 +3501,7 @@ circ.util.checkin_via_barcode2 = function(session,params,backdate,auto_print,che
 
         } else /* NETWORK TIMEOUT */ if (check.ilsevent == -1) {
             check.what_happened = 'error';
+            sound.special('checkin.error');
             error.standard_network_error_alert(document.getElementById('circStrings').getString('staff.circ.checkin.suggest_offline'));
         } else {
 
index 44b6c81..cfb5439 100644 (file)
@@ -42,6 +42,9 @@
         
         if(textbox && textbox.value != "") {
                 var opac_url =  xulG.url_prefix(urls.opac_rresult) + "?rt=keyword&tp=keyword&l=" + home_ou_id + "&d=" + search_depth +"&f=&t=" + escape(textbox.value);
+                if (urls.opac_rresult.match(/\/eg\/opac\/results/)) {
+                    opac_url =  xulG.url_prefix(urls.opac_rresult) + "?query=" + escape(textbox.value);
+                }
                 var params = {'tab_name':'Catalog'};
                 var content_params = { 'session' : ses(), 'authtime' : ses('authtime'), 'opac_url' : opac_url };
                 xulG.set_tab(urls.XUL_OPAC_WRAPPER, params, content_params);
index 6c4eb06..7bf9f65 100644 (file)
@@ -4,13 +4,13 @@ cat.batch_operation_failed=The whole batch operation failed. %1$s
 cat.copy_buckets.tab=Copy Buckets
 cat.total_bucket_items_in_bucket=Contains %1$s bucket items
 cat.results_returned=Returning %1$s hits
-staff.cat.bib_brief.record_id=Record ID = %1$s
+staff.cat.bib_brief.record_id=Database ID = %1$s
 staff.cat.bib_brief.deleted=(Deleted)
 staff.cat.bib_brief.inactive=(Inactive)
 staff.cat.bib_brief.noncat=(Not Cataloged)
 staff.cat.bib_brief.noncat.alert=Item not cataloged.
-# %1$s = Bib Record ID
-staff.cat.manage_multi_bib_items.tab_name=Manage Conjoined Items for Bib %1$s
+# %1$s = Bib Record Database ID
+staff.cat.manage_multi_bib_items.tab_name=Manage Conjoined Items for Bib with DB ID %1$s
 staff.cat.manage_multi_bib_items.result.column.value.error=Error
 staff.cat.manage_multi_bib_items.result.column.value.success=Success
 staff.cat.manage_multi_bib_items.result.column.value.failed=Failed
@@ -18,10 +18,10 @@ staff.cat.manage_multi_bib_items.result.column.value.item_linked_to_bib=Item lin
 staff.cat.manage_multi_bib_items.result.column.value.item_native_to_bib=Item native to bib
 staff.cat.manage_multi_bib_items.result.column.value.peer_type_updated=Peer Type updated
 staff.cat.manage_multi_bib_items.prompt.title=Change Peer Type
-# %1$s = Bib Record ID
-staff.cat.manage_multi_bib_items.prompt.confirm.unlink_item_from_bib.singular=Unlink selected item from Bib %1$s
-# %1$s = Bib Record ID, %2$s = Number of selected items
-staff.cat.manage_multi_bib_items.prompt.confirm.unlink_item_from_bib.plural=Unlink %2$s selected items from Bib %1$s
+# %1$s = Bib Record Database ID
+staff.cat.manage_multi_bib_items.prompt.confirm.unlink_item_from_bib.singular=Unlink selected item from Bib with DB ID %1$s
+# %1$s = Bib Record Database ID, %2$s = Number of selected items
+staff.cat.manage_multi_bib_items.prompt.confirm.unlink_item_from_bib.plural=Unlink %2$s selected items from Bib with DB ID %1$s
 staff.cat.copy_browser.add_item.title=Add Item
 staff.cat.copy_browser.add_item.error=copy browser -> add copies
 staff.cat.copy_browser.add_items_bucket.error=copy browser -> add copies to bucket
@@ -277,7 +277,7 @@ staff.cat.marc_new.loading_template.error=Error loading MARC template: %1$s
 staff.cat.opac.set_marc_edit.alert=Record successfully saved.
 staff.cat.opac.set_marc_edit.std_unexpected_error=Record not likely updated.
 staff.cat.opac.refresh.function_not_implemented.alert=Not yet implemented.  Work around: Choose Duplicate in New Tab option
-staff.cat.opac.set_tab_name=Record: %1$s
+staff.cat.opac.set_tab_name=Record DB ID: %1$s
 staff.cat.opac.title_for_hold_transfer.destination_needed.label=Need to mark a record as a Title Hold Transfer Destination first.
 staff.cat.opac.title_for_hold_transfer.success.label=Holds transferred.
 staff.cat.opac.title_for_hold_transfer.failure.label=Holds not transferred.
@@ -530,7 +530,7 @@ staff.cat.bib_brief.call_number.label=Item Call #:
 staff.cat.bib_brief.ib_call_number.accesskey=
 staff.cat.bib_brief.tcn.label=TCN:
 staff.cat.bib_brief.tcn.accesskey=
-staff.cat.bib_brief.mvr_doc_id.label=Record ID:
+staff.cat.bib_brief.mvr_doc_id.label=Bib DB ID:
 staff.cat.bib_brief.mvr_doc_id.accesskey=
 staff.cat.bib_brief.owner.label=Record Owner:
 staff.cat.bib_brief.owner.accesskey=
@@ -542,3 +542,8 @@ staff.cat.bib_brief.editor.label=Last Edited By:
 staff.cat.bib_brief.editor.accesskey=
 staff.cat.bib_brief.edit_date.label=Last Edited On:
 staff.cat.bib_brief.edit_date.accesskey=
+staff.cat.bib_brief.holds.label=Holds:
+staff.cat.bib_brief.holds.accesskey=
+staff.cat.bib_brief.items.label=Items:
+staff.cat.bib_brief.items.accesskey=
+staff.cat.bib_brief.items.available.tooltip=%1$s available
index 9bbb2cc..c3f99be 100644 (file)
@@ -111,7 +111,7 @@ staff.patron.display.render_search_form.patron_search=Patron Search
 staff.patron.display.tab_name=Patron:
 staff.patron.display.no_alerts_or_messages=No Alerts, Blocks, or Messages
 # Field 1 = actor.usr.id, Field 2 = actor.usr.create_date
-staff.patron.display.db_data=Record ID: %1$s Create Date: %2$s 
+staff.patron.display.db_data=Database ID: %1$s Create Date: %2$s
 staff.patron.hold_notices.tooltiptext=ID: %1$s Hold ID: %2$s Notifying Staff ID: %3$s
 staff.patron.hold_notices.new_notification_record=New Notification Record
 staff.patron.hold_notices.method=Method
index 490a94a..76eb5af 100644 (file)
@@ -47,9 +47,21 @@ function my_init() {
             $('credit_forward').setAttribute('value',util.money.sanitize( g.patron.credit_forward_balance() ));
         }
 
-        default_focus();
-
-        tally_all();
+        if (g.data.hash.aous['ui.circ.billing.uncheck_bills_and_unfocus_payment_box']) {
+            g.funcs.push(
+                function() {
+                    $('uncheck_all').focus();
+                    tally_all();
+                }
+            );
+        } else {
+            g.funcs.push(
+                function() {
+                    default_focus();
+                    tally_all();
+                }
+            );
+        }
 
     } catch(E) {
         var err_msg = $("commonStrings").getFormattedString('common.exception', ['patron/bill2.xul', E]);
@@ -406,8 +418,31 @@ function check_all_refunds() {
 
 function gen_list_append_func(r) {
     return function() {
-        if (typeof r == 'object') { g.row_map[ r.id() ] = g.bill_list.append( { 'retrieve_id' : r.id(), 'flesh_immediately' : true, 'row' : { 'my' : { 'checked' : true, 'mbts' : r } } } );
-        } else { g.row_map[r] = g.bill_list.append( { 'retrieve_id' : r, 'flesh_immediately' : true, 'row' : { 'my' : { 'checked' : true } } } ); }
+        var default_check_state = g.data.hash.aous[
+            'ui.circ.billing.uncheck_bills_and_unfocus_payment_box'
+        ] ? false : true;
+        if (typeof r == 'object') {
+            g.row_map[ r.id() ] = g.bill_list.append( {
+                'retrieve_id' : r.id(),
+                'flesh_immediately' : true,
+                'row' : {
+                    'my' : {
+                        'checked' : default_check_state,
+                        'mbts' : r
+                    }
+                }
+            } );
+        } else {
+            g.row_map[r] = g.bill_list.append( {
+                'retrieve_id' : r,
+                'flesh_immediately' : true,
+                'row' : {
+                    'my' : {
+                        'checked' : default_check_state
+                    }
+                }
+            } );
+        }
     }
 }
 
index e2ba9ee..8dba84d 100644 (file)
                 <hbox>
                     <hbox id="bill_list_actions" />
                     <button label="&staff.patron.bills_overlay.check_all.label;" accesskey="&staff.patron.bills_overlay.check_all.accesskey;" oncommand="check_all();"/>
-                    <button label="&staff.patron.bills_overlay.uncheck_all.label;" accesskey="&staff.patron.bills_overlay.uncheck_all.accesskey;" oncommand="uncheck_all();"/>
+                    <button id="uncheck_all" label="&staff.patron.bills_overlay.uncheck_all.label;" accesskey="&staff.patron.bills_overlay.uncheck_all.accesskey;" oncommand="uncheck_all();"/>
                     <button label="&staff.patron.bills_overlay.check_all_refunds.label;" accesskey="&staff.patron.bills_overlay.check_all_refunds.accesskey;" oncommand="check_all_refunds();"/>
                     <button id="print" label="&staff.patron.bills_overlay.print_bills.label;" accesskey="&staff.patron.bills_overlay.print_bills.accesskey;" oncommand="print_bills();"/>
                     <spacer flex="1"/>
index 9e4ebfa..7aa8b96 100644 (file)
@@ -206,7 +206,7 @@ patron.display.prototype = {
                                         obj.summary_window.g.summary.controller.render('patron_bill');
                                         obj.bill_window.g.bills.refresh(true);
                                     },
-                                    'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                    'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                     'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                     'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                     'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); }
@@ -246,7 +246,7 @@ patron.display.prototype = {
                                             'passthru_content_params' : {
                                                 'spawn_search' : spawn_search,
                                                 'spawn_editor' : spawn_editor,
-                                                'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                                'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                                 'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                                 'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                                 'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); },
@@ -291,7 +291,7 @@ patron.display.prototype = {
                                         },
                                         'spawn_search' : spawn_search,
                                         'spawn_editor' : spawn_editor,
-                                        'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                        'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                         'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                         'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                         'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); }
@@ -318,7 +318,7 @@ patron.display.prototype = {
                                 {},
                                 {
                                     'patron_id' : obj.patron.id(),
-                                    'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                    'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                     'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                     'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                     'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); }
@@ -346,7 +346,7 @@ patron.display.prototype = {
                                 {},
                                 {
                                     'patron_id' : obj.patron.id(),
-                                    'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                    'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                     'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                     'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                     'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); }
@@ -362,7 +362,7 @@ patron.display.prototype = {
                                 {},
                                 {
                                     'patron_id' : obj.patron.id(),
-                                    'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                    'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                     'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                     'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                     'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); }
@@ -465,7 +465,7 @@ patron.display.prototype = {
                                                 alert(E);
                                             }
                                         },
-                                        'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                        'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                         'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                         'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                         'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); }
@@ -488,7 +488,7 @@ patron.display.prototype = {
                                 {
                                     'display_window' : window,
                                     'patron_id' : obj.patron.id(),
-                                    'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                                    'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                                     'get_new_session' : function(a) { return xulG.get_new_session(a); },
                                     'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                                     'on_money_change' : function(b) {
@@ -991,7 +991,7 @@ patron.display.prototype = {
                 {},
                 {
                     'patron_id' : obj.patron.id(),
-                    'url_prefix' : function(url) { return xulG.url_prefix(url); },
+                    'url_prefix' : function(url,secure) { return xulG.url_prefix(url,secure); },
                     'get_new_session' : function(a) { return xulG.get_new_session(a); },
                     'new_tab' : function(a,b,c) { return xulG.new_tab(a,b,c); },
                     'new_patron_tab' : function(a,b) { return xulG.new_patron_tab(a,b); }
index a4a4f1b..aa28075 100644 (file)
@@ -115,7 +115,6 @@ function init_list() {
     g.list.init(
         {
             'columns' : columns,
-            'map_row_to_columns' : circ.util.std_map_row_to_columns(),
             'retrieve_row' : function(params) {
                 var row = params.row;
                 if (typeof params.on_retrieve == 'function') {
index dc86318..c6c1bb6 100644 (file)
@@ -75,7 +75,6 @@ patron.holds.prototype = {
                         // 'acp_circ_modifier' : { 'hidden' : false }
                     })
                 ),
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : function(params) {
                     var row = params.row;
                     try {
@@ -1148,19 +1147,19 @@ patron.holds.prototype = {
                                     var opac_url;
                                     switch(htype) {
                                         case 'M' :
-                                            opac_url = xulG.url_prefix( urls.opac_rresult ) + '?m=' + htarget;
+                                            opac_url = xulG.url_prefix( urls.opac_rresult_metarecord ) + htarget;
                                         break;
                                         case 'T' :
                                         case 'P' :
-                                            opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + htarget;
+                                            opac_url = xulG.url_prefix( urls.opac_rdetail ) + htarget;
                                         break;
                                         case 'I' :
                                             opac_url = xulG.url_prefix( urls.opac_rdetail )
-                                            + '?r=' + obj.hold_subscription_map[ obj.retrieve_ids[i].id ].record_entry();
+                                            + obj.hold_subscription_map[ obj.retrieve_ids[i].id ].record_entry();
                                         break;
                                         case 'V' :
                                             var my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative', [ htarget ]);
-                                            opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
+                                            opac_url = xulG.url_prefix( urls.opac_rdetail) + my_acn.record();
                                         break;
                                         case 'C' :
                                         case 'R' :
@@ -1173,7 +1172,7 @@ patron.holds.prototype = {
                                                 my_acn = obj.network.simple_request( 'FM_ACN_RETRIEVE.authoritative',
                                                     [ my_acp.call_number() ]);
                                             }
-                                            opac_url = xulG.url_prefix( urls.opac_rdetail) + '?r=' + my_acn.record();
+                                            opac_url = xulG.url_prefix( urls.opac_rdetail) + my_acn.record();
                                         break;
                                         default:
                                             obj.error.standard_unexpected_error_alert($("patronStrings").getFormattedString('staff.patron.holds.show_catalog.unknown_htype', [htype]), obj.retrieve_ids[i]);
index b0ec8ec..379b35d 100644 (file)
@@ -589,7 +589,7 @@ patron.items.prototype = {
                     alert($("patronStrings").getFormattedString('staff.patron.items.show_catalog.barcode_not_cataloged', [retrieve_ids[i].barcode]));
                     continue;
                 }
-                var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + doc_id;
+                var opac_url = xulG.url_prefix( urls.opac_rdetail ) + doc_id;
                 var content_params = { 
                     'session' : ses(),
                     'authtime' : ses('authtime'),
@@ -730,7 +730,6 @@ patron.items.prototype = {
         obj.list.init(
             {
                 'columns' : columns,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : retrieve_row,
                 'on_select' : function(ev) {
                     JSAN.use('util.functional');
@@ -758,7 +757,6 @@ patron.items.prototype = {
         obj.list2.init(
             {
                 'columns' : columns2,
-                'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                 'retrieve_row' : retrieve_row,
                 'on_select' : function(ev) {
                     JSAN.use('util.functional');
index 1ddf2c4..79c628d 100644 (file)
@@ -188,7 +188,9 @@ function generate_request_handler_for_penalty_apply(penalty,id) {
                     'row' : {
                         'my' : {
                             'ausp' : penalty,
-                            'csp' : data.hash.csp[ penalty.standing_penalty() ],
+                            'csp' : typeof penalty.standing_penalty() == 'object'
+                                ? penalty.standing_penalty()
+                                : data.hash.csp[ penalty.standing_penalty() ],
                             'au' : xulG.patron,
                         }
                     }
index 742b6b4..8968e0a 100644 (file)
@@ -57,6 +57,7 @@ patron.util.mbts_columns = function(modify,params) {
             'persist' : 'hidden width ordinal', 'id' : 'last_billing_ts', 'label' : commonStrings.getString('staff.mbts_last_billing_timestamp_label'), 'flex' : 1,
             'sort_type' : 'date',
             'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_billing_ts(), "%{localized}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.mbts.last_billing_ts() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'last_payment_note', 'label' : commonStrings.getString('staff.mbts_last_payment_note_label'), 'flex' : 2,
@@ -70,16 +71,19 @@ patron.util.mbts_columns = function(modify,params) {
             'persist' : 'hidden width ordinal', 'id' : 'last_payment_ts', 'label' : commonStrings.getString('staff.mbts_last_payment_timestamp_label'), 'flex' : 1,
             'sort_type' : 'date',
             'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_payment_ts(), "%{localized}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.mbts.last_payment_ts() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'mbts_xact_start', 'label' : commonStrings.getString('staff.mbts_xact_start_label'), 'flex' : 1,
             'sort_type' : 'date',
             'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mbts.xact_start() ? util.date.formatted_date( my.mbts.xact_start(), "%{localized}" ) : ""; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.mbts.xact_start() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'mbts_xact_finish', 'label' : commonStrings.getString('staff.mbts_xact_finish_label'), 'flex' : 1,
             'sort_type' : 'date',
             'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return my.mbts.xact_finish() ? util.date.formatted_date( my.mbts.xact_finish(), "%{localized}" ) : ""; }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.mbts.xact_finish() ).getTime(); }
         },
     ];
     for (var i = 0; i < c.length; i++) {
@@ -136,6 +140,7 @@ patron.util.mb_columns = function(modify,params) {
             'persist' : 'hidden width ordinal', 'id' : 'void_time', 'label' : commonStrings.getString('staff.mb_void_time_label'), 'flex' : 1,
             'sort_type' : 'date',
             'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mb.void_time(), "%{localized}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.mb.void_time() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'amount', 'label' : commonStrings.getString('staff.mb_amount_label'), 'flex' : 1,
@@ -150,6 +155,7 @@ patron.util.mb_columns = function(modify,params) {
             'persist' : 'hidden width ordinal', 'id' : 'billing_ts', 'label' : commonStrings.getString('staff.mb_billing_ts_label'), 'flex' : 1,
             'sort_type' : 'date',
             'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mb.billing_ts(), "%{localized}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.mb.billing_ts() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'note', 'label' : commonStrings.getString('staff.mb_note_label'), 'flex' : 2,
@@ -216,6 +222,7 @@ patron.util.mp_columns = function(modify,params) {
             'persist' : 'hidden width ordinal', 'id' : 'mp_payment_ts', 'label' : commonStrings.getString('staff.mp_payment_timestamp_label'), 'flex' : 1,
             'sort_type' : 'date',
             'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.mp.payment_ts(), "%{localized}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.mp.payment_ts() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'mp_note', 'label' : commonStrings.getString('staff.mp_note_label'), 'flex' : 2,
@@ -327,6 +334,7 @@ patron.util.ausp_columns = function(modify,params) {
             'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { 
                 return my.ausp ? util.date.formatted_date( my.ausp.set_date(), "%{localized}" ) : '';
             }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.ausp.set_date() ).getTime(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'ausp_note', 'label' : commonStrings.getString('staff.ausp_note_label'), 'flex' : 1,
@@ -435,11 +443,13 @@ patron.util.columns = function(modify,params) {
             'persist' : 'hidden width ordinal', 'id' : 'au_create_date', 'label' : commonStrings.getString('staff.au_create_date_label'), 'flex' : 1, 
             'sort_type' : 'date',
             'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.au.create_date(), "%{localized}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.au.create_date() ).getTime(); }
         },
         { 
             'persist' : 'hidden width ordinal', 'id' : 'expire_date', 'label' : commonStrings.getString('staff.au_expire_date_label'), 'flex' : 1, 
             'sort_type' : 'date',
             'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.au.expire_date(), "%{localized_date}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.au.expire_date() ).getTime(); }
         },
         { 
             'persist' : 'hidden width ordinal', 'id' : 'home_ou', 'label' : commonStrings.getString('staff.au_home_library_label'), 'flex' : 1, 
@@ -478,6 +488,7 @@ patron.util.columns = function(modify,params) {
             'persist' : 'hidden width ordinal', 'id' : 'dob', 'label' : commonStrings.getString('staff.au_birth_date_label'), 'flex' : 1, 
             'sort_type' : 'date',
             'primary' : false, 'hidden' : true, 'editable' : false, 'render' : function(my) { return util.date.formatted_date( my.au.dob(), "%{localized_date}" ); }
+            ,'sort_value' : function(my) { return util.date.db_date2Date( my.au.dob() ).getTime(); }
         },
         { 
             'persist' : 'hidden width ordinal', 'id' : 'ident_type', 'label' : commonStrings.getString('staff.au_ident_type_label'), 'flex' : 1, 
index 1a5cace..8d56f60 100644 (file)
@@ -1110,7 +1110,6 @@ serial.manage_dists.prototype = {
                 {
                     'no_auto_select' : true,
                     'columns' : columns,
-                    'map_row_to_columns' : circ.util.std_map_row_to_columns(' '),
                     'retrieve_row' : function(params) {
 
                         var row = params.row;
index c510848..5e734ff 100644 (file)
@@ -762,7 +762,6 @@ serial.manage_items.prototype = {
                obj.lists.main.init(
                        {
                                'columns' : columns,
-                               'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                                'retrieve_row' : retrieve_row,
                                'on_select' : function(ev) {
                     obj.selected_list = 'main';
@@ -788,7 +787,6 @@ serial.manage_items.prototype = {
                obj.lists.workarea.init(
                        {
                                'columns' : columns,
-                               'map_row_to_columns' : circ.util.std_map_row_to_columns(),
                                'retrieve_row' : retrieve_row,
                                'on_select' : function(ev) {
                     obj.selected_list = 'workarea';
index 93fd587..fa5c4c6 100644 (file)
@@ -1566,7 +1566,6 @@ serial.manage_subs.prototype = {
                 {
                     'no_auto_select' : true,
                     'columns' : columns,
-                    'map_row_to_columns' : circ.util.std_map_row_to_columns(' '),
                     'retrieve_row' : function(params) {
 
                         var row = params.row;
index 7369275..3472515 100644 (file)
@@ -45,12 +45,20 @@ treechildren::-moz-tree-row(backdate_failed,selected) {
 .checkin_screen_suppress_holds_and_transits { }
 .checkin_screen_amnesty_mode { }
 .checkin_screen_checkin_auto_print_slips { }
+.checkin_screen_checkin_clear_shelf_expired { }
+.checkin_screen_checkin_auto_retarget { }
+.checkin_screen_checkin_auto_retarget_all { }
+.checkin_screen_checkin_local_hold_as_transit { }
 
 #background-text { font-size: x-large; font-weight: bold; }
 #do_not_alert_on_precat_indicator { background-color: -moz-dialog; color: -moz-dialog-text; font-size: large; font-weight: bold; }
 #suppress_holds_and_transits_indicator { background-color: -moz-dialog; color: -moz-dialog-text; font-size: large; font-weight: bold; }
 #amnesty_mode_indicator { border: thick solid white; background-color: red; color: white; font-size: large; font-weight: bold; padding: 10px; padding-bottom: 25px; margin: 10px; }
 #checkin_auto_print_slips_indicator { background-color: -moz-dialog; color: -moz-dialog-text; font-size: large; font-weight: bold; }
+#checkin_clear_shelf_expired_indicator { background-color: -moz-dialog; color: -moz-dialog-text; font-size: large; font-weight: bold; }
+#checkin_auto_retarget_indicator { background-color: -moz-dialog; color: -moz-dialog-text; font-size: large; font-weight: bold; }
+#checkin_auto_retarget_all_indicator { background-color: -moz-dialog; color: -moz-dialog-text; font-size: large; font-weight: bold; }
+#checkin_local_hold_as_transit_indicator { background-color: -moz-dialog; color: -moz-dialog-text; font-size: large; font-weight: bold; }
 
 .big_emphasis1 { font-weight: bold; font-size: x-large; }
 .big_emphasis2 { font-weight: bold; font-size: large; }
index d7b36b6..5325fd7 100644 (file)
@@ -1,6 +1,18 @@
 /* Settings here override default values from constants.js;for example:
  
     urls['AUDIO_good'] = '/xul/server/skin/media/custom/good.wav';
+
+    urls['AUDIO_special_checkin.cataloging'] = '/xul/server/skin/media/custom/cataloging.wav';
+    urls['AUDIO_special_checkin.error'] = '/xul/server/skin/media/custom/error.wav';
+    urls['AUDIO_special_checkin.hold_capture_delayed'] = '/xul/server/skin/media/custom/hold_capture_delayed.wav';
+    urls['AUDIO_special_checkin.hold_shelf'] = '/xul/server/skin/media/custom/hold_shelf.wav';
+    urls['AUDIO_special_checkin.no_change'] = '/xul/server/skin/media/custom/no_change.wav';
+    urls['AUDIO_special_checkin.not_found'] = '/xul/server/skin/media/custom/not_found.wav';
+    urls['AUDIO_special_checkin.reservation_shelf'] = '/xul/server/skin/media/custom/reservation_shelf.wav';
+    urls['AUDIO_special_checkin.success'] = '/xul/server/skin/media/custom/success.wav';
+    urls['AUDIO_special_checkin.transit'] = '/xul/server/skin/media/custom/transit.wav';
+    urls['AUDIO_special_checkin.transit_for_hold'] = '/xul/server/skin/media/custom/transit_for_hold.wav';
+
     urls['opac'] = '/opac/' + LOCALE + '/skin/mylib/xml/advanced.xml?nps=1';
     urls['opac_rdetail'] = '/opac/' + LOCALE + '/skin/mylib/xml/rdetail.xml';
     urls['opac_rresult'] = '/opac/' + LOCALE + '/skin/mylib/xml/rresult.xml';
diff --git a/README b/README
index c09628d..fe105db 100644 (file)
--- a/README
+++ b/README
@@ -9,7 +9,7 @@ before you can successfully configure, compile, and install Evergreen.
 
 1. Begin by installing the most recent version of OpenSRF (2.0 or later).
    You can download OpenSRF releases from http://evergreen-ils.org/downloads
-2. On many distributions, it is necessary to install Postgres 9 from external
+2. On many distributions, it is necessary to install PostgreSQL 9 from external
    repositories.
 +
   * On Debian Squeeze, add the following line to `/etc/apt/sources.list`:
@@ -45,10 +45,27 @@ deb http://archive.ubuntu.com/ubuntu lucid-backports main universe multiverse re
 ------------------------------------------------------------------------------
 make -f Open-ILS/src/extras/Makefile.install <osname>
 ------------------------------------------------------------------------------
-
++
 Note: `centos` and `rhel` are less tested than the `debian`, `fedora`,
 and `ubuntu` options.  Your patches and suggestions for improvement are
 welcome!
++
+6. Add the libdbi-libdbd libraries to the system dynamic library path by
+   issuing the following commands as the root user:
++
+.Debian / Ubuntu
+[source, bash]
+------------------------------------------------------------------------------
+echo "/usr/local/lib/dbd" > /etc/ld.so.conf.d/eg.conf
+ldconfig
+------------------------------------------------------------------------------
++
+.Fedora
+[source, bash]
+------------------------------------------------------------------------------
+echo "/usr/lib64/dbd" > /etc/ld.so.conf.d/eg.conf
+ldconfig
+------------------------------------------------------------------------------
 
 Configuration and compilation instructions:
 -------------------------------------------
@@ -69,18 +86,27 @@ make
 Installation instructions:
 --------------------------
 
-Once you have configured and compiled Evergreen, issue the following
-command as the root user to install Evergreen:
-
+1. Once you have configured and compiled Evergreen, issue the following
+   command as the root user to install Evergreen, build the server portion of
+   the staff client, and copy example configuration files to `/openils/conf`.
+   Change the value of the `STAFF_CLIENT_STAMP_ID` variable to match the version
+   of the staff client that you will use to connect to the Evergreen server.
++
 [source, bash]
 ------------------------------------------------------------------------------
-make STAFF_CLIENT_STAMP_ID=rel_trunk install
+make STAFF_CLIENT_STAMP_ID=rel_name install
+------------------------------------------------------------------------------
++
+2. The server portion of the staff client expects `http://hostname/xul/server`
+   to resolve. The following command creates a symbolic link pointing to the
+   `server` subdirectory of the server portion of the staff client that we just
+   built using the staff client ID 'rel_name':
++
+[source, bash]
+------------------------------------------------------------------------------
+cd /openils/var/web/xul
+ln -sf rel_name/server server
 ------------------------------------------------------------------------------
-
-This will install Evergreen, including example configuration files in
-`/openils/conf/` that you can use as templates for your own configuration files.
-The `STAFF_CLIENT_STAMP_ID` variable stamps the server-side and client-side files
-for the staff client to ensure that they match.
 
 Create the oils_web.xml configuration file:
 -------------------------------------------
@@ -198,24 +224,63 @@ cp /openils/conf/opensrf_core.xml.example /openils/conf/opensrf_core.xml
 cp /openils/conf/opensrf.xml.example /openils/conf/opensrf.xml
 ------------------------------------------------------------------------------
 
-When you installed OpenSRF, you will have created four Jabber users on two
+When you installed OpenSRF, you created four Jabber users on two
 separate domains and edited the `opensrf_core.xml` file accordingly. Please
 refer back to the OpenSRF README and edit the Evergreen version of the
 `opensrf_core.xml` file using the same Jabber users and domains as you used
 while installing and testing OpenSRF.
 
-`eg_db_config.pl`, described in the following section, will set the database
+`eg_db_config.pl`, described in the following section, sets the database
 connection information in `opensrf.xml` for you.
 
 Creating the Evergreen database:
 --------------------------------
 
-PostgreSQL 9.0 will be installed on your system by the `Makefile.install`
-prerequisite installer if packages are available for your distribution, or
-you will have to compile PostgreSQL 9.0 from source and install it (which
-is beyond the scope of this document).
+By default, the `Makefile.install` prerequisite installer does not install
+the PostgreSQL 9.0 database server required by every Evergreen system;
+for production use, most libraries install the PostgreSQL database server on a
+dedicated machine. You can install the packages required by Debian, Ubuntu, or
+Fedora on the machine of your choice using the following commands:
+
+.(Debian / Ubuntu) Installing PostgreSQL 9.0 server packages
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install install_pgsql_server_debs_90
+------------------------------------------------------------------------------
+
+.(Fedora 15) Installing PostgreSQL 9.0 server packages
+[source, bash]
+------------------------------------------------------------------------------
+make -f Open-ILS/src/extras/Makefile.install install_fedora_pgsql_server
+------------------------------------------------------------------------------
+
+For a standalone PostgreSQL server, install the following Perl modules as the
+root user:
+
+.(Debian / Ubuntu) Installing additional Perl modules on a standalone PostgreSQL 9.0 server
+[source, bash]
+------------------------------------------------------------------------------
+aptitude install gcc libxml-libxml-perl libxml-libxslt-perl
+cpan Business::ISBN
+cpan JSON::XS
+cpan Library::CallNumber::LC
+cpan MARC::Record
+cpan MARC::File::XML
+cpan UUID::Tiny
+------------------------------------------------------------------------------
+
+.(Fedora 15) Installing additional Perl modules on a standalone PostgreSQL 9.0 server
+[source, bash]
+------------------------------------------------------------------------------
+yum install gcc perl-XML-LibXML perl-XML-LibXSLT perl-Business-ISBN
+cpan JSON::XS
+cpan Library::CallNumber::LC
+cpan MARC::Record
+cpan MARC::File::XML
+cpan UUID::Tiny
+------------------------------------------------------------------------------
 
-Once the PostgreSQL database server has been installed, you will need to
+Once the PostgreSQL database server has been installed, you must
 create the database and add the appropriate languages and extensions to
 support Evergreen. Issue the following commands as the `postgres` user to set
 up a database called `evergreen`. Note that the location of the PostgreSQL
@@ -236,12 +301,12 @@ psql -f /usr/share/postgresql/9.0/contrib/hstore.sql -d evergreen
 
 Once you have created the Evergreen database, you need to create a PostgreSQL
 user to access the database. Issue the following command as the `postgres`
-user to create a new PostgreSQL user named `evergreen`. When prompted, enter
-the new user's password and answer `yes` to make the new role a superuser:
+user to create a new PostgreSQL superuser named `evergreen`. When prompted,
+enter the new user's password:
 
 [source, bash]
 ------------------------------------------------------------------------------
-createuser -P evergreen
+createuser -s -P evergreen
 ------------------------------------------------------------------------------
 
 Once you have created the Evergreen database, you also need to create the
@@ -260,7 +325,7 @@ perl Open-ILS/src/support-scripts/eg_db_config.pl --update-config \
        --database <dbname> --admin-user <admin-user> --admin-pass <admin-pass>
 ------------------------------------------------------------------------------
 
-This will create the database schema and configure all of the services in
+This creates the database schema and configures all of the services in
 your `/openils/conf/opensrf.xml` configuration file to point to that database.
 It also creates the configuration files required by the Evergreen cgi-bin
 administration scripts, and set the user name and password for the default
@@ -270,10 +335,11 @@ Developer instructions:
 -----------------------
 
 Developers working directly with the source code from the Git
-repository will also need to install some extra packages and perform
+repository must also install some extra packages and perform
 one more step before they can proceed with the `./configure` step.
 
 Install the following packages:
+
   * autoconf
   * automake
   * libtool
@@ -298,6 +364,114 @@ tar -C /openils/var/web/js -xzf dojo-release-1.3.3.tar.gz
 cp -r /openils/var/web/js/dojo-release-1.3.3/* /openils/var/web/js/dojo/.
 ------------------------------------------------------------------------------
 
+Starting Evergreen
+------------------
+1. As the root user, start the `memcached` and `ejabberd` services (if they aren't already running):
++
+[source, bash]
+------------------------------------------------------------------------------
+/etc/init.d/ejabberd start
+/etc/init.d/memcached start
+------------------------------------------------------------------------------
++
+2. As the opensrf user, start Evergreen. The `-l` flag in the following command
+is only necessary if you want to force Evergreen to treat the hostname as
+`localhost`; if you configured `opensrf.xml` using the real hostname
+of your machine as returned by `perl -ENet::Domain 'print
+Net::Domain::hostfqdn() . "\n";'`, you should not use the `-l` flag.
++
+[source, bash]
+------------------------------------------------------------------------------
+osrf_ctl.sh -l -a start_all</code>
+------------------------------------------------------------------------------
++
+  ** If you receive the error message `bash: osrf_ctl.sh: command not found`,
+     then your environment variable `PATH` does not include the `/openils/bin`
+     directory; this should have been set in the opensrf user's `.bashrc`
+     configuration file. To manually set the `PATH` variable, edit the
+     configuration file `~/.bashrc` as the opensrf user and add the following
+     line:
++
+[source, bash]
+------------------------------------------------------------------------------
+export PATH=$PATH:/openils/bin
+------------------------------------------------------------------------------
++
+3. As the `opensrf` user, generate the Web files needed by the staff client
+   and catalogue and update the organization unit proximity (you need to do
+   this the first time you start Evergreen, and after that each time you
+   change the library hierarchy in `config.cgi`):
++
+[source, bash]
+------------------------------------------------------------------------------
+autogen.sh -u
+------------------------------------------------------------------------------
++
+4. As the `root` user, restart the Apache Web server:
++
+[source, bash]
+------------------------------------------------------------------------------
+/etc/init.d/apache2 restart
+------------------------------------------------------------------------------
++
+If the Apache Web server was running when you started the OpenSRF services, you
+might not be able to successfully log in to the OPAC or staff client until the
+Apache Web server is restarted.
+
+Testing connections to Evergreen
+--------------------------------
+
+Once you have installed and started Evergreen, test your connection to
+Evergreen via `srfsh`. Start `srfsh` and try to log onto the Evergreen server
+using the administrator user name and password that you set using the
+`eg_db_config.pl` command:
+
+[source, bash]
+------------------------------------------------------------------------------
+/openils/bin/srfsh
+srfsh% login <admin-user> <admin-pass>
+------------------------------------------------------------------------------
+
+You should see a result like:
+
+    Received Data: "250bf1518c7527a03249858687714376"
+    ------------------------------------
+    Request Completed Successfully
+    Request Time in seconds: 0.045286
+    ------------------------------------
+
+    Received Data: {
+       "ilsevent":0,
+       "textcode":"SUCCESS",
+       "desc":" ",
+       "pid":21616,
+       "stacktrace":"oils_auth.c:304",
+       "payload":{
+          "authtoken":"e5f9827cc0f93b503a1cc66bee6bdd1a",
+          "authtime":420
+       }
+
+    }
+
+    ------------------------------------
+    Request Completed Successfully
+    Request Time in seconds: 1.336568
+    ------------------------------------
+
+If this does not work, it's time to do some troubleshooting.
+
+  * As the opensrf user, run the `settings-tester.pl` script to see if it
+    finds any system configuration problems. The script is found at
+    `Open-ILS/src/support-scripts/settings-tester.pl` in the Evergreen source
+    tree.
+  * Follow the steps in the http://evergreen-ils.org/dokuwiki/doku.php?id=troubleshooting:checking_for_errors[troubleshooting guide].
+  * If you have faithfully followed the entire set of installation steps
+    listed here, you are probably extremely close to a working system.
+    Gather your configuration files and log files and contact the
+    http://open-ils.org/listserv.php[Evergreen development mailing list]
+    for assistance before making any drastic changes to your system
+    configuration.
+
 Getting help:
 -------------