LP1858213 A/T require email and stamp user id user/berick/lp1858213-at-stamp-user-and-email
authorBill Erickson <berickxx@gmail.com>
Fri, 3 Jan 2020 16:07:22 +0000 (11:07 -0500)
committerBill Erickson <berickxx@gmail.com>
Fri, 3 Jan 2020 22:31:08 +0000 (17:31 -0500)
Add require_usr_email flag to action_trigger.event_definition.  When set
and a usr_field is defined, only events for users with email addresses
will be created.

Adds a new column to action_trigger.event for tracking the related user
id.  At event collection time, if an event_definition has a usr_field,
the id value is added to the event.

Includes updates to set 'usr_field' values for existing event
definitions where possible and to set the require_usr_email flag for
SendEmail defs that have a usr_field.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Event.pm
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.at-usr-additions.sql [new file with mode: 0644]

index bb01086..5f22f50 100644 (file)
@@ -1451,6 +1451,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                        <field reporter:label="Environment Entries" name="env" oils_persist:virtual="true"  reporter:datatype="link"/>
                        <field reporter:label="Parameters" name="params" oils_persist:virtual="true"  reporter:datatype="link"/>
                        <field reporter:label="Retention Interval" name="retention_interval" reporter:datatype="interval"/>
+                       <field reporter:label="Require User Email" name="require_usr_email" reporter:datatype="bool"/>
                </fields>
                <links>
                        <link field="owner" reltype="has_a" key="id" map="" class="aou"/>
@@ -1489,12 +1490,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                        <field reporter:label="Error Output" name="error_output" reporter:datatype="text"/>
                        <field reporter:label="Asynchronous Output" name="async_output" reporter:datatype="link"/>
                        <field reporter:label="Update Process" name="update_process" reporter:datatype="int"/>
+                       <field reporter:label="User" name="usr" reporter:datatype="link"/>
                </fields>
                <links>
                        <link field="event_def" reltype="has_a" key="id" map="" class="atevdef"/>
                        <link field="template_output" reltype="has_a" key="id" map="" class="ateo"/>
                        <link field="error_output" reltype="has_a" key="id" map="" class="ateo"/>
                        <link field="async_output" reltype="has_a" key="id" map="" class="ateo"/>
+                       <link field="usr" reltype="has_a" key="id" map="" class="au"/>
                </links>
        </class>
 
index 9027beb..d7bc215 100644 (file)
@@ -25,6 +25,9 @@ my $log = 'OpenSRF::Utils::Logger';
 my $parallel_collect;
 my $parallel_react;
 
