From c7727d4966d63a14419c2a8e9df5cabf11f76ee3 Mon Sep 17 00:00:00 2001 From: Jeff Davis <jdavis@sitka.bclibraries.ca> Date: Wed, 7 Feb 2018 15:11:18 -0800 Subject: [PATCH] LP#1715767: Allow others to use my account (privacy waiver) Use case: Jane Doe has a hold ready for pickup but is unable to come into the library. Her husband John Doe goes to the library to pick up the hold on her behalf. His name is listed on Jane's account, so library staff know it's okay to check out the book on Jane's account and give it to John. This commit adds a new table which lists the names of people who are allowed to place holds, pick up holds, check out items, or view borrowing history for a user account. Staff can add, edit, or remove entries via the patron editor in the web client; patrons can do so in My Account. The entries are not linked to other user accounts and they do not add any extra functionality. They are essentially special patron notes for circulation staff. Signed-off-by: Jeff Davis <jdavis@sitka.bclibraries.ca> Signed-off-by: Chris Sharp <csharp@georgialibraries.org> --- Open-ILS/examples/fm_IDL.xml | 32 +++++++ .../src/perlmods/lib/OpenILS/Application/Actor.pm | 104 +++++++++++++++++++++ .../lib/OpenILS/WWW/EGCatLoader/Account.pm | 51 +++++++++- Open-ILS/src/sql/Pg/005.schema.actors.sql | 10 ++ Open-ILS/src/sql/Pg/950.data.seed-values.sql | 15 +++ .../sql/Pg/upgrade/XXXX.data.privacy_waiver.sql | 21 +++++ .../upgrade/XXXX.schema.actor.privacy_waiver.sql | 17 ++++ .../src/templates/opac/myopac/prefs_settings.tt2 | 44 ++++++++- .../src/templates/staff/circ/patron/t_edit.tt2 | 49 ++++++++++ .../src/templates/staff/circ/patron/t_summary.tt2 | 14 +++ .../web/js/ui/default/staff/circ/patron/regctl.js | 43 +++++++++ Open-ILS/web/js/ui/default/staff/services/user.js | 1 + .../Circulation/privacy_waiver.adoc | 15 +++ 13 files changed, 413 insertions(+), 3 deletions(-) create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.data.privacy_waiver.sql create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.schema.actor.privacy_waiver.sql create mode 100644 docs/RELEASE_NOTES_NEXT/Circulation/privacy_waiver.adoc diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index c66eaad4e5..b8d0efff60 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -2320,6 +2320,36 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA </actions> </permacrud> </class> + <class id="aupw" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::usr_privacy_waiver" oils_persist:tablename="actor.usr_privacy_waiver" reporter:label="Privacy Waiver"> + <fields oils_persist:primary="id" oils_persist:sequence="actor.usr_privacy_waiver_id_seq"> + <field reporter:label="ID" name="id" reporter:datatype="id" /> + <field reporter:label="User" name="usr" reporter:datatype="link" /> + <field reporter:label="Name" name="name" reporter:datatype="text"/> + <field reporter:label="Place Holds?" name="place_holds" reporter:datatype="bool" /> + <field reporter:label="Pick Up Holds?" name="pickup_holds" reporter:datatype="bool" /> + <field reporter:label="View Borrowing History?" name="view_history" reporter:datatype="bool" /> + <field reporter:label="Check Out Items?" name="checkout_items" reporter:datatype="bool" /> + </fields> + <links> + <link field="usr" reltype="has_a" key="id" map="" class="au"/> + </links> + <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1"> + <actions> + <create permission="UPDATE_USER"> + <context link="usr" field="home_ou"/> + </create> + <retrieve permission="VIEW_USER"> + <context link="usr" field="home_ou"/> + </retrieve> + <update permission="UPDATE_USER"> + <context link="usr" field="home_ou"/> + </update> + <delete permission="UPDATE_USER"> + <context link="usr" field="home_ou"/> + </delete> + </actions> + </permacrud> + </class> <class id="aupr" controller="open-ils.cstore" oils_obj:fieldmapper="actor::usr_password_reset" oils_persist:tablename="actor.usr_password_reset" reporter:label="User password reset requests"> <fields oils_persist:primary="id" oils_persist:sequence="actor.usr_password_reset_id_seq"> <field reporter:label="Request ID" name="id" reporter:datatype="id"/> @@ -3601,6 +3631,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA <field reporter:label="Standing Penalties" name="standing_penalties" oils_persist:virtual="true" reporter:datatype="link"/> <field reporter:label="Statistical Category Entries" name="stat_cat_entries" oils_persist:virtual="true" reporter:datatype="link"/> <field reporter:label="Survey Responses" name="survey_responses" oils_persist:virtual="true" reporter:datatype="link"/> + <field reporter:label="Privacy Waiver Entries" name = "waiver_entries" oils_persist:virtual="true" reporter:datatype="link"/> <field reporter:label="Workstation Org Unit" name="ws_ou" oils_persist:virtual="true" reporter:datatype="link"/> <field reporter:label="Workstation ID" name="wsid" oils_persist:virtual="true" reporter:datatype="link"/> <field reporter:label="Active" name="active" reporter:datatype="bool"/> @@ -3676,6 +3707,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA <link field="card" reltype="has_a" key="id" map="" class="ac"/> <link field="ident_type2" reltype="has_a" key="id" map="" class="cit"/> <link field="stat_cat_entries" reltype="has_many" key="target_usr" map="" class="actscecm"/> + <link field="waiver_entries" reltype="has_many" key="usr" map="" class="aupw"/> <link field="groups" reltype="has_many" key="usr" map="grp" class="pugm"/> <link field="usrgroup" reltype="has_many" key="usrgroup" map="" class="au"/> <link field="checkouts" reltype="has_many" key="usr" map="" class="circ"/> diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm index c2b701a0c8..219f611b6b 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm @@ -115,6 +115,78 @@ sub update_user_setting { __PACKAGE__->register_method( + method => "update_privacy_waiver", + api_name => "open-ils.actor.patron.privacy_waiver.update", + signature => { + desc => "Replaces any existing privacy waiver entries for the patron with the supplied values.", + params => [ + {desc => 'Authentication token', type => 'string'}, + {desc => 'User ID', type => 'number'}, + {desc => 'Arrayref of privacy waiver entries', type => 'object'} + ], + return => {desc => '1 on success, Event on error'} + } +); +sub update_privacy_waiver { + my($self, $conn, $auth, $user_id, $waiver) = @_; + my $e = new_editor(xact => 1, authtoken => $auth); + return $e->die_event unless $e->checkauth; + + $user_id = $e->requestor->id unless defined $user_id; + + unless($e->requestor->id == $user_id) { + my $user = $e->retrieve_actor_user($user_id) or return $e->die_event; + return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou); + } + + foreach my $w (@$waiver) { + $w->{usr} = $user_id unless $w->{usr}; + if ($w->{id} && $w->{id} ne 'new') { + my $existing_rows = $e->search_actor_usr_privacy_waiver({usr => $user_id, id => $w->{id}}); + if ($existing_rows) { + my $existing = $existing_rows->[0]; + # delete existing if name is empty + if (!$w->{name} or $w->{name} =~ /^\s*$/) { + $e->delete_actor_usr_privacy_waiver($existing) or return $e->die_event; + + # delete existing if none of the boxes were checked + } elsif (!$w->{place_holds} && !$w->{pickup_holds} && !$w->{checkout_items} && !$w->{view_history}) { + $e->delete_actor_usr_privacy_waiver($existing) or return $e->die_event; + + # otherwise, update existing waiver entry + } else { + $existing->name($w->{name}); + $existing->place_holds($w->{place_holds}); + $existing->pickup_holds($w->{pickup_holds}); + $existing->checkout_items($w->{checkout_items}); + $existing->view_history($w->{view_history}); + $e->update_actor_usr_privacy_waiver($existing) or return $e->die_event; + } + } else { + $logger->warn("No privacy waiver entry found for user $user_id with ID " . $w->{id}); + } + + } else { + # ignore new entries with empty name or with no boxes checked + next if (!$w->{name} or $w->{name} =~ /^\s*$/); + next if (!$w->{place_holds} && !$w->{pickup_holds} && !$w->{checkout_items} && !$w->{view_history}); + my $new = Fieldmapper::actor::usr_privacy_waiver->new; + $new->usr($w->{usr}); + $new->name($w->{name}); + $new->place_holds($w->{place_holds}); + $new->pickup_holds($w->{pickup_holds}); + $new->checkout_items($w->{checkout_items}); + $new->view_history($w->{view_history}); + $e->create_actor_usr_privacy_waiver($new) or return $e->die_event; + } + } + + $e->commit; + return 1; +} + + +__PACKAGE__->register_method( method => "set_ou_settings", api_name => "open-ils.actor.org_unit.settings.update", signature => { @@ -444,6 +516,9 @@ sub update_patron { ( $new_patron, $evt ) = _add_update_cards($e, $patron, $new_patron); return $evt if $evt; + ( $new_patron, $evt ) = _add_update_waiver_entries($e, $patron, $new_patron); + return $evt if $evt; + ( $new_patron, $evt ) = _add_survey_responses($e, $patron, $new_patron); return $evt if $evt; @@ -540,6 +615,7 @@ sub flesh_user { "billing_address", "mailing_address", "stat_cat_entries", + "waiver_entries", "settings", "usr_activity" ]; @@ -568,6 +644,7 @@ sub _clone_patron { $new_patron->clear_ischanged(); $new_patron->clear_isdeleted(); $new_patron->clear_stat_cat_entries(); + $new_patron->clear_waiver_entries(); $new_patron->clear_permissions(); $new_patron->clear_standing_penalties(); @@ -888,6 +965,32 @@ sub _update_card { } +sub _add_update_waiver_entries { + my $e = shift; + my $patron = shift; + my $new_patron = shift; + my $evt; + + my $waiver_entries = $patron->waiver_entries(); + for my $waiver (@$waiver_entries) { + next unless ref $waiver; + $waiver->usr($new_patron->id()); + if ($waiver->isnew()) { + next if (!$waiver->name() or $waiver->name() =~ /^\s*$/); + next if (!$waiver->place_holds() && !$waiver->pickup_holds() && !$waiver->checkout_items() && !$waiver->view_history()); + $logger->info("Adding new patron waiver entry"); + $waiver->clear_id(); + $e->create_actor_usr_privacy_waiver($waiver) or return (undef, $e->die_event); + } elsif ($waiver->ischanged()) { + $logger->info("Updating patron waiver entry " . $waiver->id); + $e->update_actor_usr_privacy_waiver($waiver) or return (undef, $e->die_event); + } elsif ($waiver->isdeleted()) { + $logger->info("Deleting patron waiver entry " . $waiver->id); + $e->delete_actor_usr_privacy_waiver($waiver) or return (undef, $e->die_event); + } + } + return ($new_patron, undef); +} # returns event on error. returns undef otherwise @@ -3007,6 +3110,7 @@ sub user_retrieve_fleshed_by_id { "billing_address", "mailing_address", "stat_cat_entries", + "waiver_entries", "usr_activity" ]; return new_flesh_user($user_id, $fields, $e); } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm index d78b59bf5f..19e8fbc538 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm @@ -34,7 +34,7 @@ sub prepare_extended_user_info { { flesh => 1, flesh_fields => { - au => [qw/card home_ou addresses ident_type billing_address/, @extra_flesh] + au => [qw/card home_ou addresses ident_type billing_address waiver_entries/, @extra_flesh] # ... } } @@ -603,6 +603,9 @@ sub load_myopac_prefs_settings { } } + my $use_privacy_waiver = $self->ctx->{get_org_setting}->( + $e->requestor->home_ou, 'circ.privacy_waiver'); + return Apache2::Const::OK unless $self->cgi->request_method eq 'POST'; @@ -699,8 +702,52 @@ sub load_myopac_prefs_settings { 'open-ils.actor.patron.settings.update', $self->editor->authtoken, undef, \%settings); - # re-fetch user prefs $self->ctx->{updated_user_settings} = \%settings; + + if ($use_privacy_waiver) { + my %waiver; + my $saved_entries = (); + my @waiver_types = qw/place_holds pickup_holds checkout_items view_history/; + + # initialize our waiver hash with waiver IDs from hidden input + # (this ensures that we capture entries with no checked boxes) + foreach my $waiver_row_id ($self->cgi->param("waiver_id")) { + $waiver{$waiver_row_id} = {}; + } + + # process our waiver checkboxes into a hash, keyed by waiver ID + # (a new entry, if any, has id = 'new') + foreach my $waiver_type (@waiver_types) { + if ($self->cgi->param("waiver_$waiver_type")) { + foreach my $waiver_id ($self->cgi->param("waiver_$waiver_type")) { + # ensure this waiver exists in our hash + $waiver{$waiver_id} = {} if !$waiver{$waiver_id}; + $waiver{$waiver_id}->{$waiver_type} = 1; + } + } + } + + foreach my $k (keys %waiver) { + my $w = $waiver{$k}; + # get name from textbox + $w->{name} = $self->cgi->param("waiver_name_$k"); + $w->{id} = $k; + foreach (@waiver_types) { + $w->{$_} = 0 unless ($w->{$_}); + } + push @$saved_entries, $w; + } + + # update patron privacy waiver entries + $U->simplereq( + 'open-ils.actor', + 'open-ils.actor.patron.privacy_waiver.update', + $self->editor->authtoken, undef, $saved_entries); + + $self->ctx->{updated_waiver_entries} = $saved_entries; + } + + # re-fetch user prefs return $self->_load_user_with_prefs || Apache2::Const::OK; } diff --git a/Open-ILS/src/sql/Pg/005.schema.actors.sql b/Open-ILS/src/sql/Pg/005.schema.actors.sql index c3879670b4..c97afd7974 100644 --- a/Open-ILS/src/sql/Pg/005.schema.actors.sql +++ b/Open-ILS/src/sql/Pg/005.schema.actors.sql @@ -1265,5 +1265,15 @@ BEGIN END; $FUNC$ LANGUAGE PLPGSQL; +CREATE TABLE actor.usr_privacy_waiver ( + id BIGSERIAL PRIMARY KEY, + usr BIGINT NOT NULL REFERENCES actor.usr(id) DEFERRABLE INITIALLY DEFERRED, + name TEXT NOT NULL, + place_holds BOOL DEFAULT FALSE, + pickup_holds BOOL DEFAULT FALSE, + view_history BOOL DEFAULT FALSE, + checkout_items BOOL DEFAULT FALSE +); +CREATE INDEX actor_usr_privacy_waiver_usr_idx ON actor.usr_privacy_waiver (usr); COMMIT; diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index 649ced5d83..1fe0bb6060 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -19495,3 +19495,18 @@ VALUES ( +INSERT INTO config.org_unit_setting_type + (name, label, description, grp, datatype) + VALUES ( + 'circ.privacy_waiver', + oils_i18n_gettext('circ.privacy_waiver', + 'Allow others to use patron account (privacy waiver)', + 'coust', 'label'), + oils_i18n_gettext('circ.privacy_waiver', + 'Add a note to a user account indicating that specified people are allowed to ' || + 'place holds, pick up holds, check out items, or view borrowing history for that user account', + 'coust', 'description'), + 'circ', + 'bool' + ); + diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.privacy_waiver.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.privacy_waiver.sql new file mode 100644 index 0000000000..ab8a6c2a13 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.privacy_waiver.sql @@ -0,0 +1,21 @@ +BEGIN; + +SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); + +INSERT INTO config.org_unit_setting_type + (name, label, description, grp, datatype) + VALUES ( + 'circ.privacy_waiver', + oils_i18n_gettext('circ.privacy_waiver', + 'Allow others to use patron account (privacy waiver)', + 'coust', 'label'), + oils_i18n_gettext('circ.privacy_waiver', + 'Add a note to a user account indicating that specified people are allowed to ' || + 'place holds, pick up holds, check out items, or view borrowing history for that user account', + 'coust', 'description'), + 'circ', + 'bool' + ); + +COMMIT; + diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.actor.privacy_waiver.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.actor.privacy_waiver.sql new file mode 100644 index 0000000000..6b2b7b8a78 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.actor.privacy_waiver.sql @@ -0,0 +1,17 @@ +BEGIN; + +INSERT INTO config.upgrade_log (version) VALUES ('XXXX'); + +CREATE TABLE actor.usr_privacy_waiver ( + id BIGSERIAL PRIMARY KEY, + usr BIGINT NOT NULL REFERENCES actor.usr(id) DEFERRABLE INITIALLY DEFERRED, + name TEXT NOT NULL, + place_holds BOOL DEFAULT FALSE, + pickup_holds BOOL DEFAULT FALSE, + view_history BOOL DEFAULT FALSE, + checkout_items BOOL DEFAULT FALSE +); +CREATE INDEX actor_usr_privacy_waiver_usr_idx ON actor.usr_privacy_waiver (usr); + +COMMIT; + diff --git a/Open-ILS/src/templates/opac/myopac/prefs_settings.tt2 b/Open-ILS/src/templates/opac/myopac/prefs_settings.tt2 index 415dcec51f..70f76a92f3 100644 --- a/Open-ILS/src/templates/opac/myopac/prefs_settings.tt2 +++ b/Open-ILS/src/templates/opac/myopac/prefs_settings.tt2 @@ -23,7 +23,7 @@ <input type='hidden' name='history_delete_confirmed' value='1'/> <input type="submit" value="[% l('Confirm') %]" class="opac-button"/> </td></tr> - [% ELSIF ctx.updated_user_settings %] + [% ELSIF ctx.updated_user_settings OR ctx.updated_waiver_entries %] <tr><td colspan='2'> <div class='renew-summary'> [% l('Account Successfully Updated') %] @@ -120,6 +120,48 @@ </tr> [% END %] + [%- IF ctx.get_org_setting(ctx.user.home_ou.id, 'circ.privacy_waiver'); %] + <tr> + <td>[% l('Allow others to use my account') %]</td> + <td> + [% FOR waiver IN ctx.user.waiver_entries %] + <div id="waiver_[% waiver.id %]"> + <input type="hidden" name="waiver_id" value="[% waiver.id %]"/> + [% l('Name:') %] <input type="textbox" name="waiver_name_[% waiver.id %]" value="[% waiver.name | html %]"/><br/> + <label> + <input type="checkbox" name="waiver_place_holds" + value="[% waiver.id %]" [% waiver.place_holds == 't' ? 'checked="checked"' : '' %]/> + [% l('Place Holds') %] + </label> + <label> + <input type="checkbox" name="waiver_pickup_holds" + value="[% waiver.id %]" [% waiver.pickup_holds == 't' ? 'checked="checked"' : '' %]/> + [% l('Pick Up Holds') %] + </label> + <label> + <input type="checkbox" name="waiver_checkout_items" + value="[% waiver.id %]" [% waiver.checkout_items == 't' ? 'checked="checked"' : '' %]/> + [% l('Check Out Items') %] + </label> + <label> + <input type="checkbox" name="waiver_view_history" + value="[% waiver.id %]" [% waiver.view_history == 't' ? 'checked="checked"' : '' %]/> + [% l('View Borrowing History') %] + </label> + </div> + [% END %] + <br/> + <div> + [% l('Name:') %] <input type="textbox" name="waiver_name_new"/><br/> + <label><input type="checkbox" name="waiver_place_holds" value="new"/>[% l('Place Holds') %]</label> + <label><input type="checkbox" name="waiver_pickup_holds" value="new"/>[% l('Pick Up Holds') %]</label> + <label><input type="checkbox" name="waiver_checkout_items" value="new"/>[% l('Check Out Items') %]</label> + <label><input type="checkbox" name="waiver_view_history" value="new"/>[% l('View Borrowing History') %]</label> + </div> + </td> + </tr> + [% END %] + <!-- <tr> <td><label for='prefs_def_font'>[% l("Default Font Size") %]</label></td> diff --git a/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 index 05e0d94947..f61f5eea07 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 @@ -803,6 +803,55 @@ within the "form" by name for validation. </div> </div> +<div class="row reg-field-row" ng-if="org_settings['circ.privacy_waiver']"> + <div class="col-md-3 reg-field-label"> + <label>[% l('Allow others to use my account') %]</label> + </div> + <div class="col-md-3 reg-field-input"> + <div class="row" ng-repeat="waiver_entry in patron.waiver_entries" ng-hide="waiver_entry.isdeleted"> + <div class="row flex-row"> + <div class="flex-cell"> + <input ng-change="field_modified()" + type='text' ng-model="waiver_entry.name"/> + </div> + <div class="flex-cell"> + <button type="button" + ng-click="field_modified();delete_waiver_entry(waiver_entry)" + class="btn btn-danger">[% l('X') %]</button> + </div> + </div> + <div class="row flex-row reg-field-input"> + <div class="flex-cell"> + <label><input ng-change="field_modified()" + type='checkbox' ng-model="waiver_entry.place_holds"/> + [% l('Place Holds?') %]</label> + </div> + <div class="flex-cell"> + <label><input ng-change="field_modified()" + type='checkbox' ng-model="waiver_entry.pickup_holds"/> + [% l('Pick Up Holds?') %]</label> + </div> + <div class="flex-cell"> + <label><input ng-change="field_modified()" + type='checkbox' ng-model="waiver_entry.view_history"/> + [% l('View Borrowing History?') %]</label> + </div> + <div class="flex-cell"> + <label><input ng-change="field_modified()" + type='checkbox' ng-model="waiver_entry.checkout_items"/> + [% l('Check Out Items?') %]</label> + </div> + </div> <!-- end checkboxes --> + </div> <!-- end ng-repeat waiver_entry --> + <div class="row"> + <div class="col-md-3 reg-field-input"> + <button type="button" ng-click="new_waiver_entry()" + class="btn btn-success">[% l('Add Person') %]</button> + </div> + </div> + </div> <!-- end waiver entries input --> +</div> <!-- end waiver entries row --> + </div> <!-- end offline test --> <!-- addresses --> diff --git a/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 index 11cf06a2b3..7963ca0bb0 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 @@ -177,6 +177,20 @@ <div class="col-md-5">[% l('Name Keywords') %]</div> <div class="col-md-7">{{patron().name_keywords()}}</div> </div> + <div class="row patron-summary-divider" ng-if="patron().waiver_entries().length > 0"> + [% l('Allow others to use my account') %] + </div> + <div class="row" ng-repeat="waiver in patron().waiver_entries()"> + <div class="col-md-5">{{waiver.name()}}</div> + <div class="col-md-7"> + <ul> + <li ng-show="waiver.place_holds() == 't'">[% l('Place holds') %]</li> + <li ng-show="waiver.pickup_holds() == 't'">[% l('Pick up holds') %]</li> + <li ng-show="waiver.view_history() == 't'">[% l('View borrowing history') %]</li> + <li ng-show="waiver.checkout_items() == 't'">[% l('Check out items') %]</li> + </ul> + </div> + </div> </div> <div class="row" ng-repeat="addr in patron().addresses()"> diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js b/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js index 4e2e9a2586..e33933acb3 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js @@ -334,6 +334,7 @@ angular.module('egCoreMod') 'ui.patron.registration.require_address', 'circ.holds.behind_desk_pickup_supported', 'circ.patron_edit.clone.copy_address', + 'circ.privacy_waiver', 'ui.patron.edit.au.prefix.require', 'ui.patron.edit.au.prefix.show', 'ui.patron.edit.au.prefix.suggest', @@ -726,6 +727,13 @@ angular.module('egCoreMod') addr.pending = addr.pending === 't'; } + service.ingest_waiver_entry = function(patron, waiver_entry) { + waiver_entry.place_holds = waiver_entry.place_holds == 't'; + waiver_entry.pickup_holds = waiver_entry.pickup_holds == 't'; + waiver_entry.view_history = waiver_entry.view_history == 't'; + waiver_entry.checkout_items = waiver_entry.checkout_items == 't'; + } + /* * Existing patron objects reqire some data munging before insertion * into the scope. @@ -773,6 +781,9 @@ angular.module('egCoreMod') } }); + angular.forEach(patron.waiver_entries, + function(waiver_entry) { service.ingest_waiver_entry(patron, waiver_entry) }); + service.get_linked_addr_users(patron.addresses); // Remove stat cat entries that link to out-of-scope stat @@ -824,6 +835,7 @@ angular.module('egCoreMod') cards : [card], home_ou : egCore.org.get(egCore.auth.user().ws_ou()), stat_cat_entries : [], + waiver_entries : [], groups : [], addresses : [addr] }; @@ -1137,6 +1149,15 @@ angular.module('egCoreMod') patron.stat_cat_entries().push(newmap); }); + var waiver_hashes = patron.waiver_entries(); + patron.waiver_entries([]); + angular.forEach(waiver_hashes, function(waiver_hash) { + if (!waiver_hash.isnew && !waiver_hash.isdeleted) + waiver_hash.ischanged = true; + var waiver_entry = egCore.idl.fromHash('aupw', waiver_hash); + patron.waiver_entries().push(waiver_entry); + }); + if (!patron.isnew()) patron.ischanged(true); return egCore.net.request( @@ -1634,6 +1655,24 @@ function($scope , $routeParams , $q , $uibModal , $window , egCore , }); } + $scope.new_waiver_entry = function() { + var waiver = egCore.idl.toHash(new egCore.idl.aupw()); + patronRegSvc.ingest_waiver_entry($scope.patron, waiver); + waiver.id = patronRegSvc.virt_id--; + waiver.isnew = true; + $scope.patron.waiver_entries.push(waiver); + } + + deleted_waiver_entries = []; + $scope.delete_waiver_entry = function(waiver_entry) { + if (waiver_entry.id > 0) { + waiver_entry.isdeleted = true; + deleted_waiver_entries.push(waiver_entry); + } + var index = $scope.patron.waiver_entries.indexOf(waiver_entry); + $scope.patron.waiver_entries.splice(index, 1); + } + $scope.replace_card = function() { $scope.patron.card.active = false; $scope.patron.card.ischanged = true; @@ -2059,6 +2098,10 @@ function($scope , $routeParams , $q , $uibModal , $window , egCore , $scope.patron.addresses = $scope.patron.addresses.concat(deleted_addresses); + // ditto for waiver entries + $scope.patron.waiver_entries = + $scope.patron.waiver_entries.concat(deleted_waiver_entries); + compress_hold_notify(); var updated_user; diff --git a/Open-ILS/web/js/ui/default/staff/services/user.js b/Open-ILS/web/js/ui/default/staff/services/user.js index ccd1d0ab71..80b2838eea 100644 --- a/Open-ILS/web/js/ui/default/staff/services/user.js +++ b/Open-ILS/web/js/ui/default/staff/services/user.js @@ -17,6 +17,7 @@ function($q, $timeout, egNet, egAuth, egOrg) { 'billing_address', 'mailing_address', 'stat_cat_entries', + 'waiver_entries', 'usr_activity', 'notes' ] diff --git a/docs/RELEASE_NOTES_NEXT/Circulation/privacy_waiver.adoc b/docs/RELEASE_NOTES_NEXT/Circulation/privacy_waiver.adoc new file mode 100644 index 0000000000..d59f6527cd --- /dev/null +++ b/docs/RELEASE_NOTES_NEXT/Circulation/privacy_waiver.adoc @@ -0,0 +1,15 @@ +Allow Others to Use My Account (Privacy Waiver) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Patrons who wish to authorize other people to use their account may +now do so via My Account. In the Search and History Preferences tab +under Account Preferences, a new section labeled "Allow others to use +my account" allows patrons to enter a name and indicate that the +specified person is allowed to place holds, pickup holds, view +borrowing history, or check out items on their account. This +information is displayed to circulation staff in the patron account +summary in the web client. (Staff may also add, edit, and remove +entries via the patron editor.) + +A new library setting, "Allow others to use patron account (privacy +waiver)," is used to enable or disable this feature. + -- 2.11.0