diff --git a/ReportImp/LebenshilfeStadeMID/CustomMitarbeiterstundenkontoBerechnung.cs b/ReportImp/LebenshilfeStadeMID/CustomMitarbeiterstundenkontoBerechnung.cs index 967d85cd2..73e45a62a 100644 --- a/ReportImp/LebenshilfeStadeMID/CustomMitarbeiterstundenkontoBerechnung.cs +++ b/ReportImp/LebenshilfeStadeMID/CustomMitarbeiterstundenkontoBerechnung.cs @@ -3,15 +3,333 @@ using System.Collections.Generic; using System.Linq; using BeWo.Data.Entities; using BeWo.Report.ReportObjects; - +using BS.Shared.Core; namespace LebenshilfeStadeMID { public class CustomMitarbeiterstundenkontoBerechnung : MitarbeiterstundenkontoBerechnung { - public override bool ShouldCreateDayDetails() + private const int ANZ_WOCHENTAGE = 5; + + public override bool ShouldCreateDayDetails() { return true; } - } + + // Reguläres Soll nur mit Vertrag berechnen, auch wenn es Arbeitszeiten gibt + protected override decimal? GetSollNachArbeitszeiten(Employee emp, DateTime start, DateTime ende) + { + return null; + } + // SollProTag für Abwesenheiten mit Vertrag berechnen, auch wenn es Arbeitszeiten gibt + public override AbsenceTimeDays GetAbsenceTimeDaysWithWorkWeeks(Employee emp, DateTime start, DateTime end, int arbeitstageProWoche) + { + return GetAbsenceTimeDaysWithWorkWeeks(emp.AbsenceTimes, start, end, arbeitstageProWoche); + } + // SollProTag für Abwesenheiten mit Vertrag berechnen, auch wenn es Arbeitszeiten gibt + public override decimal BerechneStundenDurchAbwesenheiten(AbsenceTimeDays ath, DateTime start, DateTime ende, Contract c, MitarbeiterstundenkontoRO.EmployeeDetail ed) + { + #region Standardkram + if (BerechneAlteAbwesenheitsStunden(start)) + { + return BerechneStundenDurchAbwesenheitenAlt(ath, start, ende, c, ed); + } + //if (ath.StundenGesamt.HasValue) + //{ + // return ath.StundenGesamt.Value; + //} + #endregion + + decimal stunden = 0; + if (c != null) + { + if (ath.TageGesamt.HasValue) + { + // hier würden eigentlich die Arbeitszeiten bedacht werden, das soll aber nicht passieren, daher ist der Code weg + //if (HatArbeitszeitImZeitraum(ed.Employee.Arbeitszeiten, start, ende)) + //{ + // return BerechneAbwesenheitsStundenDurchArbeitszeiten(ed.Employee, start, ende); + //} + + #region Standardkram + decimal sollStundenProWoche = BerechneSollProWoche(c, ed); + + if (sollStundenProWoche > 0) + { + if (ed.ArbeitstageProWoche == 5) + { + stunden = ath.TageGesamt.Value * (sollStundenProWoche / 5); + } + else if (ath.TageProWocheDict != null && ed.ArbeitstageProWoche > 0) + { + foreach (var week in ath.TageProWocheDict.Keys) + { + var tage = ath.TageProWocheDict[week]; + + if (tage > 0) + { + if (tage > ed.ArbeitstageProWoche) + { + tage = ed.ArbeitstageProWoche; + + } + + stunden += tage * (sollStundenProWoche / ed.ArbeitstageProWoche); + } + } + } + } + #endregion + } + } + + return stunden; + } + // hier wird mittendrin auf die Arbeitszeiten geprüft, das muss raus. Ganzer Rest ist Standard, ging aber nicht ohne alles zu kopieren.. + public override void CalculateAbsenceTimesForDay(MitarbeiterstundenkontoRO.DayDetail dd, MitarbeiterstundenkontoRO.EmployeeDetail ed) + { + #region Standardkram + var absenceTimes = ed.Employee.AbsenceTimes; + + if (absenceTimes != null) + { + foreach (var absenceTime in absenceTimes) + { + + //if (IsUrlaubAbsenceTime(absenceTime) || IsKrankheitAbsenceTime(absenceTime)) + //{ + DateTimeSpan span = new DateTimeSpan(); + + span.StartDate = dd.Date; + + if (absenceTime.Start.HasValue && absenceTime.Start.Value > span.StartDate) + { + span.StartDate = absenceTime.Start.Value; + } + + if (absenceTime.End.HasValue && absenceTime.End.Value.Date == span.StartDate.Date && + absenceTime.End.Value.Hour > 0) + { + span.EndDate = absenceTime.End.Value; + } + else + { + span.EndDate = dd.Date.AddDays(1); + if (absenceTime.End.HasValue && absenceTime.End.Value.Date.AddDays(1) < span.EndDate) + { + span.EndDate = absenceTime.End.Value.Date.AddDays(1); + } + } + + if (span.EndDate > dd.Date && span.StartDate < dd.Date.AddDays(1)) + { + DateTime day = span.StartDate; + var faktor = GetFeiertagsFaktor(day); + + + if (faktor < 1 && (day.DayOfWeek != DayOfWeek.Saturday || ed.ArbeitstageProWoche == 6) && (day.DayOfWeek != DayOfWeek.Sunday || ed.ArbeitstageProWoche > 6)) // Prüfung auf 6 + bzw 7 Tage Woche + { + //Berechne Soll, entweder aus Vertrag oder Arbeitszeiten + var sollDiesenTag = ed.SollProTag; + + bool checkMaxWochenSoll = true; + + if (!IstAnrechenbareAbsenceTime(absenceTime)) + { + sollDiesenTag = 0; + } + #endregion + // Prüfung für Arbeitszeiten raus, das ist alles, was hier anders gemacht ist als im Standard + // else if (HatArbeitszeitImZeitraum(ed.Employee.Arbeitszeiten, dd.Date, dd.Date)) + //{ + // sollDiesenTag = BerechneAlleAbwesenheitsStundenFuerArbeitszeiten(ed.Employee, dd.Date); // Hier wird der Feiertagsfaktor schon applied + + //} + #region Standardkram + else + { + var ssa = GetSollStundenForAbsenceTime(ed, absenceTime, dd.Date); + if (ssa.HasValue) + { + sollDiesenTag = ssa.Value; + checkMaxWochenSoll = false; + + } + else + { + var c = ed.Employee.GetValidContractForDate(dd.Date); + if (c != null) + { + decimal wth = 0; + int apw = ANZ_WOCHENTAGE; + + if (c.WeeklyTotalHours.HasValue) + { + wth = c.WeeklyTotalHours.Value; + } + if (c.WeeklyDays.HasValue && c.WeeklyDays.Value > 0) + { + apw = c.WeeklyDays.Value; + } + + sollDiesenTag = wth / apw; + } + } + } + + + //Dauer der Abwesenheit = Soll an diesem Tag + bool istGanztaegig = true; + var abwesenheitsDauer = sollDiesenTag; + + if (span.StartDate.Hour > 0 && span.EndDate.Hour > 0) + { + istGanztaegig = false; + + var ts = span.EndDate.Subtract(span.StartDate); + abwesenheitsDauer = (decimal)ts.TotalHours; + if (SchneideZuvieleAbwesenheitsstundenAb() && abwesenheitsDauer > sollDiesenTag) + { + abwesenheitsDauer = sollDiesenTag; + } + + sollDiesenTag -= abwesenheitsDauer; + if (sollDiesenTag < 0) + { + sollDiesenTag = 0; + } + + faktor = 1; // Keine halben Feiertag berücksichtigen, wenn die Abwesenheit in Stunden angegeben wurde + } + + if (faktor != 0 && !HatArbeitszeitImZeitraum(ed.Employee.Arbeitszeiten, dd.Date, dd.Date)) + { + abwesenheitsDauer *= faktor; //halbe Feiertage etc. berücksichtigen + } + + if (ed.AbsenceTimeDays != null && ed.AbsenceTimeDays.TageProWocheDict != null) + { + if (ed.AbsenceTimeDays.RestStundenProWocheDict == null) + { + ed.AbsenceTimeDays.RestStundenProWocheDict = new Dictionary(); + } + foreach (var week in ed.AbsenceTimeDays.TageProWocheDict.Keys) + { + if (!ed.AbsenceTimeDays.RestStundenProWocheDict.ContainsKey(week)) + { + ed.AbsenceTimeDays.RestStundenProWocheDict.Add(week, ed.SollProWoche); + } + + if (day.Date >= week.StartDate && day.Date <= week.EndDate && checkMaxWochenSoll) + { + + var rest = ed.AbsenceTimeDays.RestStundenProWocheDict[week]; + if (rest < abwesenheitsDauer) + { + abwesenheitsDauer = rest; + } + rest -= abwesenheitsDauer; + if (rest < 0) + { + rest = 0; + } + + ed.AbsenceTimeDays.RestStundenProWocheDict[week] = rest; + } + } + } + + + if (!AbsenceTimeAufIstStundenAddieren(absenceTime) && IsUrlaubAbsenceTime(absenceTime)) + { // Vermutlich diese Methode in CustomMitarbeiterStundenKontoBerechnung überschreiben und hier Prüfung machen, ob absenceReason ohne Fortzahlung ist + //und wenn ja, HoursSick oder Soll oder so für den Tag auf 0 setzen + + dd.HoursInVacation = abwesenheitsDauer; + var tspan = TimeSpan.FromHours((double)abwesenheitsDauer); + dd.TimeInVacation = String.Format("{0:00}:{1:00}", tspan.Hours, tspan.Minutes); + } + else if (!AbsenceTimeAufIstStundenAddieren(absenceTime) && IsKrankheitAbsenceTime(absenceTime)) + { + dd.HoursSick = abwesenheitsDauer; + var tspan = TimeSpan.FromHours((double)abwesenheitsDauer); + dd.TimeSick = String.Format("{0:00}:{1:00}", tspan.Hours, tspan.Minutes); + } + else + { + if (!AbsenceTimeAufIstStundenAddieren(absenceTime)) + { + dd.HoursOtherAbsenceTimes = abwesenheitsDauer; + var tspan = TimeSpan.FromHours((double)abwesenheitsDauer); + dd.TimeOtherAbsenceTimes = String.Format("{0:00}:{1:00}", tspan.Hours, tspan.Minutes); + } + if (istGanztaegig) + { + //Bei ganztägigen Abwesenheiten darf nicht noch zusätzlich gearbeitet werden + dd.MinutesTotal = 0; + dd.TimeTotal = "00:00"; + } + dd.MinutesTotal += abwesenheitsDauer * 60; + TimeSpan tspan2 = TimeSpan.FromMinutes((double)dd.MinutesTotal); + dd.TimeTotal = String.Format("{0:00}:{1:00}", tspan2.Hours, tspan2.Minutes); + } + + if (dd.AbsenceTimes == null) + { + dd.AbsenceTimes = new List(); + } + dd.AbsenceTimes.Add(absenceTime); + //dd.MinutesTotal += sollDiesenTag * 60; + } + } + + } + } + #endregion + } + + // Nur bis 2018 + private decimal BerechneStundenDurchAbwesenheitenAlt(AbsenceTimeDays ath, DateTime start, DateTime ende, Contract c, MitarbeiterstundenkontoRO.EmployeeDetail ed) + { + + decimal? sollProMonat = BerechneSollProMonat(ed.Employee, start, ende); + + if (sollProMonat.HasValue) + { + decimal stundenProTag = sollProMonat.Value / ed.ArbeitstageImBerichtszeitraum; + return (ath.TageGesamt.Value * stundenProTag); + } + else + { + decimal sollProWoche = BerechneSollProWoche(c, ed); + decimal stunden = 0; + + if (ath.TageGesamt.HasValue) + { + if (ed.ArbeitstageProWoche == 5) + { + stunden = ath.TageGesamt.Value * (sollProWoche / ed.ArbeitstageProWoche); + } + else if (ath.TageProWocheDict != null && ed.ArbeitstageProWoche > 0) + { + foreach (var week in ath.TageProWocheDict.Keys) + { + var tage = ath.TageProWocheDict[week]; + + if (tage > 0) + { + if (tage > ed.ArbeitstageProWoche) + { + tage = ed.ArbeitstageProWoche; + + } + stunden += tage * (sollProWoche / ed.ArbeitstageProWoche); + } + } + } + } + + return stunden; + } + } + } }