using BrightIdeasSoftware; using DatenDB; using Npgsql; using System; using System.CodeDom; using System.Collections.Generic; using System.ComponentModel; using System.Configuration; using System.Data; using System.Drawing; using System.Drawing.Printing; using System.Linq; using System.Reflection; using System.Runtime.ConstrainedExecution; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace Deckungsbeitrag { public partial class FormAufleger : Form { private Dictionary> auftragliste; private System.Windows.Forms.Timer timer; private Auftrag auftrag; private Meldungen meldung = new Meldungen(); private bool iswechsel = false; public FormAufleger() { InitializeComponent(); // Timer für Wartezeit bis TextChanged eintritt. timer = new System.Windows.Forms.Timer(); timer.Interval = 700; // 0,7 Sekunden timer.Tick += Timer_Tick; } private async void FormAufleger_Load(object sender, EventArgs e) { this.Cursor = Cursors.WaitCursor; this.SuspendLayout(); this.labelVersion.Text += Assembly.GetExecutingAssembly().GetName().Version; try { await GetAuftraege(); this.Invoke(new Action(() => { LoadPanel(); SortFlowLayoutPanels(); })); } finally { this.ResumeLayout(true); this.Cursor = Cursors.Default; this.textBoxScan.Focus(); } } private void LoadPanel() { this.Cursor = Cursors.WaitCursor; this.SuspendLayout(); for (int i = 0; i < this.tLPAuftrag.RowCount; i++) { if(i == 0) { int index = 0; foreach (var key in auftragliste.Keys.OrderBy(k => k)) { Control ctr = this.tLPAuftrag.GetControlFromPosition(index, i); ctr.Text = Funktionen.GetWochentagDeutsch(key.DayOfWeek); ctr.Text += " (" + key.ToShortDateString() + ")"; // "13.02.2026" index++; } } if(i == 1) { // 1. Dictionary: Column-Index → FlowLayoutPanel var flpDictionary = new Dictionary(); for (int column = 0; column < this.tLPAuftrag.ColumnCount; column++) { Control ctr = this.tLPAuftrag.GetControlFromPosition(column, i); if (ctr is FlowLayoutPanel flp) flpDictionary[column] = flp; } // 2. Dictionary: Column → Array aller UCAuftrag für diesen Tag var ucArrays = new Dictionary(); int col = 0; foreach (List liste in auftragliste.Values) { UCAuftrag[] alleUCA = new UCAuftrag[liste.Count]; int anzUCA = 0; foreach (Auftrag auftrag in liste) { UCAuftrag uca = new UCAuftrag(auftrag); uca.Tag = auftrag; if (auftrag.Status == AuftragStatus.Aufgelegt) { this.auftrag = auftrag; uca.BackColor = Color.YellowGreen; } else uca.BackColor = Color.Silver; uca.Size = new Size(flpDictionary[col].Width - 30, uca.Height); alleUCA[anzUCA] = uca; anzUCA++; } ucArrays[col] = alleUCA; col++; } // 3. ATOMAR: Alle FLPs leeren + Arrays auf einmal hinzufügen foreach (var kvp in flpDictionary) { if (ucArrays.TryGetValue(kvp.Key, out UCAuftrag[] ucArray)) { kvp.Value.Controls.Clear(); kvp.Value.Controls.AddRange(ucArray); // EIN Paint-Event pro FLP! } } } if(i == 2) { foreach (FlowLayoutPanel flowpanel in this.tLPAuftrag.Controls.OfType()) { int column = this.tLPAuftrag.GetColumn(flowpanel); int container = 0; foreach (UCAuftrag uca in flowpanel.Controls) container += int.Parse(uca.ContainerAnzahl); Control ctr = this.tLPAuftrag.GetControlFromPosition(column, i); ctr.Text = container.ToString(); } } } this.ResumeLayout(true); this.Cursor = Cursors.Default; } private async Task GetAuftraege() { var conn = new NpgsqlConnection(ConfigurationManager.AppSettings["ConnectionString"]); // Pro Task! try { await conn.OpenAsync(); auftragliste = await Auftrag.GetAuftraegeProLiefertagAsync(conn, AuftragTyp.Standart, AuftragStatus.Aufgelegt); } finally { if (conn.State == ConnectionState.Open) conn.Close(); conn.Dispose(); } } private void FormAufleger_Shown(object sender, EventArgs e) { this.ResumeLayout(true); this.Cursor = Cursors.Default; this.textBoxScan.Focus(); } protected override bool ProcessDialogKey(Keys keyData) { //TODO: Umbau in Switch. // Escape [ESC] schließt den Screen. if (Form.ModifierKeys == Keys.None && keyData == Keys.Escape) { this.Close(); return true; } return base.ProcessDialogKey(keyData); } private void textBoxScan_TextChanged(object sender, EventArgs e) { // TextChanged tritt nur ein wenn x Sekunden keine Eingabe erfolgt. Logik befindet sich in Timer_Tick timer.Stop(); // Alten Timer beenden timer.Start(); // Neuen Timer starten } private void Timer_Tick(object sender, EventArgs e) { this.Cursor = Cursors.WaitCursor; timer.Stop(); // Timer stoppen Kunde kunde; string zusatz = string.Empty; if (string.IsNullOrEmpty(textBoxScan.Text)) { return; } if (int.TryParse(textBoxScan.Text, out _)) kunde = Kunde.GetKunde(textBoxScan.Text, null, null); else { if (textBoxScan.Text.Contains(",")) { kunde = Kunde.GetKunde(textBoxScan.Text.Substring(0, textBoxScan.Text.IndexOf(',')), null, null); zusatz = textBoxScan.Text.Substring(textBoxScan.Text.IndexOf(',') + 1); } else kunde = Kunde.GetKunde(null, null, textBoxScan.Text); } List auftList = Auftrag.FindeAuftragVonKunde(kunde, zusatz); if (auftList.Count == 0) { meldung.GetFehler(this, "Es konnte kein Auftrag zum eingescannten Kunden gefunden werden.\nBitte Informiere deinen Vorgesetzten."); return; } // Alten Auftrag Speichern (Status Gewaschen) wenn neuer Auftrag gefunden wurde. if(auftrag != null) { if (AuftragSpeichern() == false) return; iswechsel = true; } if (auftList.Count == 1) auftrag = auftList[0]; if (auftList.Count > 1) { if (meldung.GetFrage(this, $"Es konnten mehrere Aufträge für den gescannten Kunden gefunden werden.\nIst auf der Containerkarte Auftrag 2 vermerkt?", false) == DialogResult.Yes) { auftrag = auftList.Find(a => a.ZusatzInfo.Contains("Auftrag 2")); } else { auftrag = auftList.Find(a => !a.ZusatzInfo.Contains("Auftrag 2")); } } SucheAuftrag(); this.Cursor = Cursors.Default; } private void SortFlowLayoutPanels() { foreach (FlowLayoutPanel flp in this.tLPAuftrag.Controls.OfType()) { if (flp.Controls.Count > 0) { var controls = flp.Controls.Cast() .OrderBy(c => ((Auftrag)c.Tag).Fahrer) // oder c.Tag .ToArray(); flp.SuspendLayout(); for (int i = 0; i < controls.Length; i++) { flp.Controls.SetChildIndex(controls[i], i); } flp.ResumeLayout(); } } } private void SucheAuftrag() { this.textBoxScan.TextChanged -= textBoxScan_TextChanged; foreach (FlowLayoutPanel flp in this.tLPAuftrag.Controls.OfType()) { foreach (UCAuftrag uca in flp.Controls) { if (((Auftrag)uca.Tag).AuftragID == this.auftrag.AuftragID) { // Wenn neuer Auftrag gefunden dann Status Aufgelegt und UserControl Grüner Hintergrund. this.auftrag.Status = AuftragStatus.Aufgelegt; this.auftrag.Save(); uca.Tag = this.auftrag; if (this.auftrag.Status == AuftragStatus.Aufgelegt) uca.BackColor = Color.YellowGreen; } } } if (iswechsel) { FormAufleger_Load(this, null); iswechsel = false; } this.textBoxScan.Clear(); this.textBoxScan.Focus(); this.textBoxScan.TextChanged += textBoxScan_TextChanged; } private bool AuftragSpeichern() { auftrag.Status = AuftragStatus.Gewaschen; if (auftrag.Save()[0] == 1) auftrag = null; else { meldung.Speicherfehler(); return false; } return true; } private void FormAufleger_FormClosing(object sender, FormClosingEventArgs e) { //if (auftrag == null) return; //if (AuftragSpeichern() == false) e.Cancel = true; } private void buttonCloseForm_Click(object sender, EventArgs e) { if (meldung.GetFrage(this, "Möchtest du das Programm wirklich schließen?", false) == DialogResult.No) return; Application.Exit(); } } } //CHANGES: Form für Aufleger soweit fertig. //CHANGES: Kontrolle ob mehrere Aufträge vorhanden fertig. //CHANGES: Status anpassen fertig. //CHANGES: Programm wird mit Button geschlossen. (Sicherheitsabfrage ob wirklich gewollt wird gemacht.) //CHANGES: Hintergrundfarbe wird jetzt immer richtig zugewiesen.