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:
- If the forecast is for July:
- 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
==========================