Programm_Wirl/UserControls/UCTabPageLKW.cs
2026-04-21 09:02:20 +02:00

400 lines
14 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DatenDB;
using Deckungsbeitrag.AA_Forms;
using Deckungsbeitrag.AA_Klassen;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.WebRequestMethods;
namespace Deckungsbeitrag.UserControls
{
public partial class UCTabPageLKW : UserControl
{
public UCTabPageLKW()
{
InitializeComponent();
}
private void FlowLayout_DragEnter(object sender, DragEventArgs e)
{
// Unterscheiden zwischen Clone und Move KundenControl
// Wenn KundenControl innerhalb eines Tages bewegt wird ist Move
// sonst ist Clone.
if (e.Data.GetDataPresent("KundeData")) // Custom Format
e.Effect = DragDropEffects.Copy;
if (e.Data.GetDataPresent(typeof(UCKunde)))
e.Effect = DragDropEffects.Move;
}
private void FlowLayout_DragOver(object sender, DragEventArgs e)
{
// Unterscheiden zwischen Clone und Move KundenControl
// Wenn KundenControl innerhalb eines Tages bewegt wird ist Move
// sonst ist Clone.
if (e.Data.GetDataPresent("KundeData")) // Custom Format
e.Effect = DragDropEffects.Copy;
if (e.Data.GetDataPresent(typeof(UCKunde)))
e.Effect = DragDropEffects.Move;
}
private void FlowLayout_DragDrop(object sender, DragEventArgs e)
{
bool toClone = true;
string saison = string.Empty;
int saisonrhythmus;
FlowLayoutPanel dropTarget = sender as FlowLayoutPanel;
DayOfWeek dropDay = DayOfWeek.Sunday;
switch (dropTarget.Tag.ToString())
{
case "MO":
dropDay = DayOfWeek.Monday; break;
case "DI":
dropDay = DayOfWeek.Tuesday; break;
case "MI":
dropDay = DayOfWeek.Wednesday; break;
case "DO":
dropDay = DayOfWeek.Thursday; break;
case "FR":
dropDay = DayOfWeek.Friday; break;
default:
break;
}
FormTourenplanung tourenplanung = (FormTourenplanung)this.ParentForm;
foreach (RadioButton rb in tourenplanung.Controls.OfType<RadioButton>()) if (rb.Checked) saison = rb.Text;
if (e.Data.GetDataPresent("KundeData"))
{
UCKunde kundectr = e.Data.GetData("KundeData") as UCKunde;
Kunde kunde = (Kunde)kundectr.Tag;
if (saison == "Sommer") saisonrhythmus = kunde.SommerLieferRhythmus;
else saisonrhythmus = kunde.WinterLieferRhythmus;
if (kundectr != null)
{
Liefertage neuerRhythmus = GetKompatiblenRhythmus(dropDay, (Liefertage)saisonrhythmus);
if (neuerRhythmus != (Liefertage)saisonrhythmus)
{
Meldungen meldung = new Meldungen();
if (meldung.GetFrage(null, $"Rhythmus von {Lieferrhythmen.GetAnzeigeText((Liefertage)saisonrhythmus)} auf {Lieferrhythmen.GetAnzeigeText((Liefertage)neuerRhythmus)} ändern?", false) == DialogResult.No) return;
else
{
if (saison == "Sommer") kunde.SommerLieferRhythmus = (int)neuerRhythmus;
else kunde.WinterLieferRhythmus = (int)neuerRhythmus;
kunde.Save();
kundectr.Tag = kunde;
FormTourenplanung.KundenControlToDelete(tourenplanung, kundectr);
}
}
// Überprüfung ob KundenControl geclont werden kann
if (neuerRhythmus == Lieferrhythmen.Unbekannt || !FormTourenplanung.KundenControlToClone(tourenplanung, kundectr)) toClone = false;
if (toClone)
{
// Kunde klonen (nicht original bewegen)
UCKunde kundeKopie = (UCKunde)kundectr.Clone();
kundeKopie.Tag = kundectr.Tag;
kundeKopie.Parent = dropTarget;
kundeKopie.Width = dropTarget.Width - 30;
dropTarget.Controls.Add(kundeKopie);
}
}
GetGesamtContainer(dropTarget);
}
// Move statt Clone KundenControl
if (e.Data.GetDataPresent(typeof(UCKunde)))
{
if (!(e.Data.GetData(typeof(UCKunde)) is UCKunde draggedControl) || dropTarget == null || draggedControl.Parent.Tag != dropTarget.Tag) return;
dropTarget.SuspendLayout();
try
{
// Drop-Position berechnen
Point dropPoint = dropTarget.PointToClient(new Point(e.X, e.Y));
int dropIndex = GetDropIndex(dropTarget, dropPoint);
// Reihenfolge ändern
dropTarget.Controls.SetChildIndex(draggedControl, dropIndex);
// Gesamt-Labels aktualisieren
GetGesamtContainer(dropTarget);
}
finally
{
dropTarget.ResumeLayout(true);
}
}
}
private int GetDropIndex(FlowLayoutPanel flp, Point dropPoint)
{
for (int i = 0; i < flp.Controls.Count; i++)
{
if (flp.Controls[i].Bounds.Contains(dropPoint))
return i;
}
return flp.Controls.Count; // Am Ende anhängen
}
private void GetGesamtContainer(FlowLayoutPanel dropTarget)
{
int[] gesamt = { 0, 0, 0 };
foreach (UCKunde kndctrl in dropTarget.Controls.OfType<UCKunde>())
{
for (int i = 0; i < Math.Min(kndctrl.ContAnzahl.Length, gesamt.Length); i++)
{
gesamt[i] += kndctrl.ContAnzahl[i];
}
}
foreach (Label ctr in tableLayoutPanelTage.Controls.OfType<Label>())
{
if (tableLayoutPanelTage.GetRow(ctr) == 2) // Zeile 3 (Index 2)
{
if (ctr.Tag.ToString() == dropTarget.Tag.ToString())
{
// ctr.Text aktualisieren
ctr.Text = $"{gesamt[0]}/{gesamt[1]}/{gesamt[2]}";
}
}
}
}
/// <summary>
/// Wenn KundeControl gedropped wird, wird der Lieferrhythmus kontrolliert.
/// Stimmt Drop-Tag mit Liefertagen überein wenn NICHT kann Lieferrhythmus angepasst werden.
/// </summary>
/// <param name="dropDay"></param>
/// <param name="originalRhythmus"></param>
/// <returns>Liefertage von Lieferrhythmen</returns>
private static Liefertage GetKompatiblenRhythmus(DayOfWeek dropDay, Liefertage originalRhythmus)
{
Meldungen meldung = new Meldungen();
string dropTag = CultureInfo.GetCultureInfo("de-DE").DateTimeFormat.GetDayName(dropDay);
// 1. Ist dropDay im Original enthalten? Wird originalRhythums zurück gegeben.
if (IstTagEnthalten(originalRhythmus, dropDay))
return originalRhythmus;
// 2. Anzahl Liefertag pro Woche von hinterlegtem Rhythmus finden
int originalAnzahl = Lieferrhythmen.GetMaxClonesNet48(originalRhythmus);
// 3. Fragen ob der Lieferrhythmus geändert werden soll.
// Wenn NEIN wird Lieferage.None zurückgegeben.
// Sonst wird Anzahl der gewünschten Lieferungen pro Woche abgefragt,
if (meldung.GetFrage(null, $"Der gewählte Liefertag {dropTag} passt nicht zum Lieferrhythmus: {originalRhythmus.GetAnzeigeText()}\n\nSoll der **Lieferrhythmus geändert** werden?", false) == DialogResult.Yes)
{
string input = Interaction.InputBox("Wie oft soll der Kunde pro Woche angefahren werden?\n\nAnzahl Lieferungen:", "Lieferungen pro Woche", originalAnzahl.ToString());
// Kontrolle ob Input ist eine Zahl.
// Bei Abbruch wird KEIN Lieferrhythmus zurück gegeben.
if (!string.IsNullOrWhiteSpace(input))
{
while (!int.TryParse(input, out int zahl) || zahl < 1)
{
MessageBox.Show("Bitte nur positive Ganzzahlen eingeben!", "Ungültig");
input = Interaction.InputBox("Wie oft soll der Kunde pro Woche angefahren werden?\n\nAnzahl Lieferungen:", "Lieferungen pro Woche", originalAnzahl.ToString());
if (string.IsNullOrWhiteSpace(input)) return Lieferrhythmen.Unbekannt;
}
}
else return Lieferrhythmen.Unbekannt;
// Wenn Input korrekt abgeschlossen, wird original Anzahl geändert.
originalAnzahl = int.Parse(input);
// Lieferrhythmus mit übereinstimmenden Liefertag und Liefertaganzahl wird gewählt und zurück gegeben.
switch (originalAnzahl)
{
case 1:
switch (dropDay)
{
case DayOfWeek.Monday: return Lieferrhythmen.WoechentlichMo;
case DayOfWeek.Tuesday: return Lieferrhythmen.WoechentlichDi;
case DayOfWeek.Wednesday: return Lieferrhythmen.WoechentlichMi;
case DayOfWeek.Thursday: return Lieferrhythmen.WoechentlichDo;
case DayOfWeek.Friday: return Lieferrhythmen.WoechentlichFr;
default: return Lieferrhythmen.WoechentlichMi;
}
case 2:
switch (dropDay)
{
case DayOfWeek.Monday: return Lieferrhythmen.ZweimalMoDo;
case DayOfWeek.Thursday: return Lieferrhythmen.ZweimalMoDo;
case DayOfWeek.Tuesday: return Lieferrhythmen.ZweimalDiFr;
case DayOfWeek.Friday: return Lieferrhythmen.ZweimalDiFr;
default:
return Lieferrhythmen.ZweimalMoDo;
}
case 3:
return Lieferrhythmen.DreimalMoMiFr;
case 4:
return Lieferrhythmen.ViermalMoDiDoFr;
case 5:
return Lieferrhythmen.TaeglichMoFr;
default:
return Lieferrhythmen.WoechentlichMo;
}
}
else return Lieferrhythmen.Unbekannt;
}
/// <summary>
/// Überprüfung ob Liefertag in hinterlegtem Lieferrhythmus enthalten ist.
/// </summary>
/// <param name="rhythmus"></param>
/// <param name="tag"></param>
/// <returns>Wenn enthalten return true</returns>
public static bool IstTagEnthalten(Liefertage rhythmus, DayOfWeek tag)
{
Liefertage tagFlag;
switch (tag)
{
case DayOfWeek.Monday:
tagFlag = Liefertage.Monday;
break;
case DayOfWeek.Tuesday:
tagFlag = Liefertage.Tuesday;
break;
case DayOfWeek.Wednesday:
tagFlag = Liefertage.Wednesday;
break;
case DayOfWeek.Thursday:
tagFlag = Liefertage.Thursday;
break;
case DayOfWeek.Friday:
tagFlag = Liefertage.Friday;
break;
default:
tagFlag = Liefertage.None;
break;
}
return (rhythmus & tagFlag) == tagFlag;
}
// ★ SPEICHERN nutzt TAG der FlowLayoutPanels ★
public TDaten SpeichereDaten()
{
var data = new TDaten
{
TourName = this.Parent?.Text ?? "Unbekannt",
FahrerId = ((Benutzer)this.Parent?.Tag).BenutzerID ?? 0
};
// Alle FlowLayoutPanels durchgehen
foreach (Control ctrl in tableLayoutPanelTage.Controls)
{
if (ctrl is FlowLayoutPanel flp && flp.Tag is string tag) // ← TAG = Wochentag
{
// Falls für diesen Tag noch keine Liste existiert, anlegen
if (!data.KundenProTag.TryGetValue(tag, out var kundenListe))
{
kundenListe = new List<KData>();
data.KundenProTag[tag] = kundenListe;
}
// Kunden sammeln
foreach (Control kundeCtrl in flp.Controls)
{
if (kundeCtrl is UCKunde kc)
{
kundenListe.Add(new KData
{
Name = kc.KundenName,
Region = kc.KundenRegion,
Tag = tag, // optional, kannst du auch weglassen, da im Dictionary-Key enthalten
KundeID = (int)((Kunde)kundeCtrl.Tag).KundeID,
ContAnzahl = kc.ContAnzahl
});
}
}
// Counter finden (labelContMO -> MO, etc.)
if (data.Counter.TryGetValue(tag, out int[] counts))
{
string baseName = $"labelCont{tag}";
for (int i = 0; i < 3; i++)
{
string lblName = $"{baseName}{i}"; // labelContMO0, labelContMO1, labelContMO2
if (tableLayoutPanelTage.Controls
.Find(lblName, true)
.FirstOrDefault() is Label lbl && int.TryParse(lbl.Text, out int value))
{
counts[i] = value;
}
}
}
}
}
return data;
}
// ★ LADEN TAG der FlowLayoutPanels nutzen ★
public void LadeDaten(TDaten data)
{
// Zuerst alle FlowLayoutPanels leeren
foreach (Control ctrl in tableLayoutPanelTage.Controls)
{
if (ctrl is FlowLayoutPanel flp)
flp.Controls.Clear();
}
// Kunden nach TAG verteilen (angepasst für Dictionary)
foreach (var kvp in data.KundenProTag) // Dictionary: Key = tag, Value = Kundenliste
{
string tag = kvp.Key;
var kundenListe = kvp.Value; // List<KundeData> für diesen Tag
FlowLayoutPanel zielFlp = tableLayoutPanelTage.Controls
.OfType<FlowLayoutPanel>()
.FirstOrDefault(flp => flp.Tag?.ToString() == tag);
if (zielFlp != null)
{
foreach (var kundeData in kundenListe) // nur die Kunden dieses Tags
{
Kunde kunde = Kunde.GetKunde(null, kundeData.KundeID, null);
UCKunde kundectrl = new UCKunde(kunde)
{
Tag = kunde
};
zielFlp.Controls.Add(kundectrl);
}
}
// Counter setzen
if (data.Counter.TryGetValue(tag, out int[] counts))
{
string counterName = $"labelCont{tag}";
if (tableLayoutPanelTage.Controls
.Find(counterName, true)
.FirstOrDefault() is Label counterLabel)
{
counterLabel.Text = $"{counts[0]}/{counts[1]}/{counts[2]}";
}
}
GetGesamtContainer(zielFlp);
}
}
}
}
//CHANGES: Innerhalb eines Tages kann die Reihenfolge angepasst werden.
//CHANGES: Wenn der Lieferrhythmus geändert wird, werden KundenControls an falschen Tagen gelöscht.
//CHANGES: Lieferrhythmen können angepasst und übernommen werden.
//CHANGES: Speichern und Laden wurde angepasst, JSON enthält jetzt pro Tag eine Kundenliste.