[open-ils-commits] r16827 - in trunk/Open-ILS: examples src/extras src/perlmods/OpenILS/Application web/js/dojo/openils/booking/nls web/js/ui/default/booking web/templates/default/booking web/templates/default/conify/global/booking (senator)

svn at svn.open-ils.org svn at svn.open-ils.org
Tue Jun 29 13:53:43 EDT 2010


Author: senator
Date: 2010-06-29 13:53:39 -0400 (Tue, 29 Jun 2010)
New Revision: 16827

Modified:
   trunk/Open-ILS/examples/fm_IDL.xml
   trunk/Open-ILS/src/extras/ils_events.xml
   trunk/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm
   trunk/Open-ILS/web/js/dojo/openils/booking/nls/capture.js
   trunk/Open-ILS/web/js/dojo/openils/booking/nls/pickup_and_return.js
   trunk/Open-ILS/web/js/dojo/openils/booking/nls/pull_list.js
   trunk/Open-ILS/web/js/dojo/openils/booking/nls/reservation.js
   trunk/Open-ILS/web/js/ui/default/booking/capture.js
   trunk/Open-ILS/web/js/ui/default/booking/common.js
   trunk/Open-ILS/web/js/ui/default/booking/populator.js
   trunk/Open-ILS/web/js/ui/default/booking/pull_list.js
   trunk/Open-ILS/web/js/ui/default/booking/reservation.js
   trunk/Open-ILS/web/templates/default/booking/capture.tt2
   trunk/Open-ILS/web/templates/default/booking/pull_list.tt2
   trunk/Open-ILS/web/templates/default/conify/global/booking/resource.tt2
   trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr.tt2
   trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_map.tt2
   trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_value.tt2
   trunk/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2
Log:
Booking: begin forward-porting code from rel_1_6.

Booking (regrettably) was largely written directly against a 1.6 environment
instead of written for trunk and backported.  So now we have booking code in
rel_1_6 and rel_1_6_1 that works, but that needs to be cleanly merged with
trunk.  There has been a lot of drift, and this won't be easy.

Here is the first step (some of the easy stuff).  These files have been updated
wholesale with their contents from rel_1_6, since they don't affect anything
other than booking itself.

Just to be clear: this commit does not complete the booking foward-port.  The
booking module did not work in trunk before this commit, and it does not work
after this commit.  For the moment, booking only works in the rel_1_6 branch,
in the rel_1_6_1 branch, and in 1.6.1.* releases.  It still does not work in
trunk, and it will take a few more hairy commits to get things in sync.

Once that's finally done, any future Booking code can be written the Right Way
(in trunk) and *back*ported thence to whatever other branches as needed.



Modified: trunk/Open-ILS/examples/fm_IDL.xml
===================================================================
--- trunk/Open-ILS/examples/fm_IDL.xml	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/examples/fm_IDL.xml	2010-06-29 17:53:39 UTC (rev 16827)
@@ -2645,7 +2645,7 @@
 
 	<class id="brt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="booking::resource_type" oils_persist:tablename="booking.resource_type" reporter:label="Resource Type">
 		<fields oils_persist:primary="id" oils_persist:sequence="booking.resource_type_id_seq">
-			<field reporter:label="Resource Type ID" name="id" reporter:datatype="id"/>
+			<field reporter:label="Resource Type ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Resource Type Name" name="name" reporter:datatype="text"/>
 			<field reporter:label="Fine Interval" name="fine_interval" reporter:datatype="interval"/>
 			<field reporter:label="Fine Amount" name="fine_amount" reporter:datatype="money"/>
@@ -2678,7 +2678,7 @@
 
 	<class id="brsrc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="booking::resource" oils_persist:tablename="booking.resource" reporter:label="Resource">
 		<fields oils_persist:primary="id" oils_persist:sequence="booking.resource_id_seq">
-			<field reporter:label="Resource ID" name="id" reporter:datatype="id"/>
+			<field reporter:label="Resource ID" name="id" reporter:datatype="id" reporter:selector="barcode" />
 			<field reporter:label="Owning Library" name="owner" reporter:datatype="org_unit"/>
 			<field reporter:label="Resource Type" name="type" reporter:datatype="link"/>
 			<field reporter:label="Overbook" name="overbook" reporter:datatype="bool"/>
@@ -2710,7 +2710,7 @@
 	
 	<class id="bra" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="booking::resource_attr" oils_persist:tablename="booking.resource_attr" reporter:label="Resource Attribute">
 		<fields oils_persist:primary="id" oils_persist:sequence="booking.resource_attr_id_seq">
-			<field reporter:label="Resource Attribute ID" name="id" reporter:datatype="id"/>
+			<field reporter:label="Resource Attribute ID" name="id" reporter:datatype="id" reporter:selector="name" />
 			<field reporter:label="Owning Library" name="owner" reporter:datatype="org_unit"/>
 			<field reporter:label="Resource Attribute Name" name="name" reporter:datatype="text"/>
 			<field reporter:label="Resource Type" name="resource_type" reporter:datatype="link"/>
@@ -2736,7 +2736,7 @@
 	
 	<class id="brav" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="booking::resource_attr_value" oils_persist:tablename="booking.resource_attr_value" reporter:label="Resource Attribute Value">
 		<fields oils_persist:primary="id" oils_persist:sequence="booking.resource_attr_value_id_seq">
-			<field reporter:label="Resource Attribute Value ID" name="id" reporter:datatype="id"/>
+			<field reporter:label="Resource Attribute Value ID" name="id" reporter:datatype="id" reporter:selector="valid_value" />
 			<field reporter:label="Owning Library" name="owner" reporter:datatype="org_unit"/>
 			<field reporter:label="Resource Attribute" name="attr" reporter:datatype="link"/>
 			<field reporter:label="Valid Value" name="valid_value" reporter:datatype="text"/>

Modified: trunk/Open-ILS/src/extras/ils_events.xml
===================================================================
--- trunk/Open-ILS/src/extras/ils_events.xml	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/src/extras/ils_events.xml	2010-06-29 17:53:39 UTC (rev 16827)
@@ -882,6 +882,9 @@
 	<event code='7023' textcode='RESERVATION_BAD_PARAMS'>
 		<desc xml:lang="en-US">Provided parameters describe unacceptable reservation.</desc>
 	</event>
+	<event code="7024" textcode="HOLD_RESERVATION_CONFLICT">
+		<desc xml:lang="en-US">Both a hold and a reservation exist for t
+	</event>
 
 
 

Modified: trunk/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm
===================================================================
--- trunk/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm	2010-06-29 17:53:39 UTC (rev 16827)
@@ -7,6 +7,7 @@
 use OpenILS::Application;
 use base qw/OpenILS::Application/;
 
+use OpenSRF::Utils qw/:datetime/;
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
 use OpenILS::Utils::Fieldmapper;
 use OpenILS::Application::AppUtils;
@@ -319,7 +320,7 @@
     return undef unless ($filters->{type} || $filters->{attribute_values});
 
     my $query = {
-        "select"   => {brsrc => ["id"]},
+        "select"   => {brsrc => [qw/id owner/], brt => ["elbow_room"]},
         "from"     => {brsrc => {"brt" => {}}},
         "where"    => {},
         "distinct" => 1
@@ -373,6 +374,7 @@
                             "end_time"
                         ),
                         {"cancel_time" => undef},
+                        {"return_time" => undef},
                         {"current_resource" => {"=" => {"+brsrc" => "id"}}}
                     ]},
                 }}
@@ -408,21 +410,58 @@
     }
 
     my $cstore = OpenSRF::AppSession->connect('open-ils.cstore');
-    my $rows = $cstore->request( 'open-ils.cstore.json_query.atomic', $query )->gather(1);
+    my $rows = $cstore->request(
+        "open-ils.cstore.json_query.atomic", $query
+    )->gather(1);
     $cstore->disconnect;
 
-    return @$rows ? [map { $_->{id} } @$rows] : [];
+    return [] if not @$rows;
+
+    if ($filters->{"pickup_lib"} && $filters->{"available"}) {
+        my @new_rows = ();
+        my $general_elbow_room = $U->ou_ancestor_setting_value(
+            $filters->{"pickup_lib"},
+            "circ.booking_reservation.default_elbow_room"
+        ) || '0 seconds';
+        my $would_start = $filters->{"available"}->[0];
+        my $dt_parser = new DateTime::Format::ISO8601;
+
+        $logger->info(
+            "general_elbow_room: '$general_elbow_room', " .
+            "would_start: '$would_start'"
+        );
+
+        # Here, elbow_room will double as required transit time padding.
+        foreach (@$rows) {
+            my $elbow_room = $_->{"elbow_room"} || $general_elbow_room;
+            if ($_->{"owner"} != $filters->{"pickup_lib"}) {
+                (my $ws = $would_start) =~ s/ /T/;
+                push @new_rows, $_ if DateTime->compare(
+                    $dt_parser->parse_datetime($ws),
+                    DateTime->now(
+                        "time_zone" => DateTime::TimeZone->new(
+                            "name" => "local"
+                        )
+                    )->add(seconds => interval_to_seconds($elbow_room))
+                ) >= 0;
+            } else {
+                push @new_rows, $_;
+            }
+        }
+        return [map { $_->{id} } @new_rows];
+    } else {
+        return [map { $_->{id} } @$rows];
+    }
 }
 __PACKAGE__->register_method(
     method   => "resource_list_by_attrs",
     api_name => "open-ils.booking.resources.filtered_id_list",
-    argc     => 3,
+    argc     => 2,
     signature=> {
         params => [
             {type => 'string', desc => 'Authentication token (unused for now,' .
                ' but at least pass undef here)'},
             {type => 'object', desc => 'Filter object: see notes for details'},
-            {type => 'bool', desc => 'Return whole objects instead of IDs?'}
         ],
         return => { desc => "An array of brsrc ids matching the requested filters." },
     },
@@ -484,8 +523,15 @@
         $query->{where}->{target_resource_type} = $filters->{type};
     }
 
