Reference

About Family- and Field-Level Rules

In GE Digital APM, family-level and field-level rules consist of code that determines how records in the GE Digital APM database will behave under specific conditions. Rule code is written in Visual Basic.Net (VB.Net), a programming language that is compatible with the language in which GE Digital APM is written. In this way, you can specify that when certain actions are taken in GE Digital APM, certain rules should be executed.

Important: Modifying rules without the proper knowledge and expertise could cause your system to work improperly.

The purpose of writing business rules for a family is to control how records in that family will behave when you work with those records in GE Digital APM. The rule code itself can be stored in two locations:

  • Within the family rule project itself.
  • Within the Rules Library.

Rules can range from very simple to highly complex. If you have sufficient knowledge of writing VB.Net code, you can use Microsoft Visual Studio to customize your system to suit the specific needs of your organization.

Writing complex rules requires knowledge of VB.Net that exceeds the scope of this documentation. The purpose of this documentation is to explain the basic structure of family rule projects and to describe the tools that are available to help you write rules. In addition, we provide some basic information about rule code itself to help you understand and navigate your existing rules and some basic examples of custom rule code.

Note: Family policies allow you to make changes similarly to family-level rules, but family policies are created in a user interface where knowledge of Visual Basic.Net (VB.Net) is not required.

About Rule Code Storage Options

Custom family-level and field-level rules can be stored in two places:

  • Within the family rule project itself.
  • Within the Rules Library.

Storing family rules within the family rule project itself means that the actual rule code is stored in the family and field classes within a family rule project. This form of rule code storage is acceptable but can be cumbersome as it can result in a large amount of rule code that must be maintained on a family-by-family basis. In addition, rule code that is stored within family rule projects applies only to one family. To apply the same rule code to another family, you would have to copy the rule code and paste it into another family rule project.

The Rules Library, on the other hand, stores rule code in projects that can be referenced from family rule projects. In this way, you can store the actual VB.Net code in one central location and then apply it to multiple families. This method of rule code storage offers many advantages, including limiting the amount of code that must be maintained and increasing the ease and efficiency with which that code can be applied to other families.

The Rules Library, however, also imposes some limitations. To take advantage of the exact same rule code across multiple families, you would need to have multiple families that should behave exactly the same way. It is more likely, however, that you will have multiple families that should behave in similar ways.

For this reason, you will probably want to use a combination of the two rule code storage methods. In the Rules Library, you can store code that will serve as the foundation on which family-level and field-level rules are built. After referencing that code from a family rule project, you can extend the rule through family-level and field-level customization.

About Rule Terminology and Concepts

To modify and create rules, you must understand the following terminology and concepts:

  • Rule projects
  • Classes
  • Functions
  • Inheritance

Rule Projects

A rule project is a container for rule code. GE Digital APM uses two types of rule projects:

  • Family Rule Project: Stores all the rules for a given family.
  • Rules Library Project: Stores all the rules that exist for that project.

Rule projects contain references and files, also called code items. The files contain rules that are defined for that project. The file structure for family projects is determined by the content of the family. The file structure of a Rules Library project is determined by the project owner and can be customized as necessary to meet the requirements of the project.

Classes

A class is a VB.Net element that serves as a container for storing objects. Classes are defined within the files that exist in a rule project.

  • In family rule projects, GE Digital APM automatically defines classes within the files that exist for the family itself and the fields within that family.
  • In baseline Rules Library projects, classes serve as containers for the code within those projects.
  • In custom Rules Library projects, you can define your own classes as needed. When you create a new project, one file will be created within that project, and within that file, a default class will be defined.

Any VB.Net class can be inherited from another class so that the rules defined in one class can be reused as often as needed.

