Forum Discussion

KR2012's avatar
KR2012
New Contributor
3 days ago

BR Rule - BR api Error log

Hello All, OS experts - Greetings !

I am trying to complete the following code to extract the year and month from a given date. To help with validation and debugging, I've enabled BRAPI.ErrorLog.LogMessage to display the variable outputs in the error log.

However, for some reason, it is not displaying any values in the error log. I would greatly appreciate any insights into what might be wrong with the code. Here is the code I am working with:

Dim vDate As String = args.NameValuePairs.XFGetValue("Date")
' e.g., "01/01/2025" (MM/DD/YYYY format)

' Log the retrieved Date for debugging
BRAPI.ErrorLog.LogMessage(si, "vDate: " & vDate)

' Ensure vDate is not null or empty before proceeding
If Not String.IsNullOrEmpty(vDate) Then
    ' Extract the year (last 4 characters) from vDate and convert to an integer
    Dim vYear As Integer = CInt(vDate.Substring(6, 4))
    BRAPI.ErrorLog.LogMessage(si, "vYear: " & vYear)

    ' Extract the month (first 2 characters) from vDate and convert to an integer
    Dim vMonth As Integer = CInt(vDate.Substring(0, 2))
    BRAPI.ErrorLog.LogMessage(si, "vMonth: " & vMonth)
Else
    BRAPI.ErrorLog.LogMessage(si, "vDate is null or empty!")
End If