+    $query->{where}->{"-and"} = [];
     if ($filters->{resource}) {
-        $query->{where}->{target_resource} = $filters->{resource};
+#       $query->{where}->{target_resource} = $filters->{resource};
+        push @{$query->{where}->{"-and"}}, {
+            "-or" => {
+                "target_resource" => $filters->{resource},
+                "current_resource" => $filters->{resource}
+            }
+        };
     }
 
     if ($filters->{attribute_values}) {
@@ -504,15 +550,23 @@
     }
 
     if ($filters->{search_start} || $filters->{search_end}) {
-        $query->{where}->{'-or'} = {};
+        my $or = {};
 
-        $query->{where}->{'-or'}->{start_time} = { 'between' => [ $filters->{search_start}, $filters->{search_end} ] }
-                if ($filters->{search_start});
+        $or->{start_time} =
+            {'between' => [ $filters->{search_start}, $filters->{search_end}]}
+                if $filters->{search_start};
 
-        $query->{where}->{'-or'}->{end_time} = { 'between' => [ $filters->{search_start}, $filters->{search_end} ] }
-                if ($filters->{search_end});
+        $or->{end_time} =
+            {'between' =>[$filters->{search_start}, $filters->{search_end}]}
+                if $filters->{search_end};
+
+        push @{$query->{where}->{"-and"}}, {"-or" => $or};
     }
 
+    if (not scalar @{$query->{"where"}->{"-and"}}) {
+        delete $query->{"where"}->{"-and"};
+    }
+
     my $cstore = OpenSRF::AppSession->connect('open-ils.cstore');
     my $ids = [ map { $_->{id} } @{
         $cstore->request(
@@ -541,11 +595,12 @@
 __PACKAGE__->register_method(
     method   => "reservation_list_by_filters",
     api_name => "open-ils.booking.reservations.filtered_id_list",
-    argc     => 2,
+    argc     => 3,
     signature=> {
         params => [
             {type => 'string', desc => 'Authentication token'},
-            {type => 'object', desc => 'Filter object -- see notes for details'}
+            {type => "object", desc => "Filter object: see notes for details"},
+            {type => "bool", desc => "Return whole object instead of ID? (default false)"}
         ],
         return => { desc => "An array of bresv ids matching the requested filters." },
     },
@@ -572,7 +627,7 @@
 sub naive_ts_string {strftime("%F %T", localtime($_[0] || time));}
 sub naive_start_of_day {strftime("%F", localtime($_[0] || time))." 00:00:00";}
 
-# Return a list of bresv or an ilsevent on failure.
+# Return a map of bresv or an ilsevent on failure.
 sub get_uncaptured_bresv_for_brsrc {
     my ($e, $o) = @_; # o's keys (all optional): owning_lib, barcode, range
 
@@ -630,6 +685,10 @@
                 "-and" => [
                     {"current_resource" => "PLACEHOLDER"},
                     {"start_time" => "PLACEHOLDER"},
+                    {"capture_time" => undef},
+                    {"cancel_time" => undef},
+                    {"return_time" => undef},
+                    {"pickup_time" => undef}
                 ]
             }
         };
@@ -727,6 +786,75 @@
 );
 
 
+sub could_capture {
+    my ($self, $client, $auth, $barcode) = @_;
+
+    my $e = new_editor("authtoken" => $auth);
+    return $e->die_event unless $e->checkauth;
+    return $e->die_event unless $e->allowed("CAPTURE_RESERVATION");
+
+    my $dt_parser = new DateTime::Format::ISO8601;
+    my $now = now DateTime; # sic
+    my $res = get_uncaptured_bresv_for_brsrc($e, {"barcode" => $barcode});
+
+    if ($res and keys %$res) {
+        my $id;
+        while ((undef, $id) = each %$res) {
+            my $bresv = $e->retrieve_booking_reservation([
+                $id, {
+                    "flesh" => 1, "flesh_fields" => {
+                        "bresv" => [qw(
+                            usr target_resource_type
+                            target_resource current_resource
+                        )]
+                    }
+                }
+            ]);
+            my $elbow_room = interval_to_seconds(
+                $bresv->target_resource_type->elbow_room ||
+                $U->ou_ancestor_setting_value(
+                    $bresv->pickup_lib,
+                    "circ.booking_reservation.default_elbow_room"
+                ) ||
+                "0 seconds"
+            );
+
+            unless ($elbow_room) {
+                $client->respond($bresv);
+            } else {
+                my $start_time = $dt_parser->parse_datetime(
+                    clense_ISO8601($bresv->start_time)
+                );
+
+                if ($now >= $start_time->subtract("seconds" => $elbow_room)) {
+                    $client->respond($bresv);
+                } else {
+                    $logger->info(
+                        "not within elbow room: $elbow_room, " .
+                        "else would have returned bresv " . $bresv->id
+                    );
+                }
+            }
+        }
+    }
+    $e->disconnect;
+    undef;
+}
+__PACKAGE__->register_method(
+    method   => "could_capture",
+    api_name => "open-ils.booking.reservations.could_capture",
+    argc     => 2,
+    streaming=> 1,
+    signature=> {
+        params => [
+            {type => "string", desc => "Authentication token"},
+            {type => "string", desc => "Resource barcode"}
+        ],
+        return => {desc => "One or zero reservations; event on error."}
+    }
+);
+
+
 sub get_copy_fleshed_just_right {
     my ($self, $client, $auth, $barcode) = @_;
 
@@ -771,7 +899,10 @@
     my ($e, $id_list) = @_;
 
     # This will almost always be the case.
-    return $id_list->[0] if @$id_list == 1;
+    if (@$id_list == 1) {
+        $logger->info("best_bresv_candidate (only) " . $id_list->[0]);
+        return $id_list->[0];
+    }
 
     my @here = ();
     my $this_ou = $e->requestor->ws_ou;
@@ -791,40 +922,48 @@
         push @here, $_->{"id"} if $_->{"pickup_lib"} == $this_ou;
     }
 
+    my $result;
     if (@here > 0) {
-        return pop @here if @here == 1;
-        return (sort @here)[0];
+        $result = @here == 1 ? pop @here : (sort @here)[0];
     } else {
-        return (sort @$id_list)[0];
+        $result = (sort @$id_list)[0];
     }
+    $logger->info(
+        "best_bresv_candidate from " . join(",", @$id_list) . ": $result"
+    );
+    return $result;
 }
 
 
 sub capture_resource_for_reservation {
-    my ($self, $client, $auth, $barcode) = @_;
+    my ($self, $client, $auth, $barcode, $no_update_copy) = @_;
 
-    my $e = new_editor(xact => 1, authtoken => $auth);
+    my $e = new_editor(authtoken => $auth);
     return $e->die_event unless $e->checkauth;
     return $e->die_event unless $e->allowed("CAPTURE_RESERVATION");
 
     my $uncaptured = get_uncaptured_bresv_for_brsrc(
         $e, {"barcode" => $barcode}
     );
-    $e->disconnect;
 
     if (keys %$uncaptured) {
         # Note this will only capture one reservation at a time, even in
         # cases with overbooking (multiple "soonest" bresv's on a resource).
-        my $key = (sort(keys %$uncaptured))[0];
+        my $bresv = best_bresv_candidate(
+            $e, $uncaptured->{
+                (sort(keys %$uncaptured))[0]
+            }
+        );
+        $e->disconnect;
         return capture_reservation(
-            $self, $client, $auth, best_bresv_candidate($e, $uncaptured->{$key})
+            $self, $client, $auth, $bresv, $no_update_copy
         );
     } else {
         return new OpenILS::Event(
             "RESERVATION_NOT_FOUND",
-            desc => "No capturable reservation found pertaining " .
+            "desc" => "No capturable reservation found pertaining " .
                 "to a resource with barcode $barcode",
-            payload => {fail_cause => 'no-reservation', captured => 0}
+            "payload" => {"fail_cause" => "no-reservation", "captured" => 0}
         );
     }
 }
@@ -836,7 +975,7 @@
         params => [
             {type => "string", desc => "Authentication token"},
             {type => "string", desc => "Barcode of booked & targeted resource"},
-            {type => "int", desc => "Pickup library (default to client ws_ou)"},
+            {type => "number", desc => "(optional) 1 to not update copy"}
         ],
         return => { desc => "An OpenILS event describing the capture outcome" }
     }
