669 lines
23 KiB
C#
669 lines
23 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|
||
}
|