Skip to content

Commit

Permalink
Updates for version 4.2
Browse files Browse the repository at this point in the history
  • Loading branch information
mnelsonGIS committed Jun 16, 2024
1 parent 0c4a805 commit 5544c63
Show file tree
Hide file tree
Showing 19 changed files with 572 additions and 0 deletions.
Binary file added v4.2/Configuration/Basemap Configuration.docx
Binary file not shown.
Binary file added v4.2/Configuration/ERM API Configuration.docx
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
32 changes: 32 additions & 0 deletions v4.2/Operational-Documentation/Delete Plan - Job Aid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
**Deleting a Plan** from ERM - [Job Aid](https://en.wiktionary.org/wiki/job_aid)
This job aid uses the Portal UI and ArcGIS Pro to find and delete plans. These tasks could be automated through the [Python API](https://developers.arcgis.com/python/) as well
1. Open the ERM_Registry table in ArcGIS Pro.
2. Search for a plan by the "Dispatch Location", "First Event" (Creation time), "Last Event" (Last updated time), or any of the other fields. Optionaly, set a definition query on any field.
![Image for Pro Query](https://user-images.githubusercontent.com/3834298/90927990-a97aac80-e3bb-11ea-9e40-0c90c28fe903.jpg)
3. Note the "Item Id" which corresponds to Feature Layer ID. The "Webmap Id" which corresponds to the Web Map, and (if applicable), the "Dashboard Id" which corresponds to a plan dashboard if one was created.

*Note: If you are using the **Workforce Extension for ERM**, save the "Item ID" somewhere you can paste it later if you also need to clear the Workforce project.*

4. In Portal, search for and delete the following items in the following order
* If applicable: the Dashboard
* Webmap item
![Image for delete web map](https://user-images.githubusercontent.com/3834298/90928011-b4cdd800-e3bb-11ea-9c39-65be90843180.jpg)
* Feature layer
* Row for the plan in ERM_Registry

The plan is now completely deleted and will no longer appear in any items inventory including RPE.

If you are using the **Workforce Extension for ERM**, follow Steps 5-7 below to delete records published into Workforce from ERM

*Note: This process is not needed for cleaning out older (prior days) features since those features will be purged on a schedule. This process is intended to truncate an active plan so that it can be replaced by a new plan.*

5. Retrive the ItemID you noted in Step 3 above.
6. Generate a token using the steps below
* a. Go to https://\<server name\>/portal/sharing/rest/generateToken. \<server name\> represents the fully qualified domain name of the server that portal is deployed on.
* b. Enter Username and Password. Use Portal credentials for an administrator level account.
* c. For Webapp URL, enter the Portal URL. This should match the config.portalUrl value in the Middleware API config file.
![Image for generate token](https://user-images.githubusercontent.com/3834298/94065006-211f6b00-fdb0-11ea-9b81-90c254e36db9.png)

7. Paste https://\<middleware server name\>/ermapi/workforce/deletePlan?planItemId=XXX&token=YYY into your browser. \<middleware server name\> represents the fully qualified domain name of the server that Middleware API is deployed on.
* Replace XXX with the plan ID previously identified.
* Replace YYY with the token that was generated.
Binary file not shown.
45 changes: 45 additions & 0 deletions v4.2/Operational-Documentation/ERM_CopySolveParameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

"""
--------------------------------
Name: ERM_Copy Solve Parameters.py
Purpose: Copy default solve parameter records for each location
Author: Mike Nelson
Created 5/26/2020
Copyright: (c) Esri
ArcGIS Version: 2.4 (Pro)
PYTHON Version: 3.6 (API 1.8)
Requirements: update variables for feature class/table paths
Expects DepotTemplate to be fully populated before running
--------------------------------
"""

import arcpy


def get_value_list(in_layer, field_name):
with arcpy.da.SearchCursor(in_layer, [field_name]) as cursor:
return sorted({row[0] for row in cursor})

################### UPDATE VARIABLES ##############################
depot_template = r"C:\ERM\services\fgdbs\ERM_Plan_Defaults.gdb\DepotTemplate"
depot_name_field = "depotname"
solve_param_defaults_table = r"C:\ERM\services\fgdbs\ERM_Solve_Parameters.gdb\Solve_Parameters_Restrictions_DefaultValues"
solve_param_table = r"C:\ERM\services\fgdbs\ERM_Solve_Parameters.gdb\Solve_Parameters_Restrictions"
solve_para_depot_field = "displocname"

# make view for tables for selection/calculate tools to use
solve_param_view = "solve_param_view"
arcpy.MakeTableView_management(solve_param_table, solve_param_view)

# get list of all depot locations
depot_list = get_value_list(depot_template, depot_name_field)

for depot in depot_list:
arcpy.AddMessage(f"Processing {depot}...")

arcpy.AddMessage("Append default records...")
arcpy.Append_management(solve_param_defaults_table, solve_param_table, "NO_TEST")
arcpy.AddMessage("Select blank records...")
arcpy.management.SelectLayerByAttribute(solve_param_view, "NEW_SELECTION", solve_para_depot_field + " = ''", None)
arcpy.AddMessage("Calculate depot name...")
arcpy.management.CalculateField(solve_param_view, solve_para_depot_field, f"'{depot}'", "PYTHON3", '', "TEXT")
37 changes: 37 additions & 0 deletions v4.2/Operational-Documentation/ERM_CreateGroups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
--------------------------------
Name: ERM_CreateGroups.py
Purpose: Create Portal groups used by Enterprise Route Management system
Author: Mike Nelson
Created 5/26/2020
Copyright: (c) Esri
ArcGIS Version: 2.4 (Pro)
PYTHON Version: 3.6 (API 1.8)
Requirements: update group_list variable.
Create Environment variables exist for credentials, or just change variables to store directly
--------------------------------
"""

import arcpy, os, sys
from arcgis.gis import GIS
from os import environ

group_list = ["COV", "OCC", "GOL", "INL"]

# portal credentials
erm_portal = environ["ERM_PORTAL"]
erm_user = environ["ERM_USER"]
erm_pswd = environ["ERM_PWD"]

# Sign in/connect to portal
gis = GIS(erm_portal, erm_user, erm_pswd, verify_cert=False)

for group_name in group_list:
tag_list = f"dispatch-location-{group_name}, ERM"
arcpy.AddMessage(f"Creating group {group_name}...")
geocaching_group = gis.groups.create(title=group_name,
tags=tag_list,
description=f"ERM group for location {group_name}",
access='org',
is_invitation_only='False')

Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import arcpy
import sys
from os import path

SHAPE_INDEX = 1
ORDERID_INDEX = 13
DEPOTNAME_INDEX = 27
DISPLOCNAME_INDEX = 28
STOPTYPE_INDEX = 45

# Add current dir to path
tool_dir = path.dirname(path.abspath(__file__))
sys.path.append(tool_dir)

geodatabase = r"C:\Users\jer11410\OneDrive - Esri\Documents\Engagements\ERM\Pro Project\ERM_Plan_Defaults.gdb"
arcpy.env.workspace = geodatabase
arcpy.env.overwriteOutput = True

def printDictionary(d, indent = 0):

for key, value in d.items():
arcpy.AddMessage('\t' * indent + str(key))
if isinstance(value, dict):
printDictionary(value, indent + 1)
else:
arcpy.AddMessage('\t' * (indent + 1) + str(value))

return

def getDepotLocations(depots):

depot_fields = []
for f in arcpy.ListFields(depots):
depot_fields.append(f.name)

depot_dict = {}
with arcpy.da.SearchCursor(depots, depot_fields) as cursor:
for row in cursor:
this_dict = {}
for ii, field_name in enumerate(depot_fields):
this_dict[field_name] = row[ii]

#arcpy.AddMessage(f"depot: {row[0]}")
depot_dict[row[depot_fields.index('displocname')]] = this_dict

return depot_dict

def main(orders, depots, write_to_same_table, new_orders, location, suf, stop_type, order_pairs):

depot_dict = getDepotLocations(depots)
#printDictionary(depot_dict)

order_fields = []
for f in arcpy.ListFields(orders):
order_fields.append(f.name)

#for i, f in enumerate(order_fields):
# arcpy.AddMessage(f"{i}: {f}")

order_pair_fields = []
for f in arcpy.ListFields(order_pairs):
order_pair_fields.append(f.name)

# only get the orders that match the given dispatch location
order_where_clause = f"displocname = '{location}'"
#arcpy.AddMessage(f"order_where_clause: {order_where_clause}")

max_objectid = 0
with arcpy.da.SearchCursor(orders, 'OBJECTID') as scursor:
max_objectid = max(max(scursor))
arcpy.AddMessage(f"max objectid: {max_objectid}")

with arcpy.da.SearchCursor(orders, order_fields, order_where_clause) as scursor:
for row in scursor:
#arcpy.AddMessage(f"orderid: {row[ORDERID_INDEX]}")

if write_to_same_table and row[0] > max_objectid:
arcpy.AddMessage("I'm writing to the same table, and I've come to the end or the original orders. Bailing out.")
break

op_orderid = row[ORDERID_INDEX] + suf
op_shape = depot_dict[row[DISPLOCNAME_INDEX]]['shape']
first_order_name = row[ORDERID_INDEX]
second_order_name = op_orderid
#depot = depot_dict[row[DISPLOCNAMEINDEX]]

original_row = list(row)
new_row = list(row)
new_row[SHAPE_INDEX] = op_shape
new_row[ORDERID_INDEX] = op_orderid
new_row[STOPTYPE_INDEX] = new_stop_type

if write_to_same_table:
# write to the original table
with arcpy.da.InsertCursor(orders, order_fields) as icursor:
icursor.insertRow(new_row)
else:
with arcpy.da.InsertCursor(new_orders, order_fields) as icursor:
# First just make a copy of the existing order
icursor.insertRow(original_row)

# Next make a new row with the delivery attributes
icursor.insertRow(new_row)

# populate the order pair table
with arcpy.da.InsertCursor(order_pairs_table_name, order_pair_fields[1:]) as opcursor:
op_new_row = []
#op_new_row.append(None) # OBJECTID
op_new_row.append(first_order_name) # First Order Name
op_new_row.append(second_order_name) # Second Order Name
op_new_row.append(None) # Max Transit Time
op_new_row.append(location) # Dispatch Location
op_new_row.append(None) # Dispatch Description
op_new_row.append(None) # Created By
op_new_row.append(None) # First Event
op_new_row.append(None) # Last Updated By
op_new_row.append(None) # Last Event
opcursor.insertRow(op_new_row)

return

if __name__ == "__main__":

order_layer = arcpy.GetParameterAsText(0) or "TestOrders"
depot_layer = arcpy.GetParameterAsText(1) or "DepotTemplate"
write_to_same_table = arcpy.GetParameter(2) or False
new_order_layer_name = arcpy.GetParameterAsText(3) or "New_" + order_layer
dispatch_location_name = arcpy.GetParameterAsText(4) or "ADU"
suffix = arcpy.GetParameterAsText(5) or "_OP"
new_stop_type = arcpy.GetParameterAsText(6) or "Delivery"
order_pairs_table_name = arcpy.GetParameterAsText(7) or "TestOrderPair"

arcpy.AddMessage(f"order_layer: {order_layer}")
arcpy.AddMessage(f"depot_layer: {depot_layer}")
arcpy.AddMessage(f"write_to_same_table: {write_to_same_table}")
arcpy.AddMessage(f"new_order_layer_name: {new_order_layer_name}")
arcpy.AddMessage(f"dispatch_location_name: {dispatch_location_name}")
arcpy.AddMessage(f"suffix: {suffix}")
arcpy.AddMessage(f"new_stop_type: {new_stop_type}")
arcpy.AddMessage(f"order_pairs_table_name: {order_pairs_table_name}")

if not write_to_same_table and new_order_layer_name == '':
arcpy.AddError(f"ERROR: you have specified to write the results to a separate table, but have not identified the table using the 'New Order Layer Name' parameter.")
exit()

# if the name given for the new order layer doesn't exist, create it.
if not arcpy.Exists(new_order_layer_name):
arcpy.conversion.ExportFeatures(order_layer, new_order_layer_name)
arcpy.management.DeleteRows(new_order_layer_name)

arcpy.AddMessage(f"entering main...")
main(order_layer, depot_layer, write_to_same_table, new_order_layer_name, dispatch_location_name, suffix, new_stop_type, order_pairs_table_name)
15 changes: 15 additions & 0 deletions v4.2/Operational-Documentation/OrderPairGeneration/ReadMe.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Instructions for running ERM_GenerateOrderPairs.py

1. Will need to popupate ERM_Plan_Defaults.gdb. Specifically GeoOrderTemplate and DepotTemplate layers.
2. In GeoOrderTemplate, set Depot Name = name of depot you want the order pair created at
3. Open Pro and add ERM_Plan_Defaults layers to map (need GeoOrderTemplate, DepotTemplate layers and OrderPairTemplate table)
4. Open Default toolbox and open ERM_GenerateOrderPairs

Parameters:
Order Layer = GeoOrderTemplate
Depot Layer = DepotTemplate
Write to Same Table = if checked, will add new orders to GeoOrderTemplate. If unchecked, will let user add new name. New feature class created in Pro default workspace.
Dispatch Location Name = name of location orders are for
Suffix = suffix to add to OrderID for new orders created
Stop Type for New Orders = Sets StopType for new orders to Pickup or Delivery. Assumes existing orders are set to the other value.
Order Pairs Table Name = OrderPiarTemplate
Loading

0 comments on commit 5544c63

Please sign in to comment.