Business Rule Compile Error and Warnings
OneStream Platform releases will periodically include an update to the Business Rules compiler, which is noted in each version’s Release Notes. The enhancements typically make the compiler stricter in detecting syntax or other conditions, which are surfaced through Error or Warning messages. Error messages must be resolved, as the Business Rules will not complete the compile process. Warning messages are exposed to provide guidance to the Administrator. The displayed line items will still function but should be updated to support the latest compiler’s requirements. The method to resolve the Warning will vary. In some cases, a replacement function may be available, or there may be a change to a function’s properties. Example The above error message informs the Administrator of a Warning on the LookupRowFieldValue function having a property change. By reviewing the current rule, and by looking at the current Function Definition, the Administrator can determine that the property for “Criteria as a String” has been modified. The current Definition now defines the field as a dbWhere object. Old Properties LookupRowFieldValue(ByVal si As SessionInfo, ByVal dbLocation As String, ByVal tableName As String, ByVal criteriaExpression As String, ByVal fieldToReturn As String, ByVal defaultValue As String) As String To correct the condition, the Administrator is required to apply the required change. In this example, a dbWhere object must be used to define the criteria against the target database table. New Properties LookupRowFieldValue(ByVal si As SessionInfo, ByVal dbLocation As String, ByVal tableName As String, ByVal dbWheres As List(Of DbWhere), ByVal fieldToReturn As String, ByVal defaultValue As String) As String Other Compile Issues - Namespaces The Vb.Net language in OneStream offers the designer flexibility to implement custom solutions using predefined libraries as well other compatible third-party libraries. During a Business Rules compile, there are NameSpaces in OneStream that will be implicitly compiled: microsoft.visualbasic system.linq system.collections.generic system.collections system.text OneStream also has predefined Namespaces in Business Rules, which if utilized, must not be removed from the rule to compile properly. Imports System Imports System.Data Imports System.Data.Common Imports System.IO Imports System.Collections.Generic Imports System.Globalization Imports System.Linq Imports Microsoft.VisualBasic Imports System.Windows.Forms Imports OneStream.Shared.Common Imports OneStream.Shared.Wcf Imports OneStream.Shared.Engine Imports OneStream.Shared.Database Imports OneStream.Stage.Engine Imports OneStream.Stage.Database Imports OneStream.Finance.Engine Imports OneStream.Finance.Database The solution to resolving a Namespace issue will depend upon whether the rule exists in a Member Formula or as part of a Business Rule file. When an unsupported Namespace is used in a Business Rule file, the Namespace can be added to the Imports to allow the Business Rules to compile. Member Formulas do not allow access to modify the Import section of Business Rules. If the unsupported Namespace is part of a Member Formula, then the full Namespace must be added to the affected expression or variable.2.1KViews7likes0Comments[How to] Log into a file instead of the Error Log
Logging with OneStream is great but when we all use the Error Log at the same time, things can get messy very quickly. Moreover, logging in a file instead of the Error Log can be very convenient when logging kickouts. The initial setup can be a little involving but once you get a knack out of it, logging in a file is as easy as using the Error Log. In this post, I will show you how to do the initial setup and then how to log into a file instead of the Error Log only when there is an exception or every time. This rule and methodology is the result of the genius work of Matt Ha and I am very thankful he shared it with us. Initial Setup In order to log into a file, you need to import a Public Business Rule, it will be called by the logger and it is available in this post (GS_GlobalHelper.xml). Side note, remember that in order to make a BR Public, you need to change the setting for ‘Contains Global Functions for Formulas’ to True. Setup of the BR to log into a file In order to call a Public function, you need to Reference it in your Business Rule You also need to add it to your Imports: Imports OneStream.BusinessRule.Finance.GS_GlobalHelper.MainClass The Logger function needs 2 variables to be declared and set, I like to do it at the very top of my rule #Region "Logging Variables" Dim bVerboseLogging As String = True Dim logger As New Text.StringBuilder #End Region Then, you need to add 2 Private Functions to your rule, this is where you set your naming convention (if you want to add the data and time or anything else) and the folder name where you want your files to be stored. Private Sub StoreLoggerOnSession(ByVal si As SessionInfo, ByVal api As FinanceRulesApi, ByRef globals As BRGlobals) ' Multithread-safe way to store logger to session Dim globalLogger As Text.StringBuilder = globals.GetObject("globalLogger") If globalLogger Is Nothing Then globals.SetObject("globalLogger", logger) Else globalLogger.AppendLine(logger.ToString) End If End Sub Private Sub WriteSessionLogToFileShare(ByVal si As SessionInfo, ByVal api As FinanceRulesApi, ByRef globals As BRGlobals, ByVal logName As String) ' Write logger stored on session to application database Dim globalLogger As Text.StringBuilder = globals.GetObject("globalLogger") If globalLogger IsNot Nothing Then WriteLogger(si, api, globalLogger, logName, "TestLogs", DateTime.Now.ToString("yyyy-MM-dd-hh-mm")) End If End Sub In the end, your rule should look like this: Logging into a file when there is an Exception You can write to a file instead of the Error log when an Exception happens, in this case, update the Exception Catcher at the end of your Main Function. Catch ex As Exception logger.AppendLine(ex.Message) If bVerboseLogging Then StoreLoggerOnSession(si, api, globals) WriteSessionLogToFileShare(si, api, globals, "MyRule") Throw ErrorHandler.LogWrite(si, New XFException(si, ex)) End Try Logging anything into a file Of course, you can also log anything you would usually log to the Error Log in a file instead. Use the “logger” instead of the Error Log. 'Log to the Error Log api.LogMessage("Logging to the Error Log with the api") brapi.ErrorLog.LogMessage(si, "Logging to the Error Log with the brapi") 'Log to a file logger.AppendLine("Logging to a file").AppendLine #Region "Push logs to the File Explorer" If bVerboseLogging Then StoreLoggerOnSession(si, api, globals) WriteSessionLogToFileShare(si, api, globals, "MyRule") #End Region Results This is what you get in the Error Log And this is what you get in the File Explorer:4.1KViews5likes5CommentsRules Formatting - Please Format Your Rules!!
General Formatting One of the most important things you can do, to make you rules readable and helpful, is making sure they are properly formatted. There are some simple rules you should probably follow all the time: Proper Case – Function names are not case-sensitive; for example, api.data.calculate, Api.Data.Calculate, or API.DATA.CALCULATE, are treated as the same. Still, it is a best practice of VB style to be consistent and to capitalize judiciously. Proper case throughout the rules file makes it much easier to read. Always Comment – Add comments to most lines of code explaining what you are doing and why. Use the apostrophe at the beginning of the comment to make sure it is not interpreted as part of the rules. If this is done in a VB editor, it should turn green by default. Indentation is critical for readability – This is especially true when using any nested statements or conditionals. Those are explained below. Indentation should be done for any scripting, even scripting objects in Business Rules Editor. Variable and Constants properly named – All variables should be given useful names. Line Continuations Properly formatting rules will typically also mean using the underscore ‘_’ and colon ‘:’ symbols. When using space + underscore, you are telling the script that the command continues on the next line. For example: api.data.Calculate("F#[Bad Debt]:A#[EBITDAVar] = " & _ "(A#54100:S#Budget:F#None-A#54100:S#Actual:F#None)") The colon allows you to combine two lines. For example: strSalesAccount = “A#7999.UD1#Sales” : strMktAccount = “A#7999.UD1#Marketing” Comments I think it is important to emphasize the importance of comments. You will not remember in a year or two why something is quite the way it is, so comments will help you from making the same mistake again. It can help provide a new administrator detailed information, such as what needs updating or regular maintenance, if you add a new cash flow account for example. Finally it can help remind you what needs to be considered for an upgrade, or rebuild. Variables & Constants Variables and constants are used to hold values or expressions. Think back to your 9th grade algebra class. In 2+y = x, y is the variable. (See, your teacher was right, this may prove useful yet...) Variables can have any name; but while ‘y’ and ‘x’ are valid names, they don't tell you anything. Names should be something that makes sense. Consider which of the following is easier to follow: 2 + y = x or 2 + strVariablePercent = strPercentMarkUp. I would say you can understand more form the second line of rules than the first, even without knowing the context. Add a line of comments, and note the proper case, and you are on your way to well formatted descriptive rules. A Variable is a value that changes depending on parameters and when it is used; whereas a Constant will not change, regardless of when it is used or changes in the application. You will want to declare constants at the beginning of rules files. They can be available to all procedures at all times. Apart from that, they are used just like variables. You should have some guidelines when writing rules; one of the simplest things to do, to keep yourself organized, is to have a naming convention. I like to use a prefix. The prefix is something that helps me remember what is in the variable. I might use ‘str’ or ‘s’ for a string, or ‘bln’ or ‘b’ for a Boolean (true or false), and ‘nbr’ or ‘n’ for number. Then using proper case I use a descriptive label for my variable. So, for a number from Net Income, my variable might be called ‘nbrNetIncome’. I can see that variable name anywhere in my file and know what the variable is for and what it is. Compare that with ‘x’; if I just see x, who knows what it is for. It also helps to know what you are going to use the variable for. We have two names for variables; Replacement Variables and Execution Variables. Replacement Variables are typically used for constants like static strings (for example topUD1=“.UD1#TopUserDefined1”). This variable might change, but it is replacing some part of a string. Execution Variables are typically used for situations in which variable is populated or reset during some condition or rule (for example sPOVEntity = api.POV.Entity.Name). The point of view changes constantly and what would be written in the variable would be updated accordingly. There are some rules for variable names that you just must follow, to write valid VB.Net. They must always begin with a letter. They cannot contain a period. You should avoid keywords such as “OneStream”, “Entity”, “Account”, when naming variables; they tend to be reserved by OneStream and could cause problems if shadowed. VB.Net requires you to declare variables before using them. Since variables will require what type they can hold, you need to make sure you avoid letting the variable use a type that Rules Engine is not expecting for that member. For example, if you write a rule checking if the year is 2010, OneStream could see that as something different than “2010”. By using the quotes and declaring it As String, the number 2010 becomes a String of text, “2010”. Otherwise you might get a Type Mismatch error in some situations; if you do get this error, double check that the variable you are testing is correctly declared.2.5KViews4likes2Comments[howto] Use "Insert Code" when posting on Forum boards
Hey guys! Just a reminder: if you're going to post code in this forum, please make it easier to read by using the "Insert/Edit Code Sample" button on the expanded formatting toolbar. Here's a short video showing how it works. If you need to edit code after you created the block, just double-click on it. Ideally you'd also indent it first, either in an editor or with something like DotNetFiddle. Remember: the easier it is for others to read your code, the more likely that they'll be able to solve your problem! Cheers! Your friendly neighborhood Spider-Mod3KViews4likes6CommentsTriggering System Business Rules
Hello All, Could someone guide on how a system business rule is triggered? As part of automating some daily tasks, we intend to automate addition, deletion of metadata members through a system business rule. Is the process similar to triggering extender rules? Any leads would be appreciated. ThanksSolved2.7KViews1like2CommentsGitHub/OneStream Integration
Does anyone have experience leveraging GitHub or any other code version control tool to manage Business Rules with OneStream? Assuming we have a remote Git repository on GitHub that keep track of all of our business rules. How do we push the code from remote repository to OneStream? Or in other words how do we run git command to push/pull. In this context, we want to assume there is file system on cloud store all the business rules in file format. If there is no file system on OneStream, how are the Business Rules managed on cloud? Any pointers will be appreciated. We found a way to update the Business Rule table: xml_data in Application Database. But we are seeking for better options.Solved1.3KViews1like12CommentsGet WFScenario in Complex Expression Time Data Source
I am trying out a complex expression in Time Data Source. The issue is the next: I have a Forecast scenario type with input frequency monthlyand on the other hand I have a Long Term scenario type with input frequency yearly. Therefore, the colum time in the file is yearly, so I developed a complex expression where I can load depending on neither scenario type year 2024 or WFTime (forecast for this case) or scenario type year 2024 + M12 or WFTime + M12 (Long Term for this case). This is my complex expression (that is not working): Dim vYear As String = args.Value Dim scenId As Integer=api.CurrentDataClusterKey.ScenarioID Dim scenType As ScenarioType = BRApi.Finance.Scenario.GetScenarioType(si,scenId) If scenType=ScenarioType.Forecast Then Return vYear + "M12" Else Return vYear End If I appreciate all your comments, Thank you.Solved695Views1like1CommentLoadCustomTableUsingExcel function not working when loading to table having unique constraints
Hi, I am using the LoadCustomTableUsingExcel function to load an Excel file to an application table. The function seems to be working fine in most cases. However, I am having issue with tables having unique constraints. The table has Payroll, PeopleGroup and Amount columns. The unique constraint was added because users can also insert into the table using an SQL editor component, so we want to avoid them do be able to insert duplicated rows. When trying to load a row which already exist in the table using the LoadCustomTableUsingExcel function I get the following error (example): “Column ‘Payroll, PeopleGroup' is constrained to be unique. Value 'Payroll_AE, PplGroup001' is already present.” This issue only appears when loading in Merge. Replace works fine. Normally (with table not having a unique constraint) it is not an issue loading rows that are already in the application table because the Merge tag in the Excel file make so that only new rows are added to the table while rows already present are ignore and not duplicated (as you would expect from a merge). Thank you for any suggestion you can give meSolved2.9KViews1like9CommentsData source with fixed UNC-Path
Hi all, is there a possibility to create a data source and give it a fixed file-name on an UNC path instead of having to select it in the user-interface? e.g. assume I get the file always put to \\fileserver\sharename\subfolder\filename.csv and want to directly load from there. If not, what would be the workaround? Thanks Markus1.3KViews1like3CommentsUnable to change certification state
Hi Team, I have tried to make a simple task - if user in not in group I would like to change a certification status to rejected. This code is in DataQualityEventHandler: Case Is = BREventOperationType.DataQuality.Certify.FinalizeSetQuestionairreState Dim sGuid As String = "419eeb3d-eaec-43fc-bc0a-cab5862323f10" Dim Guid_1 As New Guid(sGuid) If BRApi.Security.Authorization.IsUserInGroup(si, si.UserName, "GROUP",False) = False Then BRApi.DataQuality.Process.ExecuteQuestionnaireSignOff(si,si.WorkflowClusterPk,Guid_1,CertSignOffStates.ProfileRejected,"Comments") End If It always returns "Certified", but should "Rejected": Any ideas what am I missing?1.6KViews1like4Comments