The following code excerpt shows an example of the default class Class1 that is created when you create a new Rules Library project:


                    
                        Option Strict On
                    
                    
                        Option Explicit On
                    
                     
                    
                        Imports GE Digital APM.Core.DataManager
                    
                        Imports GE Digital APM.Core.DataManager.Customization
                    
                        Imports GE Digital APM.Core.Internals
                    
                        Imports GE Digital APM.Core.Metadata
                    
                        Imports GE Digital APM.Core.Security.ApplicationUser
                    
                        Imports GE Digital APMGE Digital APM.Core.Uom
                    
                        Imports System
                    
                        Imports System.Xml
                     
                    
                        Public Class Class1
                     
                        Private Sub New()
                            MyBase.New
                            '
                            'TODO: Add constructor logic here
                            '
                        End Sub
                    
                        End Class
                    
                

In this example, the lines Public Class Class1 and End Class define the class; the code in between these two lines of text represents all the objects that belong to the class.

Functions

A function is a block of rule code that defines a Function procedure. Functions can be defined to invoke specific behaviors. The standard field-level rules that are available in GE Digital APM are defined through functions. In the following example, the IsRequired function is between the two lines Public Class Class1 and End Class.


                    
                        Option Strict On
                    
                    
                        Option Explicit On
                    
                     
                    
                        Imports GE Digital APM.Core.DataManager
                    
                        Imports GE Digital APM.Core.DataManager.Customization
                    
                        Imports GE Digital APM.Core.Internals
                    
                        Imports GE Digital APM.Core.Metadata
                    
                        Imports GE Digital APM.Core.Security.ApplicationUser
                    
                        Imports GE Digital APM.Core.Uom
                    
                        Imports System
                    
                        Imports System.Xml
                     
                    
                        Public Class Class1
                     
                        Public Overrides Function IsRequired() As Boolean
                            Return True
                        End Function
                     
                    
                        End Class
                    
                

Inheritance

Inheritance allows one class to use the behaviors defined in another class.

  • The class that is inherited is considered the base class and serves as a foundation for the functionality of the class that inherits it.
  • Any class that inherits from another class is considered a derived class.

All the functions and behaviors defined in the base class are automatically applied to the derived class. Within the derived class, code can be written to extend or override specific functions defined in the base class. Inheritance allows you to create new classes based on existing classes and is an important component of the Rules Library and baseline rule storage.

Inheritance is achieved through an Inherits statement in the derived class. For instance, in the following example, the class MI_RCA_ANALY_COST_NBR (the derived class) inherits the class EntityFieldCustomization (the base class).


                    
                        Public Class MI_RCA_ANALY_COST_NBR
                        Inherits EntityFieldCustomization
                    
                        End Class
                    
                

About Rules Project References

Creating Rules Library projects is only the first step in implementing family and field customizations using the Rules Library. After a Rules Library project has been created, it must be called from the family or field class of the family or field by which it will be used. You must complete two main steps to call a Rules Library project from a family project:

  1. First, you must add a reference to the Rules Library project from the family project. This will make the rules that are stored within the Rules Library project available for use within the family rule project.
  2. Second, within the family rule project, you must make calls to the parts of the referenced Rules Library project that you want to use. How and where you make the calls will depend on how the Rules Library project is organized and where you want to invoke certain functionality.

After the Rules Library project has been called within the family rule project, it can be extended via the family rule project in order to customize the rule for that specific family.

Note: You can create references to GE Digital APM rule projects and to Client rule projects.

About Family-Level Rules

Whereas field-level rules control the behavior of specific fields within a record, family-level rules reside within the code item that represents an entity family and control actions performed against the entire record.

Note: As an alternative to writing basic family-level rules, you can use family policies to configure the actions to be performed against a record. Family policies are created in a user interface where knowledge of Visual Basic.Net (VB.Net) is not required. For a single family, you can write family-level rules or family policies, not both. You can, however, use the Baseline Rule node in a family policy to execute any existing GE Digital APM baseline rules that correspond to the policy’s family and trigger.

Family-level rules provide flexibility in determining how records will behave. Some of the most common uses of family-level rules include:

  • Managing record links.
  • Calculating values.
  • Sending email notifications.

You can create family-level rules by developing custom code.

GE Digital APM supports the following family-level rule types.

Rule TypeStores logic that is executed...
BeforeInsert Before a record is created.
AfterInsert After a record is created.
BeforeUpdate After changes have been made to a record, before those changes are saved to the database.
AfterUpdate After changes to a record have been saved.
BeforeDelete Before a record is deleted.
AfterDelete

