Calling finance rule from XFBR rule

DavidW
New Contributor II

This post is to illustrate how to call a public function of a Finance Rule from within XFBR rule.

The Finance Rule has a function called EntityText8 splitter, and I need to call it from within a XFBR rule. To make it work, first need to make the Finance Rule "True" - Contains Global Functions for Formulas (in Rule Properties) and refer to the specific rule assembly in XFBR rule properties (screenshot2).

The XFBR rule reads:

'--------------------------------------------------------------------------------------------------------------------------------
'Returns the Entity in Text8 or emtpy
'--------------------------------------------------------------------------------------------------------------------------------
'BRString(SeedingXFBRStrings, Text8Entity, curEntity=|CVEntity|, curScenario=|CVScenario|)
'XFBR(SeedingXFBRStrings, Text8Entity, curEntity=|CVEntity|, curScenario=|CVScenario|)
 
If args.FunctionName.XFEqualsIgnoreCase("Text8Entity") Then
 
Dim curEntity As String = args.NameValuePairs.XFGetValue("curEntity")
 
Dim curScenario As String = args.NameValuePairs.XFGetValue("curScenario")
Dim scenarioId As Integer = BRApi.Finance.Members.GetMember(si, DimType.Scenario.Id, curScenario).MemberId
Dim curScenarioType As String = BRApi.Finance.Scenario.GetScenarioType(si, scenarioId).Id
 
Dim entityId As Integer = brapi.Finance.Members.GetMemberId(si, DimType.Entity.Id, curEntity)
Dim entityText8 As String = BRApi.Finance.Entity.Text(si, entityId, 8, curScenarioType, si.WorkflowClusterPk.TimeKey)
 
If entityText8.Length > 0 Then
'Define reference to business rule
Dim text8Splitter As New OneStream.BusinessRule.Finance.FcstSeeding.MainClass
 
If Not text8Splitter Is Nothing Then
Dim srcEntity As String
With text8Splitter.entityText8Splitter(entityText8)
srcEntity = .srcEntity
End With
Return srcEntity
Else
Return entityText8
End If
 
Else
Return ""
End If
 
End If
4 REPLIES 4

RobbSalzmann
Valued Contributor

Hi DavidW,
What does the function entityText8Splitter do?  IOW, what changes when you pass in srcEntity?

For better readability, post your code in a preformatted element:
RobbSalzmann_0-1701120173772.png

RobbSalzmann_1-1701120237440.png

'--------------------------------------------------------------------------------------------------------------------------------
'Returns the Entity in Text8 or emtpy
'--------------------------------------------------------------------------------------------------------------------------------
'BRString(SeedingXFBRStrings, Text8Entity, curEntity=|CVEntity|, curScenario=|CVScenario|)
'XFBR(SeedingXFBRStrings, Text8Entity, curEntity=|CVEntity|, curScenario=|CVScenario|)

If args.FunctionName.XFEqualsIgnoreCase("Text8Entity") Then
	
	Dim curEntity As String = args.NameValuePairs.XFGetValue("curEntity")
	
	Dim curScenario As String = args.NameValuePairs.XFGetValue("curScenario")
	Dim scenarioId As Integer = BRApi.Finance.Members.GetMember(si, DimType.Scenario.Id, curScenario).MemberId
	Dim curScenarioType As String = BRApi.Finance.Scenario.GetScenarioType(si, scenarioId).Id
	
	Dim entityId As Integer = brapi.Finance.Members.GetMemberId(si, DimType.Entity.Id, curEntity)
	Dim entityText8 As String = BRApi.Finance.Entity.Text(si, entityId, 8, curScenarioType, si.WorkflowClusterPk.TimeKey)
	
	If entityText8.Length > 0 Then
'Define reference to business rule
		Dim text8Splitter As New OneStream.BusinessRule.Finance.FcstSeeding.MainClass
		
		If Not text8Splitter Is Nothing Then
			Dim srcEntity As String
			With text8Splitter.entityText8Splitter(entityText8)
				srcEntity = .srcEntity
			End With
			Return srcEntity
		Else
			Return entityText8
		End If
		
	Else
		Return ""
	End If

 

 

