From 25dcfb2061f9b52f9d428a6aade100b125963474 Mon Sep 17 00:00:00 2001 From: Developer01 Date: Fri, 13 Feb 2026 07:56:02 +0100 Subject: [PATCH] VorKOG_Hotspots in LOD --- app/TaskFlow/frmMain.vb | 760 ++++++++++++++++++++++++++++++---------- 1 file changed, 576 insertions(+), 184 deletions(-) diff --git a/app/TaskFlow/frmMain.vb b/app/TaskFlow/frmMain.vb index 1b2be52..5da7bde 100644 --- a/app/TaskFlow/frmMain.vb +++ b/app/TaskFlow/frmMain.vb @@ -933,8 +933,7 @@ Public Class frmMain End Sub Private Async Sub navBar_LinkClicked(ByVal sender As Object, ByVal e As NavBarLinkEventArgs) - If Not Application.OpenForms().OfType(Of frmValidator).Any Then - Else + If Application.OpenForms().OfType(Of frmValidator).Any Then FormHelper.ShowInfoMessage(S.Bitte_schließen_Sie_den_offenen_Workflow_, omsgTitleWarning) Exit Sub End If @@ -943,53 +942,82 @@ Public Class frmMain Dim _tag = e.Link.Item.Tag Timer_Inactivity_Reset_Disable("navBar_LinkClicked") - If Not IsNothing(_tag) Then - If _tag.ToString.Contains("itmProfile#") Then - _tag = _tag.ToString.Replace("itmProfile#", "") - If IsNumeric(_tag) Then - If CURRENT_CLICKED_PROFILE_ID <> _tag Then - OverviewOrDEtail = "DETAIL" - If Not Application.OpenForms().OfType(Of frmValidator).Any Then - CURRENT_CLICKED_PROFILE_ID = _tag - CURRENT_CLICKED_PROFILE_TITLE = e.Link.Item.Caption + Try + If Not IsNothing(_tag) Then + If _tag.ToString.Contains("itmProfile#") Then + ' ========== PROFIL WURDE GEKLICKT ========== + _tag = _tag.ToString.Replace("itmProfile#", "") + If IsNumeric(_tag) Then + If CURRENT_CLICKED_PROFILE_ID <> _tag Then + OverviewOrDEtail = "DETAIL" + If Not Application.OpenForms().OfType(Of frmValidator).Any Then + CURRENT_CLICKED_PROFILE_ID = _tag + CURRENT_CLICKED_PROFILE_TITLE = e.Link.Item.Caption + End If + + GRID_LOAD_TYPE = "PROFILE#" & _tag.ToString + DetailLinkActive = True + + ' RefreshHelper VORHER speichern + If GridControlWorkflows.Visible = True And FormOpenClose = False Then + RefreshHelper.SaveViewInfo() + End If + + Me.Cursor = Cursors.WaitCursor + Try + ' Zentral über Decide_Load laden + Await Decide_Load(False, True) + Finally + Me.Cursor = Cursors.Default + End Try + Else + CURRENT_CLICKED_PROFILE_TITLE = Nothing + CURRENT_CLICKED_PROFILE_ID = Nothing End If + End If - GRID_LOAD_TYPE = "PROFILE#" & _tag.ToString - TimerRefresh.Stop() - ' LoadingPanel-Verwaltung erfolgt in Load_single_Profile - DetailLinkActive = True - Me.Cursor = Cursors.WaitCursor - Await Load_single_Profile(True) - Me.Cursor = Cursors.Default - TimerRefresh.Start() - Else - CURRENT_CLICKED_PROFILE_TITLE = Nothing - CURRENT_CLICKED_PROFILE_ID = Nothing + ElseIf _tag = "OVERVIEW" Then + ' ========== OVERVIEW WURDE GEKLICKT ========== + OverviewOrDEtail = "OVERVIEW" + GRID_LOAD_TYPE = "OVERVIEW" + + Dim oForce As Boolean = False + If DetailLinkActive = True Then + oForce = True + DetailLinkActive = False + OVERVIEW_ADDED_WHEN = "" + End If + + ' RefreshHelper VORHER speichern + If GridControlWorkflows.Visible = True And FormOpenClose = False Then + RefreshHelper.SaveViewInfo() + End If + + ' Zentral über Decide_Load laden + Await Decide_Load(False, oForce) + + ' RefreshHelper NACHHER laden + If GridControlWorkflows.Visible = True And FormOpenClose = False Then + RefreshHelper.LoadViewInfo() + End If + + ' Gruppierung prüfen + If GridViewWorkflows.GroupCount = 0 And Not IsNothing(GridViewWorkflows.Columns("GROUP_TEXT")) Then + LOGGER.Info("NO GROUPS AFTER CLICK OVERVIEW...CREATING GROUPS NEW...") + Await Decide_Load(False, True) + If GridControlWorkflows.Visible = True And FormOpenClose = False Then + RefreshHelper.LoadViewInfo() + End If End If - End If - ElseIf _tag = "OVERVIEW" Then - OverviewOrDEtail = "OVERVIEW" - GRID_LOAD_TYPE = "OVERVIEW" - TimerRefresh.Stop() - Dim oForce As Boolean = False - If DetailLinkActive = True Then - oForce = True - DetailLinkActive = False - OVERVIEW_ADDED_WHEN = "" - End If - ' LoadingPanel-Verwaltung erfolgt in Load_Grid_Overview - Await Load_Grid_Overview(False, True, True) - TimerRefresh.Start() - RefreshHelper.LoadViewInfo() - If GridViewWorkflows.GroupCount = 0 And Not IsNothing(GridViewWorkflows.Columns("GROUP_TEXT")) Then - LOGGER.Info("NO GROUPS AFTER CLICK OVERVIEW...CREATING GROUPS NEW...") - Await Load_Grid_Overview(False, True, True) - RefreshHelper.LoadViewInfo() End If End If - End If - FRONTEND_ACTION = FA_NONE + Catch ex As Exception + LOGGER.Error(ex) + FormHelper.ShowInfoMessage($"Fehler beim Laden: {ex.Message}", omsgTitleWarning) + Finally + FRONTEND_ACTION = FA_NONE + End Try End Sub Function Load_Profiles_for_User() As Boolean Try @@ -1365,20 +1393,22 @@ Public Class frmMain Private Sub NotifyIcon1_Click(sender As System.Object, e As EventArgs) Handles NotifyIcon1.Click BringMonitor2Front() End Sub + ' ======================================== + ' HAUPTLADEMETHODE - Koordiniert den gesamten Ladevorgang + ' ======================================== Private Async Function Decide_Load(pIsFormLoad As Boolean, Optional ForceReload As Boolean = False) As Tasks.Task Dim perfStart As DateTime = DateTime.MinValue - Dim perfLastCheck As DateTime = DateTime.MinValue Dim refreshWasEnabled As Boolean = False If LOG_HOTSPOTS Then perfStart = DateTime.Now - perfLastCheck = perfStart LOGGER.Info($"[PERF Decide_Load] START - pIsFormLoad:[{pIsFormLoad}] ForceReload:[{ForceReload}] GRID_LOAD_TYPE:[{GRID_LOAD_TYPE}]") End If Try LOGGER.Debug($"Decide_Load: pIsFormLoad [{pIsFormLoad}] - ForceReload [{ForceReload}] - GRID_LOAD_TYPE [{GRID_LOAD_TYPE}]") + ' ========== VORBEDINGUNGEN PRÜFEN ========== If pIsFormLoad = True Then FormShown = False End If @@ -1390,46 +1420,51 @@ Public Class frmMain Exit Function End If + ' ========== TIMER MANAGEMENT ========== If TimerRefresh.Enabled Then refreshWasEnabled = True - TimerRefresh.Enabled = False + TimerRefresh.Stop() End If - TimerRefresh.Stop() FRONTEND_ACTION = "DECIDE_LOAD" - ' ========== HAUPTLADEVORGANG ========== + ' ========== UI VORBEREITEN (NUR BEI OVERVIEW) ========== + Dim loadSuccess As Boolean = False + If GRID_LOAD_TYPE = "OVERVIEW" Then If LOG_HOTSPOTS Then - LOGGER.Info("[PERF Decide_Load] ruft Load_Grid_Overview auf...") + LOGGER.Info("[PERF Decide_Load] ruft LoadOverviewData auf...") + End If + + ' UI vorbereiten + If Not PrepareGridForLoading() Then + Exit Function End If - Await Load_Grid_Overview(pIsFormLoad, ForceReload, False) + + ' Daten laden + loadSuccess = Await LoadOverviewData(pIsFormLoad, ForceReload) + ElseIf GRID_LOAD_TYPE.StartsWith("PROFILE#") Then If LOG_HOTSPOTS Then - LOGGER.Info("[PERF Decide_Load] ruft Load_single_Profile auf...") + LOGGER.Info("[PERF Decide_Load] ruft LoadProfileData auf...") End If - Await Load_single_Profile(ForceReload) - End If - ' ========== NACHBEARBEITUNG ========== - If SHOW_MASS_VALIDATOR = False Then - GridViewWorkflows.OptionsSelection.MultiSelect = False - GridViewWorkflows.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect - BarButtonItemMassValidation.Visibility = DevExpress.XtraBars.BarItemVisibility.Never - Else - BarButtonItemMassValidation.Visibility = DevExpress.XtraBars.BarItemVisibility.Always - GridViewWorkflows.OptionsSelection.MultiSelect = True - GridViewWorkflows.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect - End If + ' UI vorbereiten + If Not PrepareGridForLoading() Then + Exit Function + End If - If GridViewWorkflows.OptionsView.ShowAutoFilterRow = True Then - BarCheckItemAutofilter.Checked = True + ' Daten laden + loadSuccess = Await LoadProfileData(ForceReload) End If - If GridViewWorkflows.OptionsFind.AlwaysVisible Then - BarCheckItemShowSearch.Checked = True + + If Not loadSuccess Then + LOGGER.Warn("Daten konnten nicht geladen werden") + Exit Function End If - COLUMNS_INVISIBLE() + ' ========== NACHBEARBEITUNG ========== + ApplyPostLoadSettings() GridIsLoaded = True Catch ex As Exception @@ -1439,15 +1474,10 @@ Public Class frmMain Finally FRONTEND_ACTION = FA_NONE - ' LoadingPanel wird bereits in Load_Grid_Overview versteckt - ' Kein HideLoadingPanel() nötig! - If refreshWasEnabled Then - TimerRefresh.Enabled = True + TimerRefresh.Start() End If - TimerRefresh.Start() - If pIsFormLoad = True Then FormShown = True End If @@ -1457,6 +1487,361 @@ Public Class frmMain End If End Try End Function + + ' ======================================== + ' UI-VORBEREITUNG - Macht Grid sichtbar und zeigt LoadingPanel + ' ======================================== + Private Function PrepareGridForLoading() As Boolean + Try + ' Grid sichtbar machen + If GridControlWorkflows.Visible = False Then + GridControlWorkflows.Visible = True + End If + + ' UI-Thread Zeit geben + Application.DoEvents() + + ' LoadingPanel anzeigen + GridViewWorkflows.ShowLoadingPanel() + + ' Nochmal Zeit zum Rendern + Application.DoEvents() + + Return True + Catch ex As Exception + LOGGER.Error(ex) + Return False + End Try + End Function + + ' ======================================== + ' OVERVIEW DATEN LADEN - Spezialisiert auf Overview + ' ======================================== + Private Async Function LoadOverviewData(pFormLoad As Boolean, pForceReload As Boolean) As Task(Of Boolean) + Dim gridUpdateStarted As Boolean = False + Dim viewUpdateStarted As Boolean = False + + Try + ' ========== GRID UPDATES VORBEREITEN ========== + If GridControlWorkflows.Visible Then + GridControlWorkflows.BeginUpdate() + gridUpdateStarted = True + GridViewWorkflows.BeginUpdate() + viewUpdateStarted = True + End If + + ' ========== PROFILE VALIDIEREN ========== + If BASEDATA_DT_VW_PROFILE_USER.Rows.Count = 0 Then + LOGGER.Info("Attention: No profiles for user: '" & USER_USERNAME & "' configured!", False) + NO_WORKFLOWITEMS = True + bsiMessage.Caption = "NO PROFILES FOR USER" + bsiMessage.ItemAppearance.Normal.BackColor = Color.Red + bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black + GridControlWorkflows.Visible = False + Return False + End If + + Load_Profiles_for_User() + + ' ========== SQL VORBEREITEN ========== + Dim oSQLOverview = BASEDATA_DT_CONFIG.Rows(0).Item("SQL_PROFILE_MAIN_VIEW") + + If IsDBNull(oSQLOverview) OrElse Not oSQLOverview.ToString.Contains("GROUP_TEXT") Then + NO_WORKFLOWITEMS = True + GridControlWorkflows.Visible = False + bindsourcegrid.DataSource = Nothing + GridControlWorkflows.DataSource = Nothing + Return False + End If + + ' SQL-Platzhalter ersetzen + oSQLOverview = PrepareSQLWithReplacements(oSQLOverview) + + ' ========== DATEN ABRUFEN ========== + DT_CURR_WF_ITEMS = Await DatabaseFallback.GetDatatableECMAsync(oSQLOverview) + + If IsNothing(DT_CURR_WF_ITEMS) Then + NO_WORKFLOWITEMS = True + GridControlWorkflows.Visible = False + Return False + End If + + LOGGER.Debug($"Datatable CURR_DT_OVERVIEW loaded: {DT_CURR_WF_ITEMS.Rows.Count} rows") + + ' ========== DATEN VERARBEITEN ========== + NO_WORKFLOWITEMS = (DT_CURR_WF_ITEMS.Rows.Count = 0) + UpdateGridCaption() + + If NO_WORKFLOWITEMS Then + GridControlWorkflows.Visible = False + bindsourcegrid.DataSource = Nothing + GridControlWorkflows.DataSource = Nothing + Return False + End If + + ' ========== ICON-SPALTE VORBEREITEN ========== + PrepareIconColumn() + + ' ========== GRID MIT DATEN FÜLLEN ========== + bindsourcegrid.DataSource = DT_CURR_WF_ITEMS + GridControlWorkflows.DataSource = bindsourcegrid + GridControlWorkflows.ForceInitialize() + + Create_View_Caption() + + ' ========== LAYOUT ANWENDEN ========== + Await ApplyGridLayout(pForceReload) + + Return True + + Catch ex As Exception + LOGGER.Error(ex) + LOGGER.Info("LoadOverviewData - Fehler: " & ex.Message) + Return False + Finally + ' ========== AUFRÄUMEN ========== + If viewUpdateStarted Then + GridViewWorkflows.EndUpdate() + End If + If gridUpdateStarted Then + GridControlWorkflows.EndUpdate() + End If + + ' LoadingPanel verstecken (NUR HIER!) + GridViewWorkflows.HideLoadingPanel() + End Try + End Function + + ' ======================================== + ' PROFILE DATEN LADEN - Spezialisiert auf einzelnes Profil + ' ======================================== + Private Async Function LoadProfileData(ForceReload As Boolean) As Task(Of Boolean) + Dim gridUpdateStarted As Boolean = False + Dim viewUpdateStarted As Boolean = False + + Try + Load_Profiles_for_User() + + Dim expression As String = "GUID = " & CURRENT_CLICKED_PROFILE_ID + Dim foundRow As DataRow = CURR_DT_VWPM_PROFILE_ACTIVE.Select(expression).FirstOrDefault() + If foundRow Is Nothing Then + Return False + End If + + If GridControlWorkflows.Visible Then + GridControlWorkflows.BeginUpdate() + gridUpdateStarted = True + GridViewWorkflows.BeginUpdate() + viewUpdateStarted = True + End If + + ' ========== SQL VORBEREITEN UND AUSFÜHREN ========== + Dim oSQL = foundRow.Item("SQL_VIEW") + oSQL = PrepareSQLWithReplacements(oSQL) + + DT_CURR_WF_ITEMS = Await DatabaseFallback.GetDatatableECMAsync(oSQL) + + If IsNothing(DT_CURR_WF_ITEMS) Then + Return False + End If + + ' ========== DATEN VERARBEITEN ========== + NO_WORKFLOWITEMS = (DT_CURR_WF_ITEMS.Rows.Count = 0) + UpdateGridCaption() + + If NO_WORKFLOWITEMS Then + GridControlWorkflows.Visible = False + bindsourcegrid.DataSource = Nothing + GridControlWorkflows.DataSource = Nothing + Return False + End If + + ' ========== BASIC VIEW ERSTELLEN ========== + CreateBasicViewForProfile() + + Return True + + Catch ex As Exception + LOGGER.Error(ex) + LOGGER.Info("LoadProfileData - Error: " & ex.Message) + Return False + Finally + If viewUpdateStarted Then + GridViewWorkflows.EndUpdate() + End If + If gridUpdateStarted Then + GridControlWorkflows.EndUpdate() + End If + + ' LoadingPanel verstecken (NUR HIER!) + GridViewWorkflows.HideLoadingPanel() + End Try + End Function + + ' ======================================== + ' HILFSMETHODEN - Extrahierte Logik für Wiederverwendung + ' ======================================== + + Private Function PrepareSQLWithReplacements(oSQL As String) As String + oSQL = clsPatterns.ReplaceInternalValues(oSQL) + oSQL = clsPatterns.ReplaceUserValues(oSQL) + oSQL = oSQL.Replace("@USER_ID", USER_ID) + oSQL = oSQL.Replace("@USERNAME", USER_USERNAME) + oSQL = oSQL.Replace("@MACHINE_NAME", System.Environment.MachineName) + oSQL = oSQL.Replace("@DATE", Now.ToShortDateString) + oSQL = oSQL.Replace("@PROFILE_ID", CURRENT_CLICKED_PROFILE_ID) + Return oSQL + End Function + + Private Sub PrepareIconColumn() + If TL_ICON = True AndAlso DT_CURR_WF_ITEMS IsNot Nothing AndAlso DT_CURR_WF_ITEMS.Columns.Contains("ICON") = False Then + Dim columnStateIcon As New DataColumn() With { + .DataType = GetType(Image), + .ColumnName = "ICON", + .Caption = "" + } + DT_CURR_WF_ITEMS.Columns.Add(columnStateIcon) + End If + + RedDocuments = 0 + YellowDocuments = 0 + GreenDocuments = 0 + + If TL_ICON = True AndAlso DT_CURR_WF_ITEMS IsNot Nothing Then + For Each row As DataRow In DT_CURR_WF_ITEMS.Rows + Dim State As Integer = CInt(row.Item("TL_STATE")) + Select Case State + Case 1 + RedDocuments += 1 + row.Item("ICON") = My.Resources.bullet_red + Case 2 + YellowDocuments += 1 + row.Item("ICON") = My.Resources.bullet_orange + Case 3 + GreenDocuments += 1 + row.Item("ICON") = My.Resources.bullet_green + End Select + Next + End If + End Sub + + Private Async Function ApplyGridLayout(pForceReload As Boolean) As Tasks.Task + Dim oColNotPartofLayout As Boolean = False + + If pForceReload = True And (GridLayoutChanged() = True Or oColNotPartofLayout = True) Then + LOGGER.Debug("Now GridLayout_Reset..") + Await GridLayout_Reset(False) + Else + RestoreLayout() + End If + + If pForceReload = True And (GridLayoutChanged() = True Or oColNotPartofLayout = True) Then + Create_GroupBy_Parts() + End If + + ' Icon-Spalte konfigurieren + If TL_ICON = True Then + Try + GridViewWorkflows.Columns.Item("ICON").MaxWidth = 24 + GridViewWorkflows.Columns.Item("ICON").MinWidth = 24 + GridViewWorkflows.Columns.Item("ICON").AppearanceCell.BackColor = Color.White + GridViewWorkflows.Columns.Item("ICON").Fixed = DevExpress.XtraGrid.Columns.FixedStyle.Left + Catch ex As Exception + End Try + End If + + If GridViewWorkflows.Columns.Count <= 5 Then + LOGGER.Info("GridViewWorkflows.Columns.Count <= 5 - Reset_Gridlayout will be forced...", False) + Await Reset_GridLayout(False) + Else + RestoreLayout() + End If + + COLUMNS_INVISIBLE() + + ' Spaltenformatierung anwenden + ApplyColumnFormatting() + End Function + + Private Sub ApplyColumnFormatting() + Try + For Each oColumn As DevExpress.XtraGrid.Columns.GridColumn In GridViewWorkflows.Columns + For Each oRow As DataRow In BASEDATA_TBDD_COLUMNS_FORMAT.Rows + Dim colName = oRow("COLUMN_TITLE").ToString() + + If oColumn.FieldName = colName Then + Dim oSollFormatType = oRow("TYPE2FORMAT").ToString() + + If oSollFormatType = "DateTime" Then + If oColumn.ColumnType <> GetType(DateTime) Then + oColumn.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime + End If + + If oColumn.ColumnType = GetType(DateTime) And oColumn.DisplayFormat.FormatString <> "dd.MM.yyyy HH:mm:ss" Then + oColumn.DisplayFormat.FormatString = "dd.MM.yyyy HH:mm:ss" + End If + ElseIf oSollFormatType = "Numeric" Then + If oColumn.ColumnType <> GetType(Int32) Then + oColumn.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric + End If + End If + End If + Next + Next + Catch ex As Exception + LOGGER.Warn("⚠️ Fehler beim Anwenden der Formatierung aus TBDD_COLUMNS_FORMAT: " & ex.Message) + End Try + End Sub + + Private Sub CreateBasicViewForProfile() + GridControlWorkflows.DataSource = Nothing + Try + GridViewWorkflows.Columns.Clear() + Catch ex As Exception + LOGGER.Error(ex) + LOGGER.Warn("⚠️ Could not clear GridViewWorkflows.Columns") + End Try + + PrepareIconColumn() + + bindsourcegrid.DataSource = DT_CURR_WF_ITEMS + GridControlWorkflows.DataSource = bindsourcegrid + + RestoreLayout() + COLUMNS_INVISIBLE() + + ' Icon-Spalte konfigurieren + If TL_ICON = True Then + Try + GridViewWorkflows.Columns.Item("ICON").MaxWidth = 24 + GridViewWorkflows.Columns.Item("ICON").MinWidth = 24 + GridViewWorkflows.Columns.Item("ICON").AppearanceCell.BackColor = Color.White + GridViewWorkflows.Columns.Item("ICON").Fixed = FixedStyle.Left + Catch ex As Exception + End Try + End If + End Sub + + Private Sub ApplyPostLoadSettings() + If SHOW_MASS_VALIDATOR = False Then + GridViewWorkflows.OptionsSelection.MultiSelect = False + GridViewWorkflows.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect + BarButtonItemMassValidation.Visibility = DevExpress.XtraBars.BarItemVisibility.Never + Else + BarButtonItemMassValidation.Visibility = DevExpress.XtraBars.BarItemVisibility.Always + GridViewWorkflows.OptionsSelection.MultiSelect = True + GridViewWorkflows.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect + End If + + If GridViewWorkflows.OptionsView.ShowAutoFilterRow = True Then + BarCheckItemAutofilter.Checked = True + End If + If GridViewWorkflows.OptionsFind.AlwaysVisible Then + BarCheckItemShowSearch.Checked = True + End If + + COLUMNS_INVISIBLE() + End Sub Private Sub ToolStripButton2_Click_2(sender As Object, e As EventArgs) frmAdminPasswort.ShowDialog() End Sub @@ -1655,6 +2040,15 @@ Public Class frmMain End Try End Sub Private Async Function Item_Scope(startedFrom As String) As Task + ' ========== FRÜHE VALIDIERUNGEN (VOR UI-ÄNDERUNGEN) ========== + If Application.OpenForms().OfType(Of frmValidator).Any Then + bsiMessage.Caption = S.Es_existiert_bereits_ein_aktiver_Workflow_ + LOGGER.Info("Item Scope - Workflow open! - Exit") + bsiMessage.ItemAppearance.Normal.BackColor = Color.Red + bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black + Exit Function + End If + Dim perfStart As DateTime = DateTime.MinValue Dim useWaitCursorApplied As Boolean = False Dim previousMessage As String = bsiMessage.Caption @@ -1668,102 +2062,113 @@ Public Class frmMain Try LOGGER.Info("Starting Profile Loading") - If Application.OpenForms().OfType(Of frmValidator).Any Then - bsiMessage.Caption = S.Es_existiert_bereits_ein_aktiver_Workflow_ - LOGGER.Info("Item Scope - Workflow open! - Exit") - bsiMessage.ItemAppearance.Normal.BackColor = Color.Red - bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black - Exit Function - End If - ' ========== UI-VORBEREITUNG ========== Me.UseWaitCursor = True useWaitCursorApplied = True bsiMessage.Caption = "Processing selection..." messageApplied = True + ' ========== HITINFO NUR EINMAL BERECHNEN ========== Dim hitInfo As GridHitInfo = GridViewWorkflows.CalcHitInfo(GridCursorLocation) - Dim OItemScopeInfo = "No Item so far" + ' ========== STARTEDROM NORMALISIEREN ========== If startedFrom = "DOUBLECLICK" Then - If hitInfo.InGroupRow Then - LOGGER.Debug("User clicked group row.") - startedFrom = "CMGROUP" - Else - LOGGER.Debug("User clicked normal row.") - startedFrom = "CMROW" - End If + startedFrom = If(hitInfo.InGroupRow, "CMGROUP", "CMROW") + LOGGER.Debug($"User clicked {If(hitInfo.InGroupRow, "group", "normal")} row.") End If - Dim oHitProfilID + ' ========== PROFIL-ID ERMITTELN (OPTIMIERT) ========== + Dim oHitProfilID As Object = Nothing If hitInfo.InGroupRow Then - oHitProfilID = GridViewWorkflows.GetRowCellValue(GridViewWorkflows.GetDataRowHandleByGroupRowHandle(hitInfo.RowHandle), GridViewWorkflows.Columns("PROFILE_ID")) + oHitProfilID = GridViewWorkflows.GetRowCellValue( + GridViewWorkflows.GetDataRowHandleByGroupRowHandle(hitInfo.RowHandle), + GridViewWorkflows.Columns("PROFILE_ID")) ElseIf hitInfo.InDataRow Then - oHitProfilID = GridViewWorkflows.GetRowCellValue(GridViewWorkflows.GetDataRowHandleByGroupRowHandle(GridViewWorkflows.GetParentRowHandle(hitInfo.RowHandle)), GridViewWorkflows.Columns("PROFILE_ID")) + oHitProfilID = GridViewWorkflows.GetRowCellValue( + GridViewWorkflows.GetDataRowHandleByGroupRowHandle( + GridViewWorkflows.GetParentRowHandle(hitInfo.RowHandle)), + GridViewWorkflows.Columns("PROFILE_ID")) End If - LOGGER.Debug("Clicked ProfileId: [{0}]", oHitProfilID) - LOGGER.Debug("Started From: [{0}]", startedFrom) + LOGGER.Debug("Clicked ProfileId: [{0}], Started From: [{1}]", oHitProfilID, startedFrom) - If Len(oHitProfilID) > 0 Then - If oHitProfilID > 0 Then - If oHitProfilID <> CURRENT_CLICKED_PROFILE_ID Then - LOGGER.Debug($"Item_Scope: oHitProfilID {oHitProfilID} <> CURRENT_CLICKED_PROFILE_ID {CURRENT_CLICKED_PROFILE_ID} ") - CURRENT_CLICKED_PROFILE_ID = oHitProfilID - End If + ' ========== PROFIL-ID VALIDIERUNG UND UPDATE ========== + If oHitProfilID IsNot Nothing AndAlso IsNumeric(oHitProfilID) AndAlso CInt(oHitProfilID) > 0 Then + If oHitProfilID <> CURRENT_CLICKED_PROFILE_ID Then + LOGGER.Debug($"Item_Scope: oHitProfilID {oHitProfilID} <> CURRENT_CLICKED_PROFILE_ID {CURRENT_CLICKED_PROFILE_ID}") + CURRENT_CLICKED_PROFILE_ID = oHitProfilID End If End If - ' ========== GRUPPE VERARBEITEN ========== + ' ========== GRUPPE VERARBEITEN (OPTIMIERT) ========== If startedFrom = "CMGROUP" Then LOGGER.Debug("Loading Child DocIds..") Dim oIds As New List(Of Integer) Dim oGroupRowHandle = hitInfo.RowHandle Dim oChildRowCount = GridViewWorkflows.GetChildRowCount(oGroupRowHandle) - For index = 0 To oChildRowCount - 1 - Dim oChildRowHandle = GridViewWorkflows.GetChildRowHandle(oGroupRowHandle, index) - Dim oRow = GridViewWorkflows.GetRow(oChildRowHandle) - Dim oDocId = oRow.Item("DocId") - oIds.Add(oDocId) - Next - - LOGGER.Debug("[{0}] DocIds loaded", oIds.Count) - - If oIds.Count = 0 Then - For index = 0 To GridViewWorkflows.RowCount - Dim oRow = GridViewWorkflows.GetRow(index) - If oRow Is Nothing Then - Continue For + ' OPTIMIERUNG: Kapazität vorbelegen + oIds.Capacity = oChildRowCount + + ' OPTIMIERUNG: Direkte Schleife statt verschachtelter Logik + If oChildRowCount > 0 Then + For index = 0 To oChildRowCount - 1 + Dim oChildRowHandle = GridViewWorkflows.GetChildRowHandle(oGroupRowHandle, index) + Dim oRow = GridViewWorkflows.GetRow(oChildRowHandle) + If oRow IsNot Nothing Then + Dim oDocId = oRow.Item("DocId") + If oDocId IsNot Nothing Then + oIds.Add(oDocId) + End If End If + Next + Else + ' Fallback nur bei Bedarf + For index = 0 To GridViewWorkflows.RowCount - 1 + Dim oRow = GridViewWorkflows.GetRow(index) + If oRow Is Nothing Then Continue For + Dim oProfileId = oRow.row.item("PROFILE_ID") - If oProfileId = CURRENT_CLICKED_PROFILE_ID Then + If oProfileId Is Nothing Then Continue For + + If CInt(oProfileId) = CURRENT_CLICKED_PROFILE_ID Then oIds.Add(oRow.item("DocId")) End If Next End If + LOGGER.Debug("[{0}] DocIds loaded", oIds.Count) + If oIds.Count = 0 Then Dim omsg = String.Format(S.System_konnte_die_Profilworkflows_nicht_auswerten_, vbNewLine) FormHelper.ShowInfoMessage(omsg, omsgTitleAttention) Exit Function End If + ' ========== DB-OPERATIONEN OPTIMIERT ========== LOGGER.Debug("Cleaning up queued DocIds..") Dim oDelete = $"DELETE FROM TBPM_VALIDATION_PROFILE_GROUP_USER WHERE UserID = {USER_ID}" + If DatabaseFallback.ExecuteNonQueryECM(oDelete) = True Then LOGGER.Debug("Adding [{0}] queued DocIds..", oIds.Count) - For Each oID As Integer In oIds - Dim oInsert = $"INSERT INTO TBPM_VALIDATION_PROFILE_GROUP_USER ([PROFIL_ID] ,[DocID] - ,[UserID] ,[ADDED_WHO]) VALUES ({CURRENT_CLICKED_PROFILE_ID},{oID},{USER_ID},'{USER_USERNAME}')" - DatabaseFallback.ExecuteNonQueryECM(oInsert) + + ' OPTIMIERUNG: Batch-Insert statt einzelner Inserts + Dim oInsertBatch As New System.Text.StringBuilder() + oInsertBatch.AppendLine("INSERT INTO TBPM_VALIDATION_PROFILE_GROUP_USER ([PROFIL_ID],[DocID],[UserID],[ADDED_WHO]) VALUES") + + For i As Integer = 0 To oIds.Count - 1 + If i > 0 Then oInsertBatch.Append(",") + oInsertBatch.AppendLine($"({CURRENT_CLICKED_PROFILE_ID},{oIds(i)},{USER_ID},'{USER_USERNAME}')") Next + + DatabaseFallback.ExecuteNonQueryECM(oInsertBatch.ToString()) End If End If CURRENT_JUMP_DOC_GUID = 0 - If IsNothing(hitInfo) Then + ' ========== HITINFO VALIDIERUNG ========== + If hitInfo Is Nothing Then bsiMessage.Caption = "Could not specify hitinfo via click event (CalcHitInfo)" LOGGER.Info("Could not specify hitinfo via click event (CalcHitInfo)") bsiMessage.ItemAppearance.Normal.BackColor = Color.Red @@ -1771,32 +2176,43 @@ Public Class frmMain Exit Function End If - ' ========== HITINFO VERARBEITEN ========== - Dim groupRowText = "" + ' ========== PROFIL-TITEL ERMITTELN ========== + Dim PROFIL_TITLE As String = String.Empty If hitInfo.InGroupRow Then GridViewItem_Clicked = "GROUP" startedFrom = "CMGROUP" LOGGER.Debug($"Item_Scope: InGroupRow") - groupRowText = GridViewWorkflows.GetGroupRowDisplayText(hitInfo.RowHandle) + + Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText(hitInfo.RowHandle) LOGGER.Debug($"Item_Scope: groupRowText {groupRowText}") + + If GRID_LOAD_TYPE = "OVERVIEW" Then + groupRowText = groupRowText.Replace("Profile (Fixed): ", "").Trim() + Dim splitIndex = groupRowText.IndexOf("|") + PROFIL_TITLE = If(splitIndex >= 0, groupRowText.Substring(0, splitIndex).Trim(), groupRowText) + End If + ElseIf hitInfo.InDataRow Then GridViewItem_Clicked = "ROW" LOGGER.Debug($"Item_Scope: InDataRow") + If GRID_LOAD_TYPE = "OVERVIEW" Then LOGGER.Debug($"Item_Scope: GRID_LOAD_TYPE = OVERVIEW") - groupRowText = GridViewWorkflows.GetGroupRowDisplayText(GridViewWorkflows.GetParentRowHandle(hitInfo.RowHandle)) + Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText( + GridViewWorkflows.GetParentRowHandle(hitInfo.RowHandle)) LOGGER.Debug($"Item_Scope: OVERVIEWgroupRowText {groupRowText}") + + groupRowText = groupRowText.Replace("Profile (Fixed): ", "").Trim() + Dim splitIndex = groupRowText.IndexOf("|") + PROFIL_TITLE = If(splitIndex >= 0, groupRowText.Substring(0, splitIndex).Trim(), groupRowText) Else LOGGER.Debug($"Item_Scope: NOT GRID_LOAD_TYPE = OVERVIEW") - If IsNothing(CURRENT_CLICKED_PROFILE_ID) = False Then - If CURRENT_CLICKED_PROFILE_ID = 0 Then - LOGGER.Info("ItemScope: CURRENT_CLICKED_PROFILE_ID = 0!!!") - End If + If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) AndAlso CURRENT_CLICKED_PROFILE_ID <> 0 Then LOGGER.Debug($"Item_Scope: CURRENT_CLICKED_PROFILE_ID [{CURRENT_CLICKED_PROFILE_ID}]") oHitProfilID = CURRENT_CLICKED_PROFILE_ID Else - LOGGER.Warn("⚠️ ItemScope: CURRENT_CLICKED_PROFILE_ID is nothing!!!") + LOGGER.Warn("⚠️ ItemScope: CURRENT_CLICKED_PROFILE_ID is nothing or 0!!!") Exit Function End If End If @@ -1804,53 +2220,33 @@ Public Class frmMain Exit Function End If - ' ========== PROFIL-TITEL EXTRAHIEREN ========== - Dim PROFIL_TITLE - If GRID_LOAD_TYPE = "OVERVIEW" Then - Try - groupRowText = groupRowText.ToString.Replace("Profile (Fixed): ", "").Trim() - Catch ex As Exception - End Try - Dim _SPLIT As String() - _SPLIT = groupRowText.Split("|") - PROFIL_TITLE = _SPLIT(0).ToString.Trim() - End If - - If Len(PROFIL_TITLE) > 0 Then - CURRENT_CLICKED_PROFILE_TITLE = PROFIL_TITLE.ToString.Replace("GROUP_TEXT:", "") + ' ========== PROFIL-TITEL SETZEN ========== + If Not String.IsNullOrEmpty(PROFIL_TITLE) Then + CURRENT_CLICKED_PROFILE_TITLE = PROFIL_TITLE.Replace("GROUP_TEXT:", "") End If ' ========== PROFIL LADEN ========== - If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) And IsNumeric(CURRENT_CLICKED_PROFILE_ID) Then - LOGGER.Debug($"Item_Scope: Not IsNothing(PROFIL_ID) And IsNumeric(PROFIL_ID)") - Dim oExpression As String - oExpression = "PROFILE_ID = " & CURRENT_CLICKED_PROFILE_ID + If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) AndAlso IsNumeric(CURRENT_CLICKED_PROFILE_ID) Then + LOGGER.Debug($"Item_Scope: Valid PROFIL_ID") - If hitInfo.InGroupRow Or (startedFrom = "CMGROUP" And hitInfo.InDataRow) Then + If hitInfo.InGroupRow OrElse (startedFrom = "CMGROUP" AndAlso hitInfo.InDataRow) Then + ' GRUPPE: Workflow ohne spezifisches Dokument CURRENT_JUMP_DOC_GUID = 0 CURRENT_DOC_GUID = 0 CURRENT_ProfilGUID = CURRENT_CLICKED_PROFILE_ID LOGGER.Debug($"Item_Scope: hitInfo.InGroupRow...CURRENT_CLICKED_PROFILE_ID [{CURRENT_CLICKED_PROFILE_ID}]") - ' ========== SYNCHRONER AUFRUF - WARTEN ========== Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID) ElseIf hitInfo.InDataRow Then + ' EINZELNE ZEILE: Mit spezifischem Dokument LOGGER.Debug($"Item_Scope: hitInfo.InDataRow...") - Dim oFocusedDocGUID - Try - oFocusedDocGUID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("GUID")) - Catch ex As Exception - FormHelper.ShowInfoMessage("Could not get DocGUID. Inform Your admin-team: Check Your View-Config", omsgTitleWarning) - End Try - Dim oFocusedDocID - Try - oFocusedDocID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("DocID")) - Catch ex As Exception - FormHelper.ShowInfoMessage("Could not get DocID. Inform Your admin-team: Check Your View-Config", omsgTitleWarning) - End Try + ' ========== DOKUMENT-DATEN ABRUFEN ========== + Dim oFocusedDocGUID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("GUID")) + Dim oFocusedDocID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("DocID")) - If IsNothing(oFocusedDocID) Then + ' Validierungen + If oFocusedDocID Is Nothing Then LOGGER.Warn("⚠️ In hitInfo.InDataRow: DocID is nothing!!!") bsiMessage.Caption = "Error getting DocID!" bsiMessage.ItemAppearance.Normal.BackColor = Color.Red @@ -1858,7 +2254,7 @@ Public Class frmMain Exit Function End If - If IsNothing(oFocusedDocGUID) Then + If oFocusedDocGUID Is Nothing Then LOGGER.Warn("⚠️ In hitInfo.InDataRow: oFocusedDocGUID is nothing!!!") bsiMessage.Caption = "Error getting DocGUID!" bsiMessage.ItemAppearance.Normal.BackColor = Color.Red @@ -1868,33 +2264,29 @@ Public Class frmMain LOGGER.Debug($"Item_Scope: GotDocID {oFocusedDocID} and DocGUID {oFocusedDocGUID}") - If Not IsNothing(GridViewWorkflows.Columns(FullFilepatColName)) Then + ' ========== DATEIPFAD (OPTIONAL) ========== + If GridViewWorkflows.Columns(FullFilepatColName) IsNot Nothing Then Dim DOC_PATH = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns(FullFilepatColName)) - If IsNothing(DOC_PATH) Then - LOGGER.Warn("⚠️ In hitInfo.InDataRow: FULL_FILE_PATH is nothing!!!") - Exit Function + If DOC_PATH IsNot Nothing Then + DOC_PATH = DOC_PATH.Replace("W:\", "\\windream\objects\").Replace("K:\", "\\windream\objects\") End If - DOC_PATH = DOC_PATH.Replace("W:\", "\\windream\objects\") - DOC_PATH = DOC_PATH.Replace("K:\", "\\windream\objects\") End If - oExpression = oExpression & " AND DocID = " & oFocusedDocID + ' ========== DOKUMENT-DATEN SETZEN ========== CURRENT_DOC_ID = oFocusedDocID CURRENT_JUMP_DOC_GUID = oFocusedDocGUID CURRENT_DOC_GUID = CURRENT_JUMP_DOC_GUID + ' ========== DOKUMENT-VALIDIERUNG (OPTIMIERT) ========== Dim oSQL = $"SELECT [dbo].[FNPM_CHECK_DocGUID_Valid] ({CURRENT_DOC_GUID})" Dim oResult = DatabaseFallback.GetScalarValueECM(oSQL) - Try - If CBool(oResult) = True Then - Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID) - Else - Dim omsg = S.Der_gewählte_Beleg_ist_durch_einen_anderen_Benutzer_bereits_in_Bearbeitung_oder_anderweitig_gesperrt_ - FormHelper.ShowInfoMessage(omsg, omsgTitleAttention) - End If - Catch ex As Exception - LOGGER.Warn($"Unexpected error in Checking freefile - sql so far: {oSQL} - ") - End Try + + If CBool(oResult) = True Then + Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID) + Else + Dim omsg = S.Der_gewählte_Beleg_ist_durch_einen_anderen_Benutzer_bereits_in_Bearbeitung_oder_anderweitig_gesperrt_ + FormHelper.ShowInfoMessage(omsg, omsgTitleAttention) + End If End If Else FormHelper.ShowInfoMessage("Could not get the ProfileID of file! - Check Your configuration of MainView!", omsgTitleWarning) @@ -3074,7 +3466,7 @@ FROM VWPM_PROFILE_ACTIVE T WITH (NOLOCK) WHERE T.GUID IN (SELECT PROFILE_ID FROM End If If Ev_Filter_Panel_Closed = False Then - Dim oTermFilterActive As String = String.Format("{0} ({1})", S.Filter_aktiv, GridViewWorkflows.RowCount) + Dim oTermFilterActive As String = String.Format("{0} ({1})", S.Filter_aktiv, GridViewWorkflows.DataRowCount) If GridViewWorkflows.ActiveFilterString <> String.Empty Then If lblCaptionMainGrid.Text.Contains(oTermFilterActive) Then Ev_Filter_Panel_Closed = False @@ -3101,7 +3493,7 @@ FROM VWPM_PROFILE_ACTIVE T WITH (NOLOCK) WHERE T.GUID IN (SELECT PROFILE_ID FROM ' Filter-Info hinzufügen, falls aktiv If GridViewWorkflows.ActiveFilterString <> String.Empty Then - Dim oTermFilterActive As String = String.Format("{0} ({1})", S.Filter_aktiv, GridViewWorkflows.RowCount) + Dim oTermFilterActive As String = String.Format("{0} ({1})", S.Filter_aktiv, GridViewWorkflows.DataRowCount) lblCaptionMainGrid.Text = String.Format("{0} - {1}", S.Gesamtübersicht, oTermFilterActive) End If ElseIf GRID_LOAD_TYPE.StartsWith("PROFILE#") Then