@@ -844,89 +983,125 @@
 
 
 sub capture_reservation {
-    my ($self, $client, $auth, $res_id) = @_;
+    my ($self, $client, $auth, $res_id, $no_update_copy) = @_;
 
-    my $e = new_editor(xact => 1, authtoken => $auth);
-    return $e->event unless $e->checkauth;
-    return $e->event unless $e->allowed('CAPTURE_RESERVATION');
+    my $e = new_editor("xact" => 1, "authtoken" => $auth);
+    return $e->die_event unless $e->checkauth;
+    return $e->die_event unless $e->allowed('CAPTURE_RESERVATION');
     my $here = $e->requestor->ws_ou;
 
     my $reservation = $e->retrieve_booking_reservation([
         $res_id, {
-            flesh => 2,
-            flesh_fields => {"bresv" => ["usr"], "au" => ["card"]}
+            "flesh" => 2, "flesh_fields" => {
+                "bresv" => [qw/usr current_resource type/],
+                "au" => ["card"],
+                "brsrc" => ["type"]
+            }
         }
     ]);
-    return OpenILS::Event->new('RESERVATION_NOT_FOUND') unless $reservation;
 
-    return OpenILS::Event->new('RESERVATION_CAPTURE_FAILED', payload => { captured => 0, fail_cause => 'no-resource' })
-        if (!$reservation->current_resource); # no resource
+    return new OpenILS::Event("RESERVATION_NOT_FOUND") unless $reservation;
+    return new OpenILS::Event(
+        "RESERVATION_CAPTURE_FAILED",
+        payload => {"captured" => 0, "fail_cause" => "no-resource"}
+    ) unless $reservation->current_resource;
 
-    return OpenILS::Event->new('RESERVATION_CAPTURE_FAILED', payload => { captured => 0, fail_cause => 'cancelled' })
-        if ($reservation->cancel_time); # canceled
+    return new OpenILS::Event(
+        "RESERVATION_CAPTURE_FAILED",
+        "payload" => {"captured" => 0, "fail_cause" => "cancelled"}
+    ) if $reservation->cancel_time;
 
-    my $resource = $e->retrieve_booking_resource( $reservation->current_resource );
-    my $type = $e->retrieve_booking_resource_type( $resource->type );
+    $reservation->capture_staff($e->requestor->id);
+    $reservation->capture_time("now");
 
-    $reservation->capture_staff( $e->requestor->id );
-    $reservation->capture_time( 'now' );
+    $e->update_booking_reservation($reservation) or return $e->die_event;
 
-    my $reservation_id = undef;
-    return $e->event unless ( $e->update_booking_reservation( $reservation ) and $reservation_id = $e->data );
+    my $ret = {"captured" => 1, "reservation" => $reservation};
 
-    $reservation->id($reservation_id);
+    my $search_acp_like_this = [
+        {
+            "barcode" => $reservation->current_resource->barcode,
+            "deleted" => "f"
+        },
+        {"flesh" => 1, "flesh_fields" => {"acp" => ["call_number"]}}
+    ];
 
-    my $ret = { captured => 1, reservation => $reservation };
-
     if ($here != $reservation->pickup_lib) {
-        return OpenILS::Event->new('RESERVATION_CAPTURE_FAILED', payload => { captured => 0, fail_cause => 'not-transferable' })
-            if (!$U->is_true($type->transferable)); # non-transferable resource
+        $logger->info("resource isn't at the reservation's pickup lib...");
+        return new OpenILS::Event(
+            "RESERVATION_CAPTURE_FAILED",
+            "payload" => {"captured" => 0, "fail_cause" => "not-transferable"}
+        ) unless $U->is_true(
+            $reservation->current_resource->type->transferable
+        );
 
         # need to transit the item ... is it already in transit?
-        my $transit = $e->search_action_reservation_transit_copy( { reservation => $res_id, dest_recv_time => undef } )->[0];
+        my $transit = $e->search_action_reservation_transit_copy(
+            {"reservation" => $res_id, "dest_recv_time" => undef}
+        )->[0];
 
         if (!$transit) { # not yet in transit
             $transit = new Fieldmapper::action::reservation_transit_copy;
 
             $transit->reservation($reservation->id);
-            $transit->target_copy($resource->id);
+            $transit->target_copy($reservation->current_resource->id);
             $transit->copy_status(15);
-            $transit->source_send_time('now');
+            $transit->source_send_time("now");
             $transit->source($here);
             $transit->dest($reservation->pickup_lib);
 
-            $e->create_action_reservation_transit_copy( $transit );
+            $e->create_action_reservation_transit_copy($transit);
 
-            if ($U->is_true($type->catalog_item)) {
-                my $copy = $e->search_asset_copy( { barcode => $resource->barcode, deleted => 'f' } )->[0];
+            if ($U->is_true(
+                $reservation->current_resource->type->catalog_item
+            )) {
+                my $copy = $e->search_asset_copy($search_acp_like_this)->[0];
 
                 if ($copy) {
                     return new OpenILS::Event(
                         "OPEN_CIRCULATION_EXISTS",
-                        payload => { captured => 0, copy => $copy }
-                    ) if $copy->status == 1;
-                    $copy->status(6);
-                    $e->update_asset_copy( $copy );
-                    $$ret{catalog_item} = $copy; # $e->data is just id (int)
+                        "payload" => {"captured" => 0, "copy" => $copy}
+                    ) if $copy->status == 1 and not $no_update_copy;
+
+                    $ret->{"mvr"} = get_mvr($copy->call_number->record);
+                    if ($no_update_copy) {
+                        $ret->{"new_copy_status"} = 6;
+                    } else {
+                        $copy->status(6);
+                        $e->update_asset_copy($copy) or return $e->die_event;
+                    }
                 }
             }
         }
 
-        $$ret{transit} = $transit;
-    } elsif ($U->is_true($type->catalog_item)) {
-        my $copy = $e->search_asset_copy( { barcode => $resource->barcode, deleted => 'f' } )->[0];
+        $ret->{"transit"} = $transit;
+    } elsif ($U->is_true($reservation->current_resource->type->catalog_item)) {
+        $logger->info("resource is a catalog item...");
+        my $copy = $e->search_asset_copy($search_acp_like_this)->[0];
 
         if ($copy) {
-            return OpenILS::Event->new('OPEN_CIRCULATION_EXISTS', payload => { captured => 0, copy => $copy }) if ($copy->status == 1);
-            $copy->status(15);
-            $e->update_asset_copy( $copy );
-            $$ret{catalog_item} = $copy; # $e->data is just id (int)
+            return new OpenILS::Event(
+                "OPEN_CIRCULATION_EXISTS",
+                "payload" => {"captured" => 0, "copy" => $copy}
+            ) if $copy->status == 1 and not $no_update_copy;
+
+            $ret->{"mvr"} = get_mvr($copy->call_number->record);
+            if ($no_update_copy) {
+                $ret->{"new_copy_status"} = 15;
+            } else {
+                $copy->status(15);
+                $e->update_asset_copy($copy) or return $e->die_event;
+            }
         }
     }
 
-    $e->commit;
+    $e->commit or return $e->die_event;
 
-    return OpenILS::Event->new('SUCCESS', payload => $ret);
+    # XXX I'm not sure whether these last two elements of the payload
+    # actually get used anywhere.
+    $ret->{"resource"} = $reservation->current_resource;
+    $ret->{"type"} = $reservation->current_resource->type;
+    return new OpenILS::Event("SUCCESS", "payload" => $ret);
 }
 __PACKAGE__->register_method(
     method   => "capture_reservation",
@@ -960,10 +1135,18 @@
     ]);
     return $e->die_event if not $bresv_list;
 
+    my @results = ();
     my $circ = OpenSRF::AppSession->connect("open-ils.circ") or
         return $e->die_event;
-    my @results = ();
     foreach my $bresv (@$bresv_list) {
+        $bresv->cancel_time("now");
+        $e->update_booking_reservation($bresv) or do {
+            $circ->disconnect;
+            return $e->die_event;
+        };
+        $e->xact_commit;
+        $e->xact_begin;
+
         if (
             $bresv->target_resource_type->catalog_item == "t" &&
             $bresv->current_resource
@@ -975,16 +1158,10 @@
                         "noop" => 1}
                 )->gather(1)->{"textcode"});
         }
-        $bresv->cancel_time("now");
-        $e->update_booking_reservation($bresv) or do {
-            $circ->disconnect;
-            return $e->die_event;
-        };
-
         push @results, $bresv->id;
     }
 
-    $e->commit;
+    $e->disconnect;
     $circ->disconnect;
 
     return \@results;
@@ -1094,7 +1271,7 @@
     my $e = new_editor(xact => 1, authtoken => $auth);
     return $e->die_event unless $e->checkauth;
     return $e->die_event unless $e->allowed("VIEW_USER");