+# email-ish looking thing.  Mainly trying avoid null/empty emails.
+my $email_filter = {'~' => '.+@.+'};
+
 sub initialize {
 
     my $conf = OpenSRF::Utils::SettingsClient->new;
@@ -72,19 +75,32 @@ sub create_active_events_for_object {
     for my $def ( @$defs ) {
         next if ($granularity && $def->granularity ne $granularity );
 
-        if (!$self->{ignore_opt_in} && $def->usr_field && $def->opt_in_setting) {
+        if ($def->usr_field) {
             my $ufield = $def->usr_field;
             my $uid = $target->$ufield;
             $uid = $uid->id if (ref $uid); # fleshed user object, unflesh it
 
-            my $opt_in_setting = $editor->search_actor_user_setting(
-                { usr   => $uid,
-                  name  => $def->opt_in_setting,
-                  value => 'true'
-                }
-            );
+            if (!$self->{ignore_opt_in} && $def->opt_in_setting) {
+
+                my $opt_in_setting = $editor->search_actor_user_setting(
+                    { usr   => $uid,
+                      name  => $def->opt_in_setting,
+                      value => 'true'
+                    }
+                );
+
+                next unless (@$opt_in_setting);
+            }
+
+            if ($def->require_usr_email eq 't') {
 
-            next unless (@$opt_in_setting);
+                my $usr = $editor->search_actor_user({
+                    id => $uid,
+                    email => $email_filter
+                })->[0];
+
+                next unless $usr;
+            }
         }
 
         my $date = DateTime->now;
@@ -166,19 +182,32 @@ sub create_event_for_object_and_def {
 
     for my $def ( @$defs ) {
 
-        if ($def->usr_field && $def->opt_in_setting) {
+        if ($def->usr_field) {
             my $ufield = $def->usr_field;
             my $uid = $target->$ufield;
             $uid = $uid->id if (ref $uid); # fleshed user object, unflesh it
 
-            my $opt_in_setting = $editor->search_actor_user_setting(
-                { usr   => $uid,
-                  name  => $def->opt_in_setting,
-                  value => 'true'
-                }
-            );
+            if ($def->opt_in_setting) {
+
+                my $opt_in_setting = $editor->search_actor_user_setting(
+                    { usr   => $uid,
+                      name  => $def->opt_in_setting,
+                      value => 'true'
+                    }
+                );
+
+                next unless (@$opt_in_setting);
+            }
 
-            next unless (@$opt_in_setting);
+            if ($def->require_usr_email eq 't') {
+
+                my $usr = $editor->search_actor_user({
+                    id => $uid,
+                    email => $email_filter
+                })->[0];
+
+                next unless $usr;
+            }
         }
 
         my $date = DateTime->now;
@@ -486,17 +515,38 @@ sub create_batch_events {
 
         push @{ $filter->{'-and'} }, { '+atev' => { id => undef } };
 
-        if ($def->usr_field && $def->opt_in_setting) {
-            push @{ $filter->{'-and'} }, {
-                '-exists' => {
-                    from  => 'aus',
-                    where => {
-                        name => $def->opt_in_setting,
-                        usr  => { '=' => { '+' . $hook_hash{$def->hook}->core_type => $def->usr_field } },
-                        value=> 'true'
-                    }
+        if ($def->usr_field) {
+
+            my $usr_filter = {
+                '=' => {
+                    '+' . $hook_hash{$def->hook}->core_type => $def->usr_field 
                 }
             };
+
+            if ($def->opt_in_setting) {
+                push @{ $filter->{'-and'} }, {
+                    '-exists' => {
+                        from  => 'aus',
+                        where => {
+                            name => $def->opt_in_setting,
+                            usr  => $usr_filter,
+                            value=> 'true'
+                        }
+                    }
+                };
+            }
+
+            if ($def->require_usr_email eq 't') {
+                push @{ $filter->{'-and'} }, {
+                    '-exists' => {
+                        from  => 'au',
+                        where => {
+                            id  => $usr_filter,
+                            email => $email_filter
+                        }
+                    }
+                };
+            }
         }
 
         $class =~ s/^Fieldmapper:://o;
index bd85e38..e428404 100644 (file)
@@ -477,6 +477,8 @@ sub build_environment {
 
     $self->update_state( 'collecting') || die 'Unable to update event state';
 
+    my $usr_id;
+
     try {
    
         my $compartment = new Safe;
@@ -520,6 +522,13 @@ sub build_environment {
                 $self->_object_by_path( $self->event->event_def, undef, [qw/usr_message sending_lib/], ['owner'] );
             }
         }
+
+        if (my $ufield = $self->event->event_def->usr_field) {
+            # usr_field only works when it exists as a field directly on the 
+            # target object (see Trigger.pm). No _object_by_path() required.
+            $usr_id = $self->target->$ufield;
+            $usr_id = $usr_id->id if ref $usr_id; # de-flesh
+        }
     
         $self->environment->{complete} = 1;
     } otherwise {
@@ -528,7 +537,8 @@ sub build_environment {
     };
 
     if ($self->environment->{complete}) {
-        $self->update_state( 'collected' ) || die 'Unable to update event state';
+        my $usr_update = $usr_id ? {usr => $usr_id} : undef;
+        $self->update_state( 'collected', $usr_update ) || die 'Unable to update event state';
     } else {
         $self->update_state( 'error' ) || die 'Unable to update event state';
     }
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.at-usr-additions.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.at-usr-additions.sql
new file mode 100644 (file)
index 0000000..36848e2
--- /dev/null
@@ -0,0 +1,46 @@
+BEGIN;
+
+-- SELECT evergreen.upgrade_deps_block_check('TODO', :eg_version);
+
+-- TODO Stock schema
+-- TODO Update usr purge / merge functions
+-- TODO Update seed A/T to add 'usr' fields and set require_usr_email
+
+ALTER TABLE action_trigger.event
+    ADD COLUMN usr INTEGER REFERENCES actor.usr(id);  -- NULL-able
+
+ALTER TABLE action_trigger.event_definition
+    ADD COLUMN require_usr_email BOOLEAN DEFAULT FALSE;
+
+-- back-fill the values
+
+-- avoid "pending trigger events" error
+SET CONSTRAINTS ALL IMMEDIATE; 
+
+-- stamp user fields where we can
+UPDATE action_trigger.event_definition 
+    SET usr_field = 'usr' WHERE hook IN (
+        SELECT key FROM action_trigger.hook 
+        WHERE core_type IN ('circ', 'ahr', 'ausp', 'bresv', 'aur', 'auch', 'aupr')
+    );
+
+UPDATE action_trigger.event_definition 
+    SET usr_field = 'id' WHERE hook IN (
+        SELECT key FROM action_trigger.hook WHERE core_type IN ('au')
+    );
+
+-- Require user emails for all SendEmail event defs that have a usr_field.
+UPDATE action_trigger.event_definition 
+    SET require_usr_email = TRUE 
+    WHERE reactor = 'SendEmail' AND usr_field IS NOT NULL;
+
+UPDATE action_trigger.event_definition 
+    SET require_usr_email = FALSE 
+    WHERE reactor <> 'SendEmail' OR usr_field IS NULL;
+
+ALTER TABLE action_trigger.event_definition
+    ALTER COLUMN require_usr_email SET NOT NULL;
+
+COMMIT;
+
+