Software Architect
MindStream Analytics
"Difficult done right away. Impossible takes a bit longer"

DavidW
New Contributor II

Rob, Thanks for pointing out how to use the formatted style.

EntityText8splitter is a "string processor" function, returns different values (srcEntity, fcstSrcEntity, etc, ...). Instead of using more and more Entity Text fields for the same purpose (Forecast seeding in this case), Splitters are created to process and return drivers of "Seeding" exercise in different use cases. This is our response to the facts that logics are getting more complicated as business requirements change, and we have limited Text field for each member.

 

		Public Function entityText8Splitter(entityText8 As String) As (srcEntity As String, fcstSrcEntity As String, operSign As String, srcU6 As String)
		
			Dim srcEntity, fcstSrcEntity, operSign, srcU6 As String			
			
			srcEntity = entityText8
			fcstSrcEntity = ""
			operSign = ""
			srcU6 = ""
			
			If Instr(entityText8,"FcstSource") > 0 Then	'Test FcstSource existance
			
				fcstSrcEntity = Mid(entityText8, Instr(entityText8,"FcstSource")+10, 101)			
								
				If Instr(fcstSrcEntity,",") > 0 Then
					operSign = Mid(fcstSrcEntity, Instr(fcstSrcEntity,",")+1, 1)
					srcEntity = Left(srcEntity, (srcEntity.Length - fcstSrcEntity.Length -10 -1)) 'FcstSource and ","
					fcstSrcEntity = Left(fcstSrcEntity,Instr(fcstSrcEntity,",")-1)
				Else					
					srcEntity = Left(srcEntity, (srcEntity.Length - fcstSrcEntity.Length -10 -1))
				End If
			End If
				
			If	srcEntity.XFContainsIgnoreCase("U6#") Then 'Test U6# existance
				srcU6 =  Mid(srcEntity, Instr(srcEntity, "U6#"),101)
				srcEntity = Left(srcEntity, Instr(srcEntity, "U6#")-2)
				If	Instr(srcU6, ",") > 0	Then 'Test , existance
					operSign = Mid(srcU6, Instr(srcU6, ",")+1, 1)
					srcU6 = Left(srcU6, Instr(srcU6, ",")-1)
				End If
			End If		
		
			Return (srcEntity, fcstSrcEntity, operSign, srcU6)
			
		End Function

 

RobbSalzmann
Valued Contributor

Code reuse rocks 🙂 .  It looks like the requirements for EntityText8 may be evolving over time.  Consider encapsulating the overall text processing functionality in its own class and create methods in the class to deal with the different parsing/mangling/processing needs, currently being dealt with using multiple IF statements. 

Place the class in a BR of its own with other text processors:

Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Data.Common
Imports System.Globalization
Imports System.IO
Imports System.Linq
Imports System.Windows.Forms
Imports Microsoft.VisualBasic
Imports OneStream.Finance.Database
Imports OneStream.Finance.Engine
Imports OneStream.Shared.Common
Imports OneStream.Shared.Database
Imports OneStream.Shared.Engine
Imports OneStream.Shared.Wcf
Imports OneStream.Stage.Database
Imports OneStream.Stage.Engine

