Select to view content in your preferred language

Edit Log to capture Insert, Update, and Deletes via ArcGIS Arcade attribute rule

542
11
Jump to solution
07-31-2024 11:15 AM
tbearb
by
Regular Contributor

I attended the Esri UC this year and this arcade expression was shown as an attribute rule in ArcGIS Pro that captures the audit history of a particular feature class / field(s), regarding the Insert, Update, and Delete event triggers. The script works great for capturing attribute changes, but as soon as you try to incorporate geometry changes, we see errors.

To only test the "Insert" event, I added the following lines:

var featureGeometry = null;

featureGeometry = $feature (within the insert event)

'geometry' : featureGeometry (added to the returned dictionary)

Can anyone point out what can be wrong with this arcade expression being used in an attribute rule in ArcGIS Pro? At the moment when I try to create a new point feature, I receive an 'Invalid geometry' error

// User variables
var current_edit = "NONE";
var featureGeometry = null; 

// User-editable fields
var fieldsArray = ['comments'];
var arrayLength = Count(fieldsArray);

// Process edit

// If a new feature was added
if ($editcontext.editType == 'INSERT') {
  current_edit = 'NEW FEATURE ';
  featureGeometry = $feature;
}

// If an existing feature was updated
if ($editcontext.editType == 'UPDATE') {
  current_edit = 'UPDATED FEATURE ';

  // if the geometries are not the same, record geometry update
  if ( !Equals( $originalFeature, $feature )){
      current_edit = current_edit + " Geometry update";
      
  }

  // check for changes in attribute values, record original value if changed
  for (var i = 0; i < arrayLength; i++) {
    if ($originalFeature[fieldsArray[i]] != $feature[fieldsArray[i]]) {
      // geometryEditOnly = false;
      current_edit = current_edit + ' {' + fieldsArray[i] + ': ' + $originalFeature[fieldsArray[i]] + '}';
    }
  }
}

// If an existing feature was deleted
if ($editcontext.editType == 'DELETE') {
  current_edit = 'DELETED FEATURE ';
  featureGeometry = $feature; 

  for (var i = 0; i < arrayLength; i++) {
    current_edit = current_edit + '{' + fieldsArray[i] + ': ' + $feature[fieldsArray[i]] + '} ';
  }
}

return {
  edit: [{
      'className': 'DBO.TestPointEdit',
      'adds': [{
          'attributes': {
            'edit_date': $feature.last_edited_date,
            'edit_feature': $feature.GlobalID,
            'editor': $feature.last_edited_user,
            'edit_action': $editcontext.editType,
            'edit_log': current_edit
          },
          'geometry' : featureGeometry      
        }
      ]
    }
  ]
};

tbearb_0-1722449680460.png

 

1 Solution

Accepted Solutions
tbearb
by
Regular Contributor

As an update, we were able to add the previous X and Y values of the point in the event it was moved, displayed within the log table. Thanks again for the assistance from @ZachBodenner for getting us on the right track. Here below is our final arcade expression:

// User variables
var current_edit = "NONE";
var featureGeometry = null;
var prevX = null;
var prevY = null;

// User-editable fields
var fieldsArray = ['comments'];
var arrayLength = Count(fieldsArray);

// Process edit

// If a new feature was added
if ($editcontext.editType == 'INSERT') {
  current_edit = 'NEW FEATURE ';
  featureGeometry = $feature;
}

// If an existing feature was updated
if ($editcontext.editType == 'UPDATE') {
  current_edit = 'UPDATED FEATURE ';

  // if the geometries are not the same, record geometry update
  if ( !Equals( geometry($originalFeature), geometry($feature) )){
      current_edit = current_edit + " Geometry update";
      prevX = Geometry($originalFeature).x
      prevY = Geometry($originalFeature).y
      
  }

  // check for changes in attribute values, record original value if changed
  for (var i = 0; i < arrayLength; i++) {
    if ($originalFeature[fieldsArray[i]] != $feature[fieldsArray[i]]) {
      // geometryEditOnly = false;
      current_edit = current_edit + ' {' + fieldsArray[i] + ': ' + $originalFeature[fieldsArray[i]] + '}';
    }
  }
}

// If an existing feature was deleted
if ($editcontext.editType == 'DELETE') {
  current_edit = 'DELETED FEATURE ';
  featureGeometry = $feature; 

  for (var i = 0; i < arrayLength; i++) {
    current_edit = current_edit + '{' + fieldsArray[i] + ': ' + $feature[fieldsArray[i]] + '} ';
  }
}

