From 0e4d2442b88986702a49217fa3fbfaa6b916c5df Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Fri, 21 Sep 2012 13:58:46 -0400 Subject: [PATCH] TPAC Org unit hiding Adds support for the opac.org_unit_hiding.depth org unit setting to TPAC, which makes out-of-scope org units disappear (except when explicitly requested). Ui changes: All search org unit selectors Holds pickup lib selector Copy summary in search results page Copy list in search results page Copy summary in record detail page (which controls the copy grid). Hold summary in record detail Org unit hiding is based on the physical_loc (Physical Location) param / cookie, which is the closest analog to 'ol' (original location), from which it was based in the JSPAC. Signed-off-by: Bill Erickson Signed-off-by: Mike Rylander --- .../lib/OpenILS/Application/Circ/Holds.pm | 24 +++++- .../perlmods/lib/OpenILS/WWW/EGCatLoader.pm | 1 + .../lib/OpenILS/WWW/EGCatLoader/Record.pm | 12 ++- .../lib/OpenILS/WWW/EGCatLoader/Util.pm | 79 +++++++++++++++++++ .../src/templates/opac/parts/misc_util.tt2 | 9 +++ .../src/templates/opac/parts/org_selector.tt2 | 10 ++- .../opac/parts/record/copy_counts.tt2 | 4 +- .../templates/opac/parts/record/summary.tt2 | 16 +++- .../opac/parts/result/copy_counts.tt2 | 13 ++- docs/RELEASE_NOTES_NEXT/tpac-ou-hiding.txt | 20 +++++ 10 files changed, 177 insertions(+), 11 deletions(-) create mode 100644 docs/RELEASE_NOTES_NEXT/tpac-ou-hiding.txt diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm index 820e7c6ccc..40cf63e5a6 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm @@ -3922,6 +3922,11 @@ __PACKAGE__->register_method( selected bib record or its associated copies and call_numbers/, params => [ { desc => 'Bib ID', type => 'number' }, + { desc => q/Optional arguments. Supported arguments include: + "pickup_lib_descendant" -> limit holds to those whose pickup + library is equal to or is a child of the provided org unit/, + type => 'object' + } ], return => {desc => 'Hold count', type => 'number'} } @@ -3942,8 +3947,8 @@ __PACKAGE__->register_method( # XXX Need to add type I (and, soon, type P) holds to these counts sub rec_hold_count { - my($self, $conn, $target_id) = @_; - + my($self, $conn, $target_id, $args) = @_; + $args ||= {}; my $mmr_join = { mmrsm => { @@ -4037,6 +4042,21 @@ sub rec_hold_count { } + if (my $pld = $args->{pickup_lib_descendant}) { + $query->{where}->{'+ahr'}->{pickup_lib} = { + in => { + select => {aou => [{ + column => 'id', + transform => 'actor.org_unit_descendants', + result_field => 'id' + }]}, + from => 'aou', + where => {id => $pld} + } + }; + } + + return new_editor()->json_query($query)->[0]->{count}; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm index ad222e5a93..0838a29eb5 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm @@ -288,6 +288,7 @@ sub load_common { $self->load_copy_location_groups; $self->staff_saved_searches_set_expansion_state if $ctx->{is_staff}; $self->load_search_filter_groups($ctx->{search_ou}); + $self->load_org_util_funcs; return Apache2::Const::OK; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm index a4af2c657f..026d7925a6 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm @@ -378,13 +378,23 @@ sub prepare_browse_call_numbers { sub get_hold_copy_summary { my ($self, $rec_id, $org) = @_; + my $ctx = $self->ctx; my $search = OpenSRF::AppSession->create('open-ils.search'); my $req1 = $search->request( 'open-ils.search.biblio.record.copy_count', $org, $rec_id); + # if org unit hiding applies, limit the hold count to holds + # whose pickup library is within our depth-scoped tree + my $count_args = {}; + while ($org and $ctx->{org_within_hiding_scope}->($org)) { + $count_args->{pickup_lib_descendant} = $org; + $org = $ctx->{get_aou}->($org)->parent_ou; + } + $self->ctx->{record_hold_count} = $U->simplereq( - 'open-ils.circ', 'open-ils.circ.bre.holds.count', $rec_id); + 'open-ils.circ', 'open-ils.circ.bre.holds.count', + $rec_id, $count_args); $self->ctx->{copy_summary} = $req1->recv->content; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm index 340f9f1786..ec8b6be850 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm @@ -595,4 +595,83 @@ sub check_for_temp_list_warning { return $warn; } +sub load_org_util_funcs { + my $self = shift; + my $ctx = $self->ctx; + + # evaluates to true if test_ou is within the same depth- + # scoped tree as ctx_ou. both ou's are org unit objects. + $ctx->{org_within_scope} = sub { + my ($ctx_ou, $test_ou, $depth) = @_; + + return 1 if $ctx_ou->id == $test_ou->id; + + if ($depth) { + + # find the top-most ctx-org ancestor at the provided depth + while ($depth < $ctx_ou->ou_type->depth + and $ctx_ou->id != $test_ou->id) { + $ctx_ou = $ctx->{get_aou}->($ctx_ou->parent_ou); + } + + # the preceeding loop may have landed on our org + return 1 if $ctx_ou->id == $test_ou->id; + + } else { + + return 1 if defined $depth; # $depth == 0; + } + + for my $child (@{$ctx_ou->children}) { + return 1 if $ctx->{org_within_scope}->($child, $test_ou); + } + + return 0; + }; + + # Returns true if the provided org unit is within the same + # org unit hiding depth-scoped tree as the physical location. + # Org unit hiding is based on the immutable physical_loc + # and is not meant to change as search/pref/etc libs change + $ctx->{org_within_hiding_scope} = sub { + my $org_id = shift; + my $ploc = $ctx->{physical_loc} or return 1; + + my $depth = $ctx->{get_org_setting}->( + $ploc, 'opac.org_unit_hiding.depth'); + + return 1 unless $depth; # 0 or undef + + return $ctx->{org_within_scope}->( + $ctx->{get_aou}->($ploc), + $ctx->{get_aou}->($org_id), $depth); + + }; + + # Evaluates to true if the context org (defaults to get_library) + # is not within the hiding scope. Also evaluates to true if the + # user's pref_ou is set and it's out of hiding scope. + # Always evaluates to true when ctx.is_staff + $ctx->{org_hiding_disabled} = sub { + my $ctx_org = shift || $ctx->{search_ou}; + + return 1 if $ctx->{is_staff}; + + # beware locg values formatted as org:loc + $ctx_org =~ s/:.*//g; + + return 1 if !$ctx->{org_within_hiding_scope}->($ctx_org); + + return 1 if $ctx->{pref_ou} and $ctx->{pref_ou} != $ctx_org + and !$ctx->{org_within_hiding_scope}->($ctx->{pref_ou}); + + return 0; + }; + +} + + + + + 1; diff --git a/Open-ILS/src/templates/opac/parts/misc_util.tt2 b/Open-ILS/src/templates/opac/parts/misc_util.tt2 index 9e2a054d9d..c871c89bff 100644 --- a/Open-ILS/src/templates/opac/parts/misc_util.tt2 +++ b/Open-ILS/src/templates/opac/parts/misc_util.tt2 @@ -276,6 +276,8 @@ ); END; + ou_hiding_disabled = ctx.org_hiding_disabled(); + FOR volume IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]'); # Check volume visibility - could push this into XPath @@ -340,6 +342,13 @@ status = copy.findnodes('./*[local-name()="status"]'); NEXT IF status.getAttribute('opac_visible') == 'false'; + UNLESS ou_hiding_disabled; + # extract the circ_lib id from the circ_lib node + circ_lib = copy.findnodes('./*[local-name()="circ_lib"]'); + circ_lib_id = circ_lib.getAttribute('id').replace('.*/', ''); + NEXT UNLESS ctx.org_within_hiding_scope(circ_lib_id); + END; + holding = { label => vol.label, part_label => part_label, diff --git a/Open-ILS/src/templates/opac/parts/org_selector.tt2 b/Open-ILS/src/templates/opac/parts/org_selector.tt2 index 159af59c9a..62b189894a 100644 --- a/Open-ILS/src/templates/opac/parts/org_selector.tt2 +++ b/Open-ILS/src/templates/opac/parts/org_selector.tt2 @@ -19,6 +19,11 @@ BLOCK build_org_selector; IF !value; value = loc_value; END; + + # if the selected org unit is out of hiding scope, + # disable the ou-hide scoping altogether. + hiding_disabled = ctx.org_hiding_disabled(value); + %]