Guest User

FXT_TravelDistance_FTD.txt

a guest
Jun 4th, 2024
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 15.11 KB | Source Code | 0 0
  1. '--DESCRIPTION---------------------------------------------------------------------------------------
  2.                 ' This Extender business rule can be used to calculate travel dinstances and time between adresses/ places
  3.                 ' It is used to populate maps in dashboard tables, already discoverd distances should be stored in a table to reduce API costs
  4.                 ' Make sure --Imports System.Net and others below -- are added on the top of your code
  5.                 '----------------------------------------------------------------------------------------------------
  6.  
  7.                 '--VARIABLES-----------------------------------------------------------------------------------------
  8.                 Dim wfUnitPK As WorkflowUnitPk = BRApi.Workflow.General.GetWorkflowUnitPk(si)
  9.                 Dim sYear As String = TimeDimHelper.GetYearFromId(wfUnitPK.TimeKey).ToString
  10.                 Dim sMonth As String = TimeDimHelper.GetSubComponentsFromId(wfUnitPK.TimeKey).Month.ToString
  11.                 Dim sTime As String = sYear & "M" & sMonth
  12.                 Dim iTimeId As Integer = BRApi.Finance.Time.GetIdFromName(si, sTime)
  13.                 Dim iScenarioTypeID As Integer = BRApi.Finance.Scenario.GetScenarioType(si, brapi.Finance.Members.GetMemberId(si, dimtype.Scenario.Id, "Plan")).Id
  14.                 Dim sDestination As String = Nothing
  15.                 Dim sOrigin As String = Nothing
  16.                 Dim sAPIKey As String = "<YOUR API KEY GOES HERE>"
  17.                 Dim sSQL As String = Nothing
  18.                 '----------------------------------------------------------------------------------------------------
  19.  
  20.                 '--FIRST RUN FOR DISTANCEMATRIX----------------------------------------------------------------------
  21.                
  22.                 'Create SQL table if it doesn't exist yet
  23.                 Using dbConnApp As DBConnInfo = BRAPi.Database.CreateApplicationDbConnInfo(si)
  24.  
  25.                     'Create the aGoogleData Table if it doesn't exist
  26.                     sSQL = "IF NOT EXISTS (SELECT 1 FROM information_Schema.tables WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'aGoogleData')
  27.                             --DROP TABLE [dbo].[aGoogleData] --Only use for recreation of table
  28.                    
  29.                             CREATE TABLE [aGoogleData] (
  30.                                 [OriginDestinationKey] [varChar] (250) Not Null,
  31.                                 [Employee] [varChar] (100) Not Null,
  32.                                 [Origin] [varChar] (150) Not Null,
  33.                                 [Destination] [varChar] (150) Not Null,
  34.                                 [iDistance] integer,
  35.                                 [Distance] [VarChar] (50),
  36.                                 [iTravelTime] integer,
  37.                                 [TravelTime] [VarChar] (50),
  38.                                 CONSTRAINT PK_aGoogleData PRIMARY KEY CLUSTERED
  39.                                     (
  40.                                     OriginDestinationKey ASC,
  41.                                     Employee ASC
  42.                                     )                  
  43.                                 ) ON [PRIMARY]"
  44.                     'Execute the database creation script
  45.                     BRAPi.Database.ExecuteActionQuery(dbConnApp, sSQL.ToString, False, True)
  46.  
  47.                     'Retrieve existing table from OneStream database
  48.                     sSQL = "SELECT OriginDestinationKey
  49.                             , Employee
  50.                             , Origin
  51.                             , Destination
  52.                             , iDistance
  53.                             , Distance
  54.                             , iTravelTime
  55.                             , TravelTime
  56.                             FROM aGoogleData"
  57.  
  58.                     Dim dt As DataTable = BRApi.Database.ExecuteSqlUsingReader(dbConnApp, sSQL, False)
  59.  
  60.                     'Create a list for all employees that have an address in Text1
  61.                     Dim lstEmployees As List(Of member) = BRApi.Finance.Members.GetBaseMembers(si, brapi.Finance.Dim.GetDimPk(si, "Employees"),brapi.Finance.Members.GetMemberId(si, dimtype.UD4.Id, "Employees"))
  62.                     Dim lstEmployeesFiltered As New List(Of String)
  63.                     'Remove members that don't have a Text1 populated
  64.                     For Each mbrEmployee In lstEmployees
  65.                         Dim sText1 As String = BRApi.Finance.UD.Text(si, dimtype.ud4.Id, mbrEmployee.MemberId, 1, iScenarioTypeID, iTimeId)
  66.                         If sText1 <> ""
  67.                             'Text1 found, add to filtered list
  68.                             lstEmployeesFiltered.Add(sText1 & "|" & mbrEmployee.name)
  69.        
  70.                         End If 'sText1 <> ""
  71.                     Next 'mbrEmployee
  72.  
  73.                     'Create a list for all locaitons that have an address in Text 1
  74.                     Dim lstLocations As List(Of member) = BRApi.Finance.Members.GetBaseMembers(si, brapi.Finance.Dim.GetDimPk(si, "Locations"), brapi.Finance.Members.GetMemberId(si, dimtype.UD1.Id, "Locations"))
  75.                     Dim lstLocationsFiltered As New List(Of String)
  76.                     'Remove members that don't have a Text1 populated
  77.                     For Each mbrLocation In lstLocations
  78.                         Dim sText1 As String = BRApi.Finance.UD.Text(si, dimtype.ud1.Id, mbrLocation.MemberId, 1, iScenarioTypeID, iTimeId)
  79.                         If sText1 <> ""
  80.                             'Text1 found, add to filtered list
  81.                             lstLocationsFiltered.Add(sText1)
  82.                         End If 'sText1 <> ""
  83.                     Next 'mbrEmployee
  84.  
  85.                     'Generate request for each combination
  86.                     For Each sLocation In lstLocationsFiltered 'loop over locations
  87.                         For Each sEmployee In lstEmployeesFiltered 'loop over employees
  88.                             'Update parameters
  89.                             sDestination = sLocation
  90.                             sOrigin = sEmployee.Substring(0,sEmployee.IndexOf("|"))
  91.  
  92.                             'Validate if OrignDestinationKey already exists
  93.                             Dim drFound () As DataRow
  94.                             drFound = dt.select("OriginDestinationKey='" & sOrigin & "_TO_" & sDestination & "' AND Employee='" & sEmployee.Substring(sEmployee.IndexOf("|")+1) & "'")
  95.  
  96.  
  97.                             'If found return value, else retrieve from Google and add to DT
  98.                             If drFound.Length > 0
  99.                                 brapi.ErrorLog.LogMessage(si, "DR Found for: " & sOrigin & "_TO_" & sDestination & vbNewLine & drFound.ToString)
  100.                             Else
  101.                                 'REST API request
  102.                                 Dim wRequest As WebRequest = WebRequest.Create("https://maps.googleapis.com/maps/api/distancematrix/json?destinations=" & sDestination & "&origins=" &sOrigin & "&units=metric&key=" & sApiKey)
  103.                                 Dim request As HttpWebRequest = DirectCast(wRequest, HttpWebRequest)
  104.                                     request.ContentType = "application/json"
  105.                                     request.Method = "GET"
  106.                                 Dim sJson As String = String.Empty
  107.  
  108.                                 'Make the REST api call
  109.                                 Using httpResponse As HttpWebResponse = request.GetResponse()
  110.                                     Using respStream As Stream = httpResponse.GetResponseStream()
  111.                                         Using streamReader As New StreamReader(respStream)
  112.                                             Do While streamReader.Peek() >= 0
  113.                                                 sJson = streamReader.ReadToEnd
  114.                                             Loop 'While streamReader.Peek() >= 0
  115.                                         End Using 'streamReader
  116.                                     End Using 'respStream
  117.                                 End Using 'httpResponse
  118.  
  119.  
  120.  
  121.                                 'Parse sJson
  122.                                 Dim objResponse As distanceMatrixResponse = JsonConvert.deserializeObject(Of distanceMatrixResponse)(sJson.Replace("[","").Replace("]",""))
  123.  
  124.  
  125.                                 If objResponse.status = "OK" AndAlso objResponse.rows.elements.status = "OK"
  126.                                     'Insert into dataTable
  127.                                     Dim drNew As datarow = dt.NewRow
  128.                                     drNew("OriginDestinationKey") = sOrigin & "_TO_" & sDestination
  129.                                     drNew("Employee") = sEmployee.Substring(sEmployee.IndexOf("|")+1)
  130.                                     drNew("Origin") = sOrigin
  131.                                     drNew("Destination") = sDestination
  132.                                     drNew("iDistance") = objResponse.rows.elements.distance.value
  133.                                     drNew("Distance") = objResponse.rows.elements.distance.text
  134.                                     drNew("iTravelTime") = objResponse.rows.elements.duration.value
  135.                                     drNew("Traveltime") = objResponse.rows.elements.duration.text
  136.                                     'Add row to datatable
  137.                                     dt.Rows.Add(drNew)
  138.                                 Else
  139.                                     brapi.ErrorLog.LogMessage(si, "Error retrieving Google data for " & sOrigin & "_TO_" & sDestination & vbNewLine & "Overall: " & objResponse.status & vbNewLine & "Row: " & objResponse.rows.elements.status)
  140.                                 End If 'objResponse.status = "OK"
  141.                             End If 'drFound.Length > 0
  142.                         Next 'sEmployee
  143.                     Next 'sLocation
  144.  
  145.                     'Write datatable back to database (if updated)
  146.                     If dt.Rows.Count > 0
  147.                         'Clear data from database
  148.                         sSQL = "DELETE FROM aGoogleData"
  149.  
  150.                         'Execute the database creation script
  151.                         BRAPi.Database.ExecuteActionQuery(dbConnApp, sSQL.ToString, False, True)
  152.  
  153.                         'Write datatable back into SQL
  154.                         brapi.Database.SaveCustomDataTable(si, "Application", "aGoogleData", dt, True)
  155.                     End If 'dt.Rows.Count > 0
  156.  
  157.                 '--SECOND RUN FOR GEOCODE----------------------------------------------------------------------------
  158.  
  159.                     'Create the aGoogleDataLatLong Table if it doesn't exist
  160.                     sSQL = "IF NOT EXISTS (SELECT 1 FROM information_Schema.tables WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'aGoogleDataLatLong')
  161.                             --DROP TABLE [dbo].[aGoogleData] --Only use for recreation of table
  162.                    
  163.                             CREATE TABLE [aGoogleDataLatLong] (
  164.                                 [Location] [varChar] (150) Not Null,
  165.                                 [Lat] [varChar] (50) Not Null,
  166.                                 [Long] [varChar] (50) Not Null,
  167.                                 CONSTRAINT PK_aGoogleDataLatLong PRIMARY KEY CLUSTERED
  168.                                     (
  169.                                     Location ASC
  170.                                     )                  
  171.                                 ) ON [PRIMARY]"
  172.                     'Execute the database creation script
  173.                     BRAPi.Database.ExecuteActionQuery(dbConnApp, sSQL.ToString, False, True)
  174.  
  175.                     'Retrieve existing table from OneStream database
  176.                     sSQL = "SELECT Location
  177.                             , Lat
  178.                             , Long
  179.                             FROM aGoogleDataLatLong"
  180.  
  181.                     Dim dtLL As DataTable = BRApi.Database.ExecuteSqlUsingReader(dbConnApp, sSQL, False)
  182.  
  183.                     'Generate request for each Location (both Locations and Employees)
  184.                     For Each sLocation In lstLocationsFiltered 'loop over locations
  185.                         'Validate if Location already exists
  186.                         Dim drFound () As DataRow
  187.                         drFound = dtLL.select("Location='" & sLocation & "'")
  188.  
  189.  
  190.                         'If found return value, else retrieve from Google and add to DT
  191.                         If drFound.Length > 0
  192.                             brapi.ErrorLog.LogMessage(si, "DR Found for: " & sLocation)
  193.                         Else
  194.                             'REST API request
  195.                             Dim wRequest As WebRequest = WebRequest.Create("https://maps.googleapis.com/maps/api/geocode/json?address=" & sLocation & "&key=" & sApiKey)
  196.                             Dim request As HttpWebRequest = DirectCast(wRequest, HttpWebRequest)
  197.                                 request.ContentType = "application/json"
  198.                                 request.Method = "GET"
  199.                             Dim sJson As String = String.Empty
  200.  
  201.                             'Make the REST api call
  202.                             Using httpResponse As HttpWebResponse = request.GetResponse()
  203.                                 Using respStream As Stream = httpResponse.GetResponseStream()
  204.                                     Using streamReader As New StreamReader(respStream)
  205.                                         Do While streamReader.Peek() >= 0
  206.                                             sJson = streamReader.ReadToEnd
  207.                                         Loop 'While streamReader.Peek() >= 0
  208.                                     End Using 'streamReader
  209.                                 End Using 'respStream
  210.                             End Using 'httpResponse
  211.  
  212.  
  213.  
  214.                             'Parse sJson
  215.                             Dim objResponse As GoogleGeoCodeResponse = JsonConvert.deserializeObject(Of GoogleGeoCodeResponse)(sJson)
  216.  
  217.  
  218.                             If objResponse.status = "OK"
  219.                                 'Insert into dataTable
  220.                                 Dim drNew As datarow = dtLL.NewRow
  221.                                 drNew("Location") = sLocation
  222.                                 drNew("Lat") = objResponse.results(0).geometry.location.lat
  223.                                 drNew("Long") = objResponse.results(0).geometry.location.lng
  224.                                 dtLL.Rows.Add(drNew)
  225.                             Else
  226.                                 brapi.ErrorLog.LogMessage(si, "Error retrieving Google data for " & sLocation & vbNewLine & "Overall: " & objResponse.status)
  227.                             End If 'objResponse.status = "OK"
  228.                         End If 'drFound.Length > 0
  229.                     Next 'sLocation
  230.                                
  231.                                
  232.                     For Each sEmployee In lstEmployeesFiltered 'loop over employees
  233.                         'Validate if Location already exists
  234.                         Dim drFound () As DataRow
  235.                         drFound = dtLL.select("Location='" & sEmployee.Substring(0,sEmployee.IndexOf("|")) & "'")
  236.  
  237.  
  238.                         'If found return value, else retrieve from Google and add to DT
  239.                         If drFound.Length > 0
  240.                             brapi.ErrorLog.LogMessage(si, "DR Found for: " & sEmployee.Substring(0,sEmployee.IndexOf("|")))
  241.                         Else
  242.                             'REST API request
  243.                             Dim wRequest As WebRequest = WebRequest.Create("https://maps.googleapis.com/maps/api/geocode/json?address=" & sEmployee.Substring(0,sEmployee.IndexOf("|")) & "&key=" & sApiKey)
  244.                             Dim request As HttpWebRequest = DirectCast(wRequest, HttpWebRequest)
  245.                                 request.ContentType = "application/json"
  246.                                 request.Method = "GET"
  247.                             Dim sJson As String = String.Empty
  248.  
  249.                             'Make the REST api call
  250.                             Using httpResponse As HttpWebResponse = request.GetResponse()
  251.                                 Using respStream As Stream = httpResponse.GetResponseStream()
  252.                                     Using streamReader As New StreamReader(respStream)
  253.                                         Do While streamReader.Peek() >= 0
  254.                                             sJson = streamReader.ReadToEnd
  255.                                         Loop 'While streamReader.Peek() >= 0
  256.                                     End Using 'streamReader
  257.                                 End Using 'respStream
  258.                             End Using 'httpResponse
  259.  
  260.  
  261.  
  262.                             'Parse sJson
  263.                             Dim objResponse As GoogleGeoCodeResponse = JsonConvert.deserializeObject(Of GoogleGeoCodeResponse)(sJson)
  264.  
  265.                             If objResponse.status = "OK"
  266.                                 'Insert into dataTable
  267.                                 Dim drNew As datarow = dtLL.NewRow
  268.                                 drNew("Location") = sEmployee.Substring(0,sEmployee.IndexOf("|"))
  269.                                 drNew("Lat") = objResponse.results(0).geometry.location.lat
  270.                                 drNew("Long") = objResponse.results(0).geometry.location.lng
  271.                                 dtLL.Rows.Add(drNew)
  272.                             Else
  273.                                 brapi.ErrorLog.LogMessage(si, "Error retrieving Google data for " & sEmployee.Substring(0,sEmployee.IndexOf("|")) & vbNewLine & "Overall: " & objResponse.status)
  274.                             End If 'objResponse.status = "OK"
  275.                         End If 'drFound.Length > 0
  276.                     Next 'sEMployee
  277.  
  278.                     'Write datatable back to database (if updated)
  279.                     If dtLL.Rows.Count > 0
  280.                         'Clear data from database
  281.                         sSQL = "DELETE FROM aGoogleDataLatLong"
  282.  
  283.                         'Execute the database creation script
  284.                         BRAPi.Database.ExecuteActionQuery(dbConnApp, sSQL.ToString, False, True)
  285.  
  286.                         'Write datatable back into SQL
  287.                         brapi.Database.SaveCustomDataTable(si, "Application", "aGoogleDataLatLong", dtLL, True)
  288.                     End If 'dt.Rows.Count > 0
  289.                 End Using 'dbConnApp
  290.  
  291.                 Return Nothing
  292.             Catch ex As Exception
  293.                 Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
  294.             End Try
  295.         End Function
  296.     End Class
  297.  
  298.     Public Class distanceMatrixResponse
  299.  
  300.         'JsonProperty(PropertyName = "origin_addresses")
  301.         Public Property destination_addresses() As String
  302.         Public Property origin_addresses() As String
  303.         Public Property rows() As row
  304.         Public Property status As String
  305.  
  306.         Public Class row
  307.             Public Property elements() As element
  308.         End Class
  309.  
  310.         Public Class element
  311.             Public Property distance As distance
  312.             Public Property duration As duration
  313.             Public Property status As String
  314.         End Class
  315.  
  316.         Public Class distance
  317.             Public Property text As String
  318.             Public Property value As Integer
  319.         End Class
  320.  
  321.         Public Class duration
  322.             Public Property text As String
  323.             Public Property value As Integer
  324.         End Class
  325.  
  326.     End Class 'distanceMatrixResponse
  327.  
  328.     Public Class GooglCitiesResult
  329.         Public Property city As String
  330.         Public Property country As String
  331.         Public Property country_code As String
  332.     End Class
  333.  
  334.     Public Class GoogleGeoCodeResponse
  335.         Public Property status As String
  336.         Public Property results As results()
  337.     End Class
  338.  
  339.     Public Class results
  340.         Public Property formatted_address As String
  341.         Public Property geometry As geometry
  342.         Public Property types As String()
  343.         Public Property address_components As address_component()
  344.     End Class
  345.  
  346.     Public Class geometry
  347.         Public Property location_type As String
  348.         Public Property location As location
  349.     End Class
  350.  
  351.     Public Class location
  352.         Public Property lat As String
  353.         Public Property lng As String
  354.     End Class
  355.  
  356.     Public Class address_component
  357.         Public Property long_name As String
  358.         Public Property short_name As String
  359.         Public Property types As String()
  360.     End Class
  361. End Namespace
Tags: OneStream
Add Comment
Please, Sign In to add comment