|
| 1 | +""" |
| 2 | +Use the VersionManager - differences method to find edits made between now and a given time. |
| 3 | +Transfer those changes from one set of feature layers to another. |
| 4 | +
|
| 5 | +Scenario: |
| 6 | +An on-premise server contains a parcel fabric that is routinely edited. Over time, edits |
| 7 | +are pushed to default. A scheduled task runs this script. |
| 8 | +
|
| 9 | +The script detects version differences that occurred between the current moment |
| 10 | +and one day prior. Those changes are then inserted into a companion parcel fabric |
| 11 | +hosted in AGOL. |
| 12 | +
|
| 13 | +https://developers.arcgis.com/python/latest/api-reference/arcgis.features.managers.html#version |
| 14 | +https://developers.arcgis.com/rest/services-reference/enterprise/differences/ |
| 15 | +""" |
| 16 | + |
| 17 | +import datetime |
| 18 | +from datetime import timedelta, timezone |
| 19 | + |
| 20 | +from arcgis.gis import GIS |
| 21 | +from arcgis.features import FeatureLayer, FeatureLayerCollection, FeatureSet |
| 22 | + |
| 23 | +# Timestamp for finding version differences: |
| 24 | +from_date = datetime.datetime.now(timezone.utc) |
| 25 | +from_timestamp = (from_date - timedelta(days=1)).timestamp() * 1000 |
| 26 | + |
| 27 | +now = datetime.datetime.now(timezone.utc) |
| 28 | +to_timestamp = int(now.timestamp() * 1000) |
| 29 | + |
| 30 | +# Connect to the enterprises |
| 31 | +parent_gis = GIS(profile="dev_enterprise_profile") # prod enterprise |
| 32 | +target_gis = GIS(profile="dev_online_parcels") # public online |
| 33 | + |
| 34 | +# FeatureServer endpoints |
| 35 | +source_item = parent_gis.content.get("01a56b31801f445c8c76624a4118094a") # enterprise |
| 36 | +target_item = target_gis.content.get("1bdec1c1fd61433d9da9cda23ea57be0") # online |
| 37 | +source_service_url = source_item.url |
| 38 | +target_service_url = target_item.url |
| 39 | + |
| 40 | +# Source parcel fabric feature layer collection |
| 41 | +production_parcels = FeatureLayerCollection(source_service_url, parent_gis) |
| 42 | + |
| 43 | +# List of layer IDs for Differences: |
| 44 | +# Records, Connection Lines, Points, Tax Lines, Tax Polygons |
| 45 | +# Ensure layer Ids are the same between both servers or find a way to |
| 46 | +# tie them to each other |
| 47 | +fabric_layers = [ |
| 48 | + l.properties.id |
| 49 | + for l in production_parcels.layers |
| 50 | + if l.properties.id in [1, 7, 8, 14, 15] |
| 51 | +] |
| 52 | + |
| 53 | +# Version management server endpoint |
| 54 | +vms = production_parcels.versions |
| 55 | + |
| 56 | +# Get differences |
| 57 | +with vms.get_by_name("sde", "DEFAULT", None) as version: |
| 58 | + differences = version.differences( |
| 59 | + result_type="features", |
| 60 | + layers=fabric_layers, |
| 61 | + moment=to_timestamp, |
| 62 | + from_moment=from_timestamp, |
| 63 | + future=False, |
| 64 | + ) |
| 65 | + print(differences) |
| 66 | + |
| 67 | +# Parse differences by insert, update and delete |
| 68 | +edit_type = {} |
| 69 | +for feature in differences["features"]: |
| 70 | + layer_id = feature["layerId"] |
| 71 | + edit_type[layer_id] = {} |
| 72 | + for op in ["inserts", "updates", "deletes"]: |
| 73 | + if op in feature: |
| 74 | + edit_type[layer_id][op] = feature[op] |
| 75 | + |
| 76 | + features_dict = { |
| 77 | + "features": [ |
| 78 | + {"attributes": feat["attributes"], "geometry": feat["geometry"]} |
| 79 | + for feat in feature[op] |
| 80 | + ] |
| 81 | + } |
| 82 | + |
| 83 | + feature_set = FeatureSet.from_dict(features_dict) |
| 84 | + fl = FeatureLayer(f"{target_service_url}/{layer_id}", target_gis) |
| 85 | + if op == "inserts": |
| 86 | + result = fl.edit_features(adds=feature_set, use_global_ids=True, gdb_version=None) |
| 87 | + print("Inserts:", layer_id, result) |
| 88 | + elif op == "updates": |
| 89 | + result = fl.edit_features(updates=feature_set, use_global_ids=True) |
| 90 | + print("Updates:", layer_id, result) |
| 91 | + else: |
| 92 | + result = fl.edit_features(deletes=feature_set, use_global_ids=True) |
| 93 | + print(op, layer_id, result) |
| 94 | + else: |
| 95 | + edit_type[layer_id][op] = [] |
0 commit comments