After a record has been deleted.

A change to a record in the GE Digital APM database will trigger the appropriate rule regardless of the current user’s permissions. However, if a user does not have permissions for an action a rule is taking, the rule will not execute and the transaction will be rolled back and no changes will be made. Similarly, the transaction will be rolled back if an error occurs during the rule’s execution.

Example: AfterInsert

One use of an AfterInsert rule is to create a link between two families after a new record is created. Consider an example where, when you create a Functional Location record, you want to link it to the Site Reference record that represents the site that contains the functional location. You can accomplish this by creating a family-level rule for the Functional Location family.

The following code shows an example of an AfterInsert rule that you could write to create a link between the Functional Location record and the Site Reference record after the Functional Location record is created. You would insert this rule into the family-level code item for the Functional Location family.


                    
                        Public Overrides Sub AfterInsert()
                    ManageSiteReference()
                    
                        End Sub
                    
                     
                    Private Sub Manage Site Reference ()
                        Dim session As EntitySession = CurrentEntity.Session
                     
                        If session Is Nothing Then
                            session = New EntitySession(ApplicationUser)
                        End If
                     
                        Dim currentSite As SiteReference = SiteReference.LoadExisting(session, CurrentEntity)
                        Dim newSite As SiteReference = SiteReference.RetrieveSiteReference(session, CurrentEntity)
                     
                        If currentSite Is Nothing AndAlso newSite Is Nothing Then
                            Return
                        End If
                     
                        If currentSite Is Nothing And Not newSite Is Nothing Then
                            newSite.AddAssetToSite(CurrentEntity)
                        ElseIf Not currentSite Is Nothing And newSite Is Nothing Then
                            If Not CurrentEntity.Fields("MI_FNCLOC00_SAP_SYSTEM_C").Value Is DBNull.Value Then
                                currentSite.RemoveAssetFromSite(CurrentEntity)
                            End If
                        ElseIf currentSite.Key <> newSite.Key Then
                            currentSite.RemoveAssetFromSite(CurrentEntity)
                            newSite.AddAssetToSite(CurrentEntity)
                        End If
                    
                        End Sub
                    
                

About Field-Level Rules

Field-level rules define how a field will behave under certain circumstances. The field-level rules for a given field are stored within the family rule project for the family to which the field belongs.

Each family rule project contains a code item for each field that exists within the family. The rules for a given field are stored in the file that corresponds to that field.

Note: Code items will not exist for fields that have been spread down from a higher-level family and are configured at the subfamily level to inherit rules from the source family. In this case, the code item that exists in the family rule project of the source family will be used for defining and executing rules at the subfamily level. If the subfamily is configured not to inherit rules from the source family, a code item will exist within the family rule project of the subfamily and will be used for defining and executing rules at the subfamily level.

The following types of rules can be defined for each family field.

Rule TypeDescriptionAssociated Function
RequiredDetermines whether or not a value must be entered into a field before a record can be saved in the family.IsRequired
ValidationLets you define criteria that will be used to validate values that are entered into a field.Validate
Valid ValuesLets you define a list of values that will be available for selection in the field. You will be able to select any value from those defined in the list of Valid Values.GetPickList
Default ValueDefines the default value that will be provided for a field. When you create a new record, the default value will be provided automatically. You can accept the default value or specify a different value.GetDefaultInitialValue
DisabledDetermines when, if ever, the field will be disabled, or locked from modification.IsDisabled
FormatDetermines the formatting that will be applied to values entered into a field.FormatValue
FormulaCalculates the value in the field using a formula that has been specified through rules.GetCalculatedValue

You can develop custom field-level rules manually by accessing the code item for the appropriate field and inserting the custom code. The code for each rule type must be defined within the appropriate function, which serves as a container for the code for that rule.

Example 1: Required Rule

