Programm_Wirl/AA-Forms/FormAufleger.cs

392 lines
12 KiB
C#

using BrightIdeasSoftware;
using DatenDB;
using Deckungsbeitrag.AA_Forms;
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;
using static System.Net.Mime.MediaTypeNames;
namespace Deckungsbeitrag
{
public partial class FormAufleger : Form
{
private Dictionary<DateTime, List<Auftrag>> auftragliste;
private readonly System.Windows.Forms.Timer timer;
private Auftrag auftrag;
private readonly Meldungen meldung = new Meldungen();
private bool iswechsel = false;
private readonly string userid;
public FormAufleger()
{
InitializeComponent();
// Timer für Wartezeit bis TextChanged eintritt.
timer = new System.Windows.Forms.Timer
{
Interval = 700 // 0,7 Sekunden
};
timer.Tick += Timer_Tick;
}
public FormAufleger(string userid) : this()
{
this.userid = userid;
}
private async void FormAufleger_Load(object sender, EventArgs e)
{
this.Cursor = Cursors.WaitCursor;
this.SuspendLayout();
this.labelVersion.Text += Assembly.GetExecutingAssembly().GetName().Version.ToString();
try
{
await GetAuftraege();
this.Invoke(new Action(() =>
{
LoadPanel();
}));
}
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);
if (index == 4) ctr.Text = "Rest";
else
{
ctr.Text = Funktionen.GetWochentagDeutsch(key.DayOfWeek);
ctr.Text += " (" + key.ToShortDateString() + ")";
}
ctr.Font = Funktionen.GetFontSizeByWidth(ctr.Font, ctr.Text, ctr.Width);
index++;
}
}
if(i == 1)
{
float flpsize = 0;
// 1. Dictionary: Column-Index → FlowLayoutPanel
var flpDictionary = new Dictionary<int, FlowLayoutPanel>();
for (int column = 0; column < this.tLPAuftrag.ColumnCount; column++)
{
Control ctr = this.tLPAuftrag.GetControlFromPosition(column, i);
if (ctr is FlowLayoutPanel flp)
flpDictionary[column] = flp;
flpsize = ctr.Width;
}
// 2. Dictionary: Column → Array aller UCAuftrag für diesen Tag
var ucArrays = new Dictionary<int, UCAuftrag[]>();
int col = 0;
foreach (List<Auftrag> liste in auftragliste.Values)
{
UCAuftrag[] alleUCA = new UCAuftrag[liste.Count];
int anzUCA = 0;
foreach (Auftrag auftrag in liste)
{
UCAuftrag uca = new UCAuftrag(auftrag)
{
Tag = auftrag
};
if (auftrag.Status == AuftragStatus.Aufgelegt)
{
this.auftrag = auftrag;
uca.BackColor = Color.YellowGreen;
}
uca.Size = new Size(flpDictionary[col].Width - 30, uca.Height);
alleUCA[anzUCA] = uca;
anzUCA++;
}
ucArrays[col] = alleUCA;
col++;
}
var ucA = new Dictionary<int, UCAuftrag[]>();
foreach (KeyValuePair<int, UCAuftrag[]> auftraglist in ucArrays)
{
int key = auftraglist.Key;
// Innerhalb jedes Arrays nach Fahrer sortieren
UCAuftrag[] sortiert = auftraglist.Value
.OrderBy(a => a.Fahrer) // oder a.FahrerName
.ToArray();
ucA[key] = sortiert;
}
ucArrays = ucA;
// 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<FlowLayoutPanel>())
{
int column = this.tLPAuftrag.GetColumn(flowpanel);
int container = 0;
foreach (UCAuftrag uca in flowpanel.Controls)
{
container += int.Parse(uca.ContainerAnzahl);
Label lblKunde = uca.Controls["labelKunde"] as Label;
lblKunde.Font = Funktionen.GetFontSizeByWidth(lblKunde.Font, lblKunde.Text, uca.Width);
uca.Refresh();
}
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, 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();
}
/// <summary>
/// Erfassen von Tasten für Tastaturlose Steuerung.
/// </summary>
/// <param name="keyData"></param>
/// <returns></returns>
protected override bool ProcessDialogKey(Keys keyData)
{
// 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
if (string.IsNullOrEmpty(textBoxScan.Text)) { this.Cursor = Cursors.Default; return; }
TextBoxScan_Leave(this.textBoxScan, null);
}
private void SucheAuftrag()
{
this.textBoxScan.TextChanged -= TextBoxScan_TextChanged;
foreach (FlowLayoutPanel flp in this.tLPAuftrag.Controls.OfType<FlowLayoutPanel>())
{
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;
auftrag.MaschineID = null;
if (auftrag.Save()[0] == 1) auftrag = null;
else { meldung.Speicherfehler(); return false; }
return true;
}
private void FormAufleger_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.auftrag != null)
{
if (this.auftrag.Status == AuftragStatus.Aufgelegt)
{
AuftragSpeichern();
}
}
}
private void ButtonCloseForm_Click(object sender, EventArgs e)
{
if (meldung.GetFrage(this, "Möchtest du das Programm wirklich schließen?", false) == DialogResult.No) return;
this.Close();
}
/// <summary>
/// Waschzeitberechnung bei DoppelClick auf Container Label.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LabelCont_DoubleClick(object sender, EventArgs e)
{
Label lbl = sender as Label;
double[] zeit = { 0, 0 };
for (int i = 1; i < 3; i++)
{
if (double.TryParse(lbl.Text, out double cont)) zeit[i-1] = (cont * 2.7 * 3.5) / 60 / i;
}
meldung.GetInfo(this, $"Die Waschzeiten für den gewünschten Tag lauten:\n\n[Eine Waschstraße] => {zeit[0]:F1} Stunden\n[Zwei Waschstraßen] => {zeit[1]:F1} Stunden", false);
}
private void TextBoxScan_KeyDown(object sender, KeyEventArgs e)
{
TextBox txtScan = (TextBox)sender;
if (e.KeyCode == Keys.Enter)
{
e.SuppressKeyPress = true;
string code = txtScan.Text.Trim();
//txtScan.Clear();
if (!string.IsNullOrEmpty(code))
TextBoxScan_Leave(txtScan, null);
}
}
private void TextBoxScan_Leave(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
Kunde _kunde;
string zusatz = string.Empty;
string text = string.Empty;
if (string.IsNullOrWhiteSpace(textBox.Text)) { this.Cursor = Cursors.Default; return; }
if (textBox.Text.ToLower().StartsWith("scanhttps"))
{
int index = 1;
index += textBox.Text.IndexOf("=", index);
int i = textBox.Text.IndexOf("%", index);
text = textBox.Text.Substring(index, i - index);
textBox.Text = text;
}
else text = textBox.Text;
if (int.TryParse(text, out int j)) _kunde = Kunde.GetKunde(text, null, null);
else _kunde = Kunde.GetKunde(null, null, text.ToLower());
// Wenn kein Auftrag gefunden muss der Zettel zum Expedit gebracht werden. ÜBERGANGSZEIT FALLS AUFTRAG NICHT VON FAHRER ERFASST.
if (_kunde == null) { CustomMessageBox.Show("Titel.Achtung", "Text.Achtung.AuftragNotFound", null, new string[] { "Ok" }); ; return; }
List<Auftrag> auftList = Auftrag.FindeAuftragVonKunde(_kunde, zusatz, null, (DateTime?)null);
if (auftList.Count == 0) { CustomMessageBox.Show("Titel.Achtung", "Text.Achtung.AuftragNotFound", "Todo.VorgesetzenInformieren", new string[] { "Ok" }); return; }
// Alten Auftrag Speichern (Status Gewaschen) wenn neuer Auftrag gefunden wurde.
if (auftrag != null)
{
if (!AuftragSpeichern()) 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"));
}
}
FormMSAuswahl auswahl = new FormMSAuswahl();
if (auswahl.ShowDialog() == DialogResult.OK)
{
auftrag.MaschineID = auswahl.id;
}
SucheAuftrag();
this.Cursor = Cursors.Default;
}
}
}