Attribute rules: Recalculating a field based on the Modification of Another.

413
1
Jump to solution
07-26-2023 06:52 AM
Labels (1)
Skysurfer
New Contributor II

I am trying to set up an attribute rule that is triggered by an update to the Parent Property ID. As it currently stands it does recalculate the GIS_Property Acres for the record modified, but it doesn't update other related records that share the same Parent Property ID. I have a similar attribute rule that does the same thing if the geometry is changed, and it works perfectly. Thanks for any help that anyone can give!

 

var new_parent_property_id = $feature.ParentPropertyID
var old_parent_property_id = $originalfeature.ParentPropertyID

if(new_parent_property_id != old_parent_property_id){
    //Creates empty array and counter for iterating
    var updates = []
    var counter = 0
    var gid = $feature.GlobalId
    var id = $feature.ParentPropertyID

    //use this filter statement to get all of them for the SUM. 
    var sumfs = Filter($featureset, "ParentPropertyID = @ID")
    var property_acres = Sum(sumfs, "GIS_TractAcres")

    var fs = Filter($featureset, "ParentPropertyID = @ID AND GlobalId <> @gid")

    for (var f in fs){
        updates[counter] = { 
            'globalid': f.GlobalId,
            'attributes':{
                'GIS_PropertyAcres': property_acres,      
            } 
        }
        counter++ 
    }
          
    return {
        'edit': [{
            'className': 'Arcade_Rules_Test',
            'updates': updates
        }],
        'result': {
            "attributes": {
                "GIS_PropertyAcres": property_acres
            }
        }
 }
}
else {
   return 999
}

 

 

1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

Having the same logic in multiple rules is inefficient and can lead to errors quickly, when you change one rule and forget to update the others. In this case, It could also quickly lead to the cycling error again. It's better to expand the rule from your previous question

 

In lines 12-18, we now also check if the ParentPropertyID changed. If neither the geometry nor the parent id changed, we abort.

In lines 45-57, we now also update all features with the previous ParentPropertyID (if it changed), because their total area is now smaller.

// Calculation Attribute Rule
// field: empty
// triggers: Insert, Update, Delete
// exclude from application evaluation

var mode = $editcontext.editType

var geometry_is_equal = true
var parent_id_is_equal = true

// abort if this is an update that doesn't change the geometry or the ParentPropertyID
if(mode == "UPDATE") {
    geometry_is_equal = Equals(Geometry($feature), Geometry($originalfeature))
    parent_id_is_equal = $feature.ParentPropertyID == $originalfeature.ParentPropertyID
    if(geometry_is_equal && parent_id_is_equal) {
        return
    }
}

// get all OTHER features with this ID
var id = $feature.ParentPropertyID
var gid = $feature.GlobalID
var query = "ParentPropertyID = @ID AND GlobalID <> @gid"
var fs = Filter($featureset, query)

// get this area and the sum of the other areas
var f_area = Area($feature, "acres")
var total_area = Sum(fs, "GIS_TractAcres")
if(mode != "DELETE") { total_area += f_area }

// construct the update array
var updates = []
// update all features with the same ParentPropertyID
for(var f in fs) {
    if(f.GlobalID == $feature.GlobalID) { continue }
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            GIS_PropertyAcres: total_area
            }
        }
    Push(updates, u)
}
// update all features with the previous ParentPropertyID
if(!parent_id_is_equal) {
    var prev_id = $originalfeature.ParentPropertyID
    var prev_fs = Filter($featureset, "ParentPropertyID = @prev_id")
    for(var f in prev_fs) {
        var u = {
            globalID: f.GlobalID,
            attributes: {
                GIS_PropertyAcres: f.GIS_PropertyAcres - f_area
            }
        }
        Push(updates, u)
    }
}

return {
    result: {
        attributes: {GIS_TractAcres: f_area, GIS_PropertyAcres: total_area}
        },
    edit: [{
        className: "TestPolygons",
        updates: updates
        }]
}

 

You might have to refresh the attribute table to see the changes.


Have a great day!
Johannes

View solution in original post

0 Kudos
1 Reply
JohannesLindner
MVP Frequent Contributor

Having the same logic in multiple rules is inefficient and can lead to errors quickly, when you change one rule and forget to update the others. In this case, It could also quickly lead to the cycling error again. It's better to expand the rule from your previous question

 

In lines 12-18, we now also check if the ParentPropertyID changed. If neither the geometry nor the parent id changed, we abort.

In lines 45-57, we now also update all features with the previous ParentPropertyID (if it changed), because their total area is now smaller.

// Calculation Attribute Rule
// field: empty
// triggers: Insert, Update, Delete
// exclude from application evaluation

var mode = $editcontext.editType

var geometry_is_equal = true
var parent_id_is_equal = true

// abort if this is an update that doesn't change the geometry or the ParentPropertyID
if(mode == "UPDATE") {
    geometry_is_equal = Equals(Geometry($feature), Geometry($originalfeature))
    parent_id_is_equal = $feature.ParentPropertyID == $originalfeature.ParentPropertyID
    if(geometry_is_equal && parent_id_is_equal) {
        return
    }
}

// get all OTHER features with this ID
var id = $feature.ParentPropertyID
var gid = $feature.GlobalID
var query = "ParentPropertyID = @ID AND GlobalID <> @gid"
var fs = Filter($featureset, query)

// get this area and the sum of the other areas
var f_area = Area($feature, "acres")
var total_area = Sum(fs, "GIS_TractAcres")
if(mode != "DELETE") { total_area += f_area }

// construct the update array
var updates = []
// update all features with the same ParentPropertyID
for(var f in fs) {
    if(f.GlobalID == $feature.GlobalID) { continue }
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            GIS_PropertyAcres: total_area
            }
        }
    Push(updates, u)
}
// update all features with the previous ParentPropertyID
if(!parent_id_is_equal) {
    var prev_id = $originalfeature.ParentPropertyID
    var prev_fs = Filter($featureset, "ParentPropertyID = @prev_id")
    for(var f in prev_fs) {
        var u = {
            globalID: f.GlobalID,
            attributes: {
                GIS_PropertyAcres: f.GIS_PropertyAcres - f_area
            }
        }
        Push(updates, u)
    }
}

return {
    result: {
        attributes: {GIS_TractAcres: f_area, GIS_PropertyAcres: total_area}
        },
    edit: [{
        className: "TestPolygons",
        updates: updates
        }]
}

 

You might have to refresh the attribute table to see the changes.


Have a great day!
Johannes
0 Kudos