Files
BeWoPlaner/Report/ReportObjects/MitarbeiterstundenkontoBerechnung.cs
2021-02-02 23:23:05 +01:00

2654 lines
92 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using BeWo.Report;
using BeWo.Data.Entities;
using BeWo.Data.Access;
using BeWo.Service.Configuration;
using BeWo.Service.ServiceImplementations;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.Extensions;
using DevExpress.XtraCharts.Native;
namespace BeWo.Report.ReportObjects
{
public class MitarbeiterstundenkontoBerechnung
{
private decimal maxWochenstunden = 40;
private AppSettings appSettings;
private const int ANZ_WOCHENTAGE = 5;
public MitarbeiterstundenkontoBerechnung()
{
appSettings = AppSettings.CreateSettings();
CheckIst = true;
}
public MitarbeiterstundenkontoBerechnung(decimal maxWochenstunden) : this()
{
this.maxWochenstunden = maxWochenstunden;
}
public bool CheckIst { get; set; }
public virtual void CreateReport(MitarbeiterstundenkontoRO ro)
{
CreateEmployeeDetails(ro);
CreateTeamDetails(ro);
CreateTotals(ro);
}
public virtual void CreateTotals(MitarbeiterstundenkontoRO ro)
{
foreach (var empDetail in ro.EmployeeDetailList)
{
ro.SollGesamt += empDetail.StundenSollOhneUrlaubKrankheit;
ro.FlsSollGesamt += empDetail.FlsSoll;
ro.FlsIstGesamt += empDetail.FlsIst;
ro.MittelbarIst += empDetail.MittelbarIst;
ro.FlsDiffGesamt += empDetail.FlsDiff;
ro.StundenGesamt += empDetail.StundenGesamtIst;
}
if (ro.FlsSollGesamt != 0)
ro.RelationIstSollGesamt = (ro.FlsIstGesamt / ro.FlsSollGesamt) * 100m;
if (ro.FlsIstGesamt + ro.MittelbarIst != 0)
ro.RelationFlsZuMittelbar = (ro.FlsIstGesamt / (ro.FlsIstGesamt + ro.MittelbarIst)) * 100;
}
public virtual void CreateTeamDetails(MitarbeiterstundenkontoRO ro)
{
foreach (var teamDetail in ro.TeamDetailList)
{
teamDetail.EmployeeDetailList = FilterEmployeeList(teamDetail.EmployeeDetailList);
foreach (var empDetail in teamDetail.EmployeeDetailList)
{
teamDetail.SollGesamt += empDetail.StundenSollOhneUrlaubKrankheit;
teamDetail.FlsSollGesamt += empDetail.FlsSoll;
teamDetail.FlsIstGesamt += empDetail.FlsIst;
teamDetail.MittelbarIst += empDetail.MittelbarIst;
teamDetail.FlsDiffGesamt += empDetail.FlsDiff;
teamDetail.StundenGesamt += empDetail.StundenGesamtIst;
}
if (teamDetail.FlsSollGesamt != 0)
teamDetail.RelationIstSollGesamt = (teamDetail.FlsIstGesamt / teamDetail.FlsSollGesamt) * 100m;
if (teamDetail.FlsIstGesamt + teamDetail.MittelbarIst != 0)
teamDetail.RelationFlsZuMittelbar = (teamDetail.FlsIstGesamt / (teamDetail.FlsIstGesamt + teamDetail.MittelbarIst)) * 100;
}
}
public virtual void CreateEmployeeDetails(MitarbeiterstundenkontoRO ro)
{
foreach (var empDetail in ro.EmployeeDetailList)
{
DateTime monatsAnfang = ro.ReportStartDate;
DateTime monatsEnde = monatsAnfang.AddMonths(1);
DateTime berichtsAnfang = monatsAnfang;
DateTime berichtsEnde = monatsEnde;
Employee emp = empDetail.Employee;
decimal bu = 0;
var c = GetContractForDate(emp, ro.ReportStartDate, ro.ReportEndDate);
if (c != null)
{
if (c.EntryDate.HasValue && c.EntryDate > monatsAnfang)
{
berichtsAnfang = c.EntryDate.Value;
}
if (c.ContractEndDate.HasValue && c.ContractEndDate < monatsEnde)
{
berichtsEnde = c.ContractEndDate.Value.Date.AddDays(1);
}
empDetail.HasContract = true;
}
ServiceRecordSummary summaryTotal = new ServiceRecordSummary();
summaryTotal.RecordsImBerichtszeitraum = new List<ServiceRecord>();
decimal pause1 = 0;
decimal pause2 = 0;
decimal weeklyTotalHours = 0;
decimal flsSollGesamt = 0;
decimal? fehlZeitenGesamt = null;
decimal? tageUrlaubGesamt = null;
decimal? tageKrankheitGesamt = null;
decimal? abwesenheitTageGesamt = null;
decimal workdaysTotal = 0;
decimal stundenSollGesamt = 0;
decimal tatSollStdGesamt = 0;
IList<ServiceRecord> recordsAll = DAOFactory.SearchDAO.FindServiceRecords(emp.Oid, null);
recordsAll = AnalysisServiceImp.FilterActiveServiceRecords(recordsAll);
//
IList<ServiceRecord> groupFilteredRecords = new List<ServiceRecord>();
Dictionary<long, bool> groupBookingDict = new Dictionary<long, bool>();
foreach (var item in recordsAll)
{
if (!item.GroupOid.HasValue || !groupBookingDict.ContainsKey(item.GroupOid.Value))
{
groupFilteredRecords.Add(item);
if (item.GroupOid.HasValue)
{
groupBookingDict.Add(item.GroupOid.Value, true);
}
}
}
while (berichtsAnfang < berichtsEnde)
{
empDetail.ArbeitstageImBerichtszeitraum = GetArbeitstageImBereich(berichtsAnfang, berichtsEnde, emp);
empDetail.ArbeitstageProWoche = ANZ_WOCHENTAGE;
workdaysTotal += empDetail.ArbeitstageImBerichtszeitraum;
weeklyTotalHours = 0;
if (c != null)
{
if (c.WeeklyTotalHours.HasValue)
{
weeklyTotalHours = c.WeeklyTotalHours.Value;
bu = c.WeeklyTotalHours.Value/this.maxWochenstunden;
}
if (c.WeeklyDays.HasValue && c.WeeklyDays.Value > 0)
{
empDetail.ArbeitstageProWoche = c.WeeklyDays.Value;
}
empDetail.WeeklyFLS = c.WeeklyFLS;
empDetail.HourlyRate = c.HourlyRate;
empDetail.EmploymentType = c.EmploymentType;
}
empDetail.SollProTag = (weeklyTotalHours / empDetail.ArbeitstageProWoche);
empDetail.SollProWoche = BerechneSollProWoche(c, empDetail);
HandleServiceRecords(empDetail, groupFilteredRecords, c);
if (CheckIst)
{
var summary = BerechneStunden(empDetail, groupFilteredRecords, berichtsAnfang, berichtsEnde);
summaryTotal.IstAbrechenbar += summary.IstAbrechenbar;
summaryTotal.IstNichtAbrechenbar += summary.IstNichtAbrechenbar;
summaryTotal.RecordsImBerichtszeitraum.AddRange(summary.RecordsImBerichtszeitraum);
if (SollPauseBerechnen())
{
pause1 += BerechnePauseMinuten(summary.RecordsImBerichtszeitraum);
pause2 += BerechneAutoPausen(summary.RecordsImBerichtszeitraum);
}
}
decimal? stundenSollProMonat = null;
decimal? stundenSollImVertragsUndBerichtzeitraum = null;
if (empDetail.HasContract)
{
stundenSollImVertragsUndBerichtzeitraum = GetSollNachArbeitszeiten(empDetail.Employee, berichtsAnfang, berichtsEnde);
}
if (!stundenSollImVertragsUndBerichtzeitraum.HasValue)
{
stundenSollProMonat = BerechneSollProMonat(emp, berichtsAnfang, berichtsEnde);
stundenSollImVertragsUndBerichtzeitraum = stundenSollProMonat;
}
if (!stundenSollImVertragsUndBerichtzeitraum.HasValue)
{
if (!stundenSollImVertragsUndBerichtzeitraum.HasValue)
{
if (empDetail.ArbeitstageProWoche <= 5)
{
stundenSollImVertragsUndBerichtzeitraum =
empDetail.ArbeitstageImBerichtszeitraum * (weeklyTotalHours / 5);
}
else
{
stundenSollImVertragsUndBerichtzeitraum =
empDetail.ArbeitstageImBerichtszeitraum * (weeklyTotalHours / empDetail.ArbeitstageProWoche);
}
}
}
stundenSollGesamt += stundenSollImVertragsUndBerichtzeitraum ?? 0;
empDetail.StundenSollMax = stundenSollGesamt;
var tatSollStdImVertragsUndBerichtzeitraum = stundenSollImVertragsUndBerichtzeitraum ?? 0;
decimal? fehlZeiten = GetFehlzeiten(groupFilteredRecords, berichtsAnfang, berichtsEnde);
if (fehlZeiten.HasValue)
{
if (!fehlZeitenGesamt.HasValue)
fehlZeitenGesamt = 0;
fehlZeitenGesamt += fehlZeiten;
tatSollStdImVertragsUndBerichtzeitraum -= fehlZeiten.Value;
}
var ath = GetAbsenceTimeDaysWithWorkWeeks(emp, berichtsAnfang, berichtsEnde, empDetail.ArbeitstageProWoche);
empDetail.AbsenceTimeDays = ath;
if (ath.TageUrlaub.HasValue)
{
if (!tageUrlaubGesamt.HasValue)
tageUrlaubGesamt = 0;
tageUrlaubGesamt += ath.TageUrlaub;
}
if (ath.TageKrankheit.HasValue)
{
if (!tageKrankheitGesamt.HasValue)
tageKrankheitGesamt = 0;
tageKrankheitGesamt += ath.TageKrankheit;
}
if (ath.TageGesamt.HasValue)
{
if (!abwesenheitTageGesamt.HasValue)
abwesenheitTageGesamt = 0;
abwesenheitTageGesamt += ath.TageGesamt;
var minusStunden = BerechneStundenDurchAbwesenheiten(ath, berichtsAnfang, berichtsEnde, c, empDetail);
tatSollStdImVertragsUndBerichtzeitraum -= minusStunden;
if (tatSollStdImVertragsUndBerichtzeitraum < 0 && !StundenDurchAbwesenheitenDuerfenNegativSein())
{
tatSollStdImVertragsUndBerichtzeitraum = 0;
}
}
var ath2 = GetAbwesenheitenDurchServiceRecords(empDetail, c, groupFilteredRecords, berichtsAnfang, berichtsEnde);
if (ath2 != null)
{
var stunden = ath2.StundenKrankheit + ath2.StundenUrlaub + ath2.StundenSonstiges;
tatSollStdImVertragsUndBerichtzeitraum -= stunden;
if (tatSollStdImVertragsUndBerichtzeitraum < 0 && !StundenDurchAbwesenheitenDuerfenNegativSein())
{
tatSollStdImVertragsUndBerichtzeitraum = 0;
}
if (empDetail.SollProTag > 0)
{
if (!abwesenheitTageGesamt.HasValue)
abwesenheitTageGesamt = 0;
abwesenheitTageGesamt += stunden / empDetail.SollProTag;
if (ath2.StundenKrankheit > 0)
{
if (!tageKrankheitGesamt.HasValue)
{
tageKrankheitGesamt = 0;
}
tageKrankheitGesamt += ath2.StundenKrankheit / empDetail.SollProTag;
}
if (ath2.StundenUrlaub > 0)
{
if (!tageUrlaubGesamt.HasValue)
{
tageUrlaubGesamt = 0;
}
tageUrlaubGesamt += ath2.StundenUrlaub / empDetail.SollProTag;
}
}
}
tatSollStdGesamt += tatSollStdImVertragsUndBerichtzeitraum;
flsSollGesamt += BerechneFlsSoll(emp, c, berichtsAnfang, berichtsEnde, tatSollStdImVertragsUndBerichtzeitraum, stundenSollProMonat);
berichtsAnfang = berichtsEnde;
berichtsEnde = monatsEnde;
c = GetNextValidContractForDate(berichtsAnfang, emp);
if (c != null)
{
if (c.EntryDate.HasValue && c.EntryDate >= berichtsAnfang)
berichtsAnfang = c.EntryDate.Value;
if (c.ContractEndDate.HasValue && c.ContractEndDate < monatsEnde)
{
berichtsEnde = c.ContractEndDate.Value.Date.AddDays(1);
}
}
}
if (AddRateFactorToIst() != 1)
{
summaryTotal.IstAbrechenbar *= AddRateFactorToIst();
}
summaryTotal.IstAbrechenbar /= 60m;
summaryTotal.IstNichtAbrechenbar /= 60m;
empDetail.WorkDaysThisMonth = workdaysTotal;
//decimal stundenSollMax = arbeitstage * (maxWochenstunden / xxx) * bu;
empDetail.Fehlzeiten = fehlZeitenGesamt;
empDetail.TageUrlaub = tageUrlaubGesamt;
empDetail.TageKrankheit = tageKrankheitGesamt;
empDetail.UrlaubUndKrankheit = abwesenheitTageGesamt;
empDetail.StundenSollOhneUrlaubKrankheit = tatSollStdGesamt;
empDetail.FlsSoll = flsSollGesamt;
empDetail.MittelbarIst = summaryTotal.IstNichtAbrechenbar;
empDetail.Bu = bu;
empDetail.FlsIst = summaryTotal.IstAbrechenbar;
empDetail.FlsDiff = summaryTotal.IstAbrechenbar - empDetail.FlsSoll;
empDetail.StundenMittelbarIst = summaryTotal.IstNichtAbrechenbar;
empDetail.StundenGesamtIst = summaryTotal.IstAbrechenbar + summaryTotal.IstNichtAbrechenbar;
empDetail.StundenGesamtIst -= pause1/60;
empDetail.StundenGesamtIst -= pause2/60;
if (empDetail.FlsSoll != 0)
empDetail.RelationIstSoll = (empDetail.FlsIst/empDetail.FlsSoll)*100m;
if (summaryTotal.IstAbrechenbar + summaryTotal.IstNichtAbrechenbar != 0)
empDetail.RelationFlsZuMittelbar = (summaryTotal.IstAbrechenbar / (summaryTotal.IstAbrechenbar + summaryTotal.IstNichtAbrechenbar))*100;
decimal? ueberstunden = empDetail.StundenGesamtIst - empDetail.StundenSollOhneUrlaubKrankheit;
decimal? ueberstundenVormonat;
decimal alteExtraUeberstunden = 0;
BerechneUeberstundenBis(empDetail, groupFilteredRecords, ro.ReportStartDate, out ueberstundenVormonat,
out alteExtraUeberstunden);
decimal extraStunden = 0;
BerechneExtraUeberstunden(emp, monatsAnfang, monatsEnde, out extraStunden);
if (ShouldCreateDayDetails())
{
empDetail.Days = CreateDayDetails(monatsAnfang, monatsEnde, empDetail, summaryTotal.RecordsImBerichtszeitraum);
var ah = GetAdditionalHours(empDetail.Days, monatsAnfang, monatsEnde, empDetail, summaryTotal.RecordsImBerichtszeitraum);
ueberstunden += ah;
empDetail.StundenGesamtIst += ah;
}
empDetail.Ueberstunden = ueberstunden;
empDetail.UeberstundenVormonat = ueberstundenVormonat;
if (!empDetail.UeberstundenGesamt.HasValue)
empDetail.UeberstundenGesamt = ((ueberstundenVormonat ?? 0) + (ueberstunden ?? 0)) + extraStunden;
else
empDetail.UeberstundenGesamt += ((ueberstundenVormonat ?? 0) + (ueberstunden ?? 0)) + extraStunden;
empDetail.UeberstundenAusbezahlt = extraStunden;
//Urlaubskonto (todo)
empDetail.UrlaubGesamtImAktuellenJahr =
GetAbsenceTimeDaysWithWorkWeeks(emp, new DateTime(monatsAnfang.Year, 1, 1), monatsEnde, empDetail.ArbeitstageProWoche).TageUrlaub;
CalculateEmployeeSalary(empDetail, berichtsAnfang, berichtsEnde);
}
ro.EmployeeDetailList = FilterEmployeeList(ro.EmployeeDetailList);
}
protected virtual AbsenceTimeHours GetAbwesenheitenDurchServiceRecords(MitarbeiterstundenkontoRO.EmployeeDetail empDetail, Contract c, IList<ServiceRecord> groupFilteredRecords, DateTime berichtsAnfang, DateTime berichtsEnde)
{
return null;
}
protected virtual decimal BerechneFlsSoll(Employee emp, Contract contract, DateTime berichtsAnfang, DateTime berichtsEnde, decimal tatSollStdImVertragsUndBerichtzeitraum, decimal? stundenSollProMonat)
{
var festeflsSollProMonat = BerechneFlsSollProMonat(emp, berichtsAnfang, berichtsEnde);
decimal flsSollImVertragsUndBerichtzeitraum = 0;
if (festeflsSollProMonat.HasValue)
{
flsSollImVertragsUndBerichtzeitraum = tatSollStdImVertragsUndBerichtzeitraum;
if (stundenSollProMonat.HasValue)
{
flsSollImVertragsUndBerichtzeitraum *= (festeflsSollProMonat.Value / stundenSollProMonat.Value);
}
}
else
{
if (contract != null && contract.WeeklyFLS.HasValue)
{
flsSollImVertragsUndBerichtzeitraum = tatSollStdImVertragsUndBerichtzeitraum;
if (HatArbeitszeitImZeitraum(emp.Arbeitszeiten, berichtsAnfang, berichtsEnde))
{
var wochenArbeitszeit = GetWochenArbeitszeit(emp.Arbeitszeiten, berichtsAnfang, berichtsEnde);
if (wochenArbeitszeit > 0)
{
flsSollImVertragsUndBerichtzeitraum *= contract.WeeklyFLS.Value / wochenArbeitszeit;
}
}
else if (contract.WeeklyTotalHours.HasValue && contract.WeeklyTotalHours.Value != 0)
{
flsSollImVertragsUndBerichtzeitraum *= contract.WeeklyFLS.Value / contract.WeeklyTotalHours.Value;
}
}
}
return flsSollImVertragsUndBerichtzeitraum;
}
private decimal GetWochenArbeitszeit(IList<Arbeitszeit> arbeitszeiten, DateTime start, DateTime ende)
{
if (arbeitszeiten != null)
{
foreach (var az in arbeitszeiten)
{
if ((!az.GueltigVon.HasValue || az.GueltigVon.Value < ende) &&
(!az.GueltigBis.HasValue || az.GueltigBis.Value >= start))
{
DateTime wochenStart = start;
while (wochenStart.DayOfWeek != DayOfWeek.Monday)
{
wochenStart = wochenStart.AddDays(1);
}
decimal stunden = 0;
for (int i = 0; i < 7; i++)
{
stunden += GetArbeitszeitStundenFuerTag(az, wochenStart);
wochenStart = wochenStart.AddDays(1);
}
return stunden;
}
}
}
return 0;
}
protected virtual bool StundenDurchAbwesenheitenDuerfenNegativSein()
{
return false;
}
protected virtual decimal? GetSollNachArbeitszeiten(Employee emp, DateTime start, DateTime ende)
{
if (emp.Arbeitszeiten != null && emp.Arbeitszeiten.Count > 0)
{
if (HatArbeitszeitImZeitraum(emp.Arbeitszeiten, start, ende))
{
decimal soll = 0;
DateTime startTemp = start;
while (startTemp < ende)
{
soll += GetSollNachArbeitszeitenFuerTag(emp, startTemp);
startTemp = startTemp.AddDays(1);
}
return soll;
}
}
return null;
}
private bool HatArbeitszeitImZeitraum(IList<Arbeitszeit> arbeitszeiten, DateTime start, DateTime ende)
{
if (arbeitszeiten != null)
{
foreach (var az in arbeitszeiten)
{
if ((!az.GueltigVon.HasValue || az.GueltigVon.Value < ende) && (!az.GueltigBis.HasValue || az.GueltigBis.Value >= start) && az.ArbeitszeitEintraege != null && az.ArbeitszeitEintraege.Count > 0)
{
return true;
}
}
}
return false;
}
protected virtual decimal GetSollNachArbeitszeitenFuerTag(Employee emp, DateTime tag)
{
decimal soll = 0;
var fak = GetFeiertagsFaktor(tag);
if (fak < 1)
{
if (emp.Arbeitszeiten != null)
{
foreach (var az in emp.Arbeitszeiten)
{
if ((!az.GueltigVon.HasValue || az.GueltigVon.Value <= tag) &&
(!az.GueltigBis.HasValue || az.GueltigBis.Value >= tag))
{
var std = GetArbeitszeitStundenFuerTag(az, tag);
soll += (std * (1 - fak));
}
}
}
}
return soll;
}
private decimal GetArbeitszeitStundenFuerTag(Arbeitszeit az, DateTime tag)
{
var day = tag.DayOfWeek;
decimal stunden = 0;
foreach (var ae in az.ArbeitszeitEintraege)
{
if (SindAmGleichenWochentag(day, ae.Tag))
{
String dateStr1 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitVon);
String dateStr2 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitBis);
DateTime date1;
DateTime date2;
if (DateTime.TryParse(dateStr1, out date1) && DateTime.TryParse(dateStr2, out date2))
{
stunden += (decimal)date2.Subtract(date1).TotalHours;
}
}
}
return stunden;
}
private bool SindAmGleichenWochentag(DayOfWeek day, AppointmentDayOfWeek aeTag)
{
if (day == DayOfWeek.Monday && aeTag == AppointmentDayOfWeek.Montag)
{
return true;
}
if (day == DayOfWeek.Tuesday && aeTag == AppointmentDayOfWeek.Dienstag)
{
return true;
}
if (day == DayOfWeek.Wednesday && aeTag == AppointmentDayOfWeek.Mittwoch)
{
return true;
}
if (day == DayOfWeek.Thursday && aeTag == AppointmentDayOfWeek.Donnerstag)
{
return true;
}
if (day == DayOfWeek.Friday && aeTag == AppointmentDayOfWeek.Freitag)
{
return true;
}
if (day == DayOfWeek.Saturday && aeTag == AppointmentDayOfWeek.Samstag)
{
return true;
}
return false;
}
protected virtual void CalculateEmployeeSalary(MitarbeiterstundenkontoRO.EmployeeDetail empDetail, DateTime start, DateTime ende)
{
decimal maxpayment = 0;
Contract cstart = empDetail.Employee.GetValidContractForDate(start);
Contract cend = empDetail.Employee.GetValidContractForDate(ende);
if (cstart != null && cstart.HourlyRate.HasValue && cstart.WeeklyTotalHours.HasValue && cend != null)
{
if (cstart.Oid.Value == cend.Oid.Value || !cend.EntryDate.HasValue)
{
maxpayment = cstart.HourlyRate.Value * cstart.WeeklyTotalHours.Value * 4;
}
else
{
decimal totalHoursPerDay = cstart.WeeklyTotalHours.Value / 7m;
DateTime end = cend.EntryDate.Value;
TimeSpan ts = end.Subtract(start);
int days = (int)ts.TotalDays;
maxpayment = totalHoursPerDay * cstart.HourlyRate.Value * days;
Contract c2 = empDetail.Employee.GetValidContractForDate(end.AddDays(1));
if (c2 != null && c2.HourlyRate.HasValue && c2.WeeklyTotalHours.HasValue)
{
decimal totalHoursPerDay2 = c2.WeeklyTotalHours.Value / 7m;
TimeSpan ts2 = ende.Subtract(end);
int days2 = (int)ts2.TotalDays + 1;
maxpayment += totalHoursPerDay2 * c2.HourlyRate.Value * days2;
}
}
}
empDetail.EmployeeSalaryByContract = maxpayment;
decimal salary = 0;
if (empDetail.ServiceRecordsInSelectedTimeSpan != null)
{
foreach (var sr in empDetail.ServiceRecordsInSelectedTimeSpan)
{
if (sr.ServiceDescription.Name != "Freizeit" || sr.ServiceDescription.ServiceCategory.Name != "Selbstzahler Freizeit")
{
Contract con = empDetail.Employee.GetValidContractForDate(sr.Start);
if (con != null && con.HourlyRate.HasValue)
{
salary += con.HourlyRate.Value * (sr.RoundedDuration / 60);
}
}
}
}
empDetail.EmployeeSalaryByHours = salary;
}
protected virtual ServiceRecordSummary BerechneStunden(MitarbeiterstundenkontoRO.EmployeeDetail empDetail, IList<ServiceRecord> groupFilteredRecords, DateTime berichtsAnfang, DateTime berichtsEnde)
{
var sum = new ServiceRecordSummary();
sum.RecordsImBerichtszeitraum = new List<ServiceRecord>();
empDetail.ServiceRecordsInSelectedTimeSpan = new List<ServiceRecord>();
foreach (var item in groupFilteredRecords)
{
if (!IsServiceRecordFehlzeit(item))
{
if (item.Start.Value >= berichtsAnfang && item.Start.Value < berichtsEnde)
{
//String test = String.Format("{0:dd.MM.yyyy HH:mm}, {1:0} Minuten, {2}, {3}", item.Start, item.RoundedDuration, item.ServiceDescription.Name, item.Notice);
HandleServiceRecord(empDetail, item);
if (AddServiceRecordToDuration(item))
{
empDetail.ServiceRecordsInSelectedTimeSpan.Add(item);
String test = String.Format("{0:dd.MM. HH:mm} - {1:HH:mm}, {2}", item.Start, item.End, item.RoundedDuration);
decimal duration = 0;
if (item.GroupRoundedDuration.HasValue)
{
duration = item.GroupRoundedDuration.Value;
}
else
{
if (appSettings.ShowRoundedDurationInEmployeeAnalysis)
{
duration = item.RoundedDuration;
}
else
{
duration = (decimal)item.End.Value.Subtract(item.Start.Value).TotalMinutes;
}
}
if (UseServiceDescriptionPercentage())
{
if (item.ServiceDescription != null &&
item.ServiceDescription.ServiceCategory != null &&
item.ServiceDescription.ServiceCategory.Percentage != 100)
{
duration = (duration * item.ServiceDescription.ServiceCategory.Percentage) / 100;
}
}
if (item.ServiceDescription != null &&
item.ServiceDescription.ServiceCategory != null &&
item.ServiceDescription.ServiceCategory.IsBillable)
sum.IstAbrechenbar += duration;
else
sum.IstNichtAbrechenbar += duration;
if (duration > 0)
{
int test2 = 0;
}
}
sum.RecordsImBerichtszeitraum.Add(item);
}
}
}
return sum;
}
public virtual bool UseServiceDescriptionPercentage()
{
return false;
}
public virtual decimal BerechneAutoPausen(IList<ServiceRecord> recordsThisMonth)
{
return 0;
}
public virtual decimal BerechnePauseMinuten(IList<ServiceRecord> srList)
{
decimal pausenZeit = 0;
List<ServiceRecord> pausen = new List<ServiceRecord>();
List<ServiceRecord> nichtpausen = new List<ServiceRecord>();
foreach (var sr in srList)
{
if (sr.ServiceDescription.Name == "Pause")
{
pausen.Add(sr);
}
else
{
nichtpausen.Add(sr);
}
}
foreach (var pause in pausen)
{
foreach (var arbeitszeit in nichtpausen)
{
var pauseSpan = new DateTimeSpan
{
StartDateTime = pause.Start.Value,
EndDateTime = pause.Start.Value.AddMinutes((double) pause.RoundedDuration)
};
var arbeitszeitSpan = new DateTimeSpan
{
StartDateTime = arbeitszeit.Start.Value,
EndDateTime = arbeitszeit.Start.Value.AddMinutes((double) arbeitszeit.RoundedDuration)
};
if (arbeitszeit.GroupOid.HasValue)
{
arbeitszeitSpan.EndDateTime =
arbeitszeit.Start.Value.AddMinutes((double) (arbeitszeit.GroupRoundedDuration ?? 0));
}
if (pauseSpan.Overlaps(arbeitszeitSpan))
{
DateTime startUeberlappung = pauseSpan.StartDateTime;
if (arbeitszeitSpan.StartDateTime > startUeberlappung)
startUeberlappung = arbeitszeitSpan.StartDateTime;
DateTime endUeberlappung = pauseSpan.EndDateTime;
if (arbeitszeitSpan.EndDateTime < endUeberlappung)
endUeberlappung = arbeitszeitSpan.EndDateTime;
var overlapping = (decimal) endUeberlappung.Subtract(startUeberlappung).TotalMinutes;
pausenZeit += overlapping;
}
}
}
return pausenZeit;
}
public virtual bool SollPauseBerechnen()
{
return false;
}
public virtual List<MitarbeiterstundenkontoRO.EmployeeDetail> FilterEmployeeList(List<MitarbeiterstundenkontoRO.EmployeeDetail> employeeDetailList)
{
List<MitarbeiterstundenkontoRO.EmployeeDetail> newEmpList = new List<MitarbeiterstundenkontoRO.EmployeeDetail>();
foreach (var ed in employeeDetailList)
{
if (ed.Employee.IsActive == ActivationTypeId.Active)
{
newEmpList.Add(ed);
}
else if (ed.Employee.IsActive == ActivationTypeId.Archived)
{
if (ed.StundenGesamtIst != 0)
{
newEmpList.Add(ed);
}
}
}
return newEmpList;
}
public virtual void HandleServiceRecords(MitarbeiterstundenkontoRO.EmployeeDetail empDetail, IList<ServiceRecord> groupFilteredRecords, Contract contract)
{
//do nothing
}
public virtual void CorrectOverlappingTimes(IList<ServiceRecord> serviceRecords)
{
List<ServiceRecord> oldRecords = new List<ServiceRecord>();
foreach (var newRecord in serviceRecords)
{
if (!CorrectOverlappingTime(newRecord))
{
continue;
}
if (newRecord.Start.HasValue && newRecord.Start.Value.Second > 0)
{
continue;
}
bool isGroup = false;
var minuten = newRecord.RoundedDuration;
if (newRecord.GroupRoundedDuration.HasValue)
{
minuten = newRecord.GroupRoundedDuration.Value;
isGroup = true;
}
var newSpan = new DateTimeSpan
{
StartDateTime = newRecord.Start.Value,
EndDateTime = newRecord.Start.Value.AddMinutes((double)minuten)
};
foreach (var oldRecord in oldRecords)
{
var oldSpan = new DateTimeSpan
{
StartDateTime = oldRecord.Start.Value,
EndDateTime = oldRecord.Start.Value.AddMinutes((double)oldRecord.RoundedDuration)
};
if (oldRecord.GroupRoundedDuration.HasValue)
{
oldSpan.EndDateTime = oldRecord.Start.Value.AddMinutes((double)oldRecord.GroupRoundedDuration);
}
if (oldSpan.Overlaps(newSpan))
{
DateTime start = newSpan.StartDateTime;
if (oldSpan.StartDateTime > start)
start = oldSpan.StartDateTime;
DateTime end = newSpan.EndDateTime;
if (oldSpan.EndDateTime < end)
end = oldSpan.EndDateTime;
if (newSpan.StartDateTime >= oldSpan.StartDateTime)
{
newSpan.StartDateTime = oldSpan.EndDateTime;
if (newSpan.StartDateTime > newSpan.EndDateTime)
{
newSpan.StartDateTime = newSpan.EndDateTime;
}
newRecord.Start = newSpan.StartDateTime;
newRecord.End = newSpan.EndDateTime;
if (!isGroup)
{
newRecord.RoundedDuration =
(decimal)newRecord.End.Value.Subtract(newRecord.Start.Value).TotalMinutes;
}
else
{
newRecord.GroupRoundedDuration = (decimal)newRecord.End.Value.Subtract(newRecord.Start.Value).TotalMinutes;
}
}
else
{
oldSpan.StartDateTime = newSpan.EndDateTime;
if (oldSpan.StartDateTime > oldSpan.EndDateTime)
{
oldSpan.StartDateTime = oldSpan.EndDateTime;
}
oldRecord.Start = oldSpan.StartDateTime;
oldRecord.End = oldSpan.EndDateTime;
if (!oldRecord.GroupRoundedDuration.HasValue)
//if (!isGroup)
{
oldRecord.RoundedDuration = (decimal)oldRecord.End.Value.Subtract(oldRecord.Start.Value).TotalMinutes;
}
else
{
oldRecord.GroupRoundedDuration = (decimal)oldRecord.End.Value.Subtract(oldRecord.Start.Value).TotalMinutes;
}
}
}
}
oldRecords.Add(newRecord);
}
}
public virtual bool CorrectOverlappingTime(ServiceRecord newRecord)
{
return true;
}
public virtual decimal? BerechneSollProMonat(Employee emp, DateTime start, DateTime ende)
{
Contract c = GetContractForDate(emp, start, ende);
if (c != null && c.MonthlyTotalHours.HasValue && c.MonthlyTotalHours.Value > 0)
{
return c.MonthlyTotalHours.Value;
DateTime monatsAnfang = start;
DateTime monatsEnde = ende;
if (c.EntryDate.HasValue && c.EntryDate > monatsAnfang)
{
monatsAnfang = c.EntryDate.Value;
}
if (c.ContractEndDate.HasValue && c.ContractEndDate < monatsEnde)
{
monatsEnde = c.ContractEndDate.Value.Date.AddDays(1);
}
if (monatsAnfang < monatsEnde)
{
//if (monatsAnfang.Day == 1 && monatsEnde.Day == 1)
//{
return c.MonthlyTotalHours.Value;
//}
}
}
return null;
}
public virtual decimal? BerechneFlsSollProMonat(Employee emp, DateTime start, DateTime ende)
{
Contract c = GetContractForDate(emp, start, ende);
if (c != null && c.MonthlyFLS.HasValue && c.MonthlyFLS.Value > 0)
{
return c.MonthlyFLS.Value;
DateTime monatsAnfang = start;
DateTime monatsEnde = ende;
if (c.EntryDate.HasValue && c.EntryDate > monatsAnfang)
{
monatsAnfang = c.EntryDate.Value;
}
if (c.ContractEndDate.HasValue && c.ContractEndDate < monatsEnde)
{
monatsEnde = c.ContractEndDate.Value.Date.AddDays(1);
}
if (monatsAnfang < monatsEnde)
{
//if (monatsAnfang.Day == 1 && monatsEnde.Day == 1)
//{
return c.MonthlyFLS.Value;
//}
}
}
return null;
}
public virtual void HandleServiceRecord(MitarbeiterstundenkontoRO.EmployeeDetail emp, ServiceRecord item)
{
//do nothing
}
public virtual bool ShouldCreateDayDetails()
{
return false;
}
public virtual bool ShouldCreateDayDetailsForEachServiceRecord()
{
return false;
}
public virtual IList<MitarbeiterstundenkontoRO.DayDetail> CreateDayDetails(DateTime berichtStart, DateTime berichtEnde, MitarbeiterstundenkontoRO.EmployeeDetail ed, IList<ServiceRecord> recordsAll)
{
if (ShouldCreateDayDetailsForEachServiceRecord())
{
return CreateDayDetailsForEachServiceRecord(berichtStart, berichtEnde, ed, recordsAll);
}
Dictionary<int, MitarbeiterstundenkontoRO.DayDetail> dayToDetail = new Dictionary<int, MitarbeiterstundenkontoRO.DayDetail>();
for (int i = berichtStart.Day; i <= berichtEnde.AddDays(-1).Day; i++)
{
MitarbeiterstundenkontoRO.DayDetail dd = CreateDayDetail(new DateTime(berichtStart.Year, berichtStart.Month, i), ed);
dayToDetail.Add(i, dd);
}
foreach (var sr in recordsAll)
{
if (sr.Start.HasValue && sr.Start >= berichtStart && sr.Start < berichtEnde && sr.End.HasValue)
{
var dd = dayToDetail[sr.Start.Value.Day];
if (!IsServiceRecordFehlzeit(sr) && AddServiceRecordToDuration(sr))
{
decimal duration = GetDuration(sr);
dd.MinutesTotal += duration;
if (dd.ServiceRecords == null)
dd.ServiceRecords = new List<ServiceRecord>();
dd.ServiceRecords.Add(sr);
CalculateSpecialHours(dd, sr, duration);
}
}
}
//Berechne von bis Zeiten
foreach (var ddKeyValue in dayToDetail)
{
var dd = ddKeyValue.Value;
if (dd.ZusammenhaengendeZeitraeume == null)
{
dd.ZusammenhaengendeZeitraeume = new List<DateTimeSpan>();
}
if (dd.ServiceRecords != null)
{
var orderedList = dd.ServiceRecords.OrderBy(i => i.Start);
DateTime lastEnd = DateTime.MinValue;
var gapCount = -1;
foreach (var sr in orderedList)
{
if (sr.Start.HasValue && sr.Start.Value.Hour == 0 && sr.Start.Value.Second > 0)
{
continue;
}
decimal duration = GetDuration(sr);
DateTime dtEnd = sr.Start.Value.AddMinutes((double)duration);
if (sr.Start > lastEnd)
{
gapCount++;
}
if (dtEnd > lastEnd)
{
lastEnd = dtEnd;
}
DateTimeSpan currentSpan = null;
if (gapCount + 1 > dd.ZusammenhaengendeZeitraeume.Count)
{
currentSpan = new DateTimeSpan();
currentSpan.StartDateTime = DateTime.MaxValue;
currentSpan.EndDateTime = DateTime.MinValue;
dd.ZusammenhaengendeZeitraeume.Add(currentSpan);
}
else
{
currentSpan = dd.ZusammenhaengendeZeitraeume[gapCount];
}
if (sr.Start < currentSpan.StartDateTime)
{
currentSpan.StartDateTime = sr.Start.Value;
}
if (dtEnd > currentSpan.EndDateTime)
{
currentSpan.EndDateTime = dtEnd;
}
if (gapCount == 0)
{
if (!dd.StartDateTime1.HasValue || sr.Start < dd.StartDateTime1)
{
dd.StartDateTime1 = sr.Start;
}
if (!dd.EndDateTime1.HasValue || dtEnd > dd.EndDateTime1)
{
dd.EndDateTime1 = dtEnd;
}
}
else if (gapCount == 1)
{
if (!dd.StartDateTime2.HasValue || sr.Start < dd.StartDateTime2)
{
dd.StartDateTime2 = sr.Start;
}
if (!dd.EndDateTime2.HasValue || dtEnd > dd.EndDateTime2)
{
dd.EndDateTime2 = dtEnd;
}
}
else if (gapCount == 2)
{
if (!dd.StartDateTime3.HasValue || sr.Start < dd.StartDateTime3)
{
dd.StartDateTime3 = sr.Start;
}
if (!dd.EndDateTime3.HasValue || dtEnd > dd.EndDateTime3)
{
dd.EndDateTime3 = dtEnd;
}
}
else
{
if (!dd.StartDateTime4.HasValue || sr.Start < dd.StartDateTime4)
{
dd.StartDateTime4 = sr.Start;
}
if (!dd.EndDateTime4.HasValue || dtEnd > dd.EndDateTime4)
{
dd.EndDateTime4 = dtEnd;
}
}
}
}
}
return dayToDetail.Values.OrderBy(dd => dd.Date).ToList();
}
public virtual IList<MitarbeiterstundenkontoRO.DayDetail> CreateDayDetailsForEachServiceRecord(DateTime berichtStart, DateTime berichtEnde, MitarbeiterstundenkontoRO.EmployeeDetail ed, IList<ServiceRecord> recordsAll)
{
var details = new List<MitarbeiterstundenkontoRO.DayDetail>();
foreach (var sr in recordsAll)
{
if (sr.Start.HasValue && sr.Start >= berichtStart && sr.Start < berichtEnde && sr.End.HasValue)
{
if (sr.Start.Value.Day == 8)
{
int test = 0;
}
if (!IsServiceRecordFehlzeit(sr) && AddServiceRecordToDuration(sr))
{
var dd = CreateDayDetail(sr.Start.Value, ed);
details.Add(dd);
decimal duration = GetDuration(sr);
dd.MinutesTotal += duration;
if (dd.ServiceRecords == null)
dd.ServiceRecords = new List<ServiceRecord>();
dd.ServiceRecords.Add(sr);
dd.Date = sr.Start.Value;
if (sr.Start.Value.Second == 0)
{
DateTime dtEnd = sr.Start.Value.AddMinutes((double)duration);
dd.StartDateTime1 = sr.Start;
dd.EndDateTime1 = dtEnd;
}
CalculateSpecialHours(dd, sr, duration);
}
}
}
return details.OrderBy(dd => dd.Date).ToList();
}
private decimal GetDuration(ServiceRecord sr)
{
decimal duration = 0;
if (sr.GroupRoundedDuration.HasValue)
{
duration = sr.GroupRoundedDuration.Value;
}
else
{
if (appSettings.ShowRoundedDurationInEmployeeAnalysis)
{
duration = sr.RoundedDuration;
}
else
{
duration = (decimal)sr.End.Value.Subtract(sr.Start.Value).TotalMinutes;
}
}
return duration;
}
public virtual void CalculateSpecialHours(MitarbeiterstundenkontoRO.DayDetail dd, ServiceRecord sr, decimal duration)
{
if (sr.Start.Value.DayOfWeek == DayOfWeek.Sunday)
{
dd.HoursSunday += duration / 60;
}
else if (IstFeiertag(sr.Start.Value))
{
dd.HoursHoliday += duration / 60;
}
if (sr.Start.Value.Second == 0 && dd.NightEnd.HasValue && dd.NightStart.HasValue)
{
var minuten = CheckNachtzeiten(sr.Start.Value, dd.NightStart.Value, dd.NightEnd.Value, (double)duration);
if (minuten > 0)
{
dd.SpecialHours += (decimal)(Math.Round(minuten, 0) / 60);
}
//DateTime dtEnd = sr.Start.Value.AddMinutes((double)duration);
//if (dtEnd.Hour >= dd.NightStart.Value)
//{
// DateTime dtStart = dtEnd.Date.AddHours(dd.NightStart.Value);
// if (sr.Start.Value > dtStart)
// dtStart = sr.Start.Value;
// TimeSpan ts = dtEnd.Subtract(dtStart);
// dd.SpecialHours += (decimal)ts.TotalMinutes / 60;
//}
//if (sr.Start.Value.Hour < dd.NightEnd)
//{
// DateTime dtEnd2 = sr.Start.Value.Date.AddHours(dd.NightEnd.Value);
// if (dtEnd < dtEnd2)
// dtEnd2 = dtEnd;
// TimeSpan ts = dtEnd2.Subtract(sr.Start.Value);
// dd.SpecialHours += (decimal)(Math.Round(ts.TotalMinutes, 0) / 60);
//}
}
}
private double CheckNachtzeiten(DateTime start, int nightStart, int nightEnd, double minuten)
{
DateTime nightStartDt = start.Date.AddHours(nightStart);
DateTime nightEndDt = start.Date.AddDays(1).AddHours(nightEnd);
DateTime dtEnd = start.AddMinutes(minuten);
double minutes = GetOverlappingMinutes(start, dtEnd, nightStartDt, nightEndDt);
minutes += GetOverlappingMinutes(start, dtEnd, nightStartDt.AddDays(-1), nightEndDt.AddDays(-1));
minutes += GetOverlappingMinutes(start, dtEnd, nightStartDt.AddDays(1), nightEndDt.AddDays(1));
return minutes;
}
private double GetOverlappingMinutes(DateTime start, DateTime end, DateTime nightStart, DateTime nightEnd)
{
if (end > nightStart && start < nightEnd)
{
DateTime dtStart = start;
if (dtStart < nightStart)
dtStart = nightStart;
DateTime dtEnd = end;
if (dtEnd > nightEnd)
dtEnd = nightEnd;
TimeSpan ts = dtEnd.Subtract(dtStart);
return ts.TotalMinutes;
}
return 0;
}
public virtual MitarbeiterstundenkontoRO.DayDetail CreateDayDetail(DateTime date, MitarbeiterstundenkontoRO.EmployeeDetail ed)
{
MitarbeiterstundenkontoRO.DayDetail dd = new MitarbeiterstundenkontoRO.DayDetail();
dd.ZusammenhaengendeZeitraeume = new List<DateTimeSpan>();
dd.Date = date.Date;
dd.NightStart = 20;
dd.NightEnd = 6;
dd.MaxHoursUntilBreak = 6;
dd.BreakMinutes = 30;
CalculateAbsenceTimesForDay(dd, ed);
return dd;
}
public virtual void CalculateAbsenceTimesForDay(MitarbeiterstundenkontoRO.DayDetail dd, MitarbeiterstundenkontoRO.EmployeeDetail ed)
{
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;
}
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 && day.DayOfWeek != DayOfWeek.Sunday)
{
var soll = ed.SollProTag;
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)
{
var rest = ed.AbsenceTimeDays.RestStundenProWocheDict[week];
if (rest < soll)
{
soll = rest;
}
rest -= soll;
if (rest < 0)
{
rest = 0;
}
ed.AbsenceTimeDays.RestStundenProWocheDict[week] = rest;
}
}
}
decimal maxSoll = soll;
if (faktor != 0)
{
soll *= faktor; //halbe Feiertage etc. berücksichtigen
}
if (IsKrankheitAbsenceTime(absenceTime))
{
dd.HoursSick = soll;
}
else if (IsUrlaubAbsenceTime(absenceTime))
{
dd.HoursInVacation = soll;
}
if (dd.AbsenceTimes == null)
{
dd.AbsenceTimes = new List<AbsenceTime>();
}
dd.AbsenceTimes.Add(absenceTime);
dd.MinutesTotal += soll * 60;
}
}
}
//}
}
}
}
public virtual bool IstAnrechenbareAbsenceTime(AbsenceTime item)
{
return true;
}
public virtual bool IsKrankheitAbsenceTime(AbsenceTime absenceTime)
{
return !String.IsNullOrEmpty(absenceTime.AbsenceReason.Description) &&
(absenceTime.AbsenceReason.Description.ToLower().IndexOf("arbeitsunfähig") >= 0
|| absenceTime.AbsenceReason.Description.ToLower().IndexOf("krank") >= 0 || absenceTime.AbsenceReason.Description.ToLower() == "au");
}
public virtual bool IsUrlaubAbsenceTime(AbsenceTime absenceTime)
{
return !String.IsNullOrEmpty(absenceTime.AbsenceReason.Description) &&
absenceTime.AbsenceReason.Description.ToLower().IndexOf("urlaub") >= 0;
}
public virtual bool AddServiceRecordToDuration(ServiceRecord item)
{
return true;
}
public virtual decimal AddRateFactorToIst()
{
return 1;
}
public virtual MitarbeiterstundenkontoRO.EmployeeDetail BerechneUeberstundenBis(MitarbeiterstundenkontoRO.EmployeeDetail edOrig, IList<ServiceRecord> records, DateTime monat, out decimal? ueberstunden, out decimal alteExtraUeberstunden)
{
MitarbeiterstundenkontoRO.EmployeeDetail edTotal = new MitarbeiterstundenkontoRO.EmployeeDetail();
ueberstunden = null;
alteExtraUeberstunden = 0;
var emp = edOrig.Employee;
Contract c = emp.FirstContract;
if (c != null)
{
Dictionary<String, IList<ServiceRecord>> srDict = CreateServiceRecordDictByDate(records);
DateTime start = c.EntryDate.HasValue ? c.EntryDate.Value : new DateTime(2011, 1, 1);
while (c != null && start < monat)
{
DateTime contractEnd = c.ContractEndDate.HasValue ? c.ContractEndDate.Value : DateTime.MaxValue;
decimal bu = 0;
decimal weeklyTotalHours = this.maxWochenstunden;
int anzWochentage = ANZ_WOCHENTAGE;
//if (c.WeeklyDays.HasValue && c.WeeklyDays.Value > 0)
//{
// anzWochentage = c.WeeklyDays.Value;
//}
if (c.WeeklyTotalHours.HasValue)
{
weeklyTotalHours = c.WeeklyTotalHours.Value;
bu = c.WeeklyTotalHours.Value / maxWochenstunden;
}
while (start < monat && start < contractEnd)
{
decimal flsIst = 0;
decimal mittelbarIst = 0;
decimal minutenMonat = 0;
DateTime ende = new DateTime(start.Year, start.Month, 1).AddMonths(1);
if (contractEnd < DateTime.MaxValue && contractEnd.AddDays(1) < ende)
ende = contractEnd.AddDays(1);
IList<ServiceRecord> recordsThisMonth = new List<ServiceRecord>();
String key = String.Format("{0:yyyyMM}", start);
if (srDict.ContainsKey(key))
{
foreach (var item in srDict[key])
{
if (item.Start.HasValue && item.Start >= start && item.Start < ende)
{
if (AddServiceRecordToDuration(item))
{
decimal duration = 0;
if (item.GroupRoundedDuration.HasValue)
{
duration = item.GroupRoundedDuration.Value;
}
else
{
if (appSettings.ShowRoundedDurationInEmployeeAnalysis)
{
duration = item.RoundedDuration;
}
else
{
duration = (decimal)item.End.Value.Subtract(item.Start.Value).TotalMinutes;
}
}
if (UseServiceDescriptionPercentage())
{
if (item.ServiceDescription != null &&
item.ServiceDescription.ServiceCategory != null &&
item.ServiceDescription.ServiceCategory.Percentage != 100)
{
duration = (duration * item.ServiceDescription.ServiceCategory.Percentage) / 100;
}
}
minutenMonat += duration;
if (item.ServiceDescription != null &&
item.ServiceDescription.ServiceCategory != null &&
item.ServiceDescription.ServiceCategory.IsBillable)
flsIst += duration;
else
mittelbarIst += duration;
}
recordsThisMonth.Add(item);
}
}
}
decimal arbeitstage = GetArbeitstageImBereich(start, ende, emp);
var arbeitstageProWoche = anzWochentage;
if (c != null && c.WeeklyDays.HasValue && c.WeeklyDays.Value > 0)
{
arbeitstageProWoche = c.WeeklyDays.Value;
}
//if (anzWochentage != 5)
//{
// arbeitstage *= anzWochentage / 5m;
//}
var soll = GetSollNachArbeitszeiten(emp, start, ende);
if (!soll.HasValue)
{
var stundenSollProMonat = BerechneSollProMonat(emp, start, ende);
soll = stundenSollProMonat;
}
if (!soll.HasValue)
{
if (!soll.HasValue)
{
decimal maxSollMonat = arbeitstage * (maxWochenstunden / arbeitstageProWoche);
if (arbeitstageProWoche <= 5)
{
maxSollMonat = arbeitstage * (maxWochenstunden / 5);
}
soll = maxSollMonat * bu;
}
}
decimal sollMitarbeiter = soll ?? 0;
var ath = GetAbsenceTimeDaysWithWorkWeeks(emp, start, ende, arbeitstageProWoche);
decimal? fehlzeit = GetFehlzeiten(records, start, ende);
if (fehlzeit.HasValue)
{
sollMitarbeiter -= fehlzeit.Value;
}
MitarbeiterstundenkontoRO.EmployeeDetail ed = new MitarbeiterstundenkontoRO.EmployeeDetail();
ed.SollProTag = weeklyTotalHours / arbeitstageProWoche;
ed.ArbeitstageProWoche = arbeitstageProWoche;
ed.ArbeitstageImBerichtszeitraum = arbeitstage;
ed.SollProWoche = BerechneSollProWoche(c, ed);
ed.AbsenceTimeDays = ath;
ed.Employee = emp;
ed.StundenSollMax = sollMitarbeiter;
if (ath.TageGesamt.HasValue)
{
var minusStunden = BerechneStundenDurchAbwesenheiten(ath, start, ende, c, ed);
sollMitarbeiter -= minusStunden;
if (sollMitarbeiter < 0 && !StundenDurchAbwesenheitenDuerfenNegativSein())
{
sollMitarbeiter = 0;
}
//if (stundenSollProMonat.HasValue)
//{
// decimal stundenProTag = stundenSollProMonat.Value;
// if (arbeitstage != 0)
// {
// stundenProTag = stundenSollProMonat.Value/arbeitstage;
// }
// sollMitarbeiter -= (ath.TageGesamt.Value * stundenProTag);
//}
//else
//{
// decimal sollProWoche = maxWochenstunden*bu;
// var minusStunden = BerechneStundenDurchAbwesenheiten(ath, start, ende, c, sollProWoche);
//}
}
var ath2 = GetAbwesenheitenDurchServiceRecords(ed, c, records, start, ende);
if (ath2 != null)
{
var stunden = ath2.StundenKrankheit + ath2.StundenUrlaub + ath2.StundenSonstiges;
sollMitarbeiter -= stunden;
if (sollMitarbeiter < 0 && !StundenDurchAbwesenheitenDuerfenNegativSein())
{
sollMitarbeiter = 0;
}
}
decimal stundenMonat = minutenMonat/60m;
stundenMonat = ((flsIst*AddRateFactorToIst()) + mittelbarIst)/60m;
if (!ueberstunden.HasValue)
ueberstunden = 0;
ueberstunden += stundenMonat - sollMitarbeiter;
if (SollPauseBerechnen())
{
var pause1 = BerechnePauseMinuten(recordsThisMonth);
var pause2 = BerechneAutoPausen(recordsThisMonth);
ueberstunden -= pause1/60;
ueberstunden -= pause2/60;
}
decimal extraUeberstunden = 0;
BerechneExtraUeberstunden(emp, start, ende, out extraUeberstunden);
ueberstunden += extraUeberstunden;
alteExtraUeberstunden += extraUeberstunden;
if (ShouldCreateDayDetails())
{
var days = CreateDayDetails(start, ende, ed, records);
var ah = GetAdditionalHours(days, start, ende, ed, records);
ueberstunden += ah;
}
ed.StundenSollOhneUrlaubKrankheit = sollMitarbeiter;
ed.FlsIst = flsIst / 60;
ed.MittelbarIst = mittelbarIst / 60;
ed.StundenGesamtIst = stundenMonat;
ed.Ueberstunden = ueberstunden;
ed.UeberstundenVormonat = edTotal.Ueberstunden;
ueberstunden = BerechneUeberstunden(ed, ueberstunden, c, start, ende);
edTotal.StundenSollOhneUrlaubKrankheit += sollMitarbeiter;
edTotal.StundenSollMax += soll ?? 0;
edTotal.FlsIst += flsIst / 60;
edTotal.MittelbarIst += mittelbarIst / 60;
edTotal.StundenGesamtIst += stundenMonat;
edTotal.Ueberstunden = ueberstunden;
start = ende;
}
if (start >= contractEnd)
{
var ctemp = GetNextValidContractForDate(start, emp);
if (ctemp != null && ctemp.Oid != c.Oid)
{
c = ctemp;
}
else
{
c = null;
}
if (c != null && c.EntryDate.HasValue && c.EntryDate >= start)
start = c.EntryDate.Value;
else
{
start = start.AddMonths(1);
c = GetNextValidContractForDate(start, emp);
if (c != null && c.EntryDate.HasValue && c.EntryDate >= start)
start = c.EntryDate.Value;
}
}
}
}
return edTotal;
}
protected virtual decimal? BerechneUeberstunden(MitarbeiterstundenkontoRO.EmployeeDetail ed, decimal? ueberstundenStd, Contract contract, DateTime start, DateTime ende)
{
return ueberstundenStd;
}
public virtual decimal BerechneSollProWoche(Contract c, MitarbeiterstundenkontoRO.EmployeeDetail ed)
{
if (c != null)
{
if (c.MonthlyTotalHours.HasValue && c.MonthlyTotalHours.Value > 0)
{
if (ed.ArbeitstageImBerichtszeitraum > 0)
{
decimal stundenProTag = GetSollArbeitszeitProArbeitstag(c, ed);
return (stundenProTag * 5);
//sollStundenProWoche = stundenProTag * ed.ArbeitstageProWoche;
//return (ath.TageGesamt.Value * stundenProTag);
}
}
else if (c.WeeklyTotalHours.HasValue)
{
return c.WeeklyTotalHours.Value;
}
}
return 0;
}
public virtual decimal BerechneStundenDurchAbwesenheiten(AbsenceTimeDays ath, DateTime start, DateTime ende, Contract c, MitarbeiterstundenkontoRO.EmployeeDetail ed)
{
if (BerechneAlteAbwesenheitsStunden(start))
{
return BerechneStundenDurchAbwesenheitenAlt(ath, start, ende, c, ed);
}
decimal stunden = 0;
if (c != null)
{
if (ath.TageGesamt.HasValue)
{
if (HatArbeitszeitImZeitraum(ed.Employee.Arbeitszeiten, start, ende))
{
return BerechneAbwesenheitsStundenDurchArbeitszeiten(ed.Employee, start, ende);
}
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);
}
}
}
}
}
}
return stunden;
}
public virtual decimal BerechneAbwesenheitsStundenDurchArbeitszeiten(Employee emp, DateTime start, DateTime ende)
{
decimal stunden = 0;
DateTime startTemp = start;
while (startTemp < ende)
{
stunden += BerechneAlleAbwesenheitsStundenFuerArbeitszeiten(emp, startTemp);
startTemp = startTemp.AddDays(1);
}
return stunden;
}
public virtual decimal BerechneAlleAbwesenheitsStundenFuerArbeitszeiten(Employee emp, DateTime tag)
{
decimal stunden = 0;
foreach (var az in emp.Arbeitszeiten)
{
if ((!az.GueltigVon.HasValue || az.GueltigVon.Value <= tag) &&
(!az.GueltigBis.HasValue || az.GueltigBis.Value >= tag))
{
var day = tag.DayOfWeek;
foreach (var ae in az.ArbeitszeitEintraege)
{
if (SindAmGleichenWochentag(day, ae.Tag))
{
String dateStr1 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitVon);
String dateStr2 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitBis);
DateTime date1;
DateTime date2;
if (DateTime.TryParse(dateStr1, out date1) && DateTime.TryParse(dateStr2, out date2))
{
stunden += BerechneAbwesenheitsStundenFuerArbeitstag(emp, date1, date2);
}
}
}
}
}
return stunden;
}
public virtual decimal BerechneAbwesenheitsStundenFuerArbeitstag(Employee emp, DateTime arbeitstagStart, DateTime arbeitstagEnde)
{
foreach (var at in emp.AbsenceTimes)
{
if ((!at.Start.HasValue || at.Start.Value <= arbeitstagEnde.Date) &&
(!at.End.HasValue || at.End.Value >= arbeitstagStart.Date))
{
var faktor = GetFeiertagsFaktor(arbeitstagStart);
if (faktor < 1)
{
var hours = (decimal)arbeitstagEnde.Subtract(arbeitstagStart).TotalHours;
if (faktor != 0)
{
hours *= faktor;
}
return hours;
}
}
}
return 0;
}
//CB 12.4.18: Die Abwesenheitsstunden wurden bei Arbeitstagen < 5 früher falsch berechnet. Damit bereits erstellte Stundenkonto nicht zu veränderten Werten führen, habe
//ich einen Schalter eingebaut, mit dem bestimmt werden kann, ob die alte Berechnung angewendet werden soll oder nicht (Standard ist ja)
public virtual bool BerechneAlteAbwesenheitsStunden(DateTime monatAnfang)
{
if (monatAnfang < new DateTime(2018, 4, 1))
{
return true;
}
return false;
}
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;
}
}
public virtual decimal GetSollArbeitszeitProArbeitstag(Contract contract, MitarbeiterstundenkontoRO.EmployeeDetail ed)
{
if (contract.MonthlyTotalHours.HasValue && contract.MonthlyTotalHours.Value > 0 && ed.ArbeitstageImBerichtszeitraum > 0)
{
return contract.MonthlyTotalHours.Value / ed.ArbeitstageImBerichtszeitraum;
}
else if (contract.WeeklyTotalHours.HasValue && ed.ArbeitstageProWoche > 0)
{
return contract.WeeklyTotalHours.Value / ed.ArbeitstageProWoche;
}
return 0;
}
//Wird nicht mehr benutzt
public virtual decimal BerechneStundenDurchAbwesenheiten(AbsenceTimeDays ath, DateTime start, DateTime ende, int arbeitstageProWoche, decimal sollProWoche)
{
decimal stunden = 0;
if (ath.TageGesamt.HasValue)
{
if (arbeitstageProWoche == 5)
{
stunden = ath.TageGesamt.Value*(sollProWoche/arbeitstageProWoche);
}
else if (ath.TageProWocheDict != null && arbeitstageProWoche > 0)
{
foreach (var week in ath.TageProWocheDict.Keys)
{
var tage = ath.TageProWocheDict[week];
if (tage > 0)
{
if (tage > arbeitstageProWoche)
{
tage = arbeitstageProWoche;
}
stunden += tage * (sollProWoche / arbeitstageProWoche);
}
}
}
}
return stunden;
}
public virtual Dictionary<string, IList<ServiceRecord>> CreateServiceRecordDictByDate(IList<ServiceRecord> records)
{
var dict = new Dictionary<string, IList<ServiceRecord>>();
foreach (var item in records)
{
if (!IsServiceRecordFehlzeit(item))
{
if (item.Start.HasValue)
{
String key = String.Format("{0:yyyyMM}", item.Start.Value);
IList<ServiceRecord> list;
if (!dict.ContainsKey(key))
{
list = new List<ServiceRecord>();
dict.Add(key, list);
}
else
{
list = dict[key];
}
list.Add(item);
}
}
}
return dict;
}
public virtual decimal GetAdditionalHours(IList<MitarbeiterstundenkontoRO.DayDetail> days, DateTime berichtStart, DateTime berichtEnde, MitarbeiterstundenkontoRO.EmployeeDetail ed, IList<ServiceRecord> recordsAll)
{
decimal addHours = 0;
foreach (var dayDetail in days)
{
if (dayDetail.BreakMinutes2.HasValue && dayDetail.MaxHoursUntilBreak2.HasValue)
{
addHours += CalculateBreakMinutes(dayDetail, dayDetail.MaxHoursUntilBreak2.Value, dayDetail.BreakMinutes2.Value);
}
if (dayDetail.BreakMinutes.HasValue && dayDetail.MaxHoursUntilBreak.HasValue)
{
addHours += CalculateBreakMinutes(dayDetail, dayDetail.MaxHoursUntilBreak.Value, dayDetail.BreakMinutes.Value);
}
}
return addHours;
}
public virtual decimal CalculateBreakMinutes(MitarbeiterstundenkontoRO.DayDetail dayDetail, int maxHoursUntilBreak, int breakMinutes)
{
decimal addHours = 0;
if (dayDetail.ZusammenhaengendeZeitraeume != null && dayDetail.ZusammenhaengendeZeitraeume.Count > 0)
{
foreach (var span in dayDetail.ZusammenhaengendeZeitraeume)
{
if (span.EndDateTime.Subtract(span.StartDateTime).TotalHours > maxHoursUntilBreak)
{
addHours -= (breakMinutes / 60m);
dayDetail.MinutesTotal -= breakMinutes;
dayDetail.PauseInMinuten += breakMinutes;
}
}
return addHours;
}
if (dayDetail.EndDateTime1.HasValue && dayDetail.StartDateTime1.HasValue)
{
if (dayDetail.EndDateTime1.Value.Subtract(dayDetail.StartDateTime1.Value).TotalHours > maxHoursUntilBreak)
{
addHours -= (breakMinutes / 60m);
dayDetail.MinutesTotal -= breakMinutes;
dayDetail.PauseInMinuten += breakMinutes;
}
}
if (dayDetail.EndDateTime2.HasValue && dayDetail.StartDateTime2.HasValue)
{
if (dayDetail.EndDateTime2.Value.Subtract(dayDetail.StartDateTime2.Value).TotalHours > maxHoursUntilBreak)
{
addHours -= (breakMinutes / 60m);
dayDetail.MinutesTotal -= breakMinutes;
dayDetail.PauseInMinuten += breakMinutes;
}
}
if (dayDetail.EndDateTime3.HasValue && dayDetail.StartDateTime3.HasValue)
{
if (dayDetail.EndDateTime3.Value.Subtract(dayDetail.StartDateTime3.Value).TotalHours > maxHoursUntilBreak)
{
addHours -= (breakMinutes / 60m);
dayDetail.MinutesTotal -= breakMinutes;
dayDetail.PauseInMinuten += breakMinutes;
}
}
if (dayDetail.EndDateTime4.HasValue && dayDetail.StartDateTime4.HasValue)
{
if (dayDetail.EndDateTime4.Value.Subtract(dayDetail.StartDateTime4.Value).TotalHours > maxHoursUntilBreak)
{
addHours -= (breakMinutes / 60m);
dayDetail.MinutesTotal -= breakMinutes;
dayDetail.PauseInMinuten += breakMinutes;
}
}
return addHours;
}
public virtual void BerechneExtraUeberstunden(Employee emp, DateTime start, DateTime ende, out decimal stunden)
{
stunden = 0;
if (emp.Overtimes != null)
{
foreach (var ot in emp.Overtimes)
{
if (ot.Date >= start && ot.Date < ende)
{
stunden += ot.Betrag;
}
}
}
}
public Contract GetNextValidContractForDate(DateTime dt, Employee emp)
{
Contract contractNextToStartDate = emp.GetValidContractForDate(dt);
if (contractNextToStartDate == null)
{
foreach (var item in emp.Contracts)
{
if (item.EntryDate.HasValue && item.EntryDate.Value >= dt)
{
if (contractNextToStartDate == null || item.EntryDate.Value < contractNextToStartDate.EntryDate.Value)
{
contractNextToStartDate = item;
}
}
}
}
return contractNextToStartDate;
}
public virtual AbsenceTimeDays GetAbsenceTimeDaysWithWorkWeeks(Employee emp, DateTime start, DateTime end, int arbeitstageProWoche)
{
if (HatArbeitszeitImZeitraum(emp.Arbeitszeiten, start, end))
{
return GetAbsenceTimeDaysNachArbeitszeiten(emp, start, end, arbeitstageProWoche);
}
return GetAbsenceTimeDaysWithWorkWeeks(emp.AbsenceTimes, start, end, arbeitstageProWoche);
}
public virtual AbsenceTimeDays GetAbsenceTimeDaysNachArbeitszeiten(Employee emp, DateTime start, DateTime end, int arbeitstageProWoche)
{
var atd = new AbsenceTimeDays();
decimal? tage = null;
DateTime startTemp = start;
while (startTemp < end)
{
AddAbsenceDaysNachArbeitszeitenFuerTag(atd, emp, startTemp);
startTemp = startTemp.AddDays(1);
}
return atd;
}
public virtual void AddAbsenceDaysNachArbeitszeitenFuerTag(AbsenceTimeDays atd, Employee emp, DateTime tag)
{
foreach (var az in emp.Arbeitszeiten)
{
if ((!az.GueltigVon.HasValue || az.GueltigVon.Value <= tag) &&
(!az.GueltigBis.HasValue || az.GueltigBis.Value >= tag))
{
var day = tag.DayOfWeek;
foreach (var ae in az.ArbeitszeitEintraege)
{
if (SindAmGleichenWochentag(day, ae.Tag))
{
String dateStr1 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitVon);
String dateStr2 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitBis);
DateTime date1;
DateTime date2;
if (DateTime.TryParse(dateStr1, out date1) && DateTime.TryParse(dateStr2, out date2))
{
AddAbsenceDaysFuerTag(atd, emp, date1, date2);
}
}
}
}
}
}
private void AddAbsenceDaysFuerTag(AbsenceTimeDays atd, Employee emp, DateTime arbeitstagStart, DateTime arbeitstagEnde)
{
var hours = (decimal)arbeitstagEnde.Subtract(arbeitstagStart).TotalHours;
foreach (var at in emp.AbsenceTimes)
{
if ((!at.Start.HasValue || at.Start.Value <= arbeitstagEnde.Date) &&
(!at.End.HasValue || at.End.Value >= arbeitstagStart.Date))
{
var faktor = GetFeiertagsFaktor(arbeitstagStart);
if (faktor < 1)
{
var tag = 1m;
if (faktor != 0)
{
tag *= faktor;
hours *= faktor;
}
if (IsKrankheitAbsenceTime(at))
{
if (!atd.TageKrankheit.HasValue)
atd.TageKrankheit = 0;
atd.TageKrankheit += tag;
}
if (IsUrlaubAbsenceTime(at))
{
if (!atd.TageUrlaub.HasValue)
atd.TageUrlaub = 0;
atd.TageUrlaub += tag;
}
if (!atd.TageGesamt.HasValue)
atd.TageGesamt = 0;
atd.TageGesamt += tag;
}
}
}
}
public virtual AbsenceTimeDays GetAbsenceTimeDaysWithWorkWeeks(IList<AbsenceTime> absenceTimes, DateTime start, DateTime end, int arbeitstageProWoche)
{
var atd = new AbsenceTimeDays();
var totalSpan = new DateTimeSpan();
totalSpan.StartDate = start;
totalSpan.EndDate = end.AddDays(-1);
var weeks = totalSpan.GetWeeks(true, false);
if (BerechneAlteAbwesenheitsStunden(start))
{
totalSpan.EndDate = end;
weeks = totalSpan.GetWholeWeeks();
}
atd.TageProWocheDict = new Dictionary<DateTimeSpan, decimal>();
foreach (var week in weeks)
{
atd.TageProWocheDict.Add(week, 0);
}
decimal? tage = null;
if (absenceTimes != null)
{
foreach (var item in absenceTimes)
{
if (IstAnrechenbareAbsenceTime(item))
{
DateTimeSpan span = new DateTimeSpan();
span.StartDate = start;
if (item.Start.HasValue && item.Start.Value > span.StartDate)
{
span.StartDate = item.Start.Value;
}
span.EndDate = end;
if (item.End.HasValue && item.End.Value.Date.AddDays(1) < span.EndDate)
{
span.EndDate = item.End.Value.Date.AddDays(1);
}
if (span.EndDate >= start && span.StartDate < end)
{
DateTime day = span.StartDate;
while (day < end && day < span.EndDate)
{
var faktor = GetFeiertagsFaktor(day);
bool istWochenende =
day.DayOfWeek == DayOfWeek.Saturday || day.DayOfWeek == DayOfWeek.Sunday;
if (arbeitstageProWoche == 6)
{
istWochenende = day.DayOfWeek == DayOfWeek.Sunday;
}
else if (arbeitstageProWoche > 6)
{
istWochenende = false;
}
if (faktor < 1 && !istWochenende)
{
if (!tage.HasValue)
tage = 0;
var tag = 1m;
var std = 24m;
if (faktor != 0)
{
tag *= faktor;
std *= faktor;
}
tage += std;
if (IsKrankheitAbsenceTime(item))
{
if (!atd.TageKrankheit.HasValue)
atd.TageKrankheit = 0;
atd.TageKrankheit += tag;
}
if (IsUrlaubAbsenceTime(item))
{
if (!atd.TageUrlaub.HasValue)
atd.TageUrlaub = 0;
atd.TageUrlaub += tag;
}
foreach (var week in weeks)
{
if (day >= week.StartDate && day <= week.EndDate)
{
if (atd.TageProWocheDict.ContainsKey(week))
{
atd.TageProWocheDict[week] += 1;
}
}
}
}
day = day.AddDays(1);
}
}
}
}
}
if (tage.HasValue)
tage /= 24;
atd.TageGesamt = tage;
return atd;
}
public virtual AbsenceTimeDays GetAbsenceTimeDays(IList<AbsenceTime> absenceTimes, DateTime start, DateTime end)
{
return GetAbsenceTimeDaysWithWorkWeeks(absenceTimes, start, end, ANZ_WOCHENTAGE);
}
public virtual decimal? GetFehlzeiten(IList<ServiceRecord> records, DateTime monat)
{
return GetFehlzeiten(records, monat, monat.AddMonths(1));
}
public virtual decimal? GetFehlzeiten(IList<ServiceRecord> records, DateTime start, DateTime ende)
{
decimal? stunden = null;
decimal minuten = 0;
if (records != null)
{
foreach (var item in records)
{
if (IsServiceRecordFehlzeit(item))
{
if (item.Start.Value >= start && item.Start.Value < ende)
{
if (item.GroupRoundedDuration.HasValue)
{
minuten += item.GroupRoundedDuration.Value;
}
else
{
if (appSettings.ShowRoundedDurationInEmployeeAnalysis)
{
minuten += item.RoundedDuration;
}
else
{
minuten += (decimal)item.End.Value.Subtract(item.Start.Value).TotalMinutes;
}
}
}
}
}
}
if (minuten != 0)
stunden = minuten / 60;
return stunden;
}
public virtual decimal GetArbeitstageImMonat(DateTime datum, Employee emp)
{
Contract c = GetNextValidContractForDate(datum, emp);
if (c == null)
return 0;
DateTime start = new DateTime(datum.Year, datum.Month, 1);
DateTime end = start.AddMonths(1);
if (c.EntryDate.HasValue)
{
if (c.EntryDate >= end)
return 0;
if (c.EntryDate > start)
start = c.EntryDate.Value;
}
if (c.ContractEndDate.HasValue && c.ContractEndDate.Value.AddDays(1) < end)
end = c.ContractEndDate.Value.AddDays(1);
return GetArbeitstageImBereich(start, end, emp);
}
public virtual decimal GetArbeitstageImBereich(DateTime von, DateTime bis, Employee emp)
{
DateTime start = von;
DateTime end = bis;
TimeSpan ts = end.Subtract(start);
var maxDays = (decimal)ts.TotalDays;
while (start < end)
{
int arbeitstageProWoche = ANZ_WOCHENTAGE;
var c = GetContractForDate(emp, start, start);
if (c != null && c.WeeklyDays.HasValue && c.WeeklyDays > 0)
{
arbeitstageProWoche = c.WeeklyDays.Value;
}
if (arbeitstageProWoche <= 5 && (start.DayOfWeek == DayOfWeek.Saturday || start.DayOfWeek == DayOfWeek.Sunday))
{
maxDays -= 1;
}
else if (arbeitstageProWoche == 6 && start.DayOfWeek == DayOfWeek.Sunday)
{
maxDays -= 1;
}
else
{
maxDays -= GetFeiertagsFaktor(start);
//if (IstFeiertag(start))
// maxDays--;
}
start = start.AddDays(1);
}
return maxDays;
}
public virtual Contract GetContractForDate(Employee emp, DateTime start, DateTime ende)
{
Contract c = emp.GetValidContractForDate(start);
if (c == null) // Kein Vertrag vom 1. gefunden, gucken, ob es einen gibt, der mitten im Monat beginnt.
{
var c2 = GetNextValidContractForDate(start, emp);
if (c2 != null && c2.EntryDate.HasValue && c2.EntryDate.Value < ende)
c = c2;
}
return c;
}
//gibt 1 zurück wenn ganzer Feiertag und z.B. 0.5 bei halben etc.
public virtual decimal GetFeiertagsFaktor(DateTime start)
{
if (IstFeiertag(start))
{
return 1;
}
return 0;
}
public virtual bool IstFeiertag(DateTime start)
{
List<DateTime> feiertage = GetFeiertage(start.Year);
foreach (var ft in feiertage)
{
if (start.Date == ft)
return true;
}
return false;
}
public virtual List<DateTime> GetFeiertage(int year)
{
List<DateTime> list = new List<DateTime>();
list.Add(new DateTime(year, 1, 1)); // "Neujahr"));
//list.Add(new DateTime(year, 1, 6)); // , "Heilige Drei Könige"));
list.Add(new DateTime(year, 5, 1)); // , "Tag der Arbeit"));
//list.Add(new DateTime(year, 8, 15)); // , "Mariä Himmelfahrt"));
list.Add(new DateTime(year, 10, 3)); // , "Tag der dt. Einheit"));
//list.Add(new DateTime(year, 10, 31)); // , "Reformationstag"));
list.Add(new DateTime(year, 11, 1)); // , "Allerheiligen "));
list.Add(new DateTime(year, 12, 24)); // , "Heilig Abend"));
list.Add(new DateTime(year, 12, 25)); // , "1. Weihnachtstag"));
list.Add(new DateTime(year, 12, 26)); // , "2. Weihnachtstag"));
if (year == 2017)
{
list.Add(new DateTime(year, 10, 31)); // , "Reformationstag"));
}
DateTime osterSonntag = GetOsterSonntag(year);
//list.Add(osterSonntag); // , "Ostersonntag"));
//list.Add(osterSonntag.AddDays(-3)); // , "Gründonnerstag")); q
//list.Add(osterSonntag.AddDays(-48)); // , "Rosenmontag"));
list.Add(osterSonntag.AddDays(-2)); // , "Karfreitag"));
list.Add(osterSonntag.AddDays(1)); // , "Ostermontag"));
list.Add(osterSonntag.AddDays(39)); // , "Christi Himmelfahrt"));
//list.Add(osterSonntag.AddDays(49)); // , "Pfingstsonntag"));
list.Add(osterSonntag.AddDays(50)); // , "Pfingstmontag"));
list.Add(osterSonntag.AddDays(60)); // , "Fronleichnam"));
//01.01. Neujahr
//01.05. Tag der Arbeit
//03.10. Tag der Deutschen Einheit
//01.11. Allerheiligen
//25.12. 1. Weihnachtstag
//26.12. 2. Weihnachtstag
//Karfreitag
//Ostermontag
//Christi Himmelfahrt (39 Tage nach Ostersonntag)
//Pfingstmontag (50 Tage nach Ostersonntag)
//Fronleichnam (60 Tage nach Ostersonntag)
//24.12. Heilig Abend
return list;
}
protected DateTime GetOsterSonntag(int year)
{
int g, h, c, j, l, i;
g = year % 19;
c = year / 100;
h = ((c - (c / 4)) - (((8 * c) + 13) / 25) + (19 * g) + 15) % 30;
i = h - (h / 28) * (1 - (29 / (h + 1)) * ((21 - g) / 11));
j = (year + (year / 4) + i + 2 - c + (c / 4)) % 7;
l = i - j;
int month = (int)(3 + ((l + 40) / 44));
int day = (int)(l + 28 - 31 * (month / 4));
return new DateTime(year, month, day);
}
public virtual bool IsServiceRecordFehlzeit(ServiceRecord sr)
{
if (sr.ServiceDescription != null && sr.ServiceDescription.ServiceCategory != null && !String.IsNullOrEmpty(sr.ServiceDescription.ServiceCategory.Name) && sr.ServiceDescription.ServiceCategory.Name.ToLower().IndexOf("fehlzeit") >= 0)
return true;
return false;
}
}
public class AbsenceTimeDays
{
public decimal? TageUrlaub;
public decimal? TageKrankheit;
public decimal? TageGesamt;
public Dictionary<DateTimeSpan, decimal> TageProWocheDict;
public Dictionary<DateTimeSpan, decimal> RestStundenProWocheDict;
}
public class AbsenceTimeHours
{
public decimal StundenUrlaub;
public decimal StundenKrankheit;
public decimal StundenSonstiges;
}
public class ServiceRecordSummary
{
public decimal IstAbrechenbar { get; set; }
public decimal IstNichtAbrechenbar { get; set; }
public IList<ServiceRecord> RecordsImBerichtszeitraum { get; set; }
}
}