Files
BeWoPlaner/ReportImp/LebenshilfeStadeMID/CustomMitarbeiterstundenkontoBerechnung.cs
2026-07-24 12:10:57 +02:00

669 lines
23 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 System;
using System.Collections.Generic;
using System.Linq;
using BeWo.Data.Entities;
using BeWo.Report.ReportObjects;
using BS.Shared.Core;
using BeWo.Service.Dienstplanung;
namespace LebenshilfeStadeMID
{
public class CustomMitarbeiterstundenkontoBerechnung : MitarbeiterstundenkontoBerechnung
{
private const int ANZ_WOCHENTAGE = 5;
private Dictionary<string, decimal> _SollStundenProTagDict = new Dictionary<string, decimal>(); //Speicher die Sollstunden aus den Betreuungszeiten des Kindes pro EmployeeOid und Tag (Key = {employee oid}_{datum])
private DateTime _BerichtsAnfang = DateTime.MinValue;
// Claude: Sonderfall Timo Lafram Cache CustomerOid -> ist dieser Klient (vermeidet wiederholtes Nachladen des Customers)
private readonly Dictionary<long, bool> _IstTimoLaframCache = new Dictionary<long, bool>();
protected override void StarteBerechnung(DateTime berichtsAnfang, DateTime berichtsEnde, MitarbeiterstundenkontoRO.EmployeeDetail empDetail)
{
BerechneAlleSollZeiten(empDetail, berichtsAnfang, berichtsEnde);
}
private void BerechneAlleSollZeiten(MitarbeiterstundenkontoRO.EmployeeDetail empDetail, DateTime berichtsAnfang, DateTime berichtsEnde)
{
//Abesenheit "MA krank in der Schulzeit":
//Wenn ein Kind zugeordnet ist, dann wird die Zeit von dem entsprechenden Tag aus der Betreuungszeit genommen und bei Krank eingetragen
//Wenn ein die Ma der Martinschule zugeordnet sind, dann wird die Zeit genommen, die in der Organisation Martinschule hinterlegt ist und bei Krank eingetragen
//Wenn kein Kind zugeordnet ist, dann Vertragliche Arbeitszeit, und bei Krank eingetragen
//Prüfe Team Martinsschule
DateTime ersterVertragsStart = berichtsAnfang;
DateTime letzerVertragsEnde = berichtsEnde;
foreach (var c in empDetail.Employee.Contracts)
{
if (c.EntryDate.HasValue && c.EntryDate.Value < ersterVertragsStart)
{
ersterVertragsStart = c.EntryDate.Value;
}
}
DateTime vertragsStart = ersterVertragsStart;
DateTime vertragsEnde = letzerVertragsEnde;
var contract = empDetail.Employee.GetValidContractForDate(vertragsStart);
while (contract != null)
{
vertragsEnde = berichtsEnde;
if (contract.ContractEndDate.HasValue && contract.ContractEndDate < vertragsEnde)
{
vertragsEnde = contract.ContractEndDate.Value;
}
foreach (var e2c in empDetail.Employee.Employee2CustomerList)
{
if (e2c.Customer.IsActive != BS.Shared.ActivationTypeId.Active)
continue;
var start = vertragsStart;
var ende = vertragsEnde;
if (e2c.StartDate.HasValue && e2c.StartDate > start)
{
start = e2c.StartDate.Value;
}
if (e2c.EndDate.HasValue && e2c.EndDate < ende)
{
ende = e2c.EndDate.Value;
}
if (start <= ende)
{
var kind = e2c.Customer;
BerechneSollZeitenDictionary(kind.Arbeitszeiten, empDetail, start, ende, false);
}
}
//Füge Soll für Kinder, die bei den Mitarbeiterarbeitszeiten eingetragen wurden hinzu:
BerechneSollZeitenDictionary(empDetail.Employee.Arbeitszeiten, empDetail, vertragsStart, vertragsEnde, true);
var ctemp = GetNextValidContractForDate(vertragsEnde.AddDays(1), empDetail.Employee);
if (ctemp != null && ctemp.Oid != contract.Oid)
{
contract = ctemp;
}
else
{
contract = null;
}
if (contract != null && contract.EntryDate.HasValue && contract.EntryDate >= vertragsStart)
{
vertragsStart = contract.EntryDate.Value;
}
}
}
private void BerechneSollZeitenDictionary(IList<Arbeitszeit> arbeitszeiten, MitarbeiterstundenkontoRO.EmployeeDetail empDetail, DateTime start, DateTime ende, bool arbeitszeitenSindVomMitarbeiter)
{
DateTime dt = start;
while (dt <= ende)
{
if (dt.Date == new DateTime(2025, 08, 25))
{
}
String key = String.Format("{0}_{1:yyyyMMdd}", empDetail.Employee.Oid, dt);
if (!_SollStundenProTagDict.ContainsKey(key))
{
decimal soll = 0;
bool gibtAz = false;
foreach (var az in arbeitszeiten)
{
if ((!az.GueltigVon.HasValue || az.GueltigVon.Value <= dt) && (!az.GueltigBis.HasValue || az.GueltigBis.Value >= dt))
{
if (!arbeitszeitenSindVomMitarbeiter)
{
gibtAz = true;
}
foreach (var ae in az.ArbeitszeitEintraege)
{
if (arbeitszeitenSindVomMitarbeiter)
{
//Wenn das Flag arbeitszeitenSindVomMitarbeiter gesetzt ist, werden nur Einträge geprüft, bei dem auch ein Klient zugeordnet ist
if (ae.Customer != null)
{
if (ae.IstAmGleichenWochentag(dt))
{
gibtAz = true;
soll += ae.BerechneStunden();
}
}
}
else
{
if (ae.Employee == null || ae.Employee.Oid == empDetail.Employee.Oid)
{
if (ae.IstAmGleichenWochentag(dt))
{
soll += ae.BerechneStunden();
}
}
}
}
}
}
if (gibtAz)
{
_SollStundenProTagDict[key] = soll;
}
}
dt = dt.AddDays(1);
}
}
public override IList<MitarbeiterstundenkontoRO.DayDetail> CreateDayDetails(DateTime berichtStart, DateTime berichtEnde, MitarbeiterstundenkontoRO.EmployeeDetail ed, IList<StundenkontoServiceRecord> recordsAll)
{
var list = base.CreateDayDetails(berichtStart, berichtEnde, ed, recordsAll);
foreach (var dd in list)
{
var absenceTimes = ed.Employee.AbsenceTimes;
if (dd.AbsenceTimes == null && absenceTimes != null)
{
foreach (var absenceTime in absenceTimes)
{
if (absenceTime.Start < dd.Date.AddDays(1) && (!absenceTime.End.HasValue || absenceTime.End >= dd.Date))
{
if (dd.AbsenceTimes == null)
{
dd.AbsenceTimes = new List<AbsenceTime>();
}
dd.AbsenceTimes.Add(absenceTime);
}
}
}
bool feiertagAnrechnen = false;
if (dd.AbsenceTimes != null)
{
foreach (var at in dd.AbsenceTimes)
{
if (IstAnrechenbareAbsenceTime(at))
{
var sollProTag = BerechneSollAmTag(ed, dd.Date);
var key = String.Format("{0}_{1:yyyyMMdd}", ed.Employee.Oid, dd.Date);
// Wenn es kein Urlaub ist, wird das Soll aus den Betreuungsszeiten der Klient*innen berechnet
if (!IsUrlaubAbsenceTime(at) && _SollStundenProTagDict.ContainsKey(key))
{
sollProTag = _SollStundenProTagDict[key];
}
else if (IsUrlaubAbsenceTime(at)/* && sollProTag > dd.HoursInVacation*/)
continue;
var faktor = GetFeiertagsFaktor(dd.Date);
if (faktor < 1)
{
if (IsKrankheitAbsenceTime(at))
{
dd.HoursSick = sollProTag;
}
else if (IsUrlaubAbsenceTime(at))
{
dd.HoursInVacation = sollProTag;
if (faktor > 0)
{
dd.HoursInVacation *= faktor;
}
}
else
{
dd.MinutesTotal = sollProTag * 60;
}
}
}
}
}
if (dd.IstFeiertag)
{
if (feiertagAnrechnen && HatVertrag(ed, dd.Date))
{
var key = String.Format("{0}_{1:yyyyMMdd}", ed.Employee.Oid, dd.Date);
if (_SollStundenProTagDict.ContainsKey(key))
{
var soll = _SollStundenProTagDict[key];
soll *= GetFeiertagsFaktor(dd.Date);
if (dd.MinutesTotal <= soll)
{
dd.MinutesTotal = soll;
}
}
}
else
{
dd.MinutesTotal = 0;
}
}
}
return list;
}
private bool HatVertrag(MitarbeiterstundenkontoRO.EmployeeDetail ed, DateTime date)
{
return ed.Employee.GetValidContractForDate(date) != null;
}
public override bool ShouldCreateDayDetails()
{
return true;
}
public override MitarbeiterstundenkontoRO.DayDetail CreateDayDetail(DateTime date, MitarbeiterstundenkontoRO.EmployeeDetail ed)
{
var dd = base.CreateDayDetail(date, ed);
if (date >= new DateTime(2026, 08, 13))
{
dd.MaxHoursUntilBreak = 6;
dd.MaxHoursUntilBreak2 = 9;
dd.BreakMinutes = 30;
dd.BreakMinutes2 = 15;
}
return dd;
}
// Claude: Sonderfall Klient "Timo Lafram" für zusammenhängende Arbeitsblöcke, die (auch) Zeit für diesen
// Klienten enthalten, wird KEINE automatische Pause abgezogen. Alle übrigen Tage/Blöcke bleiben unverändert
// (Standardverhalten wie bisher = SONST IMMER Pause).
public override decimal CalculateBreakMinutesNeu(MitarbeiterstundenkontoRO.DayDetail dayDetail)
{
// Kein Timo-Lafram-Eintrag an diesem Tag -> unverändertes Standardverhalten
if (dayDetail.ServiceRecords == null || !dayDetail.ServiceRecords.Any(IstTimoLaframRecord))
{
return base.CalculateBreakMinutesNeu(dayDetail);
}
decimal addHours = 0;
if (dayDetail.ZusammenhaengendeZeitraeume != null && dayDetail.ZusammenhaengendeZeitraeume.Count > 0)
{
foreach (var span in dayDetail.ZusammenhaengendeZeitraeume)
{
// Blöcke mit Timo-Lafram-Zeit: keine automatische Pause abziehen
if (SpanEnthaeltTimoLaframZeit(dayDetail, span.StartDateTime, span.EndDateTime))
continue;
addHours -= BerechneGesetzlichePauseInMinuten(dayDetail, span.StartDateTime, span.EndDateTime) / 60;
}
return addHours;
}
// Fallback (keine ZusammenhaengendeZeitraeume) analog zum Standard, Timo-Lafram-Blöcke überspringen
if (dayDetail.EndDateTime1.HasValue && dayDetail.StartDateTime1.HasValue
&& !SpanEnthaeltTimoLaframZeit(dayDetail, dayDetail.StartDateTime1.Value, dayDetail.EndDateTime1.Value))
{
addHours -= BerechneGesetzlichePauseInMinuten(dayDetail, dayDetail.StartDateTime1.Value, dayDetail.EndDateTime1.Value) / 60;
}
if (dayDetail.EndDateTime2.HasValue && dayDetail.StartDateTime2.HasValue
&& !SpanEnthaeltTimoLaframZeit(dayDetail, dayDetail.StartDateTime2.Value, dayDetail.EndDateTime2.Value))
{
addHours -= BerechneGesetzlichePauseInMinuten(dayDetail, dayDetail.StartDateTime2.Value, dayDetail.EndDateTime2.Value) / 60;
}
if (dayDetail.EndDateTime3.HasValue && dayDetail.StartDateTime3.HasValue
&& !SpanEnthaeltTimoLaframZeit(dayDetail, dayDetail.StartDateTime3.Value, dayDetail.EndDateTime3.Value))
{
addHours -= BerechneGesetzlichePauseInMinuten(dayDetail, dayDetail.StartDateTime3.Value, dayDetail.EndDateTime3.Value) / 60;
}
if (dayDetail.EndDateTime4.HasValue && dayDetail.StartDateTime4.HasValue
&& !SpanEnthaeltTimoLaframZeit(dayDetail, dayDetail.StartDateTime4.Value, dayDetail.EndDateTime4.Value))
{
addHours -= BerechneGesetzlichePauseInMinuten(dayDetail, dayDetail.StartDateTime4.Value, dayDetail.EndDateTime4.Value) / 60;
}
return addHours;
}
// Claude: Prüft, ob im angegebenen Zeitraum (zusammenhängender Arbeitsblock) ein ServiceRecord für den
// Klienten "Timo Lafram" liegt. Die Blöcke werden aus den Startzeiten der Records gebildet, daher genügt
// die Prüfung, ob der Start eines Timo-Records innerhalb des Blocks liegt.
private bool SpanEnthaeltTimoLaframZeit(MitarbeiterstundenkontoRO.DayDetail dayDetail, DateTime spanStart, DateTime spanEnde)
{
if (dayDetail.ServiceRecords == null)
return false;
foreach (var sr in dayDetail.ServiceRecords)
{
if (!IstTimoLaframRecord(sr))
continue;
if (sr.Start >= spanStart && sr.Start < spanEnde)
return true;
}
return false;
}
// Claude: Erkennt den Klienten "Timo Lafram" über den Namen (Vorname + Nachname, Groß/Klein und
// Leerzeichen unkritisch). Ergebnis wird je CustomerOid gecacht.
private bool IstTimoLaframRecord(StundenkontoServiceRecord sr)
{
if (sr == null || !sr.CustomerOid.HasValue)
return false;
long oid = sr.CustomerOid.Value;
bool istTimo;
if (_IstTimoLaframCache.TryGetValue(oid, out istTimo))
return istTimo;
istTimo = false;
var customer = sr.Customer;
if (customer != null && customer.Person != null)
{
var vorname = (customer.Person.FirstName ?? "").Trim();
var nachname = (customer.Person.LastName ?? "").Trim();
istTimo = vorname.Equals("Timo", StringComparison.OrdinalIgnoreCase)
&& nachname.Equals("Lafram", StringComparison.OrdinalIgnoreCase);
}
_IstTimoLaframCache[oid] = istTimo;
return istTimo;
}
public override decimal? GetSollStundenForAbsenceTime(MitarbeiterstundenkontoRO.EmployeeDetail ed, AbsenceTime at, DateTime datum)
{
var key = String.Format("{0}_{1:yyyyMMdd}", ed.Employee.Oid, datum);
if (!IsUrlaubAbsenceTime(at) && _SollStundenProTagDict.ContainsKey(key))
{
return _SollStundenProTagDict[key];
}
return base.GetSollStundenForAbsenceTime(ed, at, datum);
}
// 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)
{
decimal stunden = 0;
if (ath.StundenGesamt.HasValue)
stunden = ath.StundenGesamt.Value;
//var schleifenstart = new DateTime(start.Year, start.Month, start.Day);
//while (schleifenstart <= ende)
//{
// var key = String.Format("{0}_{1:yyyyMMdd}", ed.Employee.Oid, schleifenstart.Date);
// if (_SollStundenProTagDict.ContainsKey(key))
// {
// stunden += _SollStundenProTagDict[key];
// }
// schleifenstart = schleifenstart.AddDays(1);
//}
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<DateTimeSpan, decimal>();
}
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<AbsenceTime>();
}
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;
}
}
}
}