Instead of making a field always required, you may prefer to make it required only if another field in the same record also contains a value. For example, assume that the Recommendation family contains the logical field Completed (MI_REC_COMPL_FLG), which is meant to be flagged by a user after a recommendation has been completed. The Recommendation family also contains the Completed Date field, which is meant to contain the date the recommendation was completed. Therefore, you want to create a rule so that when the Completed field is set to True, the Completed Date field is required.

To enforce this condition, you would create a Required rule on the Completed Date field that looks like this:


                    
                        Public Overrides Function IsRequired() As Boolean
                        If Object.Equals(CurrentEntity.Fields("MI_REC_COMPL_FLG").Value, True) Then
                            Return True
                        Else
                            Return False
                        End If
                    
                        End Function
                    
                

The portion of the code shown in red (MI_REC_COMPL_FLG) identifies the Field ID of the field that you want to use to enforce the Required rule condition, and the portion on the If line shown in blue (True) specifies the value that the field must contain.

Example 2: Validation Rule

Consider an example where the Recommendation family contains the field Create Work Request? (MI_REC_CREATE_SAP_NOTIF_FLG). Suppose you want to create a rule that validates the presence of an active external interface (e.g., Oracle) before GE Digital APM triggers the creation of a work request. Should the rule return no active external interface, then no work request will be created.

You could enforce the need for a work request management system by creating the following Validation rule for the Create Work Request? field:


                    
                        Public Overrides Function Validate(ByRef newValue As Object) As GE Digital APM.Core.DataManager.Customization.FieldValidationStatus
                        If InterfaceUtility.InterfacesActive(Me.ApplicationUser) Or _
                           InterfaceUtility.OracleInterfacesActive(Me.ApplicationUser) Or _
                           InterfaceUtility.MaximoInterfacesActive(Me.ApplicationUser) Then
                            Return FieldValidationStatus.Success
                        End If
                     
                        Return FieldValidationStatus.Failure(InterfaceUtility.EAM_INTERFACES_NOT_ACTIVATED)
                    
                        End Function            
                

Consider another example for a validation rule, where in the Asset Criticality Analysis datasheet, the Analysis Definition Family section contains the field Analysis ID. Suppose you want to create a rule that validates if the Analysis ID exists in the system database.

If the field validation status is a failure, then we can have the rule take the message text as input and return a failure message. We can embed a hyperlink in the validation failure error message, causing the hyperlink to be shown along with the error message under the field.

If the field validation status is a successful, then we can have the rule take the message text as input and return a success message. The message would be displayed under the field.

Example 3: Valid Values Rule

Within a list of available values, a blank value can be useful for clearing a previously selected value. When you select the blank value, it will clear whatever value had previously been selected in the list.

For example, the following code excerpt show a static Valid Values rule that will construct a list containing the values A, B, and C.


                    
                        Public Overrides Function GetPickList() As DynamicPickList
                        Dim pickList As DynamicPickList
                        'Use MyBase.CreatePickList(True) if you want a restricted PickList
                        'Use MyBase.CreatePickList(False) if you want an unrestricted PickList
                        pickList = MyBase.CreatePickList(True)
                        PopulatePickList(pickList)
                        Return pickList
                    
                        End Function
                    
                     
                    
                        Public Overrides Sub PopulatePickList(ByVal pickList As DynamicPickList)
                        pickList.AddRange("A|B|C".Split("|"c))
                    
                        End Sub
                    
                

You can add a null value to the list by inserting the code pickList.Add(DBNull.Value) above the line pickList.AddRange("A|B|C".Split("|"c)). The resulting code would look like this:


                    
                        Public Overrides Function GetPickList() As DynamicPickList
                        Dim pickList As DynamicPickList
                        'Use MyBase.CreatePickList(True) if you want a restricted PickList
                        'Use MyBase.CreatePickList(False) if you want an unrestricted PickList
                        pickList = MyBase.CreatePickList(True)
                        PopulatePickList(pickList)
                        Return pickList
                    
                        End Function
                    
                     
                    
                        Public Overrides Sub PopulatePickList(ByVal pickList As DynamicPickList)
                        pickList.Add(DBNull.Value)
                        pickList.AddRange("A|B|C".Split("|"c))
                    
                        End Sub
                    
                