-    return $e->die_event unless $e->allowed("ADMIN_BOOKING_RESERVATION");
+#    return $e->die_event unless $e->allowed("ADMIN_BOOKING_RESERVATION");
 
     my $rows = $e->json_query({
         "select" => {"bresv" => ["id"]},

Modified: trunk/Open-ILS/web/js/dojo/openils/booking/nls/capture.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/booking/nls/capture.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/dojo/openils/booking/nls/capture.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -9,10 +9,23 @@
     "CAPTURE_BRESV_DATES": "Reservation time:",
     "CAPTURE_BRESV_BRSRC": "Resource barcode:",
     "CAPTURE_BRESV_PICKUP_LIB": "Pickup library:",
-    "CAPTURE_BRESV_PATRON_BARCODE": "Patron barcode:",
     "CAPTURE_CAUSES_TRANSIT": "This item is now in transit!",
     "CAPTURE_TRANSIT_SOURCE": "From:",
     "CAPTURE_TRANSIT_DEST": "To:",
+    "BARCODE": "Barcode",
+    "TITLE": "Title",
+    "AUTHOR": "Author",
+    "RESERVED": "Reserved for patron",
+    "REQUEST": "Request time",
+    "DURATION": "Reserved from",
+    "SLIP_DATE": "Slip date",
+    "PRINTED_BY": "Printed by",
+    "AT": "at",
+    "PRINT": "<u>P</u>rint",
+    "PRINT_ACCESSKEY": "P",
+    "TRANSIT": "*** TRANSIT ***",
+    "RESERVATION_SHELF": "RESERVATION SHELF",
+    "NEEDS_ROUTED_TO": "This item need to be routed to",
 
     "AUTO_capture_heading": "Capture Reserved Resources",
     "AUTO_resource_barcode": "Enter barcode:",

Modified: trunk/Open-ILS/web/js/dojo/openils/booking/nls/pickup_and_return.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/booking/nls/pickup_and_return.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/dojo/openils/booking/nls/pickup_and_return.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -1,9 +1,7 @@
 {
     "NO_PATRON_BARCODE": "Please enter a patron barcode.",
-    "RESERVATIONS_NO_RESPONSE":
-        "No response from server when asking for reservations.",
-    "RESERVATIONS_ERROR":
-        "Error communicating with server (asking for reservations):",
+    "RESERVATIONS_NO_RESPONSE": "No response from server when asking for reservations.",
+    "RESERVATIONS_ERROR": "Error communicating with server (asking for reservations):",
     "PICKUP_NO_RESPONSE": "No response from server when attempting pickup.",
     "PICKUP_ERROR": "Error communicating with server (attempting pickup):",
     "RETURN_NO_RESPONSE": "No response from server when attempting return.",
@@ -13,7 +11,7 @@
     "NO_SUCH_RETURNABLE_RESOURCE": "No such returnable resource.",
     "RETURNABLE_RESOURCE_ERROR": "Error looking up returnable resource:",
     "NOTICE_CHANGE_OF_PATRON":
-        "Note that the resource scanned was out on reservation to different\npatron than the last resource you scanned.  If this is not\nexpected, stop to examine outstanding reservations for your patron\nor on the resource.",
+        "Note that the resource scanned was out on reservation to a different\npatron than the last resource you scanned.  If this is not\nexpected, stop to examine outstanding reservations for your patron\nor on the resource.",
 
     "AUTO_h1": "Reservations Pickup",
     "AUTO_return_h1": "Reservations Return",
@@ -22,8 +20,7 @@
     "AUTO_in_bresv": "Patron has returned these resources today:",
     "AUTO_ready_bresv": "Patron has these reservations ready for pickup:",
     "AUTO_out_bresv": "Patron currently has these reservations out:",
-    "AUTO_no_ready_bresv":
-        "Patron has no reservations ready for pickup at this time.",
+    "AUTO_no_ready_bresv": "Patron has no reservations ready for pickup at this time.",
     "AUTO_no_out_bresv": "Patron has no more reservations out at this time.",
     "AUTO_no_in_bresv": "Patron has not returned any resources today.",
     "AUTO_patron": "Patron",
@@ -31,5 +28,6 @@
     "AUTO_ATTR_VALUE_go": "Go",
     "AUTO_ATTR_VALUE_reset": "Clear / New Patron",
     "AUTO_ATTR_VALUE_pickup": "Pick up",
-    "AUTO_ATTR_VALUE_return": "Return"
+    "AUTO_ATTR_VALUE_return": "Return",
+    "ADDRESS": "${0}\n${1}\n${2}, ${3} ${4}"
 }

Modified: trunk/Open-ILS/web/js/dojo/openils/booking/nls/pull_list.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/booking/nls/pull_list.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/dojo/openils/booking/nls/pull_list.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -4,8 +4,10 @@
     "COPY_LOOKUP_NO_RESPONSE": "No response looking up copies by barcode",
     "COPY_LOOKUP_ERROR": "Error looking up copies by barcode: ",
     "COPY_MISSING": "Unexpected error: No information for copy: ",
+    "AT": "at",
+    "FOR": "for",
 
-    "AUTO_no_results": "No results",
+    "AUTO_no_results": "No results.",
     "AUTO_owning_lib_selector": "See pull list for library:",
     "AUTO_pull_list_title": "Booking Pull List",
     "AUTO_interval_in_days": "Generate list for this many days hence: ",
@@ -14,7 +16,7 @@
     "AUTO_th_barcode": "Barcode",
     "AUTO_th_call_number": "Call number",
     "AUTO_th_copy_location": "Copy location",
-    "AUTO_th_copy_number": "Copy number",
+    "AUTO_th_pickup_lib": "Pickup library",
     "AUTO_th_resv_details": "Reservation details",
     "AUTO_ATTR_VALUE_print": "Print"
 }

Modified: trunk/Open-ILS/web/js/dojo/openils/booking/nls/reservation.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/booking/nls/reservation.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/dojo/openils/booking/nls/reservation.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -2,13 +2,14 @@
     "NO_BRT_RESULTS": "There are no bookable resource types registered.",
     "NO_TARG_DIV": "Could not find target div",
     "NO_BRA_RESULTS": "Couldn't retrieve booking resource attributes.",
-    "SELECT_A_BRSRC_THEN": "Select a resource from the big list above.",
+    "SELECT_A_BRSRC_THEN": "You have clicked 'Reserve Selected', but nothing is selected!\n\nYou must select a resource from the large box above.\n\n***  If resources that you would select are highlighted in RED, ***\nthese items are not available during the requested time; if\npossible, choose another resource or change the reservation time.",
     "CREATE_BRESV_LOCAL_ERROR": "Exception trying to create reservation: ",
     "CREATE_BRESV_SERVER_ERROR": "Server error trying to create reservation: ",
     "CREATE_BRESV_SERVER_NO_RESPONSE": "No response from server after trying to create reservation.",
-    "CREATE_BRESV_OK_MISSING_TARGET": "Created ${0} reservation(s), but ${1} of these couldn't target any resources.\n\nThis means that it won't be possible to fulfill some of these\nreservations until a suitable resource becomes available.",
-    "CREATE_BRESV_OK": "Created ${0} reservation.",
-    "CREATE_BRESV_OK_PLURAL": "Created ${0} reservations",
+    "CREATE_BRESV_OK_MISSING_TARGET": "Created ${0} reservation(s), but ${1} of these could not target any resources.\n\nThis means that it won't be possible to fulfill some of these\nreservations until a suitable resource becomes available.",
+    "CREATE_BRESV_OK_MISSING_TARGET_BLOCKED_BY_CIRC": "The desired reservation(s) are blocked by circulation(s) with the following due date(s):\n${0}",
+    "CREATE_BRESV_OK_MISSING_TARGET_WILL_CANCEL": "Since the requested resource could not be targeted, this\nreservation will now be canceled.",
+    "CREATE_BRESV_OK": "Created ${0} reservation(s)",
     "WHERES_THE_BARCODE": "Enter a patron's barcode to make a reservation.",
     "ACTOR_CARD_NOT_FOUND": "Patron barcode not found. Please try again.",
     "GET_BRESV_LIST_ERR": "Error while retrieving reservation list: ",
@@ -19,20 +20,23 @@
     "HERE_ARE_EXISTING_BRESV": "Existing reservations for",
     "NO_EXISTING_BRESV": "This user has no existing reservations at this time.",
     "NO_USABLE_BRSRC": "No reservable resources.  Adjust start and end time\nuntil a resource is available for reservation.",
-    "CXL_BRESV_SUCCESS": "Canceled ${0} reservation.",
-    "CXL_BRESV_SUCCESS_PLURAL": "Canceled ${0} reservations",
+    "CXL_BRESV_SUCCESS": "Canceled ${0} reservation(s)",
     "CXL_BRESV_FAILURE": "Error canceling reservations; server silent.",
     "CXL_BRESV_FAILURE2": "Error canceling reservations:\n",
-    "CXL_BRESV_SELECT_SOMETHING": "You have not selected any reservations to cancel.",
+    "CXL_BRESV_SELECT_SOMETHING":
+        "You have not selected any reservations to cancel.",
     "NEED_EXACTLY_ONE_BRT_PASSED_IN": "Can't book multiple resource types at once",
     "COULD_NOT_RETRIEVE_BRT_PASSED_IN": "Error retrieving booking resource type",
     "INVALID_TS_RANGE": "You must choose a valid start and end time for the reservation.",
     "BRSRC_NOT_FOUND": "Could not locate that resource.",
     "BRSRC_RETRIVE_ERROR": "Error retrieving resource: ",
-    "ON_FLY_NO_RESPONSE": "No response from server attempting to make item a bookable resource.",
-    "ON_FLY_ERROR": "Error attempting to make item a bookable resource:",
+    "ON_FLY_NO_RESPONSE":
+        "No response from server attempting to make item a bookable resource.",
+    "ON_FLY_ERROR":
+        "Error attempting to make item a bookable resource:",
     "ANY": "ANY",
-
+    "ERROR_FETCHING_AOUS":
+        "Could not retrieve organizational unit settings.\nThis is a non-fatal error, but you may wish to\ncontact your system administrator.", 
     "AUTO_choose_a_brt": "Choose a Bookable Resource Type",
     "AUTO_i_need_this_resource": "I need this resource...",
     "AUTO_starting_at": "Between",
@@ -43,7 +47,7 @@
     "AUTO_ATTR_VALUE_reserve_brsrc": "Reserve Selected",
     "AUTO_ATTR_VALUE_reserve_brt": "Reserve Any",
     "AUTO_ATTR_VALUE_button_edit_existing": "Edit selected",
-    "AUTO_ATTR_VALUE_button_cancel_existing": "Cancel selcted",
+    "AUTO_ATTR_VALUE_button_cancel_existing": "Cancel selected",
     "AUTO_bresv_grid_type": "Type",
     "AUTO_bresv_grid_resource": "Resource",
     "AUTO_bresv_grid_start_time": "Start time",

Modified: trunk/Open-ILS/web/js/ui/default/booking/capture.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/booking/capture.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/ui/default/booking/capture.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -8,14 +8,19 @@
 
 var localeStrings = dojo.i18n.getLocalization("openils.booking", "capture");
 
-function CaptureDisplay(element) { this.element = element; }
+function CaptureDisplay(control_holder, data_holder) {
+    this.control_holder = control_holder;
+    this.data_holder = data_holder;
+}
 CaptureDisplay.prototype.no_payload = function() {
-    this.element.appendChild(document.createTextNode(localeStrings.NO_PAYLOAD));
+    this.data_holder.appendChild(
+        document.createTextNode(localeStrings.NO_PAYLOAD)
+    );
 };
 CaptureDisplay.prototype.dump = function(payload) {
     var div = document.createElement("div");
     div.appendChild(document.createTextNode(localeStrings.HERES_WHAT_WE_KNOW));
-    this.element.appendChild(div);
+    this.data_holder.appendChild(div);
 
     var ul = document.createElement("ul");
     for (var k in payload) {
@@ -23,90 +28,149 @@
         li.appendChild(document.createTextNode(k + ": " + payload[k]));
         ul.appendChild(li);
     }
-    this.element.appendChild(ul);
+    this.data_holder.appendChild(ul);
 };
-CaptureDisplay.prototype.generate_transit_display = function(payload) {
-    var super_div = document.createElement("div");
-    var div;
-
-    div = document.createElement("div");
+CaptureDisplay.prototype._generate_barcode_line = function(payload) {
+    var div = document.createElement("div");
     div.appendChild(document.createTextNode(
-        localeStrings.CAPTURE_CAUSES_TRANSIT
+        localeStrings.BARCODE + ": " + payload.resource.barcode()
     ));
-    div.setAttribute("class", "transit_notice");
-    super_div.appendChild(div);
-
-    div = document.createElement("div");
+    return div;
+};
+CaptureDisplay.prototype._generate_title_line = function(payload) {
+    var div = document.createElement("div");
     div.appendChild(document.createTextNode(
-        localeStrings.CAPTURE_TRANSIT_SOURCE + " " +
-        fieldmapper.aou.findOrgUnit(payload.transit.source()).shortname()
+        localeStrings.TITLE + ": " +
+        (payload.mvr ? payload.mvr.title() : payload.type.name())
     ));
-    super_div.appendChild(div);
-
-    div = document.createElement("div");
-    div.appendChild(document.createTextNode(
-        localeStrings.CAPTURE_TRANSIT_DEST + " " +
-        fieldmapper.aou.findOrgUnit(payload.transit.dest()).shortname()
-    ));
-    super_div.appendChild(div);
-
-    return super_div;
+    return div;
 };
-CaptureDisplay.prototype.display_with_transit_info = function(payload) {
-    var div;
-
-    div = document.createElement("div");
-    div.appendChild(document.createTextNode(localeStrings.CAPTURE_INFO));
-    div.setAttribute("class", "capture_info");
-    this.element.appendChild(div);
-
-    if (payload.catalog_item) {
-        div = document.createElement("div");
+CaptureDisplay.prototype._generate_author_line = function(payload) {
+    var div = document.createElement("div");
+    if (payload.mvr) {
         div.appendChild(document.createTextNode(
-            localeStrings.CAPTURE_BRESV_BRSRC + " " +
-            payload.catalog_item.barcode()
+            localeStrings.AUTHOR + ": " + payload.mvr.author()
         ));
-        this.element.appendChild(div);
     }
-
-    div = document.createElement("div");
-    div.appendChild(document.createTextNode(
-        localeStrings.CAPTURE_BRESV_DATES + " " +
-        humanize_timestamp_string(payload.reservation.start_time()) + " - " +
-        humanize_timestamp_string(payload.reservation.end_time())
+    return div;
+};
+CaptureDisplay.prototype._generate_transit_notice = function(payload) {
+    var div = document.createElement("div");
+    if (payload.transit) {
+        div.setAttribute("class", "transit_notice");
+        div.appendChild(document.createTextNode(localeStrings.TRANSIT));
+    }
+    return div;
+};
+CaptureDisplay.prototype._generate_route_line = function(payload) {
+    var div = document.createElement("div");
+    var strong = document.createElement("strong");
+    strong.appendChild(document.createTextNode(
+        (payload.transit ?
+            fieldmapper.aou.findOrgUnit(payload.transit.dest()).shortname() :
+            localeStrings.RESERVATION_SHELF) + ":"
     ));
-    this.element.appendChild(div);
-
-    div = document.createElement("div");
     div.appendChild(document.createTextNode(
-        localeStrings.CAPTURE_BRESV_PICKUP_LIB + " " +
-        fieldmapper.aou.findOrgUnit(
-            payload.reservation.pickup_lib()
-        ).shortname()
+        localeStrings.NEEDS_ROUTED_TO + " "
     ));
-    this.element.appendChild(div);
+    div.appendChild(strong);
+    return div;
+};
+CaptureDisplay.prototype._generate_patron_info = function(payload) {
+    var p = document.createElement("p");
+    p.innerHTML = "<strong>" + localeStrings.RESERVED + "</strong> " +
+        formal_name(payload.reservation.usr()) + "<br />" +
+        localeStrings.BARCODE + ": " +
+        payload.reservation.usr().card().barcode();
+    return p;
+};
+CaptureDisplay.prototype._generate_resv_info = function(payload) {
+    var p = document.createElement("p");
+    p.innerHTML = localeStrings.REQUEST + ": " +
+        humanize_timestamp_string(payload.reservation.request_time()) +
+        "<br />" + 
+        localeStrings.DURATION + ": " +
+        humanize_timestamp_string(payload.reservation.start_time()) +
+        " - " + 
+        humanize_timestamp_string(payload.reservation.end_time());
+    return p;
+};
+CaptureDisplay.prototype._generate_meta_info = function(result) {
+    var p = document.createElement("p");
+    p.innerHTML = localeStrings.SLIP_DATE + ": " + result.servertime +
+        "<br />" + localeStrings.PRINTED_BY + " " +
+        formal_name(openils.User.user) + " " + localeStrings.AT + " " +
+        fieldmapper.aou.findOrgUnit(openils.User.user.ws_ou()).shortname()
+    return p;
+};
+CaptureDisplay.prototype.display_with_transit_info = function(result) {
+    var div = document.createElement("div");
+    var span = document.createElement("span");
+    span.appendChild(document.createTextNode(localeStrings.CAPTURE_INFO));
+    span.setAttribute("class", "capture_info");
+    this.control_holder.appendChild(span);
 
-    div = document.createElement("div");
-    div.appendChild(document.createTextNode(
-        localeStrings.CAPTURE_BRESV_PATRON_BARCODE + " " +
-        payload.reservation.usr().card().barcode()
-    ));
-    this.element.appendChild(div);
+    var button = document.createElement("button");
+    button.setAttribute("class", "print_slip");
+    button.setAttribute("type", "button");
+    button.setAttribute("accesskey", localeStrings.PRINT_ACCESSKEY);
+    button.innerHTML = localeStrings.PRINT;
+    button.onclick = function() {
+        try { dojo.byId("printing_iframe").contentWindow.print(); }
+        catch (E) { alert(E); } /* XXX */
+        return false;
+    };
+    this.control_holder.appendChild(button);
 
-    if (payload.transit) {
-        this.element.appendChild(this.generate_transit_display(payload));
-    }
+    div.appendChild(this._generate_transit_notice(result.payload));
+
+    var p = document.createElement("p");
+    p.appendChild(this._generate_route_line(result.payload));
+    p.appendChild(this._generate_barcode_line(result.payload));
+    p.appendChild(this._generate_title_line(result.payload));
+    p.appendChild(this._generate_author_line(result.payload));
+    div.appendChild(p);
+
+    div.appendChild(this._generate_patron_info(result.payload));
+    div.appendChild(this._generate_resv_info(result.payload));
+    div.appendChild(this._generate_meta_info(result));
+
+    this._create_iframe(div);
 };
-CaptureDisplay.prototype.clear = function() { this.element.innerHTML = ""; };
-CaptureDisplay.prototype.load = function(payload) {
+CaptureDisplay.prototype._create_iframe = function(contents) {
+    var iframe = document.createElement("iframe");
+    iframe.setAttribute("name", "printing_iframe");
+    iframe.setAttribute("id", "printing_iframe");
+    iframe.setAttribute("src", "");
+    iframe.setAttribute("width", "100%");
+    iframe.setAttribute("height", "400"); /* hardcode 400px? really? */
+
+    this.data_holder.appendChild(iframe);
+
+    var w = dojo.byId("printing_iframe").contentWindow;
+    w.document.open();
+    w.document.write(
+        "<html><head><link rel='stylesheet' type='text/css' href='" +
+        dojo.byId("booking_stylesheet_link").href +
+        "' /><body></body></html>"
+    );
+    w.document.close();
+    w.document.body.appendChild(contents);
+    /* FIXME if (determine_autoprint_setting_somehow()) w.print(); */
+};
+CaptureDisplay.prototype.clear = function() {
+    this.control_holder.innerHTML = "";
+    this.data_holder.innerHTML = "";
+};
+CaptureDisplay.prototype.load = function(result) {
     try {
-        this.element.appendChild(document.createElement("hr"));
-        if (!payload) {
+        this.control_holder.appendChild(document.createElement("hr"));
+        if (!result.payload) {
             this.no_payload();
-        } else if (!payload.fail_cause && payload.captured) {
-            this.display_with_transit_info(payload);
+        } else if (!result.payload.fail_cause && result.payload.captured) {
+            this.display_with_transit_info(result);
         } else {
-            this.dump(payload);
+            this.dump(result.payload);
         }
     } catch (E) {
         alert(E); /* XXX */
@@ -136,10 +200,10 @@
 
     if (result && result.ilsevent !== undefined) {
         if (result.payload && result.payload.captured > 0) {
-            capture_display.load(result.payload);
+            capture_display.load(result);
             return CAPTURE_SUCCESS;
         } else {
-            capture_display.load(result.payload);
+            capture_display.load(result);
             alert(my_ils_error(localeStrings.CAPTURED_NOTHING, result));
             return CAPTURE_FAILURE;
         }
@@ -167,8 +231,9 @@
 }
 
 function my_init() {
-    init_auto_l10n(document.getElementById("auto_l10n_start_here"));
+    init_auto_l10n(dojo.byId("auto_l10n_start_here"));
     capture_display = new CaptureDisplay(
-        document.getElementById("capture_display")
+        dojo.byId("capture_info_top"),
+        dojo.byId("capture_info_bottom")
     );
 }

Modified: trunk/Open-ILS/web/js/ui/default/booking/common.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/booking/common.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/ui/default/booking/common.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -48,6 +48,13 @@
     var timeparts = parts[1].split("-")[0].split(":");
     return parts[0] + " " + timeparts[0] + ":" + timeparts[1];
 }
+function humanize_timestamp_string2(ts) {
+    /* For now, this discards time zones, too. */
+    var parts = ts.split(" ");
+    parts[1] = parts[1].replace(/[\-\+]\d+$/, "");
+    var timeparts = parts[1].split("-")[0].split(":");
+    return parts[0] + " " + timeparts[0] + ":" + timeparts[1];
+}
 function is_ils_event(e) { return (e.ilsevent != undefined); }
 function is_ils_actor_card_error(e) {
     return (e.textcode == "ACTOR_CARD_NOT_FOUND");

Modified: trunk/Open-ILS/web/js/ui/default/booking/populator.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/booking/populator.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/ui/default/booking/populator.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -2,6 +2,8 @@
  * localization (Dojo/nls) for pickup and return . */
 
 dojo.require("dojo.data.ItemFileReadStore");
+dojo.require("dojo.date.locale");
+dojo.require("openils.PermaCrud");
 
 function Populator(widgets, primary_input) {
     this.widgets = widgets;
@@ -137,7 +139,7 @@
     var r = fieldmapper.standardRequest(
         ["open-ils.booking",
         "open-ils.booking.reservations.by_returnable_resource_barcode"],
-        [xulG.auth.session.key, barcode]
+        [openils.User.authtoken, barcode]
     );
     if (!r || r.length < 1) {
         alert(localeStrings.NO_SUCH_RETURNABLE_RESOURCE);
@@ -159,7 +161,10 @@
         if (!ret) {
             alert(localeStrings.RETURN_NO_RESPONSE);
         } else if (is_ils_event(ret) && ret.textcode != "SUCCESS") {
-            alert(my_ils_error(localeStrings.RETURN_ERROR, ret));
+            if (ret.textcode == "ROUTE_ITEM")
+                display_transit_slip(ret);
+            else
+                alert(my_ils_error(localeStrings.RETURN_ERROR, ret));
         } else {
             /* XXX speedbump should go, but something has to happen else
              * there's no indication to staff that anything happened when
@@ -189,7 +194,7 @@
 
     var result = fieldmapper.standardRequest(
         ["open-ils.booking", "open-ils.booking.reservations.get_captured"],
-        [xulG.auth.session.key, this.patron_barcode, which]
+        [openils.User.authtoken, this.patron_barcode, which]
     );
 
     if (!result) {
@@ -220,7 +225,7 @@
 Populator.prototype.pickup = function(reservation) {
     return fieldmapper.standardRequest(
         ["open-ils.circ", "open-ils.circ.reservation.pickup"],
-        [xulG.auth.session.key, {
+        [openils.User.authtoken, {
             "patron_barcode": this.patron_barcode,
             "reservation": reservation
         }]
@@ -229,7 +234,7 @@
 Populator.prototype.return = function(reservation) {
     return fieldmapper.standardRequest(
         ["open-ils.circ", "open-ils.circ.reservation.return"],
-        [xulG.auth.session.key, {
+        [openils.User.authtoken, {
             "patron_barcode": this.patron_barcode,
             "reservation": reservation.id()
             /* yeah just id here ------^; lack of parallelism */
@@ -258,7 +263,10 @@
         if (!result) {
             alert(no_response_msg);
         } else if (is_ils_event(result) && result.textcode != "SUCCESS") {
-            alert(my_ils_error(error_msg, result));
+            if (result.textcode == "ROUTE_ITEM")
+                display_transit_slip(result);
+            else
+                alert(my_ils_error(error_msg, result));
         } else {
             continue;
         }
@@ -281,3 +289,50 @@
         this.primary_input.focus();
     }
 };
+
+/* XXX needs to be combined with the code that shows transit slips in the
+ * booking capture interface. */
+function display_transit_slip(e) {
+    var ou = fieldmapper.aou.findOrgUnit(e.org, /* slim_ok */false);
+    var ma = (new openils.PermaCrud()).retrieve("aoa", ou.mailing_address());
+    var mas = ma ?
+        dojo.string.substitute(
+            localeStrings.ADDRESS,
+            [ma.street1(),ma.street2(),ma.city(),ma.state(),ma.post_code()].map(
+                function(o) { return o ? o : ""; }
+            )
+        ).replace("\n\n", "\n").replace("\n", "<br />") : "[Unknown address]";
+    /* XXX i18n and/or template */
+    try {
+        var win = window.open(
+            "","","resizeable,width=600,height=400,scrollbars=1"
+        );
+        win.document.body.innerHTML =
+            "<h1>Transit Slip</h1>\n" +
+            //"<img src='/xul/server/skin/media/images/turtle.gif' />\n" +
+            "<p>Destination: <strong>" + ou.name() + "</strong></p>\n" +
+            "<p>" + mas + "</p>\n" +
+            "<p>Barcode: " + e.payload.copy.barcode() + "<br />\n" +
+            "Title: <span id='title'></span><br />\n" +
+            "Author: <span id='author'></span><br />\n" +
+            "Slip Date: " +
+                dojo.date.locale.format(new Date(), {"formatLength": "short"}) +
+            "</p>";
+        fieldmapper.standardRequest(
+            ["open-ils.search", "open-ils.search.biblio.mods_from_copy"], {
+                "params": [e.payload.copy.id()],
+                "async": true,
+                "onresponse": function(r) {
+                    var mvr = openils.Util.readResponse(r);
+                    dojo.byId("title", win.document).innerHTML = mvr.title();
+                    dojo.byId("author", win.document).innerHTML = mvr.author();
+                },
+                "oncomplete": function() {
+                    win[confirm("Print transit slip?") ? "print" : "close"]();
+                }
+            }
+        );
+    } catch (E) {
+        alert("exception rendering transit slip: " + E); // XXX
+    }
+}

Modified: trunk/Open-ILS/web/js/ui/default/booking/pull_list.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/booking/pull_list.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/ui/default/booking/pull_list.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -47,18 +47,33 @@
         return td;
     }
 
+    function render_pickup_lib(pickup_lib) {
+        var span = document.createElement("span");
+        if (pickup_lib != owning_lib_selected)
+            span.setAttribute("class", "pull_list_will_transit");
+        span.innerHTML = localeStrings.AT + " " +
+            fieldmapper.aou.findOrgUnit(pickup_lib).shortname();
+        return span;
+    }
+
     function reservation_info_cell(one) {
         var td = document.createElement("td");
         for (var i in one.reservations) {
             var one_resv = one.reservations[i];
             var div = document.createElement("div");
-            var s = humanize_timestamp_string(one_resv.start_time()) + " - " +
-                humanize_timestamp_string(one_resv.end_time()) + " " +
-                formal_name(one_resv.usr());
-            /* FIXME: The above need patron barcode instead of name, but
-             * that requires a fix in the middle layer to flesh on the
-             * right stuff. */
-            div.appendChild(document.createTextNode(s));
+            div.setAttribute("class", "pull_list_resv_detail");
+            var content = [
+                document.createTextNode(
+                    humanize_timestamp_string(one_resv.start_time()) +
+                    " - " + humanize_timestamp_string(one_resv.end_time())
+                ),
+                document.createElement("br"),
+                render_pickup_lib(one_resv.pickup_lib()),
+                document.createTextNode(
+                    " " + localeStrings.FOR + " " + formal_name(one_resv.usr())
+                )
+            ];
+            for (var k in content) { div.appendChild(content[k]); }
             td.appendChild(div);
         }
         return td;
@@ -71,7 +86,6 @@
     cells.push(cell(undefined, one.current_resource.barcode()));
     cells.push(cell(baseid + "_call_number", "-"));
     cells.push(cell(baseid + "_copy_location", "-"));
-    cells.push(cell(baseid + "_copy_number", "-"));
     cells.push(reservation_info_cell(one));
 
     var row = document.createElement("tr");
@@ -120,6 +134,7 @@
             return results;
         }
     }
+    return null;
 }
 
 function fill_in_pull_list_details(list, acp_cache) {
@@ -133,10 +148,6 @@
             var copy_location_el = document.getElementById(
                 dom_table_rowid(one.current_resource.id()) + "_copy_location"
             );
-            var copy_number_el = document.getElementById(
-                dom_table_rowid(one.current_resource.id()) + "_copy_number"
-            );
-
             var bc = one.current_resource.barcode();
 
             if (acp_cache[bc]) {
@@ -148,10 +159,6 @@
                     var value = acp_cache[bc].location().name();
                     if (value) copy_location_el.innerHTML = value;
                 }
-                if (copy_number_el) {
-                    var value = acp_cache[bc].copy_number();
-                    if (value) copy_number_el.innerHTML = value;
-                }
             } else {
                 alert(localeStrings.COPY_MISSING + bc);
             }

Modified: trunk/Open-ILS/web/js/ui/default/booking/reservation.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/booking/reservation.js	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/js/ui/default/booking/reservation.js	2010-06-29 17:53:39 UTC (rev 16827)
@@ -3,6 +3,7 @@
  */
 dojo.require("fieldmapper.OrgUtils");
 dojo.require("openils.PermaCrud");
+dojo.require("openils.User");
 dojo.require("openils.widget.OrgUnitFilteringSelect");
 dojo.require("dojo.data.ItemFileReadStore");
 dojo.require("dijit.form.DateTextBox");
@@ -21,6 +22,7 @@
 var brsrc_index = {};
 var bresv_index = {};
 var just_reserved_now = {};
+var aous_cache = {};
 
 function AttrValueTable() { this.t = {}; }
 AttrValueTable.prototype.set = function(attr, value) { this.t[attr] = value; };
@@ -262,14 +264,25 @@
 
 function check_bresv_targeting(results) {
     var missing = 0;
+    var due_dates = [];
     for (var i in results) {
-        if (!(results[i].targeting && results[i].targeting.current_resource)) {
+        var targ = results[i].targeting;
+        if (!(targ && targ.current_resource)) {
             missing++;
+            if (targ) {
+                if (targ.error == "NO_COPIES" && targ.conflicts) {
+                    for (var k in targ.conflicts) {
+                        /* Could potentially get more circ information from
+                         * targ.conflicts for display in the future. */
+                        due_dates.push(humanize_timestamp_string2(targ.conflicts[k].due_date()));
+                    }
+                }
+            }
         } else {
             just_reserved_now[results[i].targeting.current_resource] = true;
         }
     }
-    return missing;
+    return {"missing": missing, "due_dates": due_dates};
 }
 
 function create_bresv(resource_list) {
@@ -308,22 +321,44 @@
                 ));
             }
         } else {
-            var missing;
-            if (missing = check_bresv_targeting(results)) {
-                alert(dojo.string.substitute(
-                    localeStrings.CREATE_BRESV_OK_MISSING_TARGET,
-                    [results.length, missing]
-                ));
+            var targeting = check_bresv_targeting(results);
+            if (targeting.missing) {
+                if (aous_cache["booking.require_successful_targeting"]) {
+                    alert(
+                        dojo.string.substitute(
+                            localeStrings.CREATE_BRESV_OK_MISSING_TARGET,
+                                [results.length, targeting.missing]
+                        ) + "\n\n" +
+                        dojo.string.substitute(
+                            localeStrings.CREATE_BRESV_OK_MISSING_TARGET_BLOCKED_BY_CIRC,
+                                [targeting.due_dates]
+                        ) + "\n\n" +
+                        localeStrings.CREATE_BRESV_OK_MISSING_TARGET_WILL_CANCEL
+                    );
+                    cancel_reservations(
+                        results.map(
+                            function(o) { return o.bresv; },
+                            true /* skip_update */
+                        )
+                    );
+                } else {
+                    alert(
+                        dojo.string.substitute(
+                            localeStrings.CREATE_BRESV_OK_MISSING_TARGET,
+                                [results.length, targeting.missing]
+                        ) + "\n\n" +
+                        dojo.string.substitute(
+                            localeStrings.CREATE_BRESV_OK_MISSING_TARGET_BLOCKED_BY_CIRC,
+                                [targeting.due_dates]
+                        )
+                    );
+                }
             } else {
-                if (results.length == 1) {
-                    alert(dojo.string.substitute(
+                alert(
+                    dojo.string.substitute(
                         localeStrings.CREATE_BRESV_OK, [results.length]
-                    ));
-                } else {
-                    alert(dojo.string.substitute(
-                        localeStrings.CREATE_BRESV_OK_PLURAL, [results.length]
-                    ));
-                }
+                    )
+                );
             }
             update_brsrc_list();
             update_bresv_grid();
@@ -342,7 +377,7 @@
                 "id": o.id(),
                 "type": o.target_resource_type().name(),
                 "start_time": humanize_timestamp_string(o.start_time()),
-                "end_time": humanize_timestamp_string(o.end_time()),
+                "end_time": humanize_timestamp_string(o.end_time())
             };
 
             if (o.current_resource())
@@ -442,7 +477,7 @@
     }
 }
 
-function cancel_reservations(bresv_id_list) {
+function cancel_reservations(bresv_id_list, skip_update) {
     try {
         var result = fieldmapper.standardRequest(
             ["open-ils.booking", "open-ils.booking.reservations.cancel"],
@@ -452,21 +487,17 @@
         alert(localeStrings.CXL_BRESV_FAILURE2 + E);
         return;
     }
-    setTimeout(update_bresv_grid, 0);
+    if (!skip_update) setTimeout(update_bresv_grid, 0);
     if (!result) {
         alert(localeStrings.CXL_BRESV_FAILURE);
     } else if (is_ils_event(result)) {
         alert(my_ils_error(localeStrings.CXL_BRESV_FAILURE2, result));
     } else {
-        if (result.length == 1) {
-            alert(dojo.string.substitute(
+        alert(
+            dojo.string.substitute(
                 localeStrings.CXL_BRESV_SUCCESS, [result.length]
-            ));
-        } else {
-            alert(dojo.string.substitute(
-                localeStrings.CXL_BRESV_SUCCESS_PLURAL, [result.length]
-            ));
-        }
+            )
+        );
     }
 }
 
@@ -705,7 +736,7 @@
                     timePattern: "HH:mm",
                     clickableIncrement: "T00:15:00",
                     visibleIncrement: "T00:15:00",
-                    visibleRange: "T01:30:00",
+                    visibleRange: "T01:30:00"
                 },
                 onChange: function() {
                     reserve_timestamp_range.update_from_widget(this);
@@ -736,7 +767,7 @@
         /* After some delay to allow the cancellations a chance to get
          * committed, refresh the brsrc list as it might reflect newly
          * available resources now. */
-        setTimeout(update_brsrc_list, 2000);
+        if (our_brt) setTimeout(update_brsrc_list, 2000);
     } else {
         alert(localeStrings.CXL_BRESV_SELECT_SOMETHING);
     }
@@ -770,6 +801,24 @@
     return true;
 }
 
+function init_aous_cache() {
+    /* The following method call could be given a longer
+     * list of OU settings to fetch in the future if needed. */
+    var results = fieldmapper.aou.fetchOrgSettingBatch(
+        openils.User.user.ws_ou(), ["booking.require_successful_targeting"]
+    );
+    if (results && !is_ils_event(results)) {
+        for (var k in results) {
+            if (results[k] != undefined)
+                aous_cache[k] = results[k].value;
+        }
+    } else if (results) {
+        alert(my_ils_error(localeStrings.ERROR_FETCHING_AOUS, results));
+    } else {
+        alert(localeStrings.ERROR_FETCHING_AOUS);
+    }
+}
+
 /*
  * my_init
  */
@@ -778,6 +827,7 @@
     reveal_dom_element(document.getElementById("brt_search_block"));
     hide_dom_element(document.getElementById("reserve_under"));
     init_auto_l10n(document.getElementById("auto_l10n_start_here"));
+    init_aous_cache();
     init_timestamp_widgets();
 
     if (!(opts = xulG.bresv_interface_opts)) opts = {};

Modified: trunk/Open-ILS/web/templates/default/booking/capture.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/booking/capture.tt2	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/templates/default/booking/capture.tt2	2010-06-29 17:53:39 UTC (rev 16827)
@@ -1,7 +1,7 @@
 [% WRAPPER "default/base.tt2" %]
 <script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
 <script src="[% ctx.media_prefix %]/js/ui/default/booking/capture.js"></script>
-<link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" />
+<link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" id="booking_stylesheet_link" />
 <script type="text/javascript">openils.Util.addOnLoad(my_init);</script>
 <div id="auto_l10n_start_here">
 <!-- XXX This interface will probably go away soon in favor of merging its
@@ -15,7 +15,7 @@
             onclick="attempt_capture();" />
         <span id="result_display"></span>
     </form>
-    <div class="nice_vertical_padding" id="capture_display">
-    </div>
+    <div class="nice_vertical_padding" id="capture_info_top"></div>
+    <div class="nice_vertical_padding" id="capture_info_bottom"></div>
 </div>
 [% END %]

Modified: trunk/Open-ILS/web/templates/default/booking/pull_list.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/booking/pull_list.tt2	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/templates/default/booking/pull_list.tt2	2010-06-29 17:53:39 UTC (rev 16827)
@@ -28,12 +28,11 @@
         <table id="the_table" width="100%">
             <thead>
                 <tr>
-                    <th width="30%" class="AUTO_th_title_or_name"></th>
+                    <th width="25%" class="AUTO_th_title_or_name"></th>
                     <th width="10%" class="AUTO_th_barcode"></th>
-                    <th width="10%" class="AUTO_th_call_number"></th>
+                    <th width="15%" class="AUTO_th_call_number"></th>
                     <th width="10%" class="AUTO_th_copy_location"></th>
-                    <th width="10%" class="AUTO_th_copy_number"></th>
-                    <th width="30%" class="AUTO_th_resv_details"></th>
+                    <th width="40%" class="AUTO_th_resv_details"></th>
                 </tr>
             </thead>
             <tbody id="the_table_body">

Modified: trunk/Open-ILS/web/templates/default/conify/global/booking/resource.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/conify/global/booking/resource.tt2	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/templates/default/conify/global/booking/resource.tt2	2010-06-29 17:53:39 UTC (rev 16827)
@@ -1,43 +1,34 @@
 [% WRAPPER default/base.tt2 %]
 [% ctx.page_title = 'Resources' %]
-
-<script src="/opac/common/js/CGI.js" type="text/javascript"></script>
 <script type ="text/javascript">
     dojo.require('dijit.form.FilteringSelect');
     dojo.require('openils.widget.AutoGrid');
-    dojo.require('openils.XUL');
 
     openils.Util.addOnLoad(
         function() {
-            var search = undefined; // default to all objs
-            if (xulG && xulG.resultant_brsrc) {
+            var search = {"id": {"!=": null}};
+            if (xulG && xulG.resultant_brsrc)
                 search = {id: xulG.resultant_brsrc};
-            }
-            ustGrid.loadAll({order_by:{brsrc : 'barcode'}}, search);
+            brsrcGrid.loadAll({order_by:{brsrc : 'barcode'}}, search);
         }
     );
 </script>
-
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
-    <div>Resources</div>
-    <div>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.showCreateDialog()'>New Resource</button>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.deleteSelected()'>Delete Selected</button>
-    </div>
-</div>
-
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <table  jsId="ustGrid"
-            autoHeight='true'
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Resources</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='brsrcGrid.showCreateDialog()'>New Resource</button>
+            <button dojoType='dijit.form.Button' onClick='brsrcGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <table  jsId="brsrcGrid"
             dojoType="openils.widget.AutoGrid"
             fieldOrder="['owner', 'type', 'barcode',
                 'overbook', 'deposit', 'deposit_amount', 'user_fee']"
-            query="{name: '*'}"
-            defaultCellWidth='"auto"'
+            query="{id: '*'}"
             fmClass='brsrc'
             showPaginator='true'
             editOnEnter='true'>
     </table>
- </div>
-
+</div>
 [% END %]

Modified: trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr.tt2	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr.tt2	2010-06-29 17:53:39 UTC (rev 16827)
@@ -1,39 +1,31 @@
 [% WRAPPER default/base.tt2 %]
 [% ctx.page_title = 'Resource Attributes' %]
-
 <script type ="text/javascript">
     dojo.require('dijit.form.FilteringSelect');
     dojo.require('openils.widget.AutoGrid');
 
     openils.Util.addOnLoad(
         function() {
-            ustGrid.loadAll({order_by:{bra : 'name'}});
+            braGrid.loadAll({order_by:{bra : 'name'}}, {"id": {"!=": null}});
         }
     );
 </script>
-
-
-
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
-    <div>Resource Attributes</div>
-    <div>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.showCreateDialog()'>New Resource Attribute</button>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.deleteSelected()'>Delete Selected</button>
-    </div>
-</div>
-
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <table  jsId="ustGrid"
-            autoHeight='true'
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Resource Attributes</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='braGrid.showCreateDialog()'>New Resource Attribute</button>
+            <button dojoType='dijit.form.Button' onClick='braGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <table  jsId="braGrid"
             dojoType="openils.widget.AutoGrid"
-            fieldOrder="['name', 'fine_interval', 'fine_amount',
-                'owner', 'catalog_item', 'transferable', 'record']"
-            query="{name: '*'}"
-            defaultCellWidth='"auto"'
+            fieldOrder="['name', 'owner', 'resource_type', 'required']"
+            query="{id: '*'}"
             fmClass='bra'
             showPaginator='true'
             editOnEnter='true'>
     </table>
- </div>
+</div>
 
 [% END %]

Modified: trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_map.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_map.tt2	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_map.tt2	2010-06-29 17:53:39 UTC (rev 16827)
@@ -1,39 +1,28 @@
 [% WRAPPER default/base.tt2 %]
 [% ctx.page_title = 'Resource Attribute Maps' %]
-
 <script type ="text/javascript">
     dojo.require('dijit.form.FilteringSelect');
     dojo.require('openils.widget.AutoGrid');
 
     openils.Util.addOnLoad(
-        function() {
-            ustGrid.loadAll({order_by:{bram : 'name'}});
-        }
+        function() { bramGrid.loadAll({order_by:{bram : 'resource_attr'}}); }
     );
 </script>
-
-
-
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
-    <div>Resource Attribute Maps</div>
-    <div>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.showCreateDialog()'>New Resource Attribute Map</button>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.deleteSelected()'>Delete Selected</button>
-    </div>
-</div>
-
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <table  jsId="ustGrid"
-            autoHeight='true'
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Resource Attribute Maps</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='bramGrid.showCreateDialog()'>New Resource Attribute Map</button>
+            <button dojoType='dijit.form.Button' onClick='bramGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <table  jsId="bramGrid"
             dojoType="openils.widget.AutoGrid"
-            fieldOrder="['name', 'fine_interval', 'fine_amount',
-                'owner', 'catalog_item', 'transferable', 'record']"
-            query="{name: '*'}"
-            defaultCellWidth='"auto"'
+            fieldOrder="['resource', 'resource_attr', 'value']"
+            query="{id: '*'}"
             fmClass='bram'
             showPaginator='true'
             editOnEnter='true'>
     </table>
- </div>
-
+</div>
 [% END %]

Modified: trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_value.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_value.tt2	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/templates/default/conify/global/booking/resource_attr_value.tt2	2010-06-29 17:53:39 UTC (rev 16827)
@@ -1,39 +1,30 @@
 [% WRAPPER default/base.tt2 %]
 [% ctx.page_title = 'Resource Attribute Values' %]
-
 <script type ="text/javascript">
     dojo.require('dijit.form.FilteringSelect');
     dojo.require('openils.widget.AutoGrid');
 
     openils.Util.addOnLoad(
         function() {
-            ustGrid.loadAll({order_by:{brav : 'name'}});
+            bravGrid.loadAll({order_by:{brav : 'attr'}}, {"id": {"!=": null}});
         }
     );
 </script>
-
-
-
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
-    <div>Resource Attribute Values</div>
-    <div>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.showCreateDialog()'>New Resource Attribute Value</button>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.deleteSelected()'>Delete Selected</button>
-    </div>
-</div>
-
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <table  jsId="ustGrid"
-            autoHeight='true'
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Resource Attribute Values</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='bravGrid.showCreateDialog()'>New Resource Attribute Value</button>
+            <button dojoType='dijit.form.Button' onClick='bravGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <table  jsId="bravGrid"
             dojoType="openils.widget.AutoGrid"
-            fieldOrder="['name', 'fine_interval', 'fine_amount',
-                'owner', 'catalog_item', 'transferable', 'record']"
-            query="{name: '*'}"
-            defaultCellWidth='"auto"'
+            fieldOrder="['owner', 'attr', 'valid_value']"
+            query="{id: '*'}"
             fmClass='brav'
             showPaginator='true'
             editOnEnter='true'>
     </table>
- </div>
-
+</div>
 [% END %]

Modified: trunk/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2	2010-06-28 21:35:59 UTC (rev 16826)
+++ trunk/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2	2010-06-29 17:53:39 UTC (rev 16827)
@@ -1,39 +1,32 @@
 [% WRAPPER default/base.tt2 %]
 [% ctx.page_title = 'Resource Types' %]
-
 <script type ="text/javascript">
     dojo.require('dijit.form.FilteringSelect');
     dojo.require('openils.widget.AutoGrid');
 
     openils.Util.addOnLoad(
         function() {
-            ustGrid.loadAll({order_by:{brt : 'name'}});
+            brtGrid.loadAll({"order_by": {"brt": "name"}}, {"id": {"!=": null}});
         }
     );
 </script>
-
-
-
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
-    <div>Resource Types</div>
-    <div>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.showCreateDialog()'>New Resource Type</button>
-        <button dojoType='dijit.form.Button' onClick='ustGrid.deleteSelected()'>Delete Selected</button>
-    </div>
-</div>
-
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <table  jsId="ustGrid"
-            autoHeight='true'
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Resource Types</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='brtGrid.showCreateDialog()'>New Resource Type</button>
+            <button dojoType='dijit.form.Button' onClick='brtGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <table  jsId="brtGrid"
             dojoType="openils.widget.AutoGrid"
             fieldOrder="['name', 'fine_interval', 'fine_amount',
-                'owner', 'catalog_item', 'transferable', 'record']"
-            query="{name: '*'}"
-            defaultCellWidth='"auto"'
+                'owner', 'catalog_item', 'transferable']"
+            suppressFields="['record']"
+            query="{id: '*'}"
             fmClass='brt'
             showPaginator='true'
             editOnEnter='true'>
     </table>
- </div>
-
+</div>
 [% END %]



More information about the open-ils-commits mailing list