From c10285b57c5b260cdee52633df55542d20b0ebda 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 --- .../perlmods/lib/OpenILS/Application/Circ/Holds.pm | 24 ++++++- .../src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm | 1 + .../perlmods/lib/OpenILS/WWW/EGCatLoader/Record.pm | 12 +++- .../perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm | 79 ++++++++++++++++++++++ Open-ILS/src/templates/opac/parts/misc_util.tt2 | 9 +++ Open-ILS/src/templates/opac/parts/org_selector.tt2 | 10 ++- .../templates/opac/parts/record/copy_counts.tt2 | 4 +- .../src/templates/opac/parts/record/summary.tt2 | 16 ++++- .../templates/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 be54c6821a..187d872330 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm @@ -3863,6 +3863,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'} } @@ -3883,8 +3888,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 => { @@ -3978,6 +3983,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 5d536dd2d2..c8408b3cd1 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 4497c33d8d..6f1c5190c9 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 660b20ef87..525eebceba 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm @@ -594,4 +594,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 c188e97f57..2695cce58b 100644 --- a/Open-ILS/src/templates/opac/parts/misc_util.tt2 +++ b/Open-ILS/src/templates/opac/parts/misc_util.tt2 @@ -165,6 +165,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 @@ -229,6 +231,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); + %]