Thank you in advance. 

  • DanielWillis's avatar
    DanielWillis
    Valued Contributor

    Are you saying you are not even getting "vDate is null or empty!"? If you are not getting any of these logging lines from the above sample code in your error log (and there are no error messages in log) then I don't think your business rule is even getting to this section of code.

    Edit: or are you saying you're getting error messages but vDate is blank? If so then I would suggest it isn't being passed in properly.

  • MarcusH's avatar
    MarcusH
    Contributor III

    You can use DateTime.TryParse like this:

    Dim vDate As String = args.NameValuePairs.XFGetValue("Date")
    Dim parsedDate As DateTime
    
    ' Parse the date string to a DateTime object
    If DateTime.TryParse(vDate, parsedDate) Then
        ' Extract the month and year
        Dim month As Integer = parsedDate.Month
        Dim year As Integer = parsedDate.Year
    
        BRAPI.ErrorLog.LogMessage(si, $"Month: [{month}], Year: [{year}]")
    Else
        BRAPI.ErrorLog.LogMessage(si, $"Can't parse date [{vDate}]")
    End If

     

  • KR2012's avatar
    KR2012
    New Contributor

    Thank you @DanielWillis and @MarcusH

    Yes, I am receiving the output from the 'else' condition, which states 'Date is null or empty'. However, the Date field does have a value in the record, and it seems to be ignoring this and still executing the 'else' condition.

    I have highlighted the column we intend to use for the logic. Below are the record details from the Thing Register, along with the error log for further clarity.

     

     

    • DanielWillis's avatar
      DanielWillis
      Valued Contributor

      So how are you passing the value into your business rule? That seems to be the problem. I think you really need to give the full context. The screenshots were a step in the right direction.

      • KR2012's avatar
        KR2012
        New Contributor

        Hi, DanielWillis - Thank you for your reply. 

        The business wants to calculate costs based on the project start date and compare it to the workflow time.

        the business rule (payout process) will assess the project's initiation date (LetDate) and calculate the mobilization amounts of 2%, 3%, and 7% for LetMonth +1, LetMonth +2, and LetMonth +3, respectively. This applies only to projects that are expected to last 75 days or more.

        Processing Logic: The mobilization calculation applies to active projects and follows these conditions:

        • Case 1: If the number of workdays is 0, the "Left to Pay" amount should be evenly spread over 18 months.
        • Case 2: If the project has more than 75 workdays, the mobilization calculations will be as follows based on the LetMonth.

        For a project starting in May with 200 workdays, the mobilization schedule is:

        • If the forecast is for May:
          • June: 2%
          • July: 3%
          • August: 7%
        • If the forecast is for June:
          • June: 3%
          • July: 7%
        • If the forecast is for July:
          • July: 7%
        • If the forecast is for August or any later months:
          • Mobilization is not applied.

        The project start date is sourced from the Thing Planning Register.

        When I run the "calculate after update" process, it is throwing an error. To troubleshoot, I enabled debug mode and discovered that the date is not being read properly as mentioned in the earlier post.  here is the code for this function for your reference. 

        ============================================

        Public Function GetActiveDriverValue(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As DashboardStringFunctionArgs, ByRef driver As String, ByRef entityMember As String) As String

        Try

         

        'Entity is always E#UNFD for drivers

        Dim tlpHelper As New OneStream.BusinessRule.DashboardStringFunction.TLP_ParamHelper.MainClass

        Dim regID As String = args.NameValuePairs.XFGetValue("RegID")

        Dim field As String = args.NameValuePairs.XFGetValue("Field")

        Dim account As String = args.NameValuePairs.XFGetValue("Account")

        Dim period As Decimal = args.NameValuePairs.XFGetValue("Period")

         

        Dim Entity As String = "UNFD"

         

        ' Start - Mobilization logic 

        'Dim WFTimeName As String = args.NameValuePairs.XFGetValue("WFTimeName").ToString.Replace("'","")

        Dim WFTimeName As String = args.NameValuePairs.XFGetValue("WFTimeName").ToString.Replace("'","")

        BRAPI.ErrorLog.LogMessage(si, "WFTimeName: " & WFTimeName)

         

        'Dim WFYear As String = args.NameValuePairs.XFGetValue("WFYear").ToString.Replace("'","")

        Dim WFYear As String = args.NameValuePairs.XFGetValue("WFYear").ToString.Replace("'","")

         

        BRAPI.ErrorLog.LogMessage(si, "WFYear: " & WFYear)

         

         

        ' End - Mobilization logic

        Dim scenarioName As String = ScenarioDimHelper.GetNameFromId(si, si.WorkflowClusterPk.ScenarioKey)

        Dim timeID As Integer = BRApi.Finance.Members.GetMemberId(si, DimType.Time.Id, WFTimeName)                                            

         

        ' START - Mobilization logic update

        'Dim DriverTime As String = WFTimeName

         

        Dim DriverTime As String = WFTimeName

        BRAPI.ErrorLog.LogMessage(si, "DriverTime: " & DriverTime)

         

        ' END - Mobilization logic update

         

         

        ' START- Mobilization Logic update

        ' Dim letDate As String = args.NameValuePairs.XFGetValue("letDate") '09/01/2023

        ' '2023M01

        ' BRAPI.ErrorLog.LogMessage(si, "vLetDate: " & letDate)

        ' Dim letYear As Integer = CInt(letDate.Substring(0,4))

        ' BRAPI.ErrorLog.LogMessage(si, "vLetDate: " & letDate)

        ' Dim letMonth As Integer = CInt(letDate.Substring(4,2))

        ' BRAPI.ErrorLog.LogMessage(si, "vletMonth: " & letMonth)

        ' Retrieve the letDate value from the NameValuePairs

        'Dim letDate As String = args.NameValuePairs.XFGetValue("letDate") 

        'Dim letDate As String = args.NameValuePairs.XFGetValue("letDate")

        '' e.g., "09/01/2023" (MM/DD/YYYY format)

         

        '' Log the retrieved letDate

        ''BRAPI.ErrorLog.LogMessage(si, "vLetDate: " & letDate)

         

        '' Extract the year (first 4 characters) from letDate and convert to an integer

        'Dim letYear As Integer = CInt(letDate.Substring(6, 4))

        'BRAPI.ErrorLog.LogMessage(si, "LetYear: " & letYear)

         

        '' Extract the month (characters at position 1 and 2) from letDate and convert to an integer

        'Dim letMonth As Integer = CInt(letDate.Substring(0, 2))

        'BRAPI.ErrorLog.LogMessage(si, "LetMonth: " & letMonth)

         

        Dim vActiveDate As String = args.NameValuePairs.XFGetValue("ActiveDate")

        ' e.g., "01/01/2025" (MM/DD/YYYY format)

         

        ' Log the retrieved Date for debugging

        BRAPI.ErrorLog.LogMessage(si, "vActiveDate: " & vActiveDate)

         

        Dim letDate As String = args.NameValuePairs.XFGetValue("Let Date")

        ' e.g., "01/01/2025" (MM/DD/YYYY format)

         

        ' Log the retrieved Date for debugging

        BRAPI.ErrorLog.LogMessage(si, "letDate: " & letDate)

         

        Dim vletDate As Integer = args.NameValuePairs.XFGetValue("Let Date")

        ' e.g., "01/01/2025" (MM/DD/YYYY format)

         

        ' Log the retrieved Date for debugging

        BRAPI.ErrorLog.LogMessage(si, "letDate: " & letDate)

         

        ' Ensure vDate is not null or empty before proceeding

        If Not String.IsNullOrEmpty(letDate) Then

            ' Extract the year (last 4 characters) from vDate and convert to an integer

            Dim letYear As Integer = CInt(letDate.Substring(6, 4))

            BRAPI.ErrorLog.LogMessage(si, "letYear: " & letYear)

         

            ' Extract the month (first 2 characters) from vDate and convert to an integer

            Dim letMonth As Integer = CInt(letDate.Substring(0, 2))

            BRAPI.ErrorLog.LogMessage(si, "letMonth: " & letMonth)

        Else

            BRAPI.ErrorLog.LogMessage(si, "letDate is null or empty!")

        End If

         

        ' END- Mobilization Logic update

         

        'Dim value As Decimal = args.NameValuePairs.XFGetValue("Amount")

        Dim calcPer As Decimal = args.NameValuePairs.XFGetValue("calcPer")

        Dim LeftToPay As Decimal = args.NameValuePairs.XFGetValue("LeftToPay")

        Dim workDays As Decimal = args.NameValuePairs.XFGetValue("WorkDays")

        Dim presPer As Decimal = args.NameValuePairs.XFGetValue("PresPer")

        'Change on 13 Jan by Arpit

        Dim outPer As Integer = args.NameValuePairs.XFGetValue("outPer")

        Dim delayedFlag As Boolean = If(args.NameValuePairs.XFGetValue("delayFlag").Equals("'Delay'"), True, False)

        'Change on 5th feb by Arpit

        'Dim MobDictionary As New Dictionary(Of String, Integer)

        Dim mobCounter As Integer = Nothing

        Dim amountPerDay As Decimal = 0

        'The Account member can be be passed in as a parameter if this is being called from another procedure, so check for that first

        Dim accountMember As String = Nothing

        Dim monthlyAmount As Decimal = 0

        Dim ratio1 As Decimal = args.NameValuePairs.XFGetValue("mobRatio1")

        Dim ratio2 As Decimal = args.NameValuePairs.XFGetValue("mobRatio2")

        Dim ratio3 As Decimal = args.NameValuePairs.XFGetValue("mobRatio3")

         

        Dim month As String = scenarioName.Substring(8)

        Dim year As String = scenarioName.Substring(0,4)

        Dim cumulativeSum As Decimal = tlpHelper.GetSumCum(si, globals, api, args)

         

        'Get the Cube name to pull the driver from

        'TO DO: consider passing cube name or referencing through BRAPI

        Dim cubeName As String = args.NameValuePairs.XFGetValue("cubeName").ToString.Replace("'",Nothing)

        Dim cubeNamePOV As String = args.SubstVarSourceInfo.PovCube.Name.ToString

         

        Dim ud1Member As String = args.NameValuePairs.XFGetValue("ud1Member").ToString.Replace("'",Nothing)

        Dim ud2Member As String = args.NameValuePairs.XFGetValue("ud2Member").ToString.Replace("'",Nothing)

        Dim ud3Member As String = args.NameValuePairs.XFGetValue("ud3Member").ToString.Replace("'",Nothing)

        Dim ud4Member As String = args.NameValuePairs.XFGetValue("ud4Member").ToString.Replace("'",Nothing)

        Dim ud5Member As String = args.NameValuePairs.XFGetValue("ud5Member").ToString.Replace("'",Nothing)

        Dim ud6Member As String = args.NameValuePairs.XFGetValue("Category").ToString.Replace("'",Nothing)

        Dim ud7Member As String = args.NameValuePairs.XFGetValue("ud7Member").ToString.Replace("'",Nothing)

        Dim ud8Member As String = args.NameValuePairs.XFGetValue("ud8Member").ToString.Replace("'",Nothing)

         

        If Entity = Nothing Then Entity = "None"

        If accountMember = Nothing Then accountMember = "ProjectWorkdays"

        If ud1Member = Nothing Then ud1Member = "None"

        If ud2Member = Nothing Then ud2Member = "None"

        If ud3Member = Nothing Then ud3Member = "None"

        If ud4Member = Nothing Then ud4Member = "None"

        If ud5Member = Nothing Then ud5Member = "None"

        If ud6Member = Nothing Then ud6Member = "None"

        If ud7Member = Nothing Then ud7Member = "None"

        If ud8Member = Nothing Then ud8Member = "None"

         

        'Identify periods for calculation

        ''' Months 1-12  = Year 1

        ''' Months 13-24 = Year 2

        ''' Months 25-36 = Year 3

        ''' Months 37-48 = Year 4

        ''' Months 49-60 = Year 5

         

        'driverTime = WFYear & "M" & calcPer

        'Calendar

        'Dim startMonth As Integer = TXcalendarMap.Item(month) + calcPer '10

        'Dim startMonth As Integer = month + calcPer 'removed and replaced startMonth with calcPer - 2/2 AK

         

        Dim calcYear,calcPeriod As Integer

         

        calcYear = Math.Truncate(calcPer/12)

        calcPeriod = calcPer Mod 12

         

        If(calcPeriod <> 0) Then

        driverTime = WFYear + calcYear & "M" & calcPeriod

        Else

        driverTime = WFYear + calcYear -1 & "M12"

        End If

         

        'Build the driver member string to retrieve work days by category

        'Cb#TXDOT:E#UNFD:P#?:C#Local:S#Actual:T#2022M1:V#Periodic:A#WorkdaysPerMonth:F#None:O#Forms:I#None:U1#None:U2#None:U3#None:U4#None:U5#None:U6#None:U7#None:U8#None

        Dim mbrStringWDMth As String 

        mbrStringWDMth = "E#" & Entity

        mbrStringWDMth = mbrStringWDMth & ":C#Local"

        mbrStringWDMth = mbrStringWDMth & ":S#Actual" '& scenarioName 

        mbrStringWDMth = mbrStringWDMth & ":T#" & driverTime

        mbrStringWDMth = mbrStringWDMth & ":V#Periodic"

        mbrStringWDMth = mbrStringWDMth & ":A#WorkdaysPerMonth"

        mbrStringWDMth = mbrStringWDMth & ":F#None:O#Forms:I#None"

        mbrStringWDMth = mbrStringWDMth & ":U1#None"

        mbrStringWDMth = mbrStringWDMth & ":U2#" & ud2Member 

        mbrStringWDMth = mbrStringWDMth & ":U3#" & ud3Member

        mbrStringWDMth = mbrStringWDMth & ":U4#" & ud4Member

        mbrStringWDMth = mbrStringWDMth & ":U5#" & ud5Member

        mbrStringWDMth = mbrStringWDMth & ":U6#None"

        mbrStringWDMth = mbrStringWDMth & ":U7#" & ud7Member

        mbrStringWDMth = mbrStringWDMth & ":U8#" & ud8Member

        'BRAPI.ErrorLog.LogMessage(si, "Driver POV: " & mbrStringWDMth)

         

        ' 'GetDataCell and Return Driver Value: Workdays by Month

        Dim workDaysMonth As Integer

        workDaysMonth = BRApi.Finance.Data.GetDataCellUsingMemberScript(si, "TXDOT", mbrStringWDMth).DataCellEx.DataCell.CellAmount

         

        Dim mobAmt As Decimal = 0 

         

        Dim counter As Integer = globals.GetInt32Value(regID)

        'Brapi.ErrorLog.LogMessage(si,$" counter is {counter}")

        If counter = -1 Then

        'Brapi.ErrorLog.LogMessage(si,$" counter inside -1")

        globals.SetInt32Value(regID, 1)

        counter = 1

        End If

        Dim remAmt As Decimal = 0

         

        If LeftToPay > 0 Then

                    ' Handle case when workDays = 0 (spread over 18 months)

                    If workDays = 0 Then

                        remAmt = LeftToPay - cumulativeSum

                        monthlyAmount = LeftToPay / 18

                    End If

         

                    ' Handle different months and workdays greater than 75

         

                    If letMonth >= 1 and  And workDays > 75 Then

                        For i As Integer = 1 To 3

                            If letMonth = i Then

                                If counter = 1 Then

                                    globals.SetInt32Value(regID, 2)

                                    mobAmt = remAmt * ratio1

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

                                ElseIf counter = 2 Then

                                    globals.SetInt32Value(regID, 3)

                                    mobAmt = remAmt * ratio2

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

                                ElseIf counter = 3 Then

                                    globals.SetInt32Value(regID, 4)

                                    mobAmt = remAmt * ratio3

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

                                ElseIf counter = 4 Then

                                    If monthlyAmount > remAmt Then

                                        Return remAmt

                                    Else

                                        Return monthlyAmount

                                    End If

                                End If   

                            End If

                        Next i

                    End If

         

                    ' Handle cases for letMonth >= 4

                    If letMonth >= 4 Then

                        remAmt = LeftToPay - cumulativeSum

                        amountPerDay = LeftToPay / workDays

                        monthlyAmount = amountPerDay * workDaysMonth

         

                        If monthlyAmount > remAmt Then

                            Return remAmt

                        Else

                            Return monthlyAmount

                        End If

                    End If

             

        Else

        'Standard Calculation

        remAmt = LeftToPay - cumulativeSum

        amountPerDay = LeftToPay / workDays

        monthlyAmount = amountPerDay * workDaysMonth

        'Brapi.ErrorLog.LogMessage(si,$" remAmt is {remAmt} , amountPerDay is {amountPerDay} and monthlyAmount is {monthlyAmount}")

         

        If (outPer = -3) Then

        If (counter = 1) Then

        globals.SetInt32Value(regID,2)

        mobAmt = remAmt * ratio3

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

        Else If (counter = 2)

        If monthlyAmount > remAmt Then

        Return remAmt 

        Else

        Return monthlyAmount

        End If

        End If

        Else If(outPer = -2) Then

        'Brapi.ErrorLog.LogMessage(si,$" Outper is -2 , counter is {counter} and {RegID}")

        'Brapi.ErrorLog.LogMessage(si,$" counter is {counter}")

         

        If (counter = 1) Then

        globals.SetInt32Value(regID,2)

        mobAmt = remAmt * ratio2

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

        Else If (counter = 2) Then

        globals.SetInt32Value(regID,3)

        mobAmt = remAmt * ratio3

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

        Else If (counter = 3)

        If monthlyAmount > remAmt Then

        Return remAmt 

        Else

        Return monthlyAmount

        End If

        End If

        Else If(outPer >= -1) Then

        'Brapi.ErrorLog.LogMessage(si,$" Outper is -1 , counter is {counter} and {RegID}")

        'Brapi.ErrorLog.LogMessage(si,$" counter is {counter}")

         

        If(counter = 1) Then

        globals.SetInt32Value(regID,2)

        mobAmt = remAmt * ratio1

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

        Else If (counter = 2) Then

        globals.SetInt32Value(regID,3)

        mobAmt = remAmt * ratio2

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

        Else If (counter = 3) Then

        globals.SetInt32Value(regID,4)

        mobAmt = remAmt * ratio3

        If (remAmt < monthlyAmount) Then

        Return remAmt

        Else If(mobAmt > monthlyAmount) Then

        Return mobAmt

        Else

        Return monthlyAmount

        End If

        Else If (counter = 4)

        If monthlyAmount > remAmt Then

        Return remAmt 

        Else

        Return monthlyAmount

        End If

        End If

         

        Else

        If monthlyAmount > remAmt Then

        Return remAmt 

        Else

        Return monthlyAmount

        End If

        End If

        End If

        End If

         

        Return Nothing

        Catch ex As Exception

        Throw ErrorHandler.LogWrite(si, New XFException(si, ex))

        End Try

        End Function

        #End Region

        ==========================

         

         

    • rhankey's avatar
      rhankey
      Contributor

      Given this a Thing Planning register field, I believe you need to be referencing the "internal" register filed name (such as Code1, TermDate, etc), and not the user visible "alias" of the field.  If you are unsure what the internal register field name is, go to Thing Planning Settings, and then Register Field List to see how the internal field names have been mapped to the visible field aliases.

      If you are still in doubt, dump out the dictionary keys or keys and values found in args.NameValuePairs, as you are currently trying to access a dictionary key that does not exist in the dictionary.