Imports ProductiePitching.configs
Imports ProductiePitching.ServiceAgents
Imports ProductiePitching.ServiceAgents.Implementations
Module CacheMapper
#Region "Help functions"
Private ReadOnly _activiteitPerBatchServiceAgent As IActiviteitPerBatchServiceAgent
Sub New()
_activiteitPerBatchServiceAgent = New ActiviteitPerBatchServiceAgent
End Sub
'''
''' Execution of a query into a data reader.
'''
''' The query
Private Function ExecuteIntoDataSet(query As String) As DataSet
Try
Return _activiteitPerBatchServiceAgent.GeefDataSetVoorQuery(query)
Catch ex As Exception
Throw New Exception($"Could not get dataset from the Caché webservice.{vbNewLine}{ex.Message}")
End Try
End Function
Private Function ExtractItemFromDataReader(Of T)(ByRef dr As DataTableReader, key As String, Optional defaultValue As T = Nothing) As T
Dim value As Object
Try
'Check if the column name is not present. If not present, return default value.
If Not HasColumn(dr, key) Then Return defaultValue
'Extract the value with the key.
value = dr.Item(key)
'Check if the value is DBNull or Nothing.
If IsDBNull(value) Or value Is Nothing Then
'If so, return default value.
Return defaultValue
End If
Catch ex As Exception
Throw New Exception($"A value for a work item can't be fetched from the data reader. The key is '{key}'.")
End Try
Try
'Do the conversion explicitly, so exceptions can be caught.
Return CType(value, T)
Catch ex As Exception
Throw New Exception($"A value for a work item can't be converted to the specified type. The key is '{key}', the type is {GetType(T).Name}, the value is {value}.")
End Try
End Function
'''
''' Check if the data reader has a column with that name.
'''
'''
'''
'''
Private Function HasColumn(ByRef dr As DataTableReader, columnName As String) As Boolean
'Loop through each row.
For Each row As DataRow In dr.GetSchemaTable().Rows
'Check if column name matches defined one.
If row("ColumnName").ToString() = columnName Then Return True
Next
'Column name was not found.
Return False
End Function
#End Region
'''
''' Get the correct query.
'''
'''
'''
Private Function FetchQuery(workPostIndex As Integer) As String
'Fetch queries from config.
Dim sqlQueries = ConfigsLoader.SqlQueries()
'Check if index is valid.
If workPostIndex >= sqlQueries.Count Or workPostIndex < 0 Then
Throw New InternalException($"Can't fetch a Caché query with this work post index: {workPostIndex}")
End If
'If so, return correct query.
Return sqlQueries.Item(workPostIndex)
End Function
'''
''' Fetch all the work items for a workpost.
''' The corresponding query will get fetched in here.
'''
''' The index of the workpost, 0 based
''' A list of all the work items with their activities
Public Function GetData(workPostIndex As Integer, employees As List(Of IEmployee)) As List(Of IWorkItem)
'Fetch the query.
Dim queryName As String = FetchQuery(workPostIndex)
'Initialise the list with work items.
Dim workItems As New List(Of IWorkItem)
'Declare datareader.
Dim CacheDataReader As DataTableReader = Nothing
Try
'Execute query and store datareader.
Dim CacheDataSet As DataSet = ExecuteIntoDataSet(queryName)
CacheDataReader = CacheDataSet.CreateDataReader()
'Fetch amount of activities.
Dim activityAmount = FetchNumberOfActivities(workPostIndex)
'Loop through every (result) record.
While CacheDataReader.Read()
'Values of one result (line/record).
Dim workItem As New WorkItem
'Fill with values.
With workItem
.BatchVisual = ExtractItemFromDataReader(CacheDataReader, "BatchVisual", String.Empty)
.DeliverToResource = ExtractItemFromDataReader(CacheDataReader, "Naar", String.Empty)
.ProductGroup = ExtractItemFromDataReader(CacheDataReader, "Productgroep", String.Empty)
.Remark = ExtractItemFromDataReader(CacheDataReader, "Opmerking", String.Empty)
.EndTimeStamp = ExtractItemFromDataReader(CacheDataReader, "EindTijdstip", DateTime.MinValue)
.Activities = ExtractActivities(CacheDataReader, activityAmount, workItem, employees)
End With
'Add to the result list.
workItems.Add(workItem)
End While
'Return the list.
Return workItems
Catch ex As Exception
Throw New Exception($"An error occured while fetching the work items from Caché.{vbNewLine}{ex.Message}")
Finally
'Close connection if datareader is not nothing.
If Not IsNothing(CacheDataReader) Then
CacheDataReader.Close()
End If
End Try
End Function
#Region "Activities"
'''
''' Extract all activities for one work item from the data reader.
'''
'''
'''
Private Function ExtractActivities(dr As DataTableReader, numberOfActivities As Integer, workItem As IWorkItem, employees As List(Of IEmployee)) As List(Of IActivity)
'Declare result list.
Dim activities As New List(Of IActivity)
'Loop for every activity.
For i = 1 To numberOfActivities
'Initialise activity and fill with values.
Dim activity As New Activity
With activity
.Id = ExtractItemFromDataReader(dr, $"ActiviteitID_{i}", String.Empty)
.QuantityToProduce = ExtractItemFromDataReader(dr, $"Aantal_{i}", 0)
.Label = ExtractItemFromDataReader(dr, $"Label_{i}", String.Empty)
.IsReadOnly = ExtractItemFromDataReader(dr, $"ReadOnly_{i}", False)
.StartTimeStamp = ExtractItemFromDataReader(dr, $"StartTijdstip_{i}", DateTime.MinValue)
'Subtract time when date was specified. Time is gotten from config.
.StartBeforeTimestamp = If(.StartTimeStamp = DateTime.MinValue, DateTime.MinValue, .StartTimeStamp.Subtract(ConfigsLoader.StartBeforeTimeThreshold))
.StartAlmostTimeStamp = If(.StartTimeStamp = DateTime.MinValue, DateTime.MinValue, .StartTimeStamp.Subtract(ConfigsLoader.StartAlmostTimeThreshold))
'Set parent work item.
.WorkItem = workItem
'Fetch the employee if defined.
Dim employeeInitials = ExtractItemFromDataReader(dr, $"Gebruiker_{i}", String.Empty)
Dim employee As IEmployee = If(employeeInitials.Equals(String.Empty), Nothing, employees.FirstOrDefault(Function(employeeToCheck) employeeToCheck.Initials.Equals(employeeInitials)))
'Set the current state based on the enum value. If the quantity is 0, the status is automatically zero.
.State = ConvertEnumValueToActivityState(If(.QuantityToProduce = 0, ActivityStateEnum.Zero, ActivityStateEnumMapper.GetActivityStateFromLetter(ExtractItemFromDataReader(Of Char)(dr, $"Status_{i}"))), activity, employee)
End With
'Add to collection of activities.
activities.Add(activity)
Next
'Return list.
Return activities
End Function
'''
''' Get the correct amount of activities.
'''
'''
'''
Private Function FetchNumberOfActivities(workPostIndex As Integer) As String
'Fetch queries from config.
Dim activityAmounts = ConfigsLoader.NumbersOfActivities()
'Check if index is valid.
If workPostIndex >= activityAmounts.Count Or workPostIndex < 0 Then
Throw New InternalException($"Can't fetch the amount of activities with this work post index: {workPostIndex}")
End If
'If so, return correct amount.
Return activityAmounts.Item(workPostIndex)
End Function
'''
''' Produces an activity state based on the state enum value. The activity becomes part of the state.
'''
'''
'''
'''
Private Function ConvertEnumValueToActivityState(stateEnumValue As ActivityStateEnum, activity As IActivity, employee As IEmployee) As ActivityState
'Get employee if any.
Select Case stateEnumValue
Case ActivityStateEnum.Zero
Return New ActivityZeroState(activity)
Case ActivityStateEnum.Defaulted
Return New ActivityDefaultedState(activity)
Case ActivityStateEnum.Stopped
Return New ActivityStoppedState(activity, employee)
Case ActivityStateEnum.Started
Return New ActivityStartedState(activity, employee)
Case ActivityStateEnum.Finished
Return New ActivityFinishedState(activity, employee)
Case Else
Throw New InternalException($"Activity state enum value '{stateEnumValue}' cannot be used to map to an activity state.")
End Select
End Function
#End Region
End Module