Example 4: Default Value Rule

Consider an example where the Recommendation family contains the field Final Approver Name (MI_REC_FINAL_APPROVE_NAME_C). Suppose you want to create a Default Value rule on the Final Approver Name field to set it by default to the name of the user who is logged in to GE Digital APM at the time the record is approved. The resulting code would look like this:


                    
                        Public Overrides Function GetDefaultInitialValue() As Object
                        Return RecommendationUtilities.RecommendationDefaultValues.FinalApproverName(Current Entity)
                    
                        End Function
                    
                

Example 5: Disabled Rule

It may be appropriate to disable some fields conditionally, based on the value in another field.

Consider an example where the Equipment family contains the fields Plant Section (MI_EQUIP000_PLANT_SECTION_C) and Person Responsible for Plant Section (MI_EQUIP000_PLANT_SECT_DESC_C). The Person Responsible for Plant Section field does not need to be enabled until the Plant Section field contains a value.

To enforce this logic, you could create the following rule on the Person Responsible for Plant Section field so that it is disabled when the Plant Section field is empty. The resulting code would look like this:


                    
                        Public Overrides Function IsDisabled() As Boolean
                        If Convert.IsDBNull(CurrentEntity.Fields("MI_EQUIP000_PLANT_SECTION_C").Value) Or Object.Equals(CurrentEntity.Fields("MI_EQUIP000_PLANT_SECTION_C").Value, "") Then
                            Return True
                        Else
                            Return False
                        End If
                    
                        End Function
                    
                

Example 6: Format Rule

You may want to format character fields so that the value typed in the field appears in all capital letters. Consider an example where the Recommendation family contains the field Completion Comments (MI_REC_CLOSE_COMME_TX), and you want to view values in that field in all capital letters. You could create the following Format rule on the Completion Comments field to do so:


                    
                        Public Overrides Function FormatValue(ByVal value As Object) As String
                        If Not Convert.IsDBNull(CurrentEntity.Fields("MI_REC_CLOSE_COMME_TX").Value) Then
                            Return UCase(CStr(value))
                        Else
                            Return ""
                        End If
                    
                        End Function
                    
                
Note: Like all Format rules, the rule in Example 6 affects only the displayed value in places where Format rules are supported. The value will be stored in the database exactly as it is entered.

Example 7: Formula Rule

For some fields, rather than requiring users to specify a value, you may want to populate the field with a value that is calculated from values entered in other fields. Consider an example where the Work History family contains three cost fields:

  • Maintenance Cost (MI_EVWKHIST_MAINT_CST_N): The cost to date of maintenance on the asset.
  • Production Cost (MI_EVWKHIST_PRDN_CST_N): The cost to date to keep the asset in production.
  • Total Cost (MI_EVWKHIST_TOTL_CST_N): The total cost of the work, including the maintenance and production costs.

In this case, you may want to require users to enter values in the Maintenance Cost and Production Cost fields and then calculate the value for the Total Cost field by adding together the values in the Maintenance Cost and Production Cost fields. To implement this functionality, you could create the following Formula rule for the Total Cost field:


                    
                        Public Overrides Function GetCalculatedValue() As Object
                        'Total Cost = Maintenance Cost + Production Cost
                        Dim maintCost As Double = 0
                        Dim prodCost As Double = 0
                     
                        If Not Convert.IsDBNull(CurrentEntity.Fields("MI_EVWKHIST_MAINT_CST_N").Value) Then
                            maintCost = Convert.ToDouble(Current Entity.Fields("MI_EVWKHIST_MAINT_CST_N").Value)
                        End If
                     
                        If Not Convert.IsDBNull(CurrentEntity.Fields("MI_EVWKHIST_PRDN_CST_N").Value) Then
                            prodCost = Convert.ToDouble(CurrentEntity.Fields("MI_EVWKHIST_PRDN_CST_N").Value)
                        End If
                     
                        Return maintCost + prodCost
                    
                        End Function
                    
                
Note: For this example to work properly, the Total Cost field must be set up as a formula field.