diff --git a/AA-Forms/FormExpedit.cs b/AA-Forms/FormExpedit.cs index a07903e..e997f7a 100644 --- a/AA-Forms/FormExpedit.cs +++ b/AA-Forms/FormExpedit.cs @@ -262,128 +262,164 @@ namespace Deckungsbeitrag #endregion #region ObjectListView-Events - + private void Load_OLV(ObjectListView olv, List auftragliste) { - // ========== LAYOUT UND UPDATE PAUSIEREN ========== - olv.BeginUpdate(); // Stoppt Datenaktualisierungen/Redraws - olv.SuspendLayout(); // Stoppt Layout-Berechnungen (Anchor/Dock) + this.UseWaitCursor = true; - // ========== SPALTEN AUTOMATISCH AUS MODEL ERTELLEN ========== - Generator.GenerateColumns(olv, typeof(View_Auftrag_Expedit), true); + // === LAYOUT & UPDATE PAUSIEREN === + olv.BeginUpdate(); + olv.SuspendLayout(); - // ========== SPALTEN ANPASSEN ========== - var aufgabeCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Aufgabe"); + try + { + // === SPALTEN NUR EINMAL GENERIEREN (falls sinnvoll) === + if (olv.AllColumns.Count == 0) + { + Generator.GenerateColumns(olv, typeof(View_Auftrag_Expedit), true); + ConfigureColumns(olv); + } + + // === IMAGE-LIST (einmalig zentral konfigurieren, hier nur zuweisen) === + Program.imagelist.ImageSize = new Size(24, 24); + olv.SmallImageList = Program.imagelist; + + // === TOOLTIP-EVENT EINMALIG REGISTRIEREN === + olv.CellToolTipShowing -= Olv_CellToolTipShowing; + olv.CellToolTipShowing += Olv_CellToolTipShowing; + + // === DATEN LADEN === + OLV_SetObjects(olv, auftragliste); + + // === SORTIERUNG === + var statusCol = olv.AllColumns.Cast().FirstOrDefault(c => c.Text == "Status"); + var liefertagCol = olv.AllColumns.Cast().FirstOrDefault(c => c.Text == "Liefertag"); + + if (statusCol != null) olv.PrimarySortColumn = statusCol; + if (liefertagCol != null) olv.SecondarySortColumn = liefertagCol; + + if (olv.Name.Contains("Rampe") && liefertagCol != null) + olv.Sort(liefertagCol); + else + olv.Sort(); + + // === SPALTEN JE NACH TAB/ROLLE === + GetUnvisibleColumns(olv); + + // === SPALTENBREITE ANPASSEN === + olv = Funktionen.Columns_Resize(null, olv).olv; + + // === FILTER === + olv.FilterMenuBuildStrategy = new MeinFilterMenu(); + } + finally + { + olv.ResumeLayout(); + olv.EndUpdate(); + olv.Focus(); + this.UseWaitCursor = false; + } + } + private void ConfigureColumns(ObjectListView olv) + { + var columns = olv.AllColumns.Cast().ToList(); + + OLVColumn Find(string header) => + columns.FirstOrDefault(c => String.Equals(c.Text, header, StringComparison.OrdinalIgnoreCase)); + + // --- Aufgabe-Icon --- + var aufgabeCol = Find("Aufgabe"); if (aufgabeCol != null) { aufgabeCol.ImageGetter = rowObject => { - var auftrag = rowObject as View_Auftrag_Expedit; - return string.IsNullOrEmpty(auftrag?.AufgabeBezeichnung) ? -1 : 0; + var a = rowObject as View_Auftrag_Expedit; + if (a == null) return -1; + return string.IsNullOrEmpty(a.AufgabeBezeichnung) ? -1 : 0; }; } - var kundeCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Kunde"); - if (kundeCol != null) + + // --- Kunde-Icon --- + var kundeCol = Find("Kunde"); + if (kundeCol != null) { kundeCol.ImageGetter = rowObject => { - var auftrag = rowObject as View_Auftrag_Expedit; - return string.IsNullOrEmpty(auftrag?.Zusatz) ? -1 : 1; + var a = rowObject as View_Auftrag_Expedit; + if (a == null) return -1; + return string.IsNullOrEmpty(a.Zusatz) ? -1 : 1; }; } - var dirtCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Schmutzig"); + + // --- Schmutzig / Sauber --- + var dirtCol = Find("Schmutzig"); if (dirtCol != null) { dirtCol.HeaderImageKey = "dirt"; dirtCol.ShowTextInHeader = false; dirtCol.MinimumWidth = dirtCol.MaximumWidth = 80; } - var cleanCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Sauber"); + + var cleanCol = Find("Sauber"); if (cleanCol != null) { cleanCol.HeaderImageKey = "clean"; cleanCol.ShowTextInHeader = false; - cleanCol.MinimumWidth = dirtCol.MaximumWidth = 80; + cleanCol.MinimumWidth = cleanCol.MaximumWidth = 80; // Bugfix: nicht dirtCol.MaximumWidth } - var primaryCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Status"); - if (primaryCol != null) olv.PrimarySortColumn = primaryCol; - var secondaryCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Liefertag"); - if (secondaryCol != null) olv.SecondarySortColumn = secondaryCol; - var druckenCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Etikett"); + + // --- Etikett-Button --- + var druckenCol = Find("Etikett"); if (druckenCol != null) { - druckenCol.IsButton = true; // Als Button rendern - druckenCol.ButtonSizing = OLVColumn.ButtonSizingMode.CellBounds; // Button füllt gesamte Zelle + druckenCol.IsButton = true; + druckenCol.ButtonSizing = OLVColumn.ButtonSizingMode.CellBounds; druckenCol.HeaderImageKey = "print"; druckenCol.ShowTextInHeader = false; druckenCol.MinimumWidth = druckenCol.MaximumWidth = 80; } - var fertigCol = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Abschließen"); + + // --- Abschließen-Button --- + var fertigCol = Find("Abschließen"); if (fertigCol != null) { - fertigCol.IsButton = true; // Als Button rendern - fertigCol.ButtonSizing = OLVColumn.ButtonSizingMode.CellBounds; // Button füllt gesamte Zelle + fertigCol.IsButton = true; + fertigCol.ButtonSizing = OLVColumn.ButtonSizingMode.CellBounds; fertigCol.HeaderImageKey = "abschließen"; fertigCol.ShowTextInHeader = false; fertigCol.MinimumWidth = fertigCol.MaximumWidth = 80; } + } + private void Olv_CellToolTipShowing(object sender, ToolTipShowingEventArgs e) + { + // Kein Model, kein Tooltip + if (e.Model == null || e.Column == null) + return; - // ========== SPALTEN JE NACH TAB UND ROLLE AUSBLENDEN ========== - GetUnvisibleColumns(olv); - //if (_settings.OLV_State != null) olv.RestoreState(_settings.OLV_State); - - // ========== IMAGE-LIST ZUWEISEN ========== - // SmallImageList für Icons in Detail-View (24x24 Pixel standard) - Program.imagelist.ImageSize = new Size(24, 24); - olv.SmallImageList = Program.imagelist; // Voraussetzung: imagelist mit Icon Index 0 gefüllt - - // ========== TOOLTIP FÜR ICON-SPALTEN ========== - // Automatischer Cell-Tooltip bei Mouse-Hover - olv.CellToolTipShowing += (s, e) => + // Aufgabe-Tooltip + if (e.Column.Text == "Aufgabe" && e.Model is View_Auftrag_Expedit expeditAufgabe) { - // Nur für Icon-Spalte (Index 10) und gültiges Model - if (e.Column.Text == "Aufgabe" && e.Model is View_Auftrag_Expedit expedit) - { - Auftrag auftrag = Auftrag.GetAuftrag(expedit.AuftragID); - // Lade Bezeichnung der Aufgabe als Tooltip-Text - e.Text = Aufgabe.GetAufgabe(null, auftrag.AufgabeID).Bezeichnung; - } - // Nur für Icon-Spalte (Index 1) und gültiges Model - if (e.Column.Text == "Kunde" && e.Model is View_Auftrag_Expedit expedit1) - { - Auftrag _auftrag = Auftrag.GetAuftrag(expedit1.AuftragID); - if (!string.IsNullOrWhiteSpace(Kunde.GetKunde(null, _auftrag.KundeID, null).Anmerkung)) - { - // Lade Anmerkung als Tooltip-Text - e.Text = Kunde.GetKunde(null, _auftrag.KundeID, null).Anmerkung; - } - } - if (e.Column.Text == "Fahrer" && e.Model is Auftrag auftrag1) - { - e.Text = auftrag1.ZusatzInfo; - } - }; + var auftrag = Auftrag.GetAuftrag(expeditAufgabe.AuftragID); + var aufgabe = Aufgabe.GetAufgabe(null, auftrag.AufgabeID); + e.Text = aufgabe?.Bezeichnung; + return; + } - // ========== DATEN LADEN ========== - // WICHTIG: SetObjects NACH Column-Konfiguration aufrufen! - OLV_SetObjects(olv, auftragliste); - - // ========== SORTIERUNG NACH SPALTEN ========== - if (olv.Name.Contains("Rampe")) olv.Sort(secondaryCol); - else olv.Sort(); - - // ========== SPALTENBREITE ANPASSEN ========== - olv = Funktionen.Columns_Resize(null, olv).olv; - - // ========== FILTER AKTIVIEREN UND ZUWEISEN ========== - olv.FilterMenuBuildStrategy = new MeinFilterMenu(); - - // ========== AUFRÄUMEN & AKTIVIEREN ========== - olv.ResumeLayout(); // Layout-Pause beenden, Positionen neu berechnen - olv.EndUpdate(); // Update-Pause beenden, Daten neu zeichnen - olv.Focus(); // OLV fokussieren (Tastaturbedienung aktivieren) - this.UseWaitCursor = false; + // Kunde-Tooltip + if (e.Column.Text == "Kunde" && e.Model is View_Auftrag_Expedit expeditKunde) + { + var auftrag = Auftrag.GetAuftrag(expeditKunde.AuftragID); + var kunde = Kunde.GetKunde(null, auftrag.KundeID, null); + if (!string.IsNullOrWhiteSpace(kunde?.Anmerkung)) + e.Text = kunde.Anmerkung; + return; + } + // Fahrer-Tooltip – Typfix: hier passt View_Auftrag_Expedit besser + if (e.Column.Text == "Fahrer" && e.Model is View_Auftrag_Expedit expeditFahrer) + { + e.Text = expeditFahrer.Zusatz; + } } private void ObjectListViewAuftrag_FormatCell(object sender, FormatCellEventArgs e) { @@ -538,131 +574,232 @@ namespace Deckungsbeitrag break; } } - private void ObjectListViewAuftrag_ButtonClick(object sender, BrightIdeasSoftware.CellClickEventArgs e) - { - ObjectListView olv = (ObjectListView)sender; - Auftrag _auftrag = Auftrag.GetAuftrag(((View_Auftrag_Expedit)e.Model).AuftragID); - if (e.Column.Text == "Abschließen") + private void ObjectListViewAuftrag_ButtonClick(object sender, CellClickEventArgs e) + { + var olv = (ObjectListView)sender; + var view = (View_Auftrag_Expedit)e.Model; + var auftrag = Auftrag.GetAuftrag(view.AuftragID); + + this.UseWaitCursor = true; + + try { - // Wenn BenutzerRolle Frottee dann Abteilung Frottee Beendet. - if (this.benutzer.Rolle == BenutzerRolle.Frottee) { Auftrag_Fertig(); Neuladen_OLV(olv); return; } - - if (olv.CheckedItems.Count > 0) + switch (e.Column.Text) { - if (MessageBox.Show($"Möchtest du die ausgewählten {olv.CheckedItems.Count} Aufträge abschließen?", "AUFTRÄGE FERTIG", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) return; - else - { - foreach (OLVListItem item in olv.CheckedItems) - { - this.auftrag = (Auftrag)item.RowObject; - Auftrag_Fertig(); - } - var column = olv.AllColumns.Cast().FirstOrDefault(col => col.Text == "Kunde"); - if (column != null && column.HeaderCheckBox) olv.UncheckHeaderCheckBox(column); - } - } - else - { - if (this.auftrag != _auftrag) altecontclean = null; + case "Abschließen": + HandleAbschliessenClick(olv, auftrag); + break; - this.auftrag = _auftrag; - - if (this.auftrag.ContainerClean == 0) - { - if (meldung.NoCleanContainer() == DialogResult.OK) return; - } - else - { - if (altecontclean != null && this.auftrag.ContainerClean != altecontclean) - { - switch (meldung.DifferentCleanContainer()) - { - case DialogResult.Cancel: - return; - case DialogResult.Yes: - { - this.auftrag.Gedruckt = DateTime.Now; - this.auftrag.GedrucktVon = benutzer.BenutzerID; - - bool nocont = false; - - if (this.auftrag.ContainerClean > 10) - { - if (MessageBox.Show("Möchtest du die Containeranzahl am Etikett anzeigen?", "FRAGE", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) - { - nocont = true; - } - else nocont = false; - } - - try - { - Funktionen.Etikett_Drucken(auftrag, nocont); - } - catch (Exception ex) - { - MessageBox.Show("Etiketten konnten nicht gedruckt werden. Versuche es nochmals.", "DRUCKFEHLER", MessageBoxButtons.OK, MessageBoxIcon.Error); - Program.AddFehler(this.benutzer, ex.Message, ex.StackTrace, null); - return; - } - } - break; - case DialogResult.No: - this.auftrag.Erstellt = DateTime.Now; - this.auftrag.ErstelltVon = (int)benutzer.BenutzerID; - break; - default: - break; - } - } - Auftrag_Fertig(); - } + case "Etikett": + HandleEtikettClick(auftrag); + break; } } - if (e.Column.Text == "Etikett") + finally { - this.auftrag = _auftrag; - - if (this.auftrag.AufgabeID != null) - { - if (meldung.GetAchtung(this, $"Bei dem ausgewählten Auftrag ist die Aufgabe {Aufgabe.GetAufgabe(null, auftrag.AufgabeID).Bezeichnung} zu erledigen. Hast du die Aufgabe erledigt? ", false) == DialogResult.No) return; - } - - if (this.auftrag.ContainerClean != 0) - { - letzterLiefertag = this.auftrag.Liefertag; - } - else - { - string eingabe = PromptForText( - "Der Auftrag hat keine sauberen Container oder Pakete. \n\n" + - "Bitte gib an wieviele Container oder Pakete der Auftrag hat:", - "Container/Pakete eingeben", - "0"); - - if (string.IsNullOrWhiteSpace(eingabe) || !int.TryParse(eingabe, out int anzahl)) - { - this.UseWaitCursor = false; - return; - } - this.auftrag.ContainerClean = anzahl; - } - //ETIKETT DRUCKEN - DialogResult result = Funktionen.Etikett_Drucken(auftrag, nocont); - if (result == DialogResult.OK) - { - this.auftrag.Gedruckt = DateTime.Now; - this.auftrag.GedrucktVon = (int)this.benutzer.BenutzerID; - this.auftrag.Status = AuftragStatus.Vorbereitet; - this.auftrag.Save(); - this.auftrag = null; - } + Neuladen_OLV(olv); + this.UseWaitCursor = false; + } + } + + /// + /// Behandelt den Fall, dass der Button in der Spalte Abschliessen geclickt wurde + /// + /// + /// + private void HandleAbschliessenClick(ObjectListView olv, Auftrag auftrag) + { + // Sonderfall Frottee: nur Abteilung beenden und raus + if (this.benutzer.Rolle == BenutzerRolle.Frottee) + { + this.auftrag = auftrag; + Auftrag_Fertig(); + return; } - Neuladen_OLV(olv); - this.UseWaitCursor = false; + if (olv.CheckedItems.Count > 0) + { + HandleBatchAbschliessen(olv); + return; + } + + HandleSingleAbschliessen(auftrag); } + /// + /// Wenn angehackte Datensätze im Bulk abeschlossen werden sollen. + /// Hier sind mehrere oder nur ein Auftrag abschließen möglich. + /// + /// + private void HandleBatchAbschliessen(ObjectListView olv) + { + var count = olv.CheckedItems.Count; + var result = MessageBox.Show( + $"Möchtest du die ausgewählten {count} Aufträge abschließen?", + "AUFTRÄGE FERTIG", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question); + + if (result == DialogResult.No) + return; + + foreach (OLVListItem item in olv.CheckedItems) + { + this.auftrag = (Auftrag)item.RowObject; + Auftrag_Fertig(); + } + + var kundeColumn = olv.AllColumns + .Cast() + .FirstOrDefault(col => col.Text == "Kunde"); + + if (kundeColumn != null && kundeColumn.HeaderCheckBox) + olv.UncheckHeaderCheckBox(kundeColumn); + } + + /// + /// Wenn der Button geclickt wurde ohne anhacken. Es wird garantiert nur 1 Auftrag abgeschlossen + /// + /// + private void HandleSingleAbschliessen(Auftrag auftrag) + { + if (this.auftrag != auftrag) + altecontclean = null; + + this.auftrag = auftrag; + + if (this.auftrag.ContainerClean == 0) + { + if (meldung.NoCleanContainer() == DialogResult.OK) + return; + } + else + { + if (!HandleContainerCleanChange()) + return; + } + + Auftrag_Fertig(); + } + + /// + /// Behandelt den Fall, dass sich ContainerClean geändert hat. + /// Gibt false zurück, wenn der Vorgang abgebrochen werden soll. + /// + private bool HandleContainerCleanChange() + { + if (altecontclean == null || this.auftrag.ContainerClean == altecontclean) + return true; + + switch (meldung.DifferentCleanContainer()) + { + case DialogResult.Cancel: + return false; + + case DialogResult.Yes: + return TryDruckMitNeuemContainerClean(); + + case DialogResult.No: + this.auftrag.Erstellt = DateTime.Now; + this.auftrag.ErstelltVon = (int)benutzer.BenutzerID; + return true; + + default: + return true; + } + } + + /// + /// Wenn eine neue Anzahl an sauberen Containern eingegeben wurde wird ein erneuter Druck abgefragt. + /// + private bool TryDruckMitNeuemContainerClean() + { + this.auftrag.Gedruckt = DateTime.Now; + this.auftrag.GedrucktVon = benutzer.BenutzerID; + + var nocont = false; + + if (this.auftrag.ContainerClean > 10) + { + var res = MessageBox.Show( + "Möchtest du die Containeranzahl am Etikett anzeigen?", + "FRAGE", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question); + + nocont = (res == DialogResult.No); + } + + try + { + Funktionen.Etikett_Drucken(auftrag, nocont); + return true; + } + catch (Exception ex) + { + MessageBox.Show( + "Etiketten konnten nicht gedruckt werden. Versuche es nochmals.", + "DRUCKFEHLER", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + + Program.AddFehler(this.benutzer, ex.Message, ex.StackTrace, null); + return false; + } + } + + /// + /// Behandelt den Fall, dass der Button in der Spalte Etikett geclickt wurde. + /// + /// + private void HandleEtikettClick(Auftrag auftrag) + { + this.auftrag = auftrag; + + if (this.auftrag.AufgabeID != null) + { + var aufgabe = Aufgabe.GetAufgabe(null, auftrag.AufgabeID); + var text = $"Bei dem ausgewählten Auftrag ist die Aufgabe {aufgabe.Bezeichnung} zu erledigen. Hast du die Aufgabe erledigt? "; + + if (meldung.GetAchtung(this, text, false) == DialogResult.No) + return; + } + + PrepareContainerCleanForEtikett(); + + var result = Funktionen.Etikett_Drucken(auftrag, nocont); + if (result == DialogResult.OK) + { + this.auftrag.Gedruckt = DateTime.Now; + this.auftrag.GedrucktVon = (int)this.benutzer.BenutzerID; + this.auftrag.Status = AuftragStatus.Vorbereitet; + this.auftrag.Save(); + this.auftrag = null; + } + } + + private void PrepareContainerCleanForEtikett() + { + if (this.auftrag.ContainerClean != 0) + { + letzterLiefertag = this.auftrag.Liefertag; + return; + } + + string eingabe = PromptForText( + "Der Auftrag hat keine sauberen Container oder Pakete. \n\n" + + "Bitte gib an wieviele Container oder Pakete der Auftrag hat:", + "Container/Pakete eingeben", + "0"); + + if (string.IsNullOrWhiteSpace(eingabe) || !int.TryParse(eingabe, out int anzahl)) + { + this.UseWaitCursor = false; + return; + } + + this.auftrag.ContainerClean = anzahl; + } /// /// Die Objecte der ObjectListView werden neu geladen. /// diff --git a/AA-Forms/FormKundeVW.cs b/AA-Forms/FormKundeVW.cs index 7978250..dbeb694 100644 --- a/AA-Forms/FormKundeVW.cs +++ b/AA-Forms/FormKundeVW.cs @@ -273,11 +273,6 @@ namespace Deckungsbeitrag } private void ButtonProgramm_Click(object sender, EventArgs e) { - FormProgrammauswahl auswahl = new FormProgrammauswahl(); - if (auswahl.ShowDialog() == DialogResult.OK) - { - DatenLesen(); - } } private void ButtonAufgEnt_Click(object sender, EventArgs e) { diff --git a/Verwaltung_ReadMe.txt b/Verwaltung_ReadMe.txt index 3e2ad5f..a15fe59 100644 --- a/Verwaltung_ReadMe.txt +++ b/Verwaltung_ReadMe.txt @@ -95,5 +95,5 @@ Build-Info: - 🔄 Wenn Frottee-Expedit auch Relamation bearbeitet, muss BenutzerRolle abgefragt werden. siehe CHANGES. [FormFehlmengeCount.cs] - 🔄 Zuweisung zu Fahrer muss geklärt werden. [Funktionen.cs] -Installation: 15.04.2026 10:13 +Installation: 15.04.2026 11:03 =====================================