From cf20c425f84420ac070c1cebfc642a96975c0870 Mon Sep 17 00:00:00 2001 From: HirschleM Date: Mon, 13 Jul 2026 16:24:34 +0200 Subject: [PATCH] MH x Claude: Dienstplanung Pausenlogik eingebaut --- .../Detail/Report/DienstplanerView.xaml.cs | 54 ++++++++++++------- .../Dienstplanung/DienstplanungsManager.cs | 21 +++++--- Shared/DataContracts/DienstInfoDC.cs | 30 +++++++++++ 3 files changed, 77 insertions(+), 28 deletions(-) diff --git a/BeWo/View/Detail/Report/DienstplanerView.xaml.cs b/BeWo/View/Detail/Report/DienstplanerView.xaml.cs index 5681f5535..28f0bf99a 100644 --- a/BeWo/View/Detail/Report/DienstplanerView.xaml.cs +++ b/BeWo/View/Detail/Report/DienstplanerView.xaml.cs @@ -944,6 +944,11 @@ namespace BeWo.View.Detail.Report { _AuswahlDienstZeileDC.RemoveDienst(datum.Day); DeleteFromList(eintrag, null); + + // Claude: Beim Bearbeiten (alter Eintrag wird durch neuen ersetzt) die alte Dauer vom Ist/Saldo abziehen, + // sonst wird sie doppelt gezählt. Beim Löschen (dienst.Oid == -1) passiert der Abzug weiter unten. + if (dienst.Oid != -1) + CheckEintragAnAbwesenheitstagen(eintrag, null, employee, false); } } if (dienst.Oid == -1) @@ -1076,6 +1081,11 @@ namespace BeWo.View.Detail.Report { _AuswahlDienstZeileDC.RemoveDienst(datum.Day); DeleteFromList(null, vertretung); + + // Claude: Beim Bearbeiten (alte Vertretung wird durch neue ersetzt) die alte Dauer vom Ist/Saldo abziehen, + // sonst wird sie doppelt gezählt. Beim Löschen (dienst.Oid == -1) passiert der Abzug weiter unten. + if (dienst.Oid != -1) + CheckEintragAnAbwesenheitstagen(null, vertretung, employee, false); } } if (dienst.Oid == -1) @@ -1805,12 +1815,12 @@ namespace BeWo.View.Detail.Report if (eintraegeEinerWoche != null) { foreach (var eintrag in eintraegeEinerWoche) - stundenWoche.Add(eintrag.DauerInStunden); + stundenWoche.Add(DienstInfoDC.DauerAbzueglichPause(eintrag.DauerInStunden, eintrag.DienstOid, _DienstplanerRootObj.AlleDienste)); // Claude: Pause abziehen } if (vertretungenEinerWoche != null) { foreach (var vertretung in vertretungenEinerWoche) - stundenWoche.Add(vertretung.DauerInStunden); + stundenWoche.Add(DienstInfoDC.DauerAbzueglichPause(vertretung.DauerInStunden, vertretung.DienstOid, _DienstplanerRootObj.AlleDienste)); // Claude: Pause abziehen } if (ueberstundenEinerWoche != null) { @@ -2120,7 +2130,7 @@ namespace BeWo.View.Detail.Report { if (tage.Contains(e.Datum)) { - res.Add(e.DauerInStunden * -1); // Abzug von Wochen-Ist + res.Add(DienstInfoDC.DauerAbzueglichPause(e.DauerInStunden, e.DienstOid, _DienstplanerRootObj.AlleDienste) * -1); // Abzug von Wochen-Ist // Claude: gleicher Pausenabzug wie beim Aufaddieren //_DienstplanerRootObj.MonatsZusammenfassung // Abzug von Monats-Ist // .First(z => z.Employee.EmployeeOid == e.EmployeeOid).Ist -= Convert.ToDecimal(e.DauerInStunden); } @@ -2132,7 +2142,7 @@ namespace BeWo.View.Detail.Report { if (tage.Contains(v.Datum)) { - res.Add(v.DauerInStunden * -1); // Abzug von Wochen-Ist + res.Add(DienstInfoDC.DauerAbzueglichPause(v.DauerInStunden, v.DienstOid, _DienstplanerRootObj.AlleDienste) * -1); // Abzug von Wochen-Ist // Claude: gleicher Pausenabzug wie beim Aufaddieren //_DienstplanerRootObj.MonatsZusammenfassung // Abzug von Monats-Ist // .First(z => z.Employee.EmployeeOid == v.EmployeeOid).Ist -= Convert.ToDecimal(v.DauerInStunden); } @@ -2572,6 +2582,10 @@ namespace BeWo.View.Detail.Report } private List CheckEintragAnAbwesenheitstagen(DienstEintragDC eintrag, DienstvertretungDC vertretung, EmployeeDC employee, bool plus) { + // Claude: Pause des Dienstes von der Dauer abziehen, damit Ist/Saldo beim Eintragen/Löschen genauso berechnet werden wie beim Neuladen (BerechneSollSaldoUndIst) + decimal dauerEintrag = eintrag != null ? Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(eintrag.DauerInStunden, eintrag.DienstOid, _DienstplanerRootObj.AlleDienste)) : 0m; + decimal dauerVertretung = vertretung != null ? Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(vertretung.DauerInStunden, vertretung.DienstOid, _DienstplanerRootObj.AlleDienste)) : 0m; + if (!_DienstplanerRootObj.EnableDiensteAnFeiertagen) { if (eintrag != null) @@ -2584,13 +2598,13 @@ namespace BeWo.View.Detail.Report { if (plus) { - item.Ist += Convert.ToDecimal(eintrag.DauerInStunden); - item.Saldo += Convert.ToDecimal(eintrag.DauerInStunden); + item.Ist += dauerEintrag; // Claude: Dauer abzüglich Pause + item.Saldo += dauerEintrag; } else { - item.Ist -= Convert.ToDecimal(eintrag.DauerInStunden); - item.Saldo -= Convert.ToDecimal(eintrag.DauerInStunden); + item.Ist -= dauerEintrag; + item.Saldo -= dauerEintrag; } } @@ -2607,13 +2621,13 @@ namespace BeWo.View.Detail.Report { if (plus) { - item.Ist += Convert.ToDecimal(vertretung.DauerInStunden); - item.Saldo += Convert.ToDecimal(vertretung.DauerInStunden); + item.Ist += dauerVertretung; // Claude: Dauer abzüglich Pause + item.Saldo += dauerVertretung; } else { - item.Ist -= Convert.ToDecimal(vertretung.DauerInStunden); - item.Saldo -= Convert.ToDecimal(vertretung.DauerInStunden); + item.Ist -= dauerVertretung; + item.Saldo -= dauerVertretung; } } } @@ -2631,13 +2645,13 @@ namespace BeWo.View.Detail.Report { if (plus) { - item.Ist += Convert.ToDecimal(eintrag.DauerInStunden); - item.Saldo += Convert.ToDecimal(eintrag.DauerInStunden); + item.Ist += dauerEintrag; // Claude: Dauer abzüglich Pause + item.Saldo += dauerEintrag; } else { - item.Ist -= Convert.ToDecimal(eintrag.DauerInStunden); - item.Saldo -= Convert.ToDecimal(eintrag.DauerInStunden); + item.Ist -= dauerEintrag; + item.Saldo -= dauerEintrag; } } @@ -2651,13 +2665,13 @@ namespace BeWo.View.Detail.Report { if (plus) { - item.Ist += Convert.ToDecimal(vertretung.DauerInStunden); - item.Saldo += Convert.ToDecimal(vertretung.DauerInStunden); + item.Ist += dauerVertretung; // Claude: Dauer abzüglich Pause + item.Saldo += dauerVertretung; } else { - item.Ist -= Convert.ToDecimal(vertretung.DauerInStunden); - item.Saldo -= Convert.ToDecimal(vertretung.DauerInStunden); + item.Ist -= dauerVertretung; + item.Saldo -= dauerVertretung; } } } diff --git a/Service/Dienstplanung/DienstplanungsManager.cs b/Service/Dienstplanung/DienstplanungsManager.cs index 48ef45885..afdafb0c0 100644 --- a/Service/Dienstplanung/DienstplanungsManager.cs +++ b/Service/Dienstplanung/DienstplanungsManager.cs @@ -905,13 +905,14 @@ namespace BeWo.Service.Dienstplanung { foreach (var eintrag in eintraegeFuerMitarbeiterMonat) { - stunden += Convert.ToDecimal(eintrag.DauerInStunden); + // Claude: Pause des Dienstes von der Dauer abziehen + stunden += Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(eintrag.DauerInStunden, eintrag.DienstOid, root.AlleDienste)); } } if (vertretungenFuerMitarbeiterMonat.Count > 0) { foreach (var vertretung in vertretungenFuerMitarbeiterMonat) - stunden += Convert.ToDecimal(vertretung.DauerInStunden); + stunden += Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(vertretung.DauerInStunden, vertretung.DienstOid, root.AlleDienste)); // Claude: Pause abziehen } if (overTimesMonat.Count > 0) { @@ -1010,7 +1011,7 @@ namespace BeWo.Service.Dienstplanung if (abs.AbsenceSpan.ContainsDate(e.Datum.Date)) { if (dauerAbwesenheit > 0.5m) - stunden -= Convert.ToDecimal(e.DauerInStunden); + stunden -= Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(e.DauerInStunden, e.DienstOid, root.AlleDienste)); // Claude: gleicher Pausenabzug wie beim Aufaddieren } } foreach (var v in vertretungenFuerMitarbeiterMonat) @@ -1018,7 +1019,7 @@ namespace BeWo.Service.Dienstplanung if (abs.AbsenceSpan.ContainsDate(v.Datum.Date)) { if (dauerAbwesenheit > 0.5m) - stunden -= Convert.ToDecimal(v.DauerInStunden); + stunden -= Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(v.DauerInStunden, v.DienstOid, root.AlleDienste)); // Claude: gleicher Pausenabzug wie beim Aufaddieren } } } @@ -1068,6 +1069,9 @@ namespace BeWo.Service.Dienstplanung berechnung.CreateReport(konto); DienstplanerMonthlySummaryDC dc = new DienstplanerMonthlySummaryDC(); + // Claude: Dienste laden, um deren Pausen von der Dauer der Einträge abziehen zu können + var alleDienste = GetAllDienste(null); + stundenBeiAbwesenheitKey = empOid; stundenBeiAbwesenheitValue = 0; @@ -1096,13 +1100,14 @@ namespace BeWo.Service.Dienstplanung { foreach (var eintrag in eintraegeFuerMitarbeiterMonat) { - stunden += Convert.ToDecimal(eintrag.DauerInStunden); + // Claude: Pause des Dienstes von der Dauer abziehen + stunden += Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(eintrag.DauerInStunden, eintrag.DienstOid, alleDienste)); } } if (vertretungenFuerMitarbeiterMonat.Count > 0) { foreach (var vertretung in vertretungenFuerMitarbeiterMonat) - stunden += Convert.ToDecimal(vertretung.DauerInStunden); + stunden += Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(vertretung.DauerInStunden, vertretung.DienstOid, alleDienste)); // Claude: Pause abziehen } if (overTimesMonat.Count > 0) { @@ -1140,7 +1145,7 @@ namespace BeWo.Service.Dienstplanung if (abs.AbsenceSpan.ContainsDate(e.Datum.Date)) { if (dauerAbwesenheit > 0.5m) - stunden -= Convert.ToDecimal(e.DauerInStunden); + stunden -= Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(e.DauerInStunden, e.DienstOid, alleDienste)); // Claude: gleicher Pausenabzug wie beim Aufaddieren } } foreach (var v in vertretungenFuerMitarbeiterMonat) @@ -1148,7 +1153,7 @@ namespace BeWo.Service.Dienstplanung if (abs.AbsenceSpan.ContainsDate(v.Datum.Date)) { if (dauerAbwesenheit > 0.5m) - stunden -= Convert.ToDecimal(v.DauerInStunden); + stunden -= Convert.ToDecimal(DienstInfoDC.DauerAbzueglichPause(v.DauerInStunden, v.DienstOid, alleDienste)); // Claude: gleicher Pausenabzug wie beim Aufaddieren } } } diff --git a/Shared/DataContracts/DienstInfoDC.cs b/Shared/DataContracts/DienstInfoDC.cs index 523bfcf05..0f817f43a 100644 --- a/Shared/DataContracts/DienstInfoDC.cs +++ b/Shared/DataContracts/DienstInfoDC.cs @@ -74,6 +74,36 @@ namespace BS.Shared.DataContracts //public double DurationHours => Start < Ende ? (Ende - Start).TotalHours : (Ende.AddDays(1) - Start).TotalHours; public double DurationHours => Dauer; + // Claude: Zieht die am Dienst gepflegte Pause (in Minuten) von einer Dauer (in Stunden) ab, nie unter 0. + // Wird im Dienstplaner für Wochen-Ist, Monats-Ist und Monatssaldo verwendet — die gespeicherte DauerInStunden bleibt unverändert. + public static double DauerAbzueglichPause(double dauerInStunden, DienstInfoDC dienst) + { + if (dienst == null || dienst.Pause <= 0) + return dauerInStunden; + + var dauer = dauerInStunden - dienst.Pause / 60.0; + return dauer > 0 ? dauer : 0; + } + + // Claude: Überladung, die den Dienst anhand der DienstOid aus einer Liste sucht (unbekannte Oid => kein Abzug) + public static double DauerAbzueglichPause(double dauerInStunden, long dienstOid, IEnumerable dienste) + { + DienstInfoDC dienst = null; + if (dienste != null) + { + foreach (var d in dienste) + { + if (d != null && d.Oid == dienstOid) + { + dienst = d; + break; + } + } + } + + return DauerAbzueglichPause(dauerInStunden, dienst); + } + public string DarstellungInPopUp { get