Namespace OneStream.BusinessRule.DashboardStringFunction.TextProcessors
    Public Class SomeOtherTextProcessor
        '... other string parsing/mangling/processing used in multiple places
    End Class

    Public Class YetAnotherTextProcessor
        '... other string parsing/mangling/processing used in multiple places
    End Class

	Public Class EntityText8Processor
	    Private _srcEntity As String
	    Private _fcstSrcEntity As String
	    Private _operSign As String
	    Private _srcU6 As String

	    Public ReadOnly Property SrcEntity As String
	        Get
	            Return _srcEntity
	        End Get
	    End Property

	    Public ReadOnly Property FcstSrcEntity As String
	        Get
	            Return _fcstSrcEntity
	        End Get
	    End Property

	    Public ReadOnly Property OperSign As String
	        Get
	            Return _operSign
	        End Get
	    End Property

	    Public ReadOnly Property SrcU6 As String
	        Get
	            Return _srcU6
	        End Get
	    End Property

	    Public Sub New(entityText8 As String)
	        _srcEntity = entityText8
	        _fcstSrcEntity = String.Empty
	        _operSign = String.Empty
	        _srcU6 = String.Empty
	    End Sub

	    Public Sub ProcessForecastSource()
	        Dim startIdx As Integer = InStr(_srcEntity, "FcstSource") + 10
	        _fcstSrcEntity = Mid(_srcEntity, startIdx, 101)

	        Dim hasComma As Boolean = InStr(_fcstSrcEntity, ",") > 0
	        If hasComma Then
	            _operSign = Mid(_fcstSrcEntity, InStr(_fcstSrcEntity, ",") + 1, 1)
	            _fcstSrcEntity = Left(_fcstSrcEntity, InStr(_fcstSrcEntity, ",") - 1)
	        End If

	        _srcEntity = Left(_srcEntity, startIdx - 11)
	    End Sub

	    Public Sub ProcessU6()
	        Dim u6Index As Integer = InStr(_srcEntity, "U6#")
	        _srcU6 = Mid(_srcEntity, u6Index, 101)
	        _srcEntity = Left(_srcEntity, u6Index - 2)

	        Dim hasComma As Boolean = InStr(_srcU6, ",") > 0
	        If hasComma Then
	            _operSign = Mid(_srcU6, InStr(_srcU6, ",") + 1, 1)
	            _srcU6 = Left(_srcU6, InStr(_srcU6, ",") - 1)
	        End If
	    End Sub
	End Class
End Namespace

With this class, you can add new "processors" for each new requirement. by creating another "Process<thisToProcess>" sub. 

Consume the class:

'Returns the Entity in Text8 or emtpy
'--------------------------------------------------------------------------------------------------------------------------------
'BRString(SeedingXFBRStrings, Text8Entity, curEntity=|CVEntity|, curScenario=|CVScenario|)
'XFBR(SeedingXFBRStrings, Text8Entity, curEntity=|CVEntity|, curScenario=|CVScenario|)
 
If args.FunctionName.XFEqualsIgnoreCase("Text8Entity") Then 
	Dim curEntity As String = args.NameValuePairs.XFGetValue("curEntity")	 
	Dim curScenario As String = args.NameValuePairs.XFGetValue("curScenario")
	Dim scenarioId As Integer = BRApi.Finance.Members.GetMember(si, DimType.Scenario.Id, curScenario).MemberId
	Dim curScenarioType As String = CStr(BRApi.Finance.Scenario.GetScenarioType(si, scenarioId).Id)	 
	Dim entityId As Integer = brapi.Finance.Members.GetMemberId(si, DimType.Entity.Id, curEntity)
	Dim entityText8 As String = BRApi.Finance.Entity.Text(si, entityId, 8, curScenarioType, si.WorkflowClusterPk.TimeKey)
	
	If entityText8.Length > 0 Then
		Dim text8Splitter As New OneStream.BusinessRule.DashboardStringFunction.TextProcessors.EntityText8Processor(entityText8)
		
		If InStr(text8Splitter.SrcEntity, "FcstSource") > 0 Then
			text8Splitter.ProcessForecastSource()
		End If

		If InStr(text8Splitter.SrcEntity, "U6#") > 0 Then
		    text8Splitter.ProcessU6()
		End If
		
		entityText8 = text8Splitter.SrcEntity 
	End If
	Return entityText8
End If

 

Software Architect
MindStream Analytics
"Difficult done right away. Impossible takes a bit longer"

DavidW
New Contributor II

Yes, that's a very logical and concise solution. Thanks, Rob.