Select your user interface:
History Tab
The History tab typically contains one section referencing a custom data list that returns a status list for the business process.
The data list is a custom CLR-based data list, which means the code to retrieve the data for the data list is implemented as a .NET CLR class. While the data list is a custom list, Blackbaud recommends leveraging this CLR class that comes with the product which does the dirty work of retrieving the status history.
A CLR-based spec type defines the server-side catalog implementation that will be used to fetch the data for the list. Use this spec type when complex logic is required or when you need to pull data together from atypical data sources. A CLR Data List Spec requires an XML element named CLRDataList that describes a data list based on CLR code. The CLR code is implemented within a .NET class that resides within a .NET CLR assembly hosted in the web service layer. The .NET class should inherit Blackbaud.AppFx.Server.AppCatalog.AppDataList. The CLRDataList XML element can contain a list of parameters that match a set of public variables within the .NET CLR class file. When the Infinity user interface calls upon the CLR data list to display a list of data, the GetListResults() function is called on the .NET CLR class file. GetListResults() is responsible for gathering the data for the data list and returning the data as type Blackbaud.AppFx.Server.AppCatalog.AppDataListResult.
The CLR code will pull a status history from the BusinessProcessCatalog and BusinessProcessStatus tables for a given specific BusinessProcessCatalog.ID. Below is a sample Data List Spec. The CLR class assembly and class name are highlighted in yellow. The parameters passed to the class are highlighted in blue.
<DataListSpec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="7ff36611-ac9d-4ae2-a3f8-900fca2f24c2" Name="Inventory Process Business Process Status List" Description="Returns a status list for the inventory process businessbusiness process." Author="Technical Training" common:SecurityUIFolder="Constituent\Food Bank\Inventory" xmlns:common="bb_appfx_commontypes" xmlns="bb_appfx_datalist"> <CLRDataList AssemblyName="Blackbaud.AppFx.Platform.Catalog" ClassName="Blackbaud.AppFx.Platform.Catalog.BusinessProcessStatusDatalist"> <common:GrantSelectList> <common:GrantSelect>BUSINESSPROCESSCATALOG</common:GrantSelect> <common:GrantSelect>BUSINESSPROCESSSTATUS</common:GrantSelect> <common:GrantSelect>APPUSER</common:GrantSelect> </common:GrantSelectList> <common:StaticParameters> <common:ParameterList> <common:Param ID="BusinessProcessCatalogID"> <common:Value>a28d4f17-53fe-48d9-85bc-37e12884dc00</common:Value> </common:Param> <common:Param ID="ApplyParametersIDFilter"> <common:Value>True</common:Value> </common:Param> </common:ParameterList> </common:StaticParameters> </CLRDataList> <Parameters> <common:FormMetaData> <common:FormFields> <common:FormField FieldID="StatusCode" Caption="Status"> <common:ValueList> <common:Items> <common:Item> <common:Value>0</common:Value> <common:Label>Completed</common:Label> </common:Item> <common:Item> <common:Value>1</common:Value> <common:Label>Running</common:Label> </common:Item> <common:Item> <common:Value>2</common:Value> <common:Label>Did not finish</common:Label> </common:Item> </common:Items> </common:ValueList> </common:FormField> </common:FormFields> </common:FormMetaData> </Parameters> <Output> <OutputFields> <OutputField FieldID="ID" Caption="ID" IsHidden="true" DataType="Guid" /> <OutputField FieldID="Process name" Caption="Process name" IsHidden="true" DataType="String" /> <OutputField FieldID="Status" Caption="Status" DataType="String" /> <OutputField FieldID="Status message" Caption="Status message" DataType="String" /> <OutputField FieldID="Started by" Caption="Started by" DataType="String" /> <OutputField FieldID="Started on" Caption="Started on" DataType="Date" /> <OutputField FieldID="Ended on" Caption="Ended on" DataType="Date" /> <OutputField FieldID="Duration" Caption="Duration" DataType="String" /> <OutputField FieldID="Number of records processed" Caption="Number of records processed" DataType="String" /> <OutputField FieldID="NumberOfExceptionRecords" Caption="Number of exception records" DataType="String" /> <OutputField FieldID="Total count" Caption="Total count" IsHidden="true" DataType="String" /> <OutputField FieldID="Server name" Caption="Server name" DataType="String" /> <OutputField FieldID="ImageKey" Caption="ImageKey" IsHidden="true" DataType="String" /> <OutputField FieldID="Completed" Caption="Completed" IsHidden="true" DataType="String" /> <OutputField FieldID="EnableDownload" Caption="EnableDownload" IsHidden="true" DataType="String" /> <OutputField FieldID="EnableLetterMailMerge" Caption="EnableLetterMailMerge" IsHidden="true" DataType="String" /> <OutputField FieldID="EnableLabelMailMerge" Caption="EnableLabelMailMerge" IsHidden="true" DataType="String" /> </OutputFields> </Output> </DataListSpec>
Below is the code for the Blackbaud.AppFx.Platform.Catalog.BusinessProcessStatusDatalist class that does the heavy lifting of retrieving the status history data for the data list. Within the class, GetListResults() is responsible for gathering the data for the data list and returning the data as type Blackbaud.AppFx.Server.AppCatalog.AppDataListResult.
Imports Blackbaud.AppFx.Server Imports System.Data.SqlClient Public NotInheritable Class BusinessProcessStatusDatalist Inherits AppCatalog.AppDataList Public FilterBusinessProcessInstanceID As Guid = Guid.Empty 'this is passed from the filter panel Public BusinessProcessCatalogID As String = String.Empty Public StatusCode As Nullable(Of Integer) Public ApplyParametersIDFilter As Boolean = False Public RowsToReturn As Nullable(Of Integer) Public StartedDateRangeType As Nullable(Of Integer) Public StartedDateSpecificDate As Nullable(Of Date) Public Enum ProcessStatusImage check = 0 businessprocessspec warning x_16 End Enum 'Private Const STATUSTABLESUFFIX As String = "STATUS" Private Enum FieldsList ID ProcessName Status StatusMessage StartedBy StartedOn EndedOn Duration NumberOfRecordsProcessed NumberOfExceptionRecords TotalCount ServerName ImageKey Completed EnableDownload EnableLetterMailMerge EnableLabelMailMerge 'EnableMultipleLetterMailMerge deprecated ParameterSetName BusinessProcessCatalogID ParameterSetID End Enum Public Overrides Function GetListResults() As AppFx.Server.AppCatalog.AppDataListResult If BusinessProcessCatalogID = "=ContextID" Then BusinessProcessCatalogID = ProcessContext.ContextRecordID Else If FilterBusinessProcessInstanceID <> Guid.Empty Then BusinessProcessCatalogID = FilterBusinessProcessInstanceID.ToString() End If End If Dim builder As New Text.StringBuilder With builder .Append("select ID, ") .Append("ProcessName, ") .Append("Status, ") .Append("StatusMessage, ") .Append("StartedBy, ") .Append("StartedOn, ") .Append("EndedOn, ") .Append("Duration, ") .Append("NumberOfRecordsProcessed, ") .Append("NumberOfExceptionRecords, ") .Append("TotalCount, ") .Append("ServerName, ") .Append("ImageKey, ") .Append("Completed, ") .Append("EnableDownload, ") .Append("EnableLetterMailMerge, ") .Append("EnableLabelMailMerge, ") '.Append("EnableMultipleLetterMailMerge, ") deprecated .Append("coalesce(ParameterSetName,'') ") .Append("from dbo.UFN_BUSINESSPROCESSSTATUS_STANDARDDATALISTVALUES_ROWSTORETURNSTARTEDDATE(@BUSINESSPROCESSCATALOGID, @PARAMETERSETID, @STATUSCODE, @ROWSTORETURN, @STARTEDDATERANGETYPE, @STARTEDDATESPECIFICDATE) ") .Append("order by StartedOn desc") End With Dim command As New SqlCommand(builder.ToString) If ApplyParametersIDFilter Then Dim ctxID As String = Me.ProcessContext.ContextRecordID If String.IsNullOrEmpty(ctxID) Then Throw New ServiceException("The ContextRecordID must be specified for this BusinessProcessStatusDataList", ServiceErrorCode.InvalidAPIUse) End If command.Parameters.AddWithValue("@PARAMETERSETID", New Guid(ctxID)) Else command.Parameters.AddWithValue("@PARAMETERSETID", DBNull.Value) End If If BusinessProcessCatalogID <> String.Empty Then command.Parameters.AddWithValue("@BUSINESSPROCESSCATALOGID", New Guid(BusinessProcessCatalogID)) Else command.Parameters.AddWithValue("@BUSINESSPROCESSCATALOGID", DBNull.Value) End If AddNullableIntegerParameter(command, "@STATUSCODE", StatusCode) AddNullableIntegerParameter(command, "@ROWSTORETURN", RowsToReturn) AddNullableIntegerParameter(command, "@STARTEDDATERANGETYPE", StartedDateRangeType) AddNullableDateParameter(command, "@STARTEDDATESPECIFICDATE", StartedDateSpecificDate) Dim reader As SqlDataReader Dim resultList As New Generic.List(Of DataListResultRow) Using conn As SqlClient.SqlConnection = Me.RequestContext.OpenAppDBConnection SpWrap.USP_BUSINESSPROCESSSTATUS_VALIDATESTATUS.ExecuteNonQuery(conn) command.Connection = conn reader = command.ExecuteReader(CommandBehavior.CloseConnection) Do While reader.Read Dim result As New DataListResultRow Dim valueList As New Generic.List(Of String) valueList.Add(reader.GetGuid(FieldsList.ID).ToString) valueList.Add(reader.GetString(FieldsList.ProcessName)) valueList.Add(reader.GetString(FieldsList.Status)) valueList.Add(reader.GetString(FieldsList.StatusMessage)) valueList.Add(reader.GetString(FieldsList.StartedBy)) valueList.Add(FormatFieldForList(reader.GetDateTime(FieldsList.StartedOn))) If reader.IsDBNull(FieldsList.EndedOn) Then valueList.Add(String.Empty) Else valueList.Add(FormatFieldForList(reader.GetDateTime(FieldsList.EndedOn))) End If valueList.Add(reader.GetString(FieldsList.Duration)) valueList.Add(reader.GetInt32(FieldsList.NumberOfRecordsProcessed).ToString) valueList.Add(reader.GetInt32(FieldsList.NumberOfExceptionRecords).ToString) valueList.Add(reader.GetInt32(FieldsList.TotalCount).ToString) valueList.Add(reader.GetString(FieldsList.ServerName)) valueList.Add(reader.GetString(FieldsList.ImageKey)) valueList.Add(reader.GetBoolean(FieldsList.Completed).ToString) valueList.Add(reader.GetBoolean(FieldsList.EnableDownload).ToString) valueList.Add(reader.GetBoolean(FieldsList.EnableLetterMailMerge).ToString) valueList.Add(reader.GetBoolean(FieldsList.EnableLabelMailMerge).ToString) valueList.Add(Boolean.FalseString) ' deprecated -- left in so as not to break dependent specs valueList.Add(reader.GetString(FieldsList.ParameterSetName).ToString) valueList.Add(BusinessProcessCatalogID) If ApplyParametersIDFilter Then valueList.Add(Me.ProcessContext.ContextRecordID) End If result.Values = valueList.ToArray resultList.Add(result) Loop End Using Return New AppCatalog.AppDataListResult(resultList) End Function Private Sub AddNullableIntegerParameter(ByVal command As SqlClient.SqlCommand, ByVal parameterName As String, ByVal integerValue As Nullable(Of Integer)) If Not integerValue.HasValue Then integerValue = -1 End If command.Parameters.AddWithValue(parameterName, integerValue) End Sub Private Sub AddNullableDateParameter(ByVal command As SqlClient.SqlCommand, ByVal parameterName As String, ByVal dateValue As Nullable(Of Date)) If dateValue.HasValue Then command.Parameters.AddWithValue(parameterName, dateValue.Value) Else command.Parameters.AddWithValue(parameterName, DBNull.Value) End If End Sub End Class