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 object Sender; private Auftrag auftrag; private Benutzer user; private Kunde kunde; private List artikelListe; private int controlHeight; private bool neueinventur = false; private string[] lines; private bool formLoading = false; private bool _tosave = false; public event Action SizeChangedForParent; public event Action UCInventur_Update; public event Action UCInventur_Delete; private Point uci_loc; 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; this.kunde = Kunde.GetKunde(lines[1].Split(':')[1].Trim(), null, null); this.auftrag = Auftrag.GetAuftrag(int.Parse(lines[3].Split(':')[1].Trim())); } 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 == null ? this.kunde.KundeName : this.kunde.Suchtext; 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) { formAuftragDetail = sender as FormAuftragDetail; pictureBoxClose.Visible = pictureBoxClose.Enabled = false; pictureBoxPlus.Visible = pictureBoxPlus.Enabled = false; } formLoading = false; } private void Load_DGV() { this.dGArtikel.AutoGenerateColumns = false; artikelListe = KundeArtikel.GetInventurList(this.kunde.KundeID); //this.dGArtikel.DataSource = artikelListe; this.dGArtikel.AllowUserToAddRows = false; 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) { // CSV‑Zahlen 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; } /// /// Bei Click wird neue Spalte eingefügt. Titel wird durch Inputfeld erfasst und DisplayIndex ist Columns - 1 /// /// /// private void pictureBoxPlus_Click(object sender, EventArgs e) { string text = Interaction.InputBox($"Bitte gib hier den Spaltentitel ein.\n\nTitel:", "Spaltentitel", ""); int cols = this.dGArtikel.Columns.Count; 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(); auf.ArtikelID = art.ArtikelID; auf.AuftragID = auftrag.AuftragID; auf.Anzahl = art.Korrektur; auf.ArtikelName = art.ArtikelName; auf.Gesamt = art.Korrektur; auf.Save(); } } auftrag.Status = AuftragStatus.Herrichten; auftrag.Save(); GetInventurCSV(sender, auftrag.AuftragID); UCInventur_Update(); } /// /// DataGridView wird geladen. /// Wenn Inventurdatei vorhanden werden Spalten hinzugefügt und Zeilen aufgefüllt. /// /// private void GetInventurCSV(object sender, int? auftragID) { Button btn = (Button)sender; Kunde _knd = this.kunde; Benutzer _user = this.user; List _artikelliste = this.artikelListe; string status = string.Empty; string savePath = Path.Combine(ConfigurationManager.AppSettings["DateiSavePfad"], "Listen\\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.ToString()}-{_knd.KundeNummer}.csv"); if (File.Exists(delPath)) File.Delete(delPath); } string artikel = string.Empty; string cols = string.Empty; string fileName = $"{status}-{auftragID.ToString()}-{_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().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.ToString()}"); csv.AppendLine($"Letzte Inventur: {dTPInvDatum.Value.Date.ToString("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(); 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); } } /// /// Nachdem die DataGridView fertig ist werden Spalten entfernt, die Größe neu berechnet und auf GroupBox und UserControl übertragen. /// /// /// 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); } /// /// Die Größe von GroupBox und UserControl wird an die aktuelle und neue Größe der DataGridView angepasst. /// /// 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.ClientSize.Width, dgv.Height + pictureBoxPlus.Bottom + 10); this.ClientSize = new Size(this.groupBoxInventur.ClientSize.Width + 10, this.groupBoxInventur.Height + panelButtons.Height + 10); } /// /// Größe des UserControls wird verringert. /// /// /// 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) { DateTime? letzteInventur = null; bool result = false; int lineNumber = 0; string[] lines = new string[lineNumber]; foreach (string line in File.ReadLines(csvPath, Encoding.UTF8)) { Array.Resize(ref lines, lineNumber + 1); lines[lineNumber] = line; lineNumber++; if (lineNumber == 5) { letzteInventur = DateTime.Parse(line.Split(':')[1]); result = dTPInvDatum.Value.Date > letzteInventur.Value.Date; if (result == true) lines[lineNumber - 1] = $"Letzte Inventur: {dTPInvDatum.Value.Date.ToString("yyyy-MM-dd")}"; } if (lineNumber == 8) { lines[lineNumber - 1] = cols; } } File.WriteAllLines(csvPath, lines, Encoding.UTF8); return result; } /// /// Location der Controls im UserControl wird berechnet. /// /// /// private void UCInventur_SizeChanged(object sender, EventArgs e) { int label_y = this.pictureBoxPlus.Location.Y + ((this.pictureBoxPlus.Height - this.label1.Height) / 2); int x = 0; this.pictureBoxClose.Location = new Point(this.Width - pictureBoxClose.Width + this.Margin.All, 0); this.pictureBoxPlus.Location = new Point(this.groupBoxInventur.Width - pictureBoxPlus.Width - this.groupBoxInventur.Margin.Right - this.Margin.Right, 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)); this.labelInvDat.Location = new Point(x = this.dGArtikel.Left, label_y); this.dTPInvDatum.Location = new Point(x = 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(); } /// /// Größe des UserControls wird wiederhergestellt. /// /// /// 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_Leave(object sender, EventArgs e) { DataGridView dgv = (DataGridView)sender; } private void dGArtikel_CellLeave(object sender, DataGridViewCellEventArgs e) { } private void dGArtikel_CellEndEdit(object sender, DataGridViewCellEventArgs e) { int iststand = 0; int invausgleich = 0; int schwund = 0; int sollstand = 0; int fehlmenge = 0; DataGridView dgv = (DataGridView)sender; if (int.TryParse(dgv.CurrentCell.Value.ToString(), out int n)) { 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 Zell‑Bearbeitung 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(); } } } //TODO: 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.