diff --git a/app/DD-Record-Organizer/Classes/ClassDocGrid.vb b/app/DD-Record-Organizer/Classes/ClassDocGrid.vb index 809cdf2..b1cff46 100644 --- a/app/DD-Record-Organizer/Classes/ClassDocGrid.vb +++ b/app/DD-Record-Organizer/Classes/ClassDocGrid.vb @@ -274,11 +274,20 @@ Public Class ClassDocGrid End If End If End Sub - Public Shared Sub FillColumns(pDocGridView As GridView, - DT_RESULT As DataTable, DT_WINDREAM_RESULTLIST As DataTable, DT_DOCRESULT_DROPDOWN_ITEMS As DataTable, - DropdownValueChangedHandler As EventHandler, DatepickerValueChangedHandler As EventHandler, TextValueChangedHandler As EventHandler, CheckValueChangedHandler As EventHandler, - SearchType As String, RECORD_ID As Integer) + DT_RESULT As DataTable, DT_WINDREAM_RESULTLIST As DataTable, DT_DOCRESULT_DROPDOWN_ITEMS As DataTable, + DropdownValueChangedHandler As EventHandler, DatepickerValueChangedHandler As EventHandler, TextValueChangedHandler As EventHandler, CheckValueChangedHandler As EventHandler, + SearchType As String, RECORD_ID As Integer) + + ' ── 1. KRITISCH: Event-Handler ENTFERNEN vor Neuregistrierung ─────────── + RemoveHandler pDocGridView.MasterRowExpanded, AddressOf gridView_MasterRowExpanded + RemoveHandler pDocGridView.CustomColumnDisplayText, AddressOf gridView_CustomColumnDisplayText + RemoveHandler pDocGridView.FocusedRowChanged, AddressOf GVDoc_Values_FocusedRowChanged + + ' ── 2. DATE_COLUMNS Listen leeren (verhindert Duplikate) ──────────────── + DATE_COLUMNS.Clear() + DATE_COLUMNS_CONFIG.Clear() + ' Handler speichern _dropdownValueChangedHandler = DropdownValueChangedHandler _datepickerValueChangedHandler = DatepickerValueChangedHandler @@ -299,7 +308,6 @@ Public Class ClassDocGrid Dim columnTitle As String = row.Item("HEADER_CAPTION") Dim type As Integer = row.Item("TYPE_ID") - If type = 3 And isConfig = False Then DATE_COLUMNS.Add(columnTitle) ElseIf type = 3 And isConfig = True Then @@ -329,13 +337,13 @@ Public Class ClassDocGrid DT_DETAIL_VALUES = ClassDataCache.GetOrLoad(cacheKey, Function() Dim sql = String.Format( - "SELECT T.[GUID],T.[DocID],T.[CONFIG_ID],T1.HEADER_CAPTION,T.[VALUE],T1.[LANGUAGE], " & - "T1.COLUMN_VIEW,T1.EDITABLE,T1.TYPE_ID,T1.VISIBLE,T.CHANGED_WHEN,T.CHANGED_WHO " & - "FROM TBPMO_DOC_VALUES T " & - "INNER JOIN TBPMO_STRUCTURE_NODES_USER_TEMP TTEMP ON T.RECORD_ID = TTEMP.RECORD_ID " & - "RIGHT JOIN TBPMO_DOCSEARCH_RESULTLIST_CONFIG T1 ON T.CONFIG_ID = T1.GUID " & - "WHERE T1.ENTITY_ID = {0} AND LANGUAGE = '{1}' AND T1.CONFIG_COLUMNS = 1", - CURRENT_ENTITY_ID, USER_LANGUAGE) + "SELECT T.[GUID],T.[DocID],T.[CONFIG_ID],T1.HEADER_CAPTION,T.[VALUE],T1.[LANGUAGE], " & + "T1.COLUMN_VIEW,T1.EDITABLE,T1.TYPE_ID,T1.VISIBLE,T.CHANGED_WHEN,T.CHANGED_WHO " & + "FROM TBPMO_DOC_VALUES T " & + "INNER JOIN TBPMO_STRUCTURE_NODES_USER_TEMP TTEMP ON T.RECORD_ID = TTEMP.RECORD_ID " & + "RIGHT JOIN TBPMO_DOCSEARCH_RESULTLIST_CONFIG T1 ON T.CONFIG_ID = T1.GUID " & + "WHERE T1.ENTITY_ID = {0} AND LANGUAGE = '{1}' AND T1.CONFIG_COLUMNS = 1", + CURRENT_ENTITY_ID, USER_LANGUAGE) Return MYDB_ECM.GetDatatable(sql) End Function, TimeSpan.FromMinutes(2)) @@ -344,12 +352,12 @@ Public Class ClassDocGrid DT_DETAIL_VALUES = ClassDataCache.GetOrLoad(cacheKey, Function() Dim sql = String.Format( - "SELECT T.[GUID],T.[DocID],T.[CONFIG_ID],T1.HEADER_CAPTION,T.[VALUE],T1.[LANGUAGE], " & - "T1.COLUMN_VIEW,T1.EDITABLE,T1.TYPE_ID,T1.VISIBLE,T.CHANGED_WHEN,T.CHANGED_WHO " & - "FROM TBPMO_DOC_VALUES T " & - "RIGHT JOIN TBPMO_DOCSEARCH_RESULTLIST_CONFIG T1 ON T.CONFIG_ID = T1.GUID " & - "WHERE T1.ENTITY_ID = {0} AND LANGUAGE = '{1}' AND T1.CONFIG_COLUMNS = 1 AND T.RECORD_ID = {2}", - CURRENT_ENTITY_ID, USER_LANGUAGE, RECORD_ID) + "SELECT T.[GUID],T.[DocID],T.[CONFIG_ID],T1.HEADER_CAPTION,T.[VALUE],T1.[LANGUAGE], " & + "T1.COLUMN_VIEW,T1.EDITABLE,T1.TYPE_ID,T1.VISIBLE,T.CHANGED_WHEN,T.CHANGED_WHO " & + "FROM TBPMO_DOC_VALUES T " & + "RIGHT JOIN TBPMO_DOCSEARCH_RESULTLIST_CONFIG T1 ON T.CONFIG_ID = T1.GUID " & + "WHERE T1.ENTITY_ID = {0} AND LANGUAGE = '{1}' AND T1.CONFIG_COLUMNS = 1 AND T.RECORD_ID = {2}", + CURRENT_ENTITY_ID, USER_LANGUAGE, RECORD_ID) Return MYDB_ECM.GetDatatable(sql) End Function, TimeSpan.FromMinutes(2)) End Select @@ -374,9 +382,6 @@ Public Class ClassDocGrid If oFlteredRows.Length > 0 Then value = oFlteredRows(0)("VALUE").ToString() End If - - - 'value = MYDB_ECM.GetScalarValue(String.Format("SELECT VALUE FROM TBPMO_DOC_VALUES WHERE CONFIG_ID = {0} AND DocID = {1} AND RECORD_ID = {2}", oConfigID, oDocID, RECORD_ID)) Catch ex As Exception LOGGER.Warn(String.Format("Attention: Could not get Value from TBPMO_DOC_VALUES for ConfigId[{0}], DocId[{1}]: ", oConfigID, oDocID) & ex.Message) End Try @@ -389,6 +394,7 @@ Public Class ClassDocGrid LOGGER.Warn($"Attention: Could not load values from TBPMO_DOC_VALUES: " & ex.Message & vbNewLine & $"SELECT VALUE FROM TBPMO_DOC_VALUES WHERE CONFIG_ID = {oConfigID} AND DocID = {oDocID} AND RECORD_ID = {RECORD_ID}") End Try LOGGER.Debug("Values loaded...") + Try ' Tabellen zum DataSet hinzufügen ds.Tables.Add(DT_RESULT) @@ -422,24 +428,26 @@ Public Class ClassDocGrid Dim gridControl As GridControl = pDocGridView.GridControl - - ' ── Performance-optimiertes DataSource-Setzen ───────────────────────── + ' ── 3. KRITISCH: Performance-optimiertes DataSource-Setzen ─────────── _isGridRefreshing = True ' Flag setzen VOR DataSource-Änderung Try pDocGridView.BeginDataUpdate() ' Events unterdrücken + pDocGridView.BeginUpdate() ' UI-Updates unterdrücken ' Datasource auf Master-Tabelle setzen gridControl.DataSource = ds.Tables(0) gridControl.ForceInitialize() - pDocGridView.EndDataUpdate() ' Events reaktivieren + pDocGridView.EndUpdate() ' UI-Updates reaktivieren + pDocGridView.EndDataUpdate() ' Events reaktivieren + Catch ex As Exception + LOGGER.Error($"Error setting DataSource: {ex.Message}") Finally - _isGridRefreshing = False ' Flag zurücksetzen + ' Flag NICHT hier zurücksetzen - erst NACH allen Grid-Operationen! End Try ' Detail View anlegen und der Relation `docIdDetails` zuweisen Dim GVDoc_Values As New GridView(gridControl) - 'grvwDetail.OptionsBehavior.Editable = False GVDoc_Values.OptionsView.ShowGroupPanel = False GVDoc_Values.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Style3D GVDoc_Values.OptionsView.EnableAppearanceEvenRow = True @@ -447,18 +455,17 @@ Public Class ClassDocGrid GVDoc_Values.Appearance.HeaderPanel.BackColor = Color.Orange GVDoc_Values.Appearance.HeaderPanel.Options.UseBackColor = True - gridControl.LevelTree.Nodes.Add("docIdDetails", GVDoc_Values) Catch ex As Exception MsgBox("Error in FillColumns: " & vbNewLine & ex.Message, MsgBoxStyle.Critical) LOGGER.Warn("Attention: Could not load converted datatable DocSearch: " & ex.Message) End Try + ' ── 4. KRITISCH: Handler NACH DataSource-Setzen registrieren ───────────── AddHandler pDocGridView.MasterRowExpanded, AddressOf gridView_MasterRowExpanded AddHandler pDocGridView.CustomColumnDisplayText, AddressOf gridView_CustomColumnDisplayText AddHandler pDocGridView.FocusedRowChanged, AddressOf GVDoc_Values_FocusedRowChanged - For Each row As DataRow In DT_WINDREAM_RESULTLIST.Rows Dim col As GridColumn = pDocGridView.Columns(row.Item("HEADER_CAPTION")) Dim colCaption = row.Item("HEADER_CAPTION") @@ -501,18 +508,22 @@ Public Class ClassDocGrid oChangedColumn.DisplayFormat.FormatString = CURRENT_DATE_FORMAT & " HH:MM:ss" End If + ' ── 5. BestFitColumns mit gesetztem Flag ────────────────────────────────── If GridDocResult_BestFitColumns Then - _isGridRefreshing = True ' Auch hier Events unterdrücken + ' _isGridRefreshing ist bereits True Try pDocGridView.BeginUpdate() pDocGridView.OptionsView.BestFitMaxRowCount = -1 pDocGridView.BestFitColumns(True) pDocGridView.EndUpdate() - Finally - _isGridRefreshing = False + Catch ex As Exception + LOGGER.Error($"Error in BestFitColumns: {ex.Message}") End Try End If + ' ── 6. KRITISCH: Flag ERST JETZT zurücksetzen! ──────────────────────────── + _isGridRefreshing = False + ' Alle Spalten aus ReadOnly setzen, danach werden alle passenden auf nicht ReadOnly gesetzt For Each column As GridColumn In pDocGridView.Columns column.OptionsColumn.AllowEdit = False @@ -623,69 +634,54 @@ Public Class ClassDocGrid End If Dim fieldName As String = e.Column.FieldName + Dim valueString As String = e.Value.ToString() + + ' ── WICHTIG: Verhindere rekursive Aufrufe ──────────────────────────── + ' Wenn DisplayText bereits korrekt ist, nichts ändern + If e.DisplayText = valueString Then Return + Dim parsedDate As DateTime ' ── Datumskonvertierung für Standard-Datumsspalten ─────────────────── If DATE_COLUMNS IsNot Nothing AndAlso DATE_COLUMNS.Contains(fieldName) Then - ' Nur bei Verbose-Logging loggen - If EnableVerboseGridLogging Then - LOGGER.Debug($"gridView_CustomColumnDisplayText [Standard] [{fieldName}]") - End If - Try - ' Versuche direktes Parsen - If DateTime.TryParse(e.Value.ToString(), parsedDate) Then - e.DisplayText = parsedDate.ToString(CURRENT_DATE_FORMAT & " HH:mm:ss") - Else - ' Fallback: ParseExact - parsedDate = DateTime.ParseExact(e.Value.ToString(), - CURRENT_DATE_FORMAT & " HH:mm:ss", - System.Globalization.DateTimeFormatInfo.InvariantInfo) - e.DisplayText = parsedDate.ToString(CURRENT_DATE_FORMAT & " HH:mm:ss") + If DateTime.TryParse(valueString, parsedDate) Then + Dim formattedDate As String = parsedDate.ToString(CURRENT_DATE_FORMAT & " HH:mm:ss") + ' Nur setzen wenn unterschiedlich + If e.DisplayText <> formattedDate Then + e.DisplayText = formattedDate + End If End If Catch ex As FormatException - ' Bei Parsing-Fehler Original-Wert anzeigen - e.DisplayText = e.Value.ToString() + ' Bei Fehler Original-Wert belassen (NICHT setzen!) If EnableVerboseGridLogging Then - LOGGER.Debug($"Date parsing failed for [{fieldName}]: {e.Value}") + LOGGER.Debug($"Date parsing failed for [{fieldName}]: {valueString}") End If End Try - - Return ' Früher Exit - keine weitere Prüfung nötig + Return End If ' ── Datumskonvertierung für Config-Datumsspalten ────────────────────── If DATE_COLUMNS_CONFIG IsNot Nothing AndAlso DATE_COLUMNS_CONFIG.Contains(fieldName) Then - ' Nur bei Verbose-Logging loggen - If EnableVerboseGridLogging Then - LOGGER.Debug($"gridView_CustomColumnDisplayText [Config] [{fieldName}]") - End If - Try - ' Versuche direktes Parsen - If DateTime.TryParse(e.Value.ToString(), parsedDate) Then - e.DisplayText = parsedDate.ToString(CURRENT_DATE_FORMAT) - Else - ' Fallback: ParseExact - parsedDate = DateTime.ParseExact(e.Value.ToString(), - CURRENT_DATE_FORMAT, - System.Globalization.DateTimeFormatInfo.InvariantInfo) - e.DisplayText = parsedDate.ToString(CURRENT_DATE_FORMAT) + If DateTime.TryParse(valueString, parsedDate) Then + Dim formattedDate As String = parsedDate.ToString(CURRENT_DATE_FORMAT) + ' Nur setzen wenn unterschiedlich + If e.DisplayText <> formattedDate Then + e.DisplayText = formattedDate + End If End If Catch ex As FormatException - ' Bei Parsing-Fehler Original-Wert anzeigen - e.DisplayText = e.Value.ToString() + ' Bei Fehler Original-Wert belassen If EnableVerboseGridLogging Then - LOGGER.Debug($"Date parsing failed for [{fieldName}]: {e.Value}") + LOGGER.Debug($"Date parsing failed for [{fieldName}]: {valueString}") End If End Try End If Catch ex As Exception - ' Fehler IMMER loggen (aber nicht Debug) LOGGER.Error($"gridView_CustomColumnDisplayText Error [{e.Column?.FieldName}]: {ex.Message}") End Try - End Sub Public Shared Sub GVDoc_Values_FocusedRowChanged(sender As GridView, e As DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs) Try diff --git a/app/DD-Record-Organizer/Classes/ClassHelper.vb b/app/DD-Record-Organizer/Classes/ClassHelper.vb index 70000fb..dfc0534 100644 --- a/app/DD-Record-Organizer/Classes/ClassHelper.vb +++ b/app/DD-Record-Organizer/Classes/ClassHelper.vb @@ -301,68 +301,7 @@ Public Class ClassHelper End Try End Try End Sub - 'Private Shared Sub BWFileHandler_DoWork() - ' Try - ' Dim oOverrideRunPath As String = "" - ' Dim oExtension = Path.GetExtension(BW_DocPath).ToLower - ' For Each oROW As DataRow In CURRENT_TBFILE_EXTENSION_OVERRIDE.Rows - ' If oExtension.Replace(".", "") = oROW.Item("FILE_EXTENSION") Then - ' LOGGER.Debug($"Specific fileextension override for extension [{oExtension}] found! ") - ' oOverrideRunPath = oROW.Item("PROCESS") - ' End If - ' Next - ' Dim oMyProcess = New Process() - ' Dim oSql - ' Try - ' '###### - ' Dim startInfo As New ProcessStartInfo() - ' If oOverrideRunPath <> "" Then - ' startInfo.FileName = oOverrideRunPath - ' startInfo.Arguments = """" & BW_DocPath & """" - ' startInfo.UseShellExecute = True - ' startInfo.RedirectStandardOutput = False - ' Else - ' startInfo.FileName = BW_DocPath - ' startInfo.UseShellExecute = True - ' startInfo.RedirectStandardOutput = False - ' End If - ' '##### - ' oMyProcess.Start(startInfo) - ' Dim myViewerProcessID = oMyProcess.Id - ' oMyProcess.WaitForExit() - ' oExtension = Path.GetExtension(BW_DocPath).ToLower - ' LOGGER.Debug($"Checking oExtension [{oExtension}]...") - ' If FILE_FORMATS_CHANGE_DURING_EDIT.Contains(oExtension) Then - ' oSql = $"SELECT * FROM VWOF_DOCID_HANDLE WHERE dwParentID = {BW_ParentID} and [Filename] = '{BW_Filename}'" - ' Dim oDTNEWDoc As DataTable = MYDB_ECM.GetDatatable(oSql) - ' If Not IsNothing(oDTNEWDoc) Then - ' If oDTNEWDoc.Rows.Count = 1 Then - - ' Dim oInsert = $"INSERT INTO TBPMO_DOC_ID_CHANGED (USER_ID,PROCESS_ID,VERSION_ID,OLD_DOC_ID,NEW_DOC_ID, DOC_PATH) VALUES ( - ' {USER_GUID},'{myViewerProcessID.ToString}',{oDTNEWDoc.Rows(0).Item("dwVersionID")},{BW_DocID},{oDTNEWDoc.Rows(0).Item("NewDocID")}, '{BW_DocPath}')" - ' MYDB_ECM.ExecuteNonQuery(oInsert) - ' End If - - - ' End If - ' End If - - ' Catch ex As Exception - ' LOGGER.Warn("Error in Process1.Start(): " & ex.Message & vBCrlf & " - Path: " & BW_DocPath & " - DocID: " & BW_DocID) - ' MsgBox("Error in OpenFile: " & ex.Message & vBCrlf & " - Path: " & BW_DocPath & " - DocID: " & BW_DocID, MsgBoxStyle.Exclamation) - ' Exit Sub - ' End Try - - ' Catch ex As Exception - ' LOGGER.Warn("Error in Process.Start(): " & ex.Message & vBCrlf & " - Path: " & BW_DocPath & " - DocID: " & BW_DocID) - ' Try - ' Process.Start(BW_DocPath) - ' Catch ex1 As Exception - ' LOGGER.Warn("Error in Process.Start(1): " & ex1.Message & vBCrlf & " - Path: " & BW_DocPath & " - DocID: " & BW_DocID) - ' End Try - ' End Try - 'End Sub Private Shared Sub FOLDER_OPEN(PATH As Object, DocID As String) Try If PATH <> Nothing Then @@ -461,12 +400,35 @@ Public Class ClassHelper End Function Public Shared Sub REMOVE_OLD_DROP_FILES() Try + ' ✅ NEU: Pre-Check - welche Dateien sind betroffen? + Dim preCheckSQL = $"SELECT GUID, FILENAME_ONLY, ADDED_WHEN, DATEDIFF(MINUTE, ADDED_WHEN, GETDATE()) AS AGE_MINUTES " & + $"FROM TBPMO_FILES_USER " & + $"WHERE ADDED_WHEN < DATEADD(MINUTE, -15, GETDATE()) " & + $"AND WORKED = 0 AND USER_WORK = '{USER_USERNAME}'" + + Dim preCheckDT = MYDB_ECM.GetDatatable(preCheckSQL) + + If preCheckDT IsNot Nothing AndAlso preCheckDT.Rows.Count > 0 Then + LOGGER.Warn($"REMOVE_OLD_DROP_FILES: {preCheckDT.Rows.Count} Dateien werden als TIMEOUT markiert:") + For Each row As DataRow In preCheckDT.Rows + LOGGER.Warn($" - GUID={row("GUID")}, Datei={row("FILENAME_ONLY")}, Alter={row("AGE_MINUTES")} Minuten") + Next + Else + LOGGER.Debug($"REMOVE_OLD_DROP_FILES: Keine Dateien älter als 15 Minuten (User: {USER_USERNAME})") + End If + + ' ✅ Dann UPDATE Dim oDEL = String.Format("UPDATE [DD_ECM].[dbo].[TBPMO_FILES_USER] - SET [USER_WORK] = [USER_WORK] + '_TIMEOUT', - WORKED = 1 - WHERE ADDED_WHEN < DATEADD(MINUTE, -5, GETDATE()) - AND WORKED = 0 AND USER_WORK = '{0}' ;", USER_USERNAME) - MYDB_ECM.ExecuteNonQuery(oDEL) + SET [USER_WORK] = [USER_WORK] + '_TIMEOUT', + WORKED = 1 + WHERE ADDED_WHEN < DATEADD(MINUTE, -15, GETDATE()) + AND WORKED = 0 AND USER_WORK = '{0}' ;", USER_USERNAME) + + Dim rowsAffected = MYDB_ECM.ExecuteNonQuery(oDEL) + + If rowsAffected > 0 Then + LOGGER.Warn($"REMOVE_OLD_DROP_FILES: {rowsAffected} Dateien wurden als TIMEOUT markiert") + End If Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Critical, "Unexpected error while REMOVE_OLD_DROP_FILES") End Try @@ -475,7 +437,19 @@ Public Class ClassHelper Try Dim sql = String.Format("SELECT *, CONVERT(BIT,0) AS DELETE_FILE FROM TBPMO_FILES_USER WHERE (USER_WORK = '{0}') AND WORKED = 0", USER_USERNAME) CURRENT_TBPMO_FILES_USER = MYDB_ECM.GetDatatable(sql) + ' ✅ NEU: Logging + If CURRENT_TBPMO_FILES_USER Is Nothing Then + LOGGER.Warn($"Create_USER_FILE_TABLE: GetDatatable gab Nothing zurück (User: {USER_USERNAME})") + Else + LOGGER.Debug($"Create_USER_FILE_TABLE: {CURRENT_TBPMO_FILES_USER.Rows.Count} Dateien geladen (User: {USER_USERNAME})") + + ' ✅ DEBUG: Zeige GUIDs der geladenen Dateien + For Each row As DataRow In CURRENT_TBPMO_FILES_USER.Rows + LOGGER.Debug($" - GUID={row("GUID")}, WORKED={row("WORKED")}, Datei={row("FILENAME2WORK")}") + Next + End If Catch ex As Exception + LOGGER.Error($"Create_USER_FILE_TABLE Exception: {ex.Message}") MsgBox(ex.Message, MsgBoxStyle.Critical, "Unexpected error while creating User_File_Table") End Try End Sub @@ -551,9 +525,11 @@ Public Class ClassHelper Else LOGGER.Warn($"File does not exist: [{pFilename}] - Cannot compute hash.") End If + Dim oSQL = $"SELECT Filename, ADDED_WHO, FORMAT(ADDED_WHEN, 'dd-MM-yyyy HH:mm') AS ADDED_WHEN_STRING FROM TBPMO_DOCRESULT_LIST WHERE FILE_HASH = '{CURRENT_FILE_HASH}' ORDER BY ADDED_WHEN DESC" LOGGER.Debug($"Inserting File - hash is [{CURRENT_FILE_HASH}]") Dim oDTCHECK As DataTable = MYDB_ECM.GetDatatable(oSQL) + If Not IsNothing(oDTCHECK) Then If oDTCHECK.Rows.Count >= 1 Then LOGGER.Info($"We got a file with the same hash [{CURRENT_FILE_HASH}]") @@ -561,34 +537,74 @@ Public Class ClassHelper Dim oUSER = oDTCHECK.Rows(0).Item(1) Dim oADDED_WHEN = oDTCHECK.Rows(0).Item(2) Dim oMSG As String + If USER_LANGUAGE <> "de-DE" Then oMSG = $"This file has already been imported into orgFLOW!" & vbCrLf & - $"File: [{oFilename}]" & vbCrLf & - $"Imported on: {oADDED_WHEN}" & vbCrLf & - $"Imported by: {oUSER}" & vbCrLf & - $"Total imports with identical content: {oDTCHECK.Rows.Count}" & vbCrLf & vbCrLf & - "Do you want to import this file again?" & vbCrLf & - "NO → Teh complete Import will be cancelled." + $"File: [{oFilename}]" & vbCrLf & + $"Imported on: {oADDED_WHEN}" & vbCrLf & + $"Imported by: {oUSER}" & vbCrLf & + $"Total imports with identical content: {oDTCHECK.Rows.Count}" & vbCrLf & vbCrLf & + "Do you want to import this file again?" & vbCrLf & + "NO → Teh complete Import will be cancelled." Else oMSG = $"Diese Datei wurde bereits in orgFLOW importiert!" & vbCrLf & - $"Datei: [{oFilename}]" & vbCrLf & - $"Importiert am: {oADDED_WHEN}" & vbCrLf & - $"Importiert von: {oUSER}" & vbCrLf & - $"Anzahl Importe mit identischem Inhalt: {oDTCHECK.Rows.Count}" & vbCrLf & vbCrLf & - "Möchten Sie die Datei dennoch erneut importieren?" & vbCrLf & - "NEIN → Der gesamte Import (alle folgenden) wird abgebrochen." + $"Datei: [{oFilename}]" & vbCrLf & + $"Importiert am: {oADDED_WHEN}" & vbCrLf & + $"Importiert von: {oUSER}" & vbCrLf & + $"Anzahl Importe mit identischem Inhalt: {oDTCHECK.Rows.Count}" & vbCrLf & vbCrLf & + "Möchten Sie die Datei dennoch erneut importieren?" & vbCrLf & + "NEIN → Der gesamte Import (alle folgenden) wird abgebrochen." End If + Dim result As MsgBoxResult result = MessageBox.Show(oMSG, CAPTION_CONFIRMATION, MessageBoxButtons.YesNo, MessageBoxIcon.Question) + If result = MsgBoxResult.No Then + LOGGER.Info($"User wählte NEIN bei Hash-Duplikat-Check für [{filename_only}] - Import abgebrochen") Return False + Else + LOGGER.Info($"User wählte JA bei Hash-Duplikat-Check für [{filename_only}] - fahre fort") End If End If End If - Dim ins As String = String.Format("INSERT INTO TBPMO_FILES_USER (FILENAME2WORK, USER_WORK,HANDLE_TYPE,FILENAME_ONLY,FILE_HASH) VALUES ('{0}','{1}','{2}','{3}','{4}')", pFilename, USER_USERNAME, handleType, filename_only, CURRENT_FILE_HASH) - Return MYDB_ECM.ExecuteNonQuery(ins) + ' ✅ NEU: Pre-Check - gibt es bereits einen Eintrag mit diesem Hash? + Dim preCheckSQL = $"SELECT GUID, USER_WORK, WORKED FROM TBPMO_FILES_USER WHERE FILE_HASH = '{CURRENT_FILE_HASH}' AND USER_WORK = '{USER_USERNAME}'" + Dim preCheckDT = MYDB_ECM.GetDatatable(preCheckSQL) + + If preCheckDT IsNot Nothing AndAlso preCheckDT.Rows.Count > 0 Then + LOGGER.Warn($"WARNUNG: Datei mit Hash [{CURRENT_FILE_HASH}] bereits in TBPMO_FILES_USER vorhanden:") + For Each row As DataRow In preCheckDT.Rows + LOGGER.Warn($" - GUID={row("GUID")}, USER_WORK={row("USER_WORK")}, WORKED={row("WORKED")}") + Next + End If + + ' ✅ INSERT mit explizitem Logging + Dim ins As String = String.Format("INSERT INTO TBPMO_FILES_USER (FILENAME2WORK, USER_WORK, HANDLE_TYPE, FILENAME_ONLY, FILE_HASH) VALUES ('{0}','{1}','{2}','{3}','{4}')", pFilename, USER_USERNAME, handleType, filename_only, CURRENT_FILE_HASH) + + LOGGER.Debug($"Führe INSERT aus: [{ins}]") + Dim insertResult = MYDB_ECM.ExecuteNonQuery(ins) + + If insertResult Then + ' ✅ VERIFY - wurde wirklich eingefügt? + Dim verifySQL = $"SELECT TOP 1 GUID, ADDED_WHEN FROM TBPMO_FILES_USER WHERE FILE_HASH = '{CURRENT_FILE_HASH}' AND USER_WORK = '{USER_USERNAME}' ORDER BY GUID DESC" + Dim verifyDT = MYDB_ECM.GetDatatable(verifySQL) + + If verifyDT IsNot Nothing AndAlso verifyDT.Rows.Count > 0 Then + Dim insertedGUID = verifyDT.Rows(0)("GUID") + Dim insertedADDED_WHEN = verifyDT.Rows(0)("ADDED_WHEN") + LOGGER.Info($"INSERT ERFOLGREICH: GUID={insertedGUID}, ADDED_WHEN={insertedADDED_WHEN}, Datei=[{filename_only}]") + Else + LOGGER.Error($"INSERT fehlgeschlagen (VERIFY)! Datei=[{filename_only}], Hash=[{CURRENT_FILE_HASH}]") + End If + Else + LOGGER.Error($"INSERT fehlgeschlagen (ExecuteNonQuery)! Datei=[{filename_only}]") + End If + + Return insertResult + Catch ex As Exception + LOGGER.Error($"Insert_USER_File Exception: {ex.Message}") MsgBox("Unexpected Error in Insert file for user (TBPMO_FILES_USER): " & ex.Message, MsgBoxStyle.Critical) Return False End Try diff --git a/app/DD-Record-Organizer/Log_ewa.txt b/app/DD-Record-Organizer/Log_ewa.txt new file mode 100644 index 0000000..1c7a20f Binary files /dev/null and b/app/DD-Record-Organizer/Log_ewa.txt differ diff --git a/app/DD-Record-Organizer/OrgFlow.vbproj b/app/DD-Record-Organizer/OrgFlow.vbproj index 0267fb9..c7c1643 100644 --- a/app/DD-Record-Organizer/OrgFlow.vbproj +++ b/app/DD-Record-Organizer/OrgFlow.vbproj @@ -1717,6 +1717,7 @@ PreserveNewest + diff --git a/app/DD-Record-Organizer/frmNodeNavigation.vb b/app/DD-Record-Organizer/frmNodeNavigation.vb index b5e6aab..9d43d9b 100644 --- a/app/DD-Record-Organizer/frmNodeNavigation.vb +++ b/app/DD-Record-Organizer/frmNodeNavigation.vb @@ -2307,7 +2307,7 @@ Public Class frmNodeNavigation End If End If If CURRENT_RECORD_ID = 0 Then - ClassHelper.MSGBOX_Handler("INFO", "Attention", "Input missing: ", "Please choose a record.") + ClassHelper.MSGBOX_Handler("INFO", "Achtung", "Fokus unklar: ", "Bitte wählen Sie erneut einen Knoten aus!") Exit Sub End If If DROPPED_CHECKED = False Then @@ -2349,30 +2349,44 @@ Public Class frmNodeNavigation End If ClassHelper.REMOVE_OLD_DROP_FILES() ClassHelper.Create_USER_FILE_TABLE() - If Not IsNothing(CURRENT_TBPMO_FILES_USER) Then - If CURRENT_TBPMO_FILES_USER.Rows.Count > 0 Then - For Each Filerow As DataRow In CURRENT_TBPMO_FILES_USER.Rows - If CBool(Filerow.Item("WORKED")) = False Then - 'Dim datei = Str.ToString.Replace("@DROPFROMFSYSTEM@", "") - CURRENT_FILEID = Filerow.Item("GUID") - ' CURRENT_PARENT_ENTITY_ID = PARENT_ENTITYID - 'CURRENT_RECORD_ID = RECORD_ID - 'CURRENT_ENTITY_ID = ENTITY_ID - CURRENT_FORMVIEW_ID = FORMVIEW_ID - frmWM_IndexFile.ShowDialog() - Else - - End If - Next + ' ✅ ENDLOS-SCHLEIFE: Solange Dateien vorhanden sind, Formular öffnen + Do While True + ' ✅ Prüfe, ob noch Dateien vorhanden sind + If CURRENT_TBPMO_FILES_USER Is Nothing OrElse CURRENT_TBPMO_FILES_USER.Rows.Count = 0 Then + NNLogger.Info("Keine weiteren Dateien zu verarbeiten - beende Check_Dropped_Files") + Exit Do End If - End If + + ' ✅ Hole die ERSTE unverarbeitete Datei + Dim firstFile = CURRENT_TBPMO_FILES_USER.Rows.Cast(Of DataRow)() _ + .Where(Function(r) CBool(r("WORKED")) = False) _ + .FirstOrDefault() + + If firstFile Is Nothing Then + NNLogger.Info("Alle Dateien wurden verarbeitet - beende Check_Dropped_Files") + Exit Do + End If + + ' ✅ Setze globale Variablen + CURRENT_FILEID = CInt(firstFile("GUID")) + CURRENT_FORMVIEW_ID = FORMVIEW_ID + + NNLogger.Debug($"Öffne frmWM_IndexFile für FileId={CURRENT_FILEID}") + + ' ✅ Öffne Formular (kann Multi-Indexing ausführen!) + frmWM_IndexFile.ShowDialog() + + ' ✅ WICHTIG: Lade Dateiliste NEU aus Datenbank! + ClassHelper.Create_USER_FILE_TABLE() + + ' ✅ Schleife läuft weiter, prüft erneut ob Dateien vorhanden sind + Loop Catch ex As Exception NNLogger.Error(ex) ClassHelper.MSGBOX_Handler("ERROR", "Unexpected Error", "Error in Check_Dropped_Files: ", ex.Message) End Try - End Sub Private Async Sub GridControlDocSearch_DragDrop(sender As Object, e As DragEventArgs) Handles GridControlDocSearch.DragDrop Await Drag_Drop(e) diff --git a/app/DD-Record-Organizer/frmWM_IndexFile.resx b/app/DD-Record-Organizer/frmWM_IndexFile.resx index e46c40f..381dec3 100644 --- a/app/DD-Record-Organizer/frmWM_IndexFile.resx +++ b/app/DD-Record-Organizer/frmWM_IndexFile.resx @@ -126,10 +126,10 @@ - 6, 25 + 7, 33 - 62, 15 + 74, 20 5 @@ -160,10 +160,10 @@ True - 428, 25 + 489, 33 - 70, 15 + 86, 20 6 @@ -190,10 +190,10 @@ True - 6, 54 + 7, 72 - 73, 15 + 84, 20 8 @@ -217,10 +217,10 @@ True - 12, 9 + 14, 12 - 61, 15 + 79, 20 0 @@ -244,10 +244,13 @@ Top, Left, Right - 15, 27 + 17, 36 + + + 3, 4, 3, 4 - 574, 23 + 655, 27 1 @@ -271,10 +274,10 @@ Segoe UI Semibold, 9.75pt, style=Bold - 12, 58 + 14, 77 - 188, 17 + 238, 23 2 @@ -298,10 +301,13 @@ Segoe UI Semibold, 9.75pt, style=Bold - 15, 78 + 17, 104 + + + 3, 4, 3, 4 - 203, 25 + 231, 29 3 @@ -340,10 +346,13 @@ MiddleLeft - 431, 444 + 493, 592 + + + 3, 4, 3, 4 - 158, 28 + 181, 37 4 @@ -370,10 +379,13 @@ Top, Left, Right - 85, 22 + 97, 29 + + + 3, 4, 3, 4 - 281, 23 + 321, 27 6 @@ -394,10 +406,13 @@ Top, Left, Right - 85, 51 + 97, 68 + + + 3, 4, 3, 4 - 469, 23 + 535, 27 9 @@ -418,10 +433,13 @@ Top, Right - 504, 22 + 576, 29 + + + 3, 4, 3, 4 - 50, 23 + 57, 27 7 @@ -442,10 +460,16 @@ Segoe UI, 9pt, style=Italic - 15, 117 + 17, 156 + + + 3, 4, 3, 4 + + + 3, 4, 3, 4 - 560, 80 + 640, 107 7 @@ -475,10 +499,13 @@ Verdana, 9.75pt, style=Italic - 24, 450 + 27, 603 + + + 3, 4, 3, 4 - 177, 20 + 226, 24 8 @@ -511,10 +538,13 @@ Verdana, 9.75pt, style=Bold, Italic - 24, 476 + 27, 638 + + + 3, 4, 3, 4 - 519, 20 + 688, 24 9 @@ -547,10 +577,16 @@ Top, Bottom, Left, Right - 15, 203 + 17, 271 + + + 3, 4, 3, 4 + + + 3, 4, 3, 4 - 574, 191 + 656, 255 10 @@ -583,10 +619,10 @@ Segoe UI Semibold, 9pt, style=Bold, Italic - 21, 397 + 24, 529 - 134, 15 + 172, 20 11 @@ -616,10 +652,13 @@ Segoe UI Semibold, 9pt, style=Bold, Italic - 24, 415 + 27, 553 + + + 3, 4, 3, 4 - 551, 24 + 629, 28 12 @@ -643,10 +682,10 @@ True - 7, 15 + 8, 20 - 604, 513 + 690, 684 Segoe UI, 9pt @@ -1100,6 +1139,9 @@ wAH//wAA///AAf//AAD//8AB//8AAP//wAH//wAA///AD///AAD///H///8AAP///////wAA + + 3, 4, 3, 4 + Import nach windream: diff --git a/app/DD-Record-Organizer/frmWM_IndexFile.vb b/app/DD-Record-Organizer/frmWM_IndexFile.vb index 020e74b..235e704 100644 --- a/app/DD-Record-Organizer/frmWM_IndexFile.vb +++ b/app/DD-Record-Organizer/frmWM_IndexFile.vb @@ -41,11 +41,18 @@ Public Class frmWM_IndexFile Function WORK_FILE(ImportFilePath As String, VerzeichnisZiel As String, vDokart_ID As Integer, vDokart As String, multiindex As Boolean) 'Dim swWORK_FILE As New SW("WORK_FILE: " & DOCTYPE_IDTextBox.Text) Try + LOGGER.Debug($" WORK_FILE aufgerufen: CURRENT_FILEID={CURRENT_FILEID}, Datei={Me.txtFilepath.Text}") + LOGGER.Debug($"=== WORK_FILE START: multiindex={multiindex} ===") + LOGGER.Debug($" Datei: {ImportFilePath}") + LOGGER.Debug($" Flags: _multiIndexDecisionMade={_multiIndexDecisionMade}, _multiIndexOverwriteExisting={_multiIndexOverwriteExisting}") + CURRENT_DOC_ID = Nothing Dim odeleteRights As Boolean = True - Dim oSQL = $"SELECT GUID FROM TBPMO_FILES_USER WHERE FILENAME2WORK = '{ImportFilePath}' AND WORKED = 0 AND USER_WORK = '{Environment.UserName}'" - CURRENT_FILEID = MYDB_ECM.GetScalarValue(oSQL) + If CURRENT_FILEID = 0 OrElse CURRENT_FILEID = Nothing Then + LOGGER.Error("WORK_FILE: CURRENT_FILEID ist ungültig (0 oder Nothing)!") + Return False + End If CURRENT_DOKARTSTRING = vDokart Dim err As Boolean = False '################################################################# @@ -64,6 +71,7 @@ Public Class frmWM_IndexFile If multiindex = True Then If _multiIndexDecisionMade = False Then + LOGGER.Debug(" ZEIGE DIALOG für Multi-Index-Entscheidung") ' Erste Kollision → Benutzer fragen Dim msg As String If USER_LANGUAGE <> "de-DE" Then @@ -84,12 +92,16 @@ Public Class frmWM_IndexFile _multiIndexOverwriteExisting = (result = MsgBoxResult.Yes) _multiIndexDecisionMade = True - LOGGER.Info($"Multi-Indexing: User decision for file conflicts = {If(_multiIndexOverwriteExisting, "OVERWRITE", "VERSION")}") + LOGGER.Debug($" Benutzer-Entscheidung: {If(_multiIndexOverwriteExisting, "OVERWRITE", "VERSION")}") + LOGGER.Debug($" Flags NACH Dialog: _multiIndexDecisionMade={_multiIndexDecisionMade}, _multiIndexOverwriteExisting={_multiIndexOverwriteExisting}") + Else + LOGGER.Debug($" Verwende GESPEICHERTE Entscheidung: {If(_multiIndexOverwriteExisting, "OVERWRITE", "VERSION")}") End If shouldOverwrite = _multiIndexOverwriteExisting Else ' Einzeldatei → wie bisher + LOGGER.Debug(" Einzeldatei: Zeige Dialog") Dim msg As String If USER_LANGUAGE <> "de-DE" Then msg = "A file with the same name already exists!" & vbCrLf & @@ -104,10 +116,12 @@ Public Class frmWM_IndexFile Dim result As MsgBoxResult = MessageBox.Show(msg, "File already exists:", MessageBoxButtons.YesNo, MessageBoxIcon.Question) shouldOverwrite = (result = MsgBoxResult.Yes) + LOGGER.Debug($" Einzeldatei-Entscheidung: {If(shouldOverwrite, "OVERWRITE", "VERSION")}") End If ' ── Entscheidung ausführen ──────────────────────────────────── If shouldOverwrite Then + LOGGER.Debug(" Führe OVERWRITE aus") If WMMOD.RemoveFile(CURRENT_NEWFILENAME) = False Then Return False Else @@ -127,8 +141,12 @@ Public Class frmWM_IndexFile Next End If Else + LOGGER.Debug(" Führe VERSIONIERUNG aus") CURRENT_NEWFILENAME = ClassHelper.Versionierung_Datei(CURRENT_NEWFILENAME) + LOGGER.Debug($" Neuer Dateiname: {CURRENT_NEWFILENAME}") End If + Else + LOGGER.Debug(" Datei existiert NICHT, kein Konflikt") End If sw.Done() '################################################################# @@ -291,15 +309,23 @@ Public Class frmWM_IndexFile stg1 = "Success:" End If If multiindex = False Then CURRENT_NOTIFICATION_MSG = stg - MYDB_ECM.GetScalarValue("UPDATE TBPMO_FILES_USER SET WORKED = 1 WHERE GUID = " & CURRENT_FILEID) - For Each row As DataRow In CURRENT_TBPMO_FILES_USER.Rows - If row.Item("GUID") = CURRENT_FILEID Then - row.Item("WORKED") = 1 - If IsNothing(droptype) Then - droptype = row.Item("HANDLE_TYPE") - End If - End If - Next + + ' Neu - NUR wenn NICHT im Multi-Index-Modus: + If multiindex = False Then + MYDB_ECM.ExecuteNonQuery("UPDATE TBPMO_FILES_USER SET WORKED = 1 WHERE GUID = " & CURRENT_FILEID) + LOGGER.Debug($" Einzeldatei als WORKED markiert: GUID={CURRENT_FILEID}") + + ' ✅ DEBUG: Was steht JETZT in der DB? + Dim debugSQL = $"SELECT GUID, WORKED, FILENAME_ONLY FROM TBPMO_FILES_USER WHERE USER_WORK = '{USER_USERNAME}' ORDER BY GUID DESC" + Dim debugDT = MYDB_ECM.GetDatatable(debugSQL) + LOGGER.Debug($" ═══ DEBUG NACH UPDATE ═══") + LOGGER.Debug($" Anzahl Dateien in DB: {debugDT.Rows.Count}") + For Each row As DataRow In debugDT.Rows + LOGGER.Debug($" - GUID={row("GUID")}, WORKED={row("WORKED")}, Datei={row("FILENAME_ONLY")}") + Next + LOGGER.Debug($" ═══════════════════════") + End If + If IsNothing(CURRENT_DOC_ID) Then sw = New SW("GettingDocID") sql = String.Format("SELECT DocID FROM VWPMO_DOC_SYNC WHERE FULL_FILENAME = '{0}' AND CONVERT(DATE,Change_DateTime) = CONVERT(DATE,GETDATE())", CURRENT_FILEIN_WD) @@ -425,31 +451,70 @@ Public Class frmWM_IndexFile Me.Cursor = Cursors.WaitCursor SaveMySettingsValue("WD_IndexDeleteDocs", WD_IndexDeleteDocs, "ConfigMain") - ' ── Multi-Indexing-Flags zurücksetzen beim Start ────────────────── + LOGGER.Debug("=== HANDLE_FILE START ===") + LOGGER.Debug($" Flags VOR Reset: _multiIndexDecisionMade={_multiIndexDecisionMade}, _multiIndexOverwriteExisting={_multiIndexOverwriteExisting}") + _multiIndexDecisionMade = False _multiIndexOverwriteExisting = False + LOGGER.Debug($" Flags NACH Reset: _multiIndexDecisionMade={_multiIndexDecisionMade}, _multiIndexOverwriteExisting={_multiIndexOverwriteExisting}") + LOGGER.Debug($" chkMultiIndexer: Visible={chkMultiIndexer.Visible}, Checked={chkMultiIndexer.Checked}") + If chkMultiIndexer.Visible = True And chkMultiIndexer.Checked = True Then - ' ── Erste Datei: FILE_HASH sicherstellen ─────────────────────── + LOGGER.Debug("=== MULTI-INDEXING MODUS AKTIV ===") + + ' ── Erste Datei: FILE_HASH und CURRENT_FILEID sicherstellen ─── + Dim firstFileId As Integer = CURRENT_FILEID + Dim firstFileName As String = CURRENT_FILENAME + For Each oRow As DataRow In CURRENT_TBPMO_FILES_USER.Rows If oRow.Item("GUID") = CURRENT_FILEID Then FILE_HASH = oRow.Item("FILE_HASH") + firstFileName = oRow.Item("FILENAME2WORK") Exit For End If Next - If WORK_FILE(Me.txtFilepath.Text, Me.PATHTextBox.Text, doctype_id, My.Settings.WD_INDEXDOKART_SAVE, True) = False Then + LOGGER.Debug($" Verarbeite erste Datei (CURRENT_FILEID={firstFileId}): {firstFileName}") + + If WORK_FILE(firstFileName, Me.PATHTextBox.Text, doctype_id, My.Settings.WD_INDEXDOKART_SAVE, True) = False Then Me.Cursor = Cursors.Default + LOGGER.Warn(" Erste Datei fehlgeschlagen!") Return False End If - ' ── Erste Datei erfolgreich: GUID merken, Folgedateien laden ── - Dim firstFileId = CURRENT_FILEID - Dim DTFiles2Work As DataTable = MYDB_ECM.GetDatatable( - "SELECT * FROM TBPMO_FILES_USER WHERE WORKED = 0 " & - "AND GUID <> " & firstFileId & " AND USER_WORK = '" & USER_USERNAME & "'") + LOGGER.Debug(" Erste Datei erfolgreich verarbeitet") - If DTFiles2Work Is Nothing OrElse DTFiles2Work.Rows.Count = 0 Then + ' ── WICHTIG: Erste Datei als WORKED markieren UND DataTable neu laden ── + LOGGER.Debug($" Markiere erste Datei als WORKED: GUID={firstFileId}") + MYDB_ECM.ExecuteNonQuery($"UPDATE TBPMO_FILES_USER SET WORKED = 1 WHERE GUID = {firstFileId}") + + LOGGER.Debug(" Lade aktualisierte Dateiliste aus Datenbank...") + + ' ✅ SCHRITT 1: Prüfe mit COUNT(*), wie viele Dateien in der DB sind + Dim countSQL = $"SELECT COUNT(*) FROM TBPMO_FILES_USER WHERE USER_WORK = '{USER_USERNAME}' AND WORKED = 0" + Dim remainingCount = CInt(MYDB_ECM.GetScalarValue(countSQL)) + LOGGER.Debug($" SQL COUNT ergab: {remainingCount} verbleibende Dateien") + + ' ✅ SCHRITT 2: Nur wenn COUNT > 0, dann DataTable laden + If remainingCount > 0 Then + CURRENT_TBPMO_FILES_USER = MYDB_ECM.GetDatatable("SELECT *, CONVERT(BIT,0) AS DELETE_FILE FROM TBPMO_FILES_USER " & + "WHERE USER_WORK = '" & USER_USERNAME & "' AND WORKED = 0") + + If CURRENT_TBPMO_FILES_USER Is Nothing Then + LOGGER.Error(" WARNUNG: GetDatatable gab Nothing zurück, obwohl COUNT > 0!") + CURRENT_TBPMO_FILES_USER = New DataTable() + Else + LOGGER.Debug($" DataTable geladen: {CURRENT_TBPMO_FILES_USER.Rows.Count} Zeilen") + End If + Else + LOGGER.Info(" SQL COUNT ergab 0 Dateien") + CURRENT_TBPMO_FILES_USER = New DataTable() + End If + + ' ── Folgedateien aus aktualierter DataTable verarbeiten ── + If CURRENT_TBPMO_FILES_USER Is Nothing OrElse CURRENT_TBPMO_FILES_USER.Rows.Count = 0 Then + LOGGER.Info(" Keine weiteren Dateien vorhanden") NEW_FILES_ADDED = True FILE_WORKED = True Me.Cursor = Cursors.Default @@ -457,12 +522,24 @@ Public Class frmWM_IndexFile Return True End If + LOGGER.Debug($" Weitere Dateien gefunden: {CURRENT_TBPMO_FILES_USER.Rows.Count}") + LOGGER.Debug($" Flags VOR Schleife: _multiIndexDecisionMade={_multiIndexDecisionMade}, _multiIndexOverwriteExisting={_multiIndexOverwriteExisting}") + Dim err As Boolean = False - For Each filerow As DataRow In DTFiles2Work.Rows - CURRENT_FILEID = filerow.Item("GUID") - CURRENT_FILENAME = filerow.Item("FILENAME2WORK") - FILE_HASH = filerow.Item("FILE_HASH") - aktFiledropped = CURRENT_FILENAME + Dim fileCount As Integer = 0 + For Each filerow As DataRow In CURRENT_TBPMO_FILES_USER.Rows + fileCount += 1 + Dim currentFileId As Integer = filerow.Item("GUID") + Dim currentFileName As String = filerow.Item("FILENAME2WORK") + Dim currentFileHash As String = filerow.Item("FILE_HASH") + + CURRENT_FILEID = currentFileId + CURRENT_FILENAME = currentFileName + FILE_HASH = currentFileHash + aktFiledropped = currentFileName + + LOGGER.Debug($" [{fileCount}/{CURRENT_TBPMO_FILES_USER.Rows.Count}] Verarbeite Datei: {currentFileName}, FILEID={currentFileId}") + LOGGER.Debug($" Flags: _multiIndexDecisionMade={_multiIndexDecisionMade}, _multiIndexOverwriteExisting={_multiIndexOverwriteExisting}") Dim handleType As String = filerow.Item("HANDLE_TYPE") Select Case handleType @@ -476,10 +553,15 @@ Public Class frmWM_IndexFile droptype = handleType End Select - If WORK_FILE(CURRENT_FILENAME, Me.PATHTextBox.Text, doctype_id, My.Settings.WD_INDEXDOKART_SAVE, True) = False Then + If WORK_FILE(currentFileName, Me.PATHTextBox.Text, doctype_id, My.Settings.WD_INDEXDOKART_SAVE, True) = False Then err = True + LOGGER.Warn($" Datei fehlgeschlagen!") Exit For End If + + LOGGER.Debug($" Datei erfolgreich verarbeitet") + LOGGER.Debug($" Markiere Datei als WORKED: GUID={currentFileId}") + MYDB_ECM.ExecuteNonQuery($"UPDATE TBPMO_FILES_USER SET WORKED = 1 WHERE GUID = {currentFileId}") Next Me.Cursor = Cursors.Default @@ -493,6 +575,7 @@ Public Class frmWM_IndexFile stg = "All files were transferred via Multiindexing to windream" stg1 = "Success:" End If + LOGGER.Info("=== MULTI-INDEXING ERFOLGREICH ABGESCHLOSSEN ===") MsgBox(stg, MsgBoxStyle.Information, stg1) Me.Close() Return True @@ -501,25 +584,123 @@ Public Class frmWM_IndexFile Return False Else - ' ── Einzeldatei ─────────────────────────────────────────────── - If WORK_FILE(Me.txtFilepath.Text, Me.PATHTextBox.Text, doctype_id, My.Settings.WD_INDEXDOKART_SAVE, False) = True Then - NEW_FILES_ADDED = True - FILE_WORKED = True + ' ✅ EINZELDATEI MODUS + LOGGER.Debug("=== EINZELDATEI MODUS ===") + + ' ✅ WICHTIG: CURRENT_FILEID VOR WORK_FILE setzen! + For Each oRow As DataRow In CURRENT_TBPMO_FILES_USER.Rows + If oRow.Item("FILENAME2WORK") = Me.txtFilepath.Text Then + CURRENT_FILEID = CInt(oRow("GUID")) + FILE_HASH = oRow("FILE_HASH").ToString() + LOGGER.Debug($" Datei gefunden in CURRENT_TBPMO_FILES_USER: FILEID={CURRENT_FILEID}") + Exit For + End If + Next + + ' ✅ Validierung NACH Schleife + If CURRENT_FILEID = 0 Then + LOGGER.Error($" Datei nicht gefunden in CURRENT_TBPMO_FILES_USER: {Me.txtFilepath.Text}") + Me.Cursor = Cursors.Default + MessageBox.Show("Die Datei konnte nicht in der Verarbeitungsliste gefunden werden!", + "Fehler:", MessageBoxButtons.OK, MessageBoxIcon.Error) + Return False + End If + + If WORK_FILE(Me.txtFilepath.Text, Me.PATHTextBox.Text, doctype_id, My.Settings.WD_INDEXDOKART_SAVE, False) = False Then + Me.Cursor = Cursors.Default + MessageBox.Show("Import to windream was not successful." & vbCrLf & + "Check the log for further information!", + "Unexpected Error in windream-Stream:", + MessageBoxButtons.OK, MessageBoxIcon.Error) + Return False + End If + + ' ── Datei erfolgreich verarbeitet ── + NEW_FILES_ADDED = True + FILE_WORKED = True + LOGGER.Debug(" Einzeldatei erfolgreich verarbeitet") + + ' ✅ Prüfen, ob weitere Dateien vorhanden sind + LOGGER.Debug(" Lade aktualisierte Dateiliste für Einzeldatei-Check...") + + ' ✅ SCHRITT 1: Prüfe mit COUNT(*), wie viele Dateien in der DB sind + Dim countSQL = $"SELECT COUNT(*) FROM TBPMO_FILES_USER WHERE USER_WORK = '{USER_USERNAME}' AND WORKED = 0" + Dim remainingCount = CInt(MYDB_ECM.GetScalarValue(countSQL)) + LOGGER.Debug($" ═══ SQL COUNT NACH WORK_FILE ═══") + LOGGER.Debug($" COUNT(*) ergab: {remainingCount} verbleibende Dateien") + + ' ✅ SCHRITT 2: Dateiliste laden UND vergleichen + ClassHelper.Create_USER_FILE_TABLE() + + If CURRENT_TBPMO_FILES_USER Is Nothing Then + LOGGER.Error($" ❌ KRITISCHER FEHLER: Create_USER_FILE_TABLE gab Nothing zurück!") + ElseIf CURRENT_TBPMO_FILES_USER.Rows.Count <> remainingCount Then + LOGGER.Error($" ❌ KRITISCHER FEHLER: COUNT ergab {remainingCount}, aber DataTable hat {CURRENT_TBPMO_FILES_USER.Rows.Count} Zeilen!") + LOGGER.Error($" ❌ VERDACHT: Race-Condition oder Transaction-Problem!") + Else + LOGGER.Debug($" ✅ OK: COUNT und DataTable stimmen überein ({remainingCount} Dateien)") + End If + LOGGER.Debug($" ═══════════════════════════════") + + If CURRENT_TBPMO_FILES_USER IsNot Nothing AndAlso CURRENT_TBPMO_FILES_USER.Rows.Count > 0 Then + LOGGER.Info($" Einzeldatei-Modus: Weitere {CURRENT_TBPMO_FILES_USER.Rows.Count} Dateien vorhanden - aktualisiere Formular") + + ' ── Lade ERSTE Datei aus der NEUEN Liste ── + Dim nextFile = CURRENT_TBPMO_FILES_USER.Rows(0) + CURRENT_FILEID = CInt(nextFile("GUID")) + CURRENT_FILENAME = nextFile("FILENAME2WORK").ToString() + FILE_HASH = nextFile("FILE_HASH").ToString() + aktFiledropped = CURRENT_FILENAME + txtFilepath.Text = CURRENT_FILENAME + + LOGGER.Debug($" Nächste Datei geladen: FILEID={CURRENT_FILEID}, Datei={CURRENT_FILENAME}") + + ' ── Update MULTIFILES-Anzeige ── + MULTIFILES = CURRENT_TBPMO_FILES_USER.Rows.Count - 1 + If MULTIFILES > 0 Then + chkMultiIndexer.Text = "Multi-Indexing - Alle nachfolgenden Dateien (" & MULTIFILES & ") identisch indexieren" + chkMultiIndexer.Visible = True + chkMultiIndexer.Checked = False + Else + chkMultiIndexer.Visible = False + End If + + ' ── Handle-Type setzen ── + Dim handleType As String = nextFile("HANDLE_TYPE").ToString() + Select Case handleType + Case "@DROPFROMFSYSTEM@" + droptype = "dragdrop file" + chkdelete_origin.Visible = True + Case "@OUTLOOK_ATTMNT@" + droptype = "dragdrop attachment" + chkdelete_origin.Visible = True + Case "@OUTLOOKMESSAGE@" + droptype = "dragdrop message" + chkdelete_origin.Visible = True + Case "SCAN" + droptype = "scan" + chkdelete_origin.Visible = False + Case Else + droptype = handleType + chkdelete_origin.Visible = False + End Select + + Me.Cursor = Cursors.Default + LOGGER.Debug(" Formular bleibt offen für nächste Datei") + Return True ' ← Formular bleibt offen! + + Else + ' ✅ Keine weiteren Dateien → Formular schließen + LOGGER.Info(" Einzeldatei-Modus: Keine weiteren Dateien - schließe Formular") Me.Cursor = Cursors.Default Me.Close() Return True - Else - Me.Cursor = Cursors.Default - MessageBox.Show("Import to windream was not successful." & vbCrLf & - "Check the log for further information!", - "Unexpected Error in windream-Stream:", - MessageBoxButtons.OK, MessageBoxIcon.Error) - Return False End If End If Catch ex As Exception MsgBox("Error in Indexing_File:" & vbCrLf & ex.Message, MsgBoxStyle.Critical) + LOGGER.Error($"Handle_File Exception: {ex.Message}{vbCrLf}{ex.StackTrace}") Return False Finally Me.Cursor = Cursors.Default @@ -1113,37 +1294,63 @@ Public Class frmWM_IndexFile CURRENT_FILENAME = "" Me.VWDDINDEX_AUTOMTableAdapter.Connection.ConnectionString = MYDB_ECM.CurrentConnectionString chkMultiIndexer.Checked = False + + ' ── Multi-Indexing-Flags beim Formular-Load zurücksetzen ── + LOGGER.Debug("=== FORM LOAD: Flags zurücksetzen ===") + LOGGER.Debug($" VOR Reset: _multiIndexDecisionMade = {_multiIndexDecisionMade}, _multiIndexOverwriteExisting = {_multiIndexOverwriteExisting}") + + _multiIndexDecisionMade = False + _multiIndexOverwriteExisting = False + _processedFileIds.Clear() + + LOGGER.Debug($" NACH Reset: _multiIndexDecisionMade = {_multiIndexDecisionMade}, _multiIndexOverwriteExisting = {_multiIndexOverwriteExisting}") + LOGGER.Debug($" ProcessedFileIds Count: {_processedFileIds.Count}") + LOGGER.Debug("frmWD_Index_Dokart_Load") chkdelete_origin.Checked = False chkdelete_origin.Visible = False Dim oReconnect = WMMOD.SessionReconnect - '= New Windream(LOGCONFIG, False, WMDriveLetter, WMPATH_PREFIX, True, WM_SERVER, WM_USER, WM_USER_PW, WM_DOMAIN) + + ' ── WICHTIG: Prüfen, ob überhaupt Dateien vorhanden sind ── + If CURRENT_TBPMO_FILES_USER Is Nothing OrElse CURRENT_TBPMO_FILES_USER.Rows.Count = 0 Then + LOGGER.Info("frmWD_Index_Dokart_Load: Keine Dateien vorhanden - Formular wird geschlossen") + Me.Close() + Exit Sub + End If + Dim oHandleType As String For Each oRow As DataRow In CURRENT_TBPMO_FILES_USER.Rows If oRow.Item("GUID") = CURRENT_FILEID Then CURRENT_FILENAME = oRow.Item("FILENAME2WORK") oHandleType = oRow.Item("HANDLE_TYPE") FILE_HASH = oRow.Item("FILE_HASH") + Exit For ' ← Hinzugefügt: Schleife verlassen, wenn gefunden End If Next + If CURRENT_FILENAME = "" Then - MsgBox("Chekc the Temp Files Table, as it seems to be empty!", MsgBoxStyle.Exclamation) + LOGGER.Warn("Check the Temp Files Table, as it seems to be empty or CURRENT_FILEID not found!") + MsgBox("Check the Temp Files Table, as it seems to be empty!", MsgBoxStyle.Exclamation) + Me.Close() ' ← Formular schließen statt Exit Sub Exit Sub End If - MULTIFILES = 0 - For Each row As DataRow In CURRENT_TBPMO_FILES_USER.Rows - If row.Item("GUID") <> CURRENT_FILEID Then - MULTIFILES += 1 - End If - Next + + ' ── KORREKTUR: Zähle alle Dateien außer der aktuellen ── + MULTIFILES = CURRENT_TBPMO_FILES_USER.Rows.Count - 1 + LOGGER.Debug($" MULTIFILES berechnet: Gesamt={CURRENT_TBPMO_FILES_USER.Rows.Count}, MULTIFILES={MULTIFILES}") + If MULTIFILES > 0 Then chkMultiIndexer.Text = "Multi-Indexing - Alle nachfolgenden Dateien (" & MULTIFILES & ") identisch indexieren" chkMultiIndexer.Visible = True + LOGGER.Debug($" chkMultiIndexer: Visible=True, Text={chkMultiIndexer.Text}") Else chkMultiIndexer.Visible = False + LOGGER.Debug(" chkMultiIndexer: Visible=False (keine weiteren Dateien)") End If + aktFiledropped = CURRENT_FILENAME txtFilepath.Text = aktFiledropped + If oHandleType = "@DROPFROMFSYSTEM@" Then droptype = "dragdrop file" chkdelete_origin.Visible = True @@ -1159,21 +1366,19 @@ Public Class frmWM_IndexFile ElseIf oHandleType = "SCAM" Then droptype = "scan" End If - Dim sql = String.Format("SELECT FORMVIEW_ID, FORM_ID, FORM_TITLE, DOKUMENTTYPE_ID, DOKUMENTTYPE, PATH, SHORTNAME, OBJECT_TYPE, FW_DOCTYPE_ID FROM VWPMO_DOKUMENTTYPES WHERE (FORMVIEW_ID = {0}) " & - "ORDER BY SEQUENCE, DOKUMENTTYPE", CURRENT_FORMVIEW_ID) - DTVWPMO_DOKUMENTTYPES = MYDB_ECM.GetDatatable(sql) - 'VWPMO_DOKUMENTTYPESTableAdapter.Connection.ConnectionString = MYDB_ECM.CurrentConnectionString - 'Me.VWPMO_DOKUMENTTYPESTableAdapter.Fill(Me.DD_DMSDataSet.VWPMO_DOKUMENTTYPES, CURRENT_FORMVIEW_ID) + Dim sql = String.Format("SELECT FORMVIEW_ID, FORM_ID, FORM_TITLE, DOKUMENTTYPE_ID, DOKUMENTTYPE, PATH, SHORTNAME, OBJECT_TYPE, FW_DOCTYPE_ID FROM VWPMO_DOKUMENTTYPES WHERE (FORMVIEW_ID = {0}) " & + "ORDER BY SEQUENCE, DOKUMENTTYPE", CURRENT_FORMVIEW_ID) + DTVWPMO_DOKUMENTTYPES = MYDB_ECM.GetDatatable(sql) CURRENT_REDUNDANT_FORM_ID = 0 CURRENT_REDUNDANT_FORMVIEW_ID = 0 - If DTVWPMO_DOKUMENTTYPES.Rows.Count = 0 Then ' DD_DMSDataSet.VWPMO_DOKUMENTTYPES.Rows.Count = 0 Then + If DTVWPMO_DOKUMENTTYPES.Rows.Count = 0 Then If CURRENT_ENTITY_REDUNDANT_ID <> 0 Then Dim FVID = MYDB_ECM.GetScalarValue(String.Format("SELECT GUID FROM TBPMO_FORM_VIEW WHERE FORM_ID = {0} and SCREEN_ID = 1", CURRENT_ENTITY_REDUNDANT_ID), True) - 'Me.VWPMO_DOKUMENTTYPESTableAdapter.Fill(Me.DD_DMSDataSet.VWPMO_DOKUMENTTYPES, FVID) - If DTVWPMO_DOKUMENTTYPES.Rows.Count = 0 Then 'DD_DMSDataSet.VWPMO_DOKUMENTTYPES.Rows.Count = 0 Then + If DTVWPMO_DOKUMENTTYPES.Rows.Count = 0 Then MsgBox("No documenttypes for the redundant entity configured either! Indexing is not possible!" & vbCrLf & "Please check the configuration!", MsgBoxStyle.Exclamation) + Me.Close() Exit Sub Else LOGGER.Debug("Redundant EntityID: " & CURRENT_ENTITY_REDUNDANT_ID) @@ -1184,12 +1389,15 @@ Public Class frmWM_IndexFile End If Else MsgBox("No documenttypes for this entity configured! Indexing is not possible!" & vbCrLf & "Please check the configuration!", MsgBoxStyle.Exclamation) + Me.Close() Exit Sub End If - End If + Catch ex As Exception + LOGGER.Error($"Error in frmWD_Index_Dokart_Load: {ex.Message}") MsgBox("Error in frmWD_Index_Dokart_Load:" & vbCrLf & ex.Message, MsgBoxStyle.Critical) + Me.Close() End Try End Sub @@ -1242,19 +1450,63 @@ Public Class frmWM_IndexFile Private Sub frmWM_IndexFile_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing Try - ' Alle nicht-verarbeiteten Dateien löschen (außer den erfolgreichen) - Dim processedIds = String.Join(",", _processedFileIds) - Dim oDelete = $"DELETE FROM TBPMO_FILES_USER WHERE USER_WORK = '{USER_USERNAME}' AND WORKED = 0" - If _processedFileIds.Count > 0 Then - oDelete &= $" AND GUID NOT IN ({processedIds})" + ' ── Multi-Indexing-Flags zurücksetzen ── + _multiIndexDecisionMade = False + _multiIndexOverwriteExisting = False + + ' ✅ WICHTIG: Liste NEU LADEN, bevor wir zählen! + LOGGER.Debug("=== CLOSING: Lade aktuelle Dateiliste ===") + ClassHelper.Create_USER_FILE_TABLE() ' ← Lädt CURRENT_TBPMO_FILES_USER NEU! + + ' ── Prüfen, ob noch Dateien zu verarbeiten sind ── + If CURRENT_TBPMO_FILES_USER IsNot Nothing AndAlso CURRENT_TBPMO_FILES_USER.Rows.Count > 0 Then + ' Es gibt noch nicht verarbeitete Dateien → Benutzer fragen + LOGGER.Debug($"TBPMO_FILES_USER: Formular wird geschlossen, aber {CURRENT_TBPMO_FILES_USER.Rows.Count} Dateien sind noch vorhanden.") + + Dim msg As String + Dim title As String + If USER_LANGUAGE <> "de-DE" Then + msg = $"There are still {CURRENT_TBPMO_FILES_USER.Rows.Count} unprocessed file(s)!" & vbCrLf & vbCrLf & + "Do you really want to cancel the import?" & vbCrLf & vbCrLf & + "YES → Cancel import and delete all pending files" & vbCrLf & + "NO → Continue indexing" + title = "Cancel Import?" + Else + msg = $"Es sind noch {CURRENT_TBPMO_FILES_USER.Rows.Count} nicht verarbeitete Datei(en) vorhanden!" & vbCrLf & vbCrLf & + "Möchten Sie den Import wirklich abbrechen?" & vbCrLf & vbCrLf & + "JA → Import abbrechen und alle ausstehenden Dateien löschen" & vbCrLf & + "NEIN → Indexierung fortsetzen" + title = "Import abbrechen?" + End If + + Dim result As MsgBoxResult = MessageBox.Show(msg, title, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) + + If result = MsgBoxResult.No Then + ' Benutzer will NICHT abbrechen → Formular-Schließen verhindern + LOGGER.Info("Benutzer hat Abbruch verhindert - Formular bleibt offen") + e.Cancel = True + Exit Sub + Else + ' Benutzer will abbrechen → Alle Dateien löschen + LOGGER.Info("Benutzer hat Abbruch bestätigt - Lösche alle ausstehenden Dateien") + Dim oDelete = $"DELETE FROM TBPMO_FILES_USER WHERE USER_WORK = '{USER_USERNAME}' AND WORKED = 0" + MYDB_ECM.ExecuteNonQuery(oDelete) + LOGGER.Info($"TBPMO_FILES_USER: {CURRENT_TBPMO_FILES_USER.Rows.Count} nicht-verarbeitete Einträge wurden gelöscht (User: {USER_USERNAME})") + + ' ── WICHTIG: DataTable leeren, damit Load-Event korrekt reagiert ── + CURRENT_TBPMO_FILES_USER.Clear() + LOGGER.Debug("CURRENT_TBPMO_FILES_USER wurde geleert") + End If + Else + ' Keine Dateien mehr vorhanden → Normal schließen, aufräumen + LOGGER.Debug("Keine ausstehenden Dateien mehr vorhanden ") + End If - MYDB_ECM.ExecuteNonQuery(oDelete) - LOGGER.Info($"TBPMO_FILES_USER: Nicht-verarbeitete Einträge bereinigt (User: {USER_USERNAME})") + Catch ex As Exception LOGGER.Warn($"Fehler beim Bereinigen von TBPMO_FILES_USER (Closing): {ex.Message}") End Try End Sub - Private Sub frmWM_IndexFile_Closed(sender As Object, e As EventArgs) Handles Me.Closed Try Cursor = Cursors.Default @@ -1262,4 +1514,8 @@ Public Class frmWM_IndexFile End Try End Sub + + Private Sub chkMultiIndexer_CheckedChanged(sender As Object, e As EventArgs) Handles chkMultiIndexer.CheckedChanged + LOGGER.Debug($"chkMultiIndexer.CheckedChanged: {chkMultiIndexer.Checked}") + End Sub End Class \ No newline at end of file