// Write to the edit log table
return {
  edit: [{
      'className': 'DBO.AuditTracking',
      'adds': [{
          'attributes': {
            'edit_date': $feature.last_edited_date,
            'edit_feature': $feature.GlobalID,
            'editor': $feature.last_edited_user,
            'edit_action': $editcontext.editType,
            'edit_log': current_edit,
            'last_lat_Yvalue' : prevY,
            'last_long_Xvalue' : prevX
          },
          'shape' : featureGeometry      
        }
      ]
    }
  ]
};

 

View solution in original post

11 Replies
ZachBodenner
MVP Regular Contributor

I got a slightly different error where it said 'Keyword 'geometry' cannot be used for a table'. I changed 'geometry' to 'Shape' and it worked. 

0 Kudos
tbearb
by
Regular Contributor

Thanks, changing the word 'geometry' to 'shape' worked for me as well. Did you happen to have any luck with it recording the geometry when the original point was moved?

Incorporating featureGeometry = $originalFeature in the Update event if the geometry was changed.

0 Kudos
ZachBodenner
MVP Regular Contributor

Maybe depends on what you mean by record? I did get the script to only record "Geometry Update" in the resulting log by changing:

 

// if the geometries are not the same, record geometry update
  if ( !Equals( $originalFeature, $feature ))

 

to:

 

// if the geometries are not the same, record geometry update
  if ( !Equals( geometry($originalFeature), geometry($feature) ))

 

 

That wont give you like the lat/long of the previous point or anything, but I imagine you might be able to add those fields to the log and then include them in the dictionary?

0 Kudos
tbearb
by
Regular Contributor

I appreciate that tip as well, that is working great for me. At the very least it helps better distinguish between what kind of edit happened - attribute vs geometry update. If we could update the dictionary and capture the previous lat/long that would be excellent.

0 Kudos
tbearb
by
Regular Contributor

As an update, we were able to add the previous X and Y values of the point in the event it was moved, displayed within the log table. Thanks again for the assistance from @ZachBodenner for getting us on the right track. Here below is our final arcade expression:

// User variables
var current_edit = "NONE";
var featureGeometry = null;
var prevX = null;
var prevY = null;

// User-editable fields
var fieldsArray = ['comments'];
var arrayLength = Count(fieldsArray);

// Process edit

// If a new feature was added
if ($editcontext.editType == 'INSERT') {
  current_edit = 'NEW FEATURE ';
  featureGeometry = $feature;
}

// If an existing feature was updated
if ($editcontext.editType == 'UPDATE') {
  current_edit = 'UPDATED FEATURE ';

  // if the geometries are not the same, record geometry update
  if ( !Equals( geometry($originalFeature), geometry($feature) )){
      current_edit = current_edit + " Geometry update";
      prevX = Geometry($originalFeature).x
      prevY = Geometry($originalFeature).y
      
  }

  // check for changes in attribute values, record original value if changed
  for (var i = 0; i < arrayLength; i++) {
    if ($originalFeature[fieldsArray[i]] != $feature[fieldsArray[i]]) {
      // geometryEditOnly = false;
      current_edit = current_edit + ' {' + fieldsArray[i] + ': ' + $originalFeature[fieldsArray[i]] + '}';
    }
  }
}

// If an existing feature was deleted
if ($editcontext.editType == 'DELETE') {
  current_edit = 'DELETED FEATURE ';
  featureGeometry = $feature; 

  for (var i = 0; i < arrayLength; i++) {
    current_edit = current_edit + '{' + fieldsArray[i] + ': ' + $feature[fieldsArray[i]] + '} ';
  }
}

// Write to the edit log table
return {
  edit: [{
      'className': 'DBO.AuditTracking',
      'adds': [{
          'attributes': {
            'edit_date': $feature.last_edited_date,
            'edit_feature': $feature.GlobalID,
            'editor': $feature.last_edited_user,
            'edit_action': $editcontext.editType,
            'edit_log': current_edit,
            'last_lat_Yvalue' : prevY,
            'last_long_Xvalue' : prevX
          },
          'shape' : featureGeometry      
        }
      ]
    }
  ]
};

 

ZachBodenner
MVP Regular Contributor

Very welcome! Remember to mark it as a solution if you think it will help others who find the post!

0 Kudos
tbearb
by
Regular Contributor

@ZachBodenner We currently receive a "Value exceeds valid range of column" error on deletes. We occasionally notice the error come in on the update trigger while editing 12+ fields in Field Maps before hitting submit. Any idea what this could be?

tbearb_0-1722860871425.png

tbearb_1-1722863165365.png

 

 

0 Kudos
ZachBodenner
MVP Regular Contributor

Usually that's something to do with the length of the field (ie. your string field can contain 500 characters, but what you're attempting to write in has 501 or more characters). 

tbearb
by
Regular Contributor

That was exactly it, we just needed to increase the length of the text field.

0 Kudos