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

556 lines
20 KiB
C#
Raw 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 Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.LinkLabel;
namespace Deckungsbeitrag.UserControls
{
public partial class UCInventur : UserControl
{
public FormAuftragDetail formAuftragDetail;
private readonly object Sender;
private Auftrag auftrag;
private readonly Benutzer user;
private readonly Kunde kunde;
private List<KundeArtikel> artikelListe;
private bool neueinventur = false;
private readonly string[] lines;
private bool formLoading = false;
public event Action SizeChangedForParent;
public event Action UCInventur_Update;
public event Action UCInventur_Delete;
private Point uci_loc;
private bool _tosave = false;
public bool Tosave
{
get { return _tosave; }
set
{
_tosave = value;
if (_tosave)
{
buttonSpeichern.Enabled = true;
buttonSpeichern.BackColor = Color.FromArgb(0, 192, 0);
if ((this.user.Rolle == BenutzerRolle.Verwaltung) || (this.user.Rolle == BenutzerRolle.Admin)) { this.buttonFreigeben.Enabled = true; this.buttonFreigeben.BackColor = Color.Turquoise; }
}
else
{
buttonSpeichern.Enabled = false;
buttonSpeichern.BackColor = Color.Gray;
buttonFreigeben.Enabled = false;
buttonFreigeben.BackColor = Color.Gray;
}
}
}
public UCInventur()
{
formLoading = true;
InitializeComponent();
}
public UCInventur(Kunde kunde, Benutzer benutzer) : this()
{
this.kunde = kunde;
this.user = benutzer;
}
public UCInventur(string[] lines, Benutzer benutzer, object sender) : this()
{
this.lines = lines;
this.user = benutzer;
this.Sender = sender;
string kndnr = lines[1].Split(':')[1].Trim();
int auftragnr = int.Parse(lines[3].Split(':')[1].Trim());
this.kunde = Kunde.GetKunde(kndnr, null, null);
this.auftrag = Auftrag.GetAuftrag(auftragnr);
}
private void UCInventur_Load(object sender, EventArgs e)
{
if ((this.user.Rolle == BenutzerRolle.Verwaltung & Tosave) || (this.user.Rolle == BenutzerRolle.Admin & Tosave)) { this.buttonFreigeben.Enabled = true; this.buttonFreigeben.BackColor = Color.Turquoise; }
string kundeName = this.kunde.Suchtext ?? this.kunde.KundeName;
this.groupBoxInventur.Text = $"Inventur-{this.kunde.KundeNummer} {kundeName}";
if (lines == null || lines.Length == 0) { this.dTPInvDatum.Value = DateTime.Today.Date; }
else { this.dTPInvDatum.Value = DateTime.Parse(lines[4].Split(':')[1]); this.dTPInvDatum.Enabled = true; }
if (auftrag != null) this.dTPLieferDat.Value = auftrag.Liefertag;
Load_DGV();
if (lines != null & Sender is FormMain) PictureBoxClose_Click(sender, e);
if (Sender is FormAuftragDetail)
{
pictureBoxClose.Visible = pictureBoxClose.Enabled = false;
buttonAbbrechen.Visible = buttonAbbrechen.Enabled = false;
}
formLoading = false;
}
private void Load_DGV()
{
this.dGArtikel.AutoGenerateColumns = false;
artikelListe = KundeArtikel.GetInventurList(this.kunde.KundeID);
this.dGArtikel.AllowUserToAddRows = false;
this.dGArtikel.AllowUserToResizeColumns = true;
this.dGArtikel.Rows.Clear();
if (lines != null)
{
string[] aufID = lines[3].Split(':');
if (aufID.Length > 1) auftrag = Auftrag.GetAuftrag(int.Parse(aufID[1]));
// Artikelbezeichnungn für SpaltenHeader = 8. Zeile
string[] headerCols = lines[7].Split(';'); // oder "," je nach Trennzeichen
// Spalten hinzufügen oder bestehende Spalte ignorieren
foreach (string header in headerCols)
{
string cleanHeader = header.Trim();
if (cleanHeader == "Status" || string.IsNullOrWhiteSpace(cleanHeader)) continue;
// prüfen, ob Spalte mit diesem Header schon existiert
if (FindColumnByHeaderText(dGArtikel, cleanHeader) == null)
{
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn
{
HeaderText = cleanHeader,
Name = "col_" + cleanHeader.Replace("-", "_").Replace(" ", ""),
ReadOnly = false
};
dGArtikel.Columns.Add(col);
}
}
}
// Zeilen manuell aus artikelListe und CSV laden
int idx = 0;
int index = 8;
foreach (KundeArtikel ka in artikelListe)
{
var row = new DataGridViewRow();
row.CreateCells(dGArtikel);
row.Cells[0].Value = ka.ArtikelNR;
row.Cells[1].Value = ka.ArtikelName;
row.Cells[2].Value = ka.Stand;
row.Cells[3].Value = ka.Reklamation;
row.Cells[4].Value = ka.Fehlmenge;
row.Cells[6].Value = ka.Korrektur;
if (lines != null)
{
// CSVZahlen ab dt.Columns.Count
string line = lines[index];
string[] fields = line.Split(';');
for (int j = 0; j < fields.Length; j++)
{
if (j != 0)
{
if (string.IsNullOrWhiteSpace(fields[j])) continue;
if (j == 6) row.Cells[5].Value = fields[6];
row.Cells[j - 1].Value = fields[j];
}
}
index++;
idx++;
}
dGArtikel.Rows.Add(row);
}
DGArtikel_DataBindingComplete(this.dGArtikel, null);
this.dGArtikel.Refresh();
}
private DataGridViewColumn FindColumnByHeaderText(DataGridView dgv, string headerText)
{
foreach (DataGridViewColumn col in dgv.Columns)
{
if (string.Equals(col.HeaderText, headerText, StringComparison.OrdinalIgnoreCase))
{
return col;
}
}
return null;
}
/// <summary>
/// Bei Click wird neue Spalte eingefügt. Titel wird durch Inputfeld erfasst und DisplayIndex ist Columns - 1
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PictureBoxPlus_Click(object sender, EventArgs e)
{
string text = Interaction.InputBox($"Bitte gib hier den Spaltentitel ein.\n\nTitel:", "Spaltentitel", "");
// Wenn Inputbox gibt string.empty zurück dann keine Column anlegen.
if (string.IsNullOrWhiteSpace(text)) return;
DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn()
{
HeaderText = text,
ReadOnly = false,
};
this.dGArtikel.Columns.Add(column);
DataGridView_GetNewSize(this.dGArtikel);
}
private void GroupBoxInventur_Paint(object sender, PaintEventArgs e)
{
GroupBox gb = (GroupBox)sender;
base.OnPaint(e);
Funktionen.GetGroupBoxBoarder(gb, e);
}
private void ButtonFreigeben_Click(object sender, EventArgs e)
{
if (this.auftrag == null) return;
this.auftrag.Liefertag = dTPLieferDat.Value;
foreach (DataGridViewRow row in this.dGArtikel.Rows)
{
// KundeArtikel updaten. Neuen Stand eintragen, Reklamation & Fehlmenge auf Null setzten und Korrektur als InventruAusgleich speichern.
KundeArtikel art = (KundeArtikel)artikelListe[row.Index];
art.Reklamation = 0;
art.Fehlmenge = 0;
art.StandBearbeitet = this.user.BenutzerName + " am " + DateTime.Now;
art.FehlmengeBearbeitet = this.user.BenutzerName + " am " + DateTime.Now;
art.KorrekturBearbeitet = this.user.BenutzerName + " am " + DateTime.Now;
art.Stand = int.Parse(row.Cells[2].Value.ToString());
art.Korrektur = int.Parse(row.Cells[6].Value.ToString());
art.Save();
// AuftragArtikel erstellen.
if (int.Parse(row.Cells[6].Value.ToString()) != 0)
{
AuftragArtikel auf = new AuftragArtikel
{
ArtikelID = art.ArtikelID,
AuftragID = auftrag.AuftragID,
Anzahl = art.Korrektur,
ArtikelName = art.ArtikelName,
Gesamt = art.Korrektur
};
auf.Save();
}
}
auftrag.Status = AuftragStatus.Herrichten;
auftrag.Save();
GetInventurCSV(sender, auftrag.AuftragID);
UCInventur_Update();
}
/// <summary>
/// DataGridView wird geladen.
/// Wenn Inventurdatei vorhanden werden Spalten hinzugefügt und Zeilen aufgefüllt.
/// </summary>
/// <param name="sender"></param>
private void GetInventurCSV(object sender, int? auftragID)
{
Button btn = (Button)sender;
Kunde _knd = this.kunde;
Benutzer _user = this.user;
List<KundeArtikel> _artikelliste = this.artikelListe;
string status = string.Empty;
string savePath = Path.Combine(ConfigurationManager.AppSettings["DateiSavePfad"], "Listen\\Inventuren") ?? "Inventuren";
if (ConfigurationManager.AppSettings["ConnectionString"].Split(';')[4].Split('=')[1] == "Test_Wirl") savePath = Path.Combine(ConfigurationManager.AppSettings["DateiSavePfad"], "Test\\Inventuren") ?? "Inventuren";
// Inventur Status Warten wenn noch Zahlen fehlen und Herrichten wenn alle vorhanden.
if (btn.Text.ToString() == "Speichern") status = "Warten";
else
{
status = "Herrichten";
string delPath = Path.Combine(savePath, $"Warten-{auftragID}-{_knd.KundeNummer}.csv");
if (File.Exists(delPath)) File.Delete(delPath);
}
string artikel = string.Empty;
string cols = string.Empty;
string fileName = $"{status}-{auftragID}-{_knd.KundeNummer}.csv"; // Immer gleiche Datei!
string csvPath;
csvPath = Path.Combine(savePath, fileName);
// Prüfen ob Header schon existiert
bool headerExists = File.Exists(csvPath);
// Artikelbezeichnungen in string convertieren
foreach (KundeArtikel art in _artikelliste) artikel += art.ArtikelName + ";";
foreach (var col in dGArtikel.Columns.Cast<DataGridViewColumn>().Where(c => c.Visible).OrderBy(c => c.DisplayIndex))
{
if (col.Visible) cols += col.HeaderText + ";";
}
// Prüfen ob Inventur neu ist
if (headerExists) neueinventur = NeueInventur(csvPath, cols);
// Nur Header bei NEUER Datei
var csv = new StringBuilder();
if (!headerExists || !neueinventur)
{
csv.AppendLine("=== INVENTUR INFO ===");
csv.AppendLine($"KundeNr: {_knd.KundeNummer}");
csv.AppendLine($"Kunde: {_knd.KundeName}");
csv.AppendLine($"Auftrag: {auftragID}");
csv.AppendLine($"Letzte Inventur: {dTPInvDatum.Value.Date:yyyy-MM-dd}");
csv.AppendLine();
csv.AppendLine(new string('=', 30));
csv.AppendLine($"Status;{cols}");
File.WriteAllText(csvPath, csv.ToString(), Encoding.UTF8);
}
// NEUE Artikel ANHÄNGEN (ohne Header)
var appendCsv = new StringBuilder();
foreach (DataGridViewRow row in this.dGArtikel.Rows)
{
// Nur sichtbare Spalten auslesen
var values = new List<string>();
for (int i = 0; i < row.Cells.Count; i++)
{
if (row.Cells[i].Visible)
{
if (i == 0)
{
if (artikelListe[row.Index].Korrektur == 0) values.Add("Erledigt");
else values.Add("Offen");
}
values.Add(row.Cells[i].Value?.ToString() ?? "0");
}
}
// Eine Zeile pro Row, mit allen Werten getrennt durch ";"
appendCsv.AppendLine(string.Join(";", values));
}
// ANHÄNGEN statt überschreiben
if (neueinventur)
{
File.AppendAllText(csvPath, appendCsv.ToString(), Encoding.UTF8);
}
else
{
File.WriteAllText(csvPath, csv.ToString(), Encoding.UTF8);
File.AppendAllText(csvPath, appendCsv.ToString(), Encoding.UTF8);
}
}
/// <summary>
/// Nachdem die DataGridView fertig ist werden Spalten entfernt, die Größe neu berechnet und auf GroupBox und UserControl übertragen.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DGArtikel_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
// Alle Spaltenbreiten an den Zellinhalt anpassen
this.dGArtikel.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
// Alle Zeilenhöhen an Zellinhalt anpassen
this.dGArtikel.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
DataGridView_GetNewSize(this.dGArtikel);
}
/// <summary>
/// Die Größe von GroupBox und UserControl wird an die aktuelle und neue Größe der DataGridView angepasst.
/// </summary>
/// <param name="dgv"></param>
private void DataGridView_GetNewSize(DataGridView dgv)
{
int totalWidth = dgv.RowHeadersVisible ? dgv.RowHeadersWidth : 0;
foreach (DataGridViewColumn col in dgv.Columns)
{
if (col.Visible) totalWidth += col.Width;
}
int totalHeight = dgv.ColumnHeadersVisible ? dgv.ColumnHeadersHeight : 0;
foreach (DataGridViewRow row in dGArtikel.Rows)
{
if (row.Visible) totalHeight += row.Height;
}
totalHeight += dgv.ColumnHeadersHeight;
dgv.ClientSize = new Size(totalWidth, totalHeight);
this.groupBoxInventur.ClientSize = new Size(dgv.Width + 10, dgv.Height + dgv.Top + 10);
this.ClientSize = new Size(this.groupBoxInventur.ClientSize.Width + 10, this.groupBoxInventur.Height + panelButtons.Height + 10);
}
/// <summary>
/// Größe des UserControls wird verringert.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PictureBoxClose_Click(object sender, EventArgs e)
{
if (Tosave) if (MessageBox.Show("Du hast die Zahlen geändert. Möchtest du die Inventur so speichern?", "INVENTUR SPEICHERN", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) ButtonSpeichern_Click(this.buttonSpeichern, null);
if (groupBoxInventur.Visible)
{
this.buttonFreigeben.Visible = false;
this.buttonSpeichern.Visible = false;
this.labelInvText.Text = groupBoxInventur.Text;
this.groupBoxInventur.Visible = false;
this.labelInvText.Visible = true;
this.Height = panelButtons.Height + 6;
this.Width = labelInvText.Right + 10;
this.Location = uci_loc;
}
}
private bool NeueInventur(string csvPath, string cols)
{
bool result = false;
int lineNumber = 0;
string[] lines = new string[lineNumber];
foreach (string line in File.ReadLines(csvPath, Encoding.UTF8))
{
Array.Resize<string>(ref lines, lineNumber + 1);
lines[lineNumber] = line;
lineNumber++;
if (lineNumber == 5)
{
DateTime? letzteInventur = DateTime.Parse(line.Split(':')[1]);
result = dTPInvDatum.Value.Date > letzteInventur.Value.Date;
if (result == true) lines[lineNumber - 1] = $"Letzte Inventur: {dTPInvDatum.Value.Date:yyyy-MM-dd}";
}
if (lineNumber == 8)
{
lines[lineNumber - 1] = cols;
}
}
File.WriteAllLines(csvPath, lines, Encoding.UTF8);
return result;
}
/// <summary>
/// Location der Controls im UserControl wird berechnet.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UCInventur_SizeChanged(object sender, EventArgs e)
{
int label_y = this.pictureBoxPlus.Location.Y + ((this.pictureBoxPlus.Height - this.label1.Height) / 2);
this.pictureBoxClose.Location = new Point(this.groupBoxInventur.Right - pictureBoxClose.Width - 2, 0);
this.pictureBoxPlus.Location = new Point(this.dGArtikel.Right - pictureBoxPlus.Width, this.pictureBoxPlus.Location.Y);
this.label1.Location = new Point(this.pictureBoxPlus.Left - this.label1.Width - 10, this.pictureBoxPlus.Location.Y + ((this.pictureBoxPlus.Height - this.label1.Height) / 2));
int x;
this.labelInvDat.Location = new Point(x = this.dGArtikel.Left, label_y);
this.dTPInvDatum.Location = new Point(x += labelInvDat.Width, this.pictureBoxPlus.Location.Y);
this.labelLieferDat.Location = new Point(x = x + dTPInvDatum.Width + 10, label_y);
this.dTPLieferDat.Location = new Point(x + labelLieferDat.Width, this.pictureBoxPlus.Location.Y);
this.buttonSpeichern.Location = new Point(buttonFreigeben.Left - buttonSpeichern.Width - buttonSpeichern.Margin.Left, buttonSpeichern.Top);
if (Sender is FormAuftragDetail) SizeChangedForParent?.Invoke();
}
/// <summary>
/// Größe des UserControls wird wiederhergestellt.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LabelInvText_Click(object sender, EventArgs e)
{
if (!groupBoxInventur.Visible)
{
uci_loc = this.Location;
DataGridView_GetNewSize(this.dGArtikel);
this.buttonFreigeben.Visible = true;
this.buttonSpeichern.Visible = true;
groupBoxInventur.Visible = true;
this.labelInvText.Visible = false;
}
}
private void DGArtikel_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
int iststand = 0; int sollstand; int fehlmenge;
DataGridView dgv = (DataGridView)sender;
if (int.TryParse(dgv.CurrentCell.Value.ToString(), out _))
{
var row = dgv.Rows[e.RowIndex];
sollstand = int.Parse(row.Cells[2].Value.ToString());
fehlmenge = int.Parse(row.Cells[3].Value.ToString()) + int.Parse(row.Cells[4].Value.ToString());
for (int j = 7; j < row.Cells.Count; j++)
{
if (row.Cells[j].Value == null) row.Cells[j].Value = 0;
iststand += int.TryParse(row.Cells[j].Value.ToString(), out int r) ? r : 0;
}
if (e.ColumnIndex >= 7)
{
row.Cells[5].Value = sollstand - fehlmenge - iststand;
row.Cells[6].Value = artikelListe[e.RowIndex].Korrektur = sollstand - iststand;
}
if (e.ColumnIndex == 2)
{
row.Cells[6].Value = artikelListe[e.RowIndex].Korrektur = sollstand - iststand;
}
}
else return;
dgv.Refresh();
}
private void DGArtikel_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (!formLoading) { Tosave = true; }
else Tosave = false;
}
private void ButtonSpeichern_Click(object sender, EventArgs e)
{
this.dGArtikel.EndEdit(); // beendet aktuelle ZellBearbeitung
if (Tosave)
{
if (auftrag == null)
{
auftrag = new Auftrag()
{
KundeID = (int)this.kunde.KundeID,
Liefertag = this.dTPLieferDat.Value,
Erstellt = DateTime.Now,
ErstelltVon = (int)this.user.BenutzerID,
Status = AuftragStatus.Warten,
Container = 0,
ContainerClean = 0,
Typ = AuftragTyp.Inventur,
};
auftrag.Save();
}
GetInventurCSV(sender, auftrag.AuftragID);
}
this.dTPLieferDat.Focus();
Tosave = false;
}
private void DGArtikel_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
if (e.ColumnIndex == 2)
{
if (MessageBox.Show("Möchtest du den Stand wirklich verändern?", "FRAGE", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) return;
else
{
dgv.Columns[e.ColumnIndex].ReadOnly = false;
}
}
}
private void ButtonAbbrechen_Click(object sender, EventArgs e)
{
if (Tosave) { if (MessageBox.Show("Möchtest du wirklich Abbrechen und die Inventur verwerfen?", "FRAGE", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) UCInventur_Delete(); }
else UCInventur_Delete();
}
}
}
//DONE: CLick auf Inventur freigeben Dateiname von "Warten" auf "Herrichten" ändern.
//DONE: Inventur freigeben nur für Admin oder Verwaltung.
//DONE: Inventur für Expedit zugänglich machen.