Skip to content

Procedure Types

Entity Updates

When doing CRUD entity changes there is a need to apply local side effects before or after the local change. Entity updates run within a transaction. Any changes made will be rolled back on an error. The following methods can be implemented for each entity:

Prepare

EntityPrepare is called when creating blank records. Use this to populate the default values for new records. Any changes to the record will be visible to the user before they save.

@Override   
procedure EntityPrepare<WoMaterial> Structure(WoMaterial) {  
   execute {        
      super(Record) into Record;  
      set Record.Objstate = "New";  
      return Record;  
   }  
}  

If an entity is OnlineOnly then the procedure will be called after a successful call to the server. The result from the server will be placed in the Result parameter and the procedure should return the prepared row.

// WoObject is an OnlineOnly entity  
@Overtake Core  
procedure EntityPrepare<WoObject> Structure(WoObject) {  
   parameter Result Structure(WoObject);  
   execute {  
      // Result can be manipulated here  
      return Result;  
   }  
}  

Insert

EntityInsert is called when inserting a new row.

@Override   
procedure EntityInsert<WoMaterial> {  
   execute {  

      if [Record.PlannedQty <= 0] {  
         error("Planned Quantity must be greater than zero.", "Record.PlannedQty");  
      }  

      set Record.Objstate = "New";  

      super(Record);  
   }  
}  

If an entity is OnlineOnly then the procedure will be called after a successful call to the server. The result from the server will be placed in the Result parameter and the procedure should return the inserted row.

// WoObject is an OnlineOnly entity  
@Overtake Core  
procedure EntityInsert<WoObject> Structure(WoObject) {  
   parameter Result Structure(WoObject);  
   execute {  
      // Result can be manipulated here  
      return Result;  
   }  
}  

Update

EntityUpdate is called when updating an existing row.

@Override   
procedure EntityUpdate<WoMaterial> {  
   execute {  

      set Record.QtyIssued = [Record.QtyIssued + Record.QtyToIssue];  
      set Record.QtyToIssue = 0;  

      if [Record.QtyIssued > 0] {  
         set Record.Objstate = "Issued";  
      }  

      super(Record);  
   }  
}  

If an entity is OnlineOnly then the procedure will be called after a successful call to the server. The result from the server will be placed in the Result parameter and the procedure should return the updated row.

// WoObject is an OnlineOnly entity  
@Overtake Core  
procedure EntityUpdate<WoObject> Structure(WoObject) {  
   parameter Result Structure(WoObject);  
   execute {  
      // Result can be manipulated here  
      return Result;  
   }  
}  

Delete

EntityDelete is called when deleting a row.

@Override   
procedure EntityDelete<WoMaterial> {  
   execute {  

      if [Record.Objstate = "Issued"] {  
         error("Issued materials cannot be deleted.")  
      }  

      super(Record);  
   }  
}  

If an entity is OnlineOnly then the procedure will be called after a successful call to the server. The record from before the delete will be placed in the Record parameter.

// WoObject is an OnlineOnly entity  
@Overtake Core  
procedure EntityDelete<WoObject> {  
   parameter Record Structure(WoObject);  
   execute {  
      // Record can be used here  
   }  
}  

Actions

Action side effects can be used to validate and change the state of the client database before the action is sent to the server. Results from the action must be returned from the procedure. The server cannot return anything to the client when performing the action. Actions run within a transaction. Any changes made will be rolled back on an error.

@Override  
procedure Action<ChangeWoAddress> {  
   // parameter WoNo Number;  
   // parameter NewAddress Text;  

   variable Wo Structure(WorkOrder);  

   execute {  

      super(WoNo, NewAddress);  

      fetch WorkOrder i where [ i.WoNo = WoNo ] into Wo;  
      set Wo.AddressDetail = NewAddress;  
      saveLocal Wo;  
   }  
}  

Bound Actions

Bound actions have a record that the action is related to. The record is passed into the procedure as a parameter.

@Override  
procedure Action<WorkOrder.ChangeAddress> {  
   // parameter Record Structure(WorkOrder);  
   // parameter NewAddress Text;  

   execute {  

      super(Record, NewAddress);  

      set Record.AddressDetail = NewAddress;  
      saveLocal Wo;  
   }  
}  

Online Actions

If an action is Online then the procedure will be called after a successful call to the server. The result from the server will be placed in the Result parameter and the procedure should return the result.

// TestOnlineAction is an Online action  
@Overtake Core  
procedure Action<TestOnlineAction> Text {  
   parameter Param1 Text;  
   parameter Param2 Text;  
   parameter Result Text;  
   execute {  
      // Result can be manipulated here  
      return Result;  
   }  
}  

Functions

Functions work in a similar manner to actions but are only used for querying data. All functions that are called in the client file must have an accompanying procedure implementation. Functions are just used to get data from the server. In an offline client, there is no server, so a client implementation must be provided.

@alert warning Functions should just be used for getting data. Functions are not run within a transaction for performance reasons. Any data changes made within a function will not roll back on an error. @end

@Overtake Core  
procedure Function<GetWoAddress> Text {  
   // parameter WoNo Number;  
   variable Wo Structure(WorkOrder);  
   execute {  
      fetch WorkOrder i where [ i.WoNo = WoNo ] into Wo;   
      return [Wo.AddressLine1 + Wo.AddressLine2];  
   }  
}  

Bound Functions

Bound functions have a record that the function is related to. The record is passed into the procedure as a parameter.

@Overtake Core  
procedure Function<WorkOrder.GetAddress> Text {  
   parameter Record Structure(WorkOrder);  

   execute {  
      return [Record.AddressLine1 + Record.AddressLine2];  
   }  
}  

Online Functions

If a function is Online then the procedure will be called after a successful call to the server. The result from the server will be placed in the Result parameter and the procedure should return the result.

// TestOnlineFunction is an Online action  
@Overtake Core  
procedure Function<TestOnlineFunction> Text {  
   parameter Param1 Text;  
   parameter Param2 Text;  
   parameter Result Text;  
   execute {  
      // Result can be manipulated here  
      return Result;  
   }  
}  

Events

Device events can be hooked into to allow altering data.

@alert warning Events are not run within a transaction for performance reasons. Any data changes made within an event will not roll back on an error. If an event calls an Action it will still run within a transaction. @end

Synchronization Ended Event

@Overtake Core  
procedure Event<SynchronizationEnded> {  
    parameter ChangedEntities List<Text>;  

    variable Wo Structure(WorkOrder);  
    variable Index Integer;  

    execute {  
        call List.IndexOf(ChangedEntities, "WorkOrder") into Index;  

        if [Index >= 0] {  
           for WorkOrders where [DownloadedAt = null] into Wo {  
              call DateTime.Timestamp() into Wo.DownloadedAt;  
              saveAndSend Wo;  
           }  
        }  
    }  
}   

The SynchronizationEnded event can be used to alter data after the synchronization process ends. This event will only fire if data in the client database was altered during the synchronization. ChangedEntities can be used to detect which entities were changed during the sync.

This event can be fired often especially if the user is altering lots of data. This event also fires for system data being changed. An example would be the user selecting an item from different lookups on a screen. After each selection we save the users choice as a recently used item to the users profile and sync this to the server. This means you could have this event firing multiple times per second.

@alert important The processing time of this procedure must be kept to a minimum. The app can become unresponsive while queries are running. It is advised to keep the running time below 100ms. If the procedure takes more than 500ms for three consecutive runs a warning message will be shown to the user. See the Procedures > Performance section for more advice. @end

@alert important If data is changed that needs to be sent to the server during this event it will cause the sync process to run again and the SynchronizationEnded event can fire again. When handling this event ensure that data is only changed once otherwise the app will go into a loop where it continuously syncs and then fires the SynchronizationEnded event. @end

Transaction Failed Event

@Overtake Core  
procedure Event<TransactionFailed> {  
   parameter EntityName Text;  
   parameter Action Text;  
   parameter ErrorMessage Text;  
   parameter Keys List<Text>;  
   parameter Values List<Text>;  

   variable ListCount Number;  
   variable CurrentKey Text;  
   variable CurrentValue Text;  
   variable Counter Number;  

   execute {  
      debug("EntityName: ${EntityName}");  
      debug("Action: ${Action}");  
      debug("ErrorMessage: ${ErrorMessage}");  

      call List.Count(Keys) into ListCount;  

      set Counter = 0;  
      while [Counter < ListCount] {  
         call List.Get(Keys, Counter) into CurrentKey;  
         call List.Get(Values, Counter) into CurrentValue;  

         debug("Key: ${CurrentKey} / Value: ${CurrentValue}");  

         set Counter = [Counter+1];  
      }  
   }  
}  

The TransactionFailed event returns a boolean value that if it is true it means the application has handled the exception and the transaction should be deleted from the out queue. If it is false then it will default to the existing behavior.

When client side error handling is enabled, this event will be triggered when the client receives a failed transaction message. It can be used to perform any logic on the local data while making use of the parameters passed into the event. These parameters EntityName, Action, ErrorMessage provide information about the failed transaction that had taken place. There are two additional lists called Keys and Values which contain the key/value pairs of the attributes that was sent to the server initially. They can be used to fetch the record that caused the failed transaction, from the local database.

Utility

When implementing procedures, there may cases where the same validations or database changes are done in multiple places. To reduce duplication utility procedures can be used to reuse functionality. If the calling procedure is run within a transaction then the Utility procedure will run in the same transaction.

@Override   
procedure EntityUpdate<WoMaterial> {  
   execute {  
      call ValidateMaterial(Record);  
      super(Record);  
   }  
}  

procedure ValidateMaterial {  
   parameter Material Structure(WoMaterial);  

   execute {  

      if [Material.QtyToIssue < 0] {  
         error("Quantity to issue must be positive.", "Record.QtyToIssue")  
      }  

   }  
}