Files
BeWoPlaner/Report/ReportObjects/MitarbeiterstundenkontoRO.cs

672 lines
21 KiB
C#

using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Dienstplanung;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace BeWo.Report.ReportObjects
{
public class MitarbeiterstundenkontoRO : AbstractBeWoReportObject<MitarbeiterstundenkontoRO>
{
List<EmployeeDetail> _EmployeeDetailList = new List<EmployeeDetail>();
List<TeamDetail> _TeamDetailList = new List<TeamDetail>();
List<StundenkontoServiceRecord> _AllServiceRecords = null;
public DateTime ReportStartDate { get; set; }
public DateTime ReportEndDate { get; set; }
public decimal SollGesamt { get; set; }
public decimal FlsSollGesamt { get; set; }
public decimal FlsIstGesamt { get; set; }
public decimal FlsDiffGesamt { get; set; }
public decimal StundenGesamt { get; set; }
public decimal RelationIstSollGesamt { get; set; }
public decimal MittelbarIst { get; set; }
public decimal RelationFlsZuMittelbar { get; set; }
public string AbsenceNotice { get; set; }
public List<EmployeeDetail> EmployeeDetailList
{
get { return this._EmployeeDetailList; }
set { this._EmployeeDetailList = value; }
}
public List<TeamDetail> TeamDetailList
{
get { return this._TeamDetailList; }
set { this._TeamDetailList = value; }
}
public List<StundenkontoServiceRecord> AllServiceRecords
{
get { return this._AllServiceRecords; }
set { this._AllServiceRecords = value; }
}
public static MitarbeiterstundenkontoRO Create(long? employeeOid, IList<long> teamOids, DateTime startDate, DateTime endDate, IEnumerable<long> employeeOids)
{
Team team = null;
Dictionary<long, bool> empOidDict = new Dictionary<long, bool>();
var ro = new MitarbeiterstundenkontoRO {ReportStartDate = startDate, ReportEndDate = endDate};
IList<Employee> employees = null;
if (employeeOid.HasValue)
{
var emp = DAOFactory.GenericDAO.GetByID<Employee>(employeeOid.Value);
employees = new List<Employee> {emp};
}
else if (teamOids != null)
{
foreach (var teamOid in teamOids)
{
team = DAOFactory.GenericDAO.GetByID<Team>(teamOid);
if (employees == null)
{
employees = team.MemberList;
}
else
{
employees.AddRange(team.MemberList);
team = null;
}
}
}
else if(employeeOids != null)
{
employees = DAOFactory.GenericDAO.LoadByIDs<Employee>(employeeOids);
}
else
{
employees = DAOFactory.GenericDAO.GetAllActiveAndArchived<Employee>();
}
if (employees == null)
{
employees = new List<Employee>();
}
foreach (var emp in employees)
{
if (!empOidDict.ContainsKey(emp.Oid.Value))
{
var empDetail = new EmployeeDetail();
bool add = true;
if (emp.IsActive == ActivationTypeId.Archived)
{
Contract c = emp.GetValidContractForDate(ro.ReportStartDate);
if (c == null) // Kein Vertrag vom 1. gefunden, gucken, ob es einen gibt, der mitten im Monat beginnt.
{
var c2 = GetNextValidContractForDate(ro.ReportStartDate, emp);
if (c2 != null && c2.EntryDate.HasValue && c2.EntryDate.Value < ro.ReportEndDate)
c = c2;
}
if (c == null)
{
add = false;
}
}
if (add)
{
ro.EmployeeDetailList.Add(CreateEmployeeDetail(emp, team));
}
if (!empOidDict.ContainsKey(emp.Oid.Value))
{
empOidDict.Add(emp.Oid.Value, true);
}
}
}
var teamOid2Details = new Dictionary<long, TeamDetail>();
foreach (var employee in ro.EmployeeDetailList)
{
if (employee.Teams.Count > 0)
{
foreach (var t in employee.Teams)
{
TeamDetail td;
if (!teamOid2Details.ContainsKey(t.Oid.Value))
{
td = new TeamDetail {TeamName = t.Name, TeamLeader = t.Leader};
ro.TeamDetailList.Add(td);
teamOid2Details.Add(t.Oid.Value, td);
}
else
{
td = teamOid2Details[t.Oid.Value];
}
td.EmployeeDetailList.Add(employee);
}
}
}
ro.TeamDetailList.Sort((t1, t2) => t1.TeamName.CompareTo(t2.TeamName));
foreach (var teamDetail in ro.TeamDetailList)
{
if (teamDetail.EmployeeDetailList != null)
{
teamDetail.EmployeeDetailList.Sort((e1, e2) => e1.FullName.CompareTo(e2.FullName));
}
}
ro.EmployeeDetailList.Sort((e1, e2) => e1.FullName.CompareTo(e2.FullName));
ro.AbsenceNotice = CreateAbsenceNotice(ro.ReportStartDate, ro.ReportEndDate, ro.EmployeeDetailList);
return ro;
}
public void BerechneServiceRecordPool()
{
_AllServiceRecords = new List<StundenkontoServiceRecord>();
if (EmployeeDetailList.Count > 0)
{
var allServiceDescs = DAOFactory.GenericDAO.GetAll<ServiceDescription>();
Dictionary<long, ServiceDescriptionDC> serviceDict = new Dictionary<long, ServiceDescriptionDC>();
foreach (var item in allServiceDescs)
{
serviceDict.Add(item.Oid.Value, MapperFactory.ServiceDescriptionDC_ServiceDescription.MapToNewDC(item));
}
String sql = "SELECT Oid, StartDate, EndDate, RoundedDuration, GroupEmployeeCount, GroupPersonCount, GroupRoundedDuration, GroupOid, DistanceInMeter, Betrag, CostBearer2SupportConceptOid, ServiceDescriptionOid, CustomerOid, EmployeeOid, Notice, Notice2, Notice3, InsUser, InsTs, Relevance FROM servicerecord";
sql += String.Format(" WHERE EmployeeOid in ({0})", String.Join(",", EmployeeDetailList.Select(e => e.Employee.Oid.Value)));
sql += String.Format(" AND (CustomerOid is null OR CustomerOID not in (select oid from customer where isactive = 0))");
sql += String.Format(" AND (CostBearer2SupportConceptOid is null OR CostBearer2SupportConceptOid not in (select c2s.oid from CostBearer2SupportConcept c2s join supportconcept sc on c2s.SupportConceptOid = sc.Oid where sc.isactive = 0))");
var sqlresult = DAOFactory.SearchDAO.GetSqlResult(sql);
//
//update customer set debitornumber = '5' + debitornumber where debitornumber is not null
foreach (object[] srRow in sqlresult)
{
var sr = CreateServiceRecord(srRow, serviceDict);
_AllServiceRecords.Add(sr);
}
}
}
private static StundenkontoServiceRecord CreateServiceRecord(object[] sqlRow, Dictionary<long, ServiceDescriptionDC> serviceDict)
{
var dc = new StundenkontoServiceRecord();
//"SELECT Oid, StartDate, EndDate, RoundedDuration, GroupEmployeeCount, GroupPersonCount, GroupRoundedDuration, GroupOid, DistanceInMeter, Betrag, CostBearer2SupportConceptOid, ServiceDescriptionOid, CustomerOid, EmployeeOid FROM servicerecord";
dc.ServiceRecordOid = (long?)sqlRow[0];
dc.Start = (DateTime)sqlRow[1];
dc.End = (DateTime)sqlRow[2];
dc.RoundedDuration = (decimal)sqlRow[3];
dc.GroupEmployeeCount = (int?)sqlRow[4];
dc.GroupPersonCount = (int?)sqlRow[5];
dc.GroupRoundedDuration = (decimal?)sqlRow[6];
dc.GroupOid = (long?)sqlRow[7];
var test = sqlRow[8];
if (test != null)
{
decimal meter = 0;
if (Decimal.TryParse(test.ToString(), out meter))
{
dc.DistanceInMeter = meter;
}
}
dc.Betrag = (decimal?)sqlRow[9];
dc.CostBearer2SupportConceptOid = (long?)sqlRow[10];
long? sdOid = (long?)sqlRow[11];
if (sdOid.HasValue && serviceDict.ContainsKey(sdOid.Value))
{
dc.ServiceDescription = serviceDict[sdOid.Value];
}
dc.CustomerOid = (long?)sqlRow[12];
dc.EmployeeOid = (long?)sqlRow[13];
dc.Notice = (String)sqlRow[14];
dc.Notice2 = (String)sqlRow[15];
dc.Notice3 = (String)sqlRow[16];
dc.InsUser = (String)sqlRow[17];
dc.InsTs = (DateTime?)sqlRow[18];
dc.Relevance = (int?)sqlRow[19];
return dc;
}
private static 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;
}
// Bei Abwesenheiten ohne Endatum kommt es im Stundenkonto zu massiven Fehlberechnungen. Daher soll ab dem Release 04/2025
// auf dem Ausdruck ein Hinweis stehen, der auf solche Abwesenheiten hinweist und die Namen nennt, bei denen solche eingetragen wurden.
private static string CreateAbsenceNotice(DateTime reportStartDate, DateTime reportEndDate, List<EmployeeDetail> employeeDetailList)
{
// String, in dem alle Mitarbeitenden mit Abwesenheiten ohne Enddatum gesammelt werden, um damit eine Warnung zu erstellen
string mitarbeiterMitAbwesenheitenOhneEnde = "";
foreach (var empDetail in employeeDetailList)
{
var absTimes = empDetail.Employee.AbsenceTimes.Where(a => a.Start <= reportStartDate).ToList();
if (absTimes.Any(a => a.Start <= reportEndDate && !a.End.HasValue))
{
mitarbeiterMitAbwesenheitenOhneEnde += empDetail.FirstName + " " + empDetail.LastName + ", ";
// Im EmployeeDetail gibt es auch einen Warnungsstring, damit in der Tages- und Jahressicht nur bei den wirklich betroffenen
// eine Warnung steht. In den Ansicheren werden ja pro Person eine Seite erstellt, nicht eine Seite für alle.
empDetail.AbsenceString = "Warnung: Bei " + empDetail.FirstName + " " + empDetail.LastName + " kann es durch Abwesenheiten ohne Enddatum zu Fehlberechnungen gekommen sein.";
}
}
// Warnungsstring für die Monatsansicht erstellen. Hier werden die Personennamen alle hintereinander gesetzt,
// da ja alle auf einer Seite stehen.
string absenceNotice = "";
if (!mitarbeiterMitAbwesenheitenOhneEnde.IsNullOrEmpty())
{
mitarbeiterMitAbwesenheitenOhneEnde = mitarbeiterMitAbwesenheitenOhneEnde.Remove(mitarbeiterMitAbwesenheitenOhneEnde.Length - 2, 1);
// Wenn es nur eine Person gibt, die eine Warnung auslösen soll
if (!mitarbeiterMitAbwesenheitenOhneEnde.Contains(','))
absenceNotice = "Warnung: Bei " + mitarbeiterMitAbwesenheitenOhneEnde + "kann es durch Abwesenheiten ohne Enddatum zu Fehlberechnungen gekommen sein.";
// Wenn es mehrere Personen gibt, für die gewarnt werden soll
else
absenceNotice = "Warnung: Bei folgenden Mitarbeitenden kann es durch Abwesenheiten ohne Enddatum zu Fehlberechnungen gekommen sein:\n"
+ mitarbeiterMitAbwesenheitenOhneEnde;
}
return absenceNotice;
}
public class TeamDetail
{
private List<EmployeeDetail> _EmployeeDetailList = new List<EmployeeDetail>();
public string TeamName { get; set; }
public Employee TeamLeader { get; set; }
public decimal SollGesamt { get; set; }
public decimal FlsSollGesamt { get; set; }
public decimal FlsIstGesamt { get; set; }
public decimal FlsDiffGesamt { get; set; }
public decimal StundenGesamt { get; set; }
public decimal RelationIstSollGesamt { get; set; }
public decimal MittelbarIst { get; set; }
public decimal RelationFlsZuMittelbar { get; set; }
public List<EmployeeDetail> EmployeeDetailList
{
get
{
return this._EmployeeDetailList;
}
set
{
this._EmployeeDetailList = value;
}
}
}
[DebuggerDisplay("{LastName}, {FirstName}")]
public class EmployeeDetail
{
public IList<Team> Teams { get; set; }
public IList<DayDetail> Days { get; set; }
public IList<StundenkontoServiceRecord> AllServiceRecords { get; set; }
public IList<StundenkontoServiceRecord> ServiceRecordsInSelectedTimeSpan { get; set; }
public Employee Employee { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
public bool HasContract { get; set; }
public decimal FlsIst { get; set; }
public decimal MittelbarIst { get; set; }
public decimal Bu { get; set; }
public decimal StundenSollMax { get; set; }
//FLS Max - Urlaub/Krankheit und Fortbildung
public decimal StundenSollOhneUrlaubKrankheit { get; set; }
public decimal FlsSoll { get; set; }
public decimal FlsDiff { get; set; }
public decimal? Fehlzeiten { get; set; }
public decimal? TageUrlaub { get; set; }
public decimal? TageKrankheit { get; set; }
public decimal? UrlaubUndKrankheit { get; set; }
public decimal? UrlaubGesamtImAktuellenJahr { get; set; }
public decimal? UrlaubSoll { get; set; }
public decimal? UrlaubsKonto { get; set; }
public decimal StundenMittelbarIst { get; set; }
public decimal StundenGesamtIst { get; set; }
public decimal RelationFlsZuMittelbar { get; set; }
public decimal RelationIstSoll { get; set; }
public decimal? Ueberstunden { get; set; }
public decimal? UeberstundenVormonat { get; set; }
public decimal? UeberstundenGesamt { get; set; }
public decimal UeberstundenAusbezahlt { get; set; }
public decimal WorkDaysThisMonth { get; set; }
public decimal SollProTag { get; set; }
public decimal SollProWoche { get; set; }
public decimal Custom1 { get; set; }
public decimal Custom2 { get; set; }
public decimal Custom3 { get; set; }
public decimal Custom4 { get; set; }
public decimal Custom5 { get; set; }
public decimal Custom6 { get; set; }
public decimal Custom7 { get; set; }
public decimal Custom8 { get; set; }
public decimal Custom9 { get; set; }
public decimal Custom10 { get; set; }
public decimal Custom11 { get; set; }
public decimal Custom12 { get; set; }
public decimal Custom13 { get; set; }
public decimal Custom14 { get; set; }
public decimal Custom15 { get; set; }
public decimal Custom16 { get; set; }
public decimal Custom17 { get; set; }
public decimal Custom18 { get; set; }
public decimal Custom19 { get; set; }
public decimal Custom20 { get; set; }
public decimal Custom21 { get; set; }
public decimal Custom22 { get; set; }
public decimal Custom23 { get; set; }
public decimal Custom24 { get; set; }
public decimal Custom25 { get; set; }
public String Regelarbeitszeit { get; set; }
public int ArbeitstageProWoche { get; set; }
public decimal ArbeitstageImBerichtszeitraum { get; set; }
public AbsenceTimeDays AbsenceTimeDays { get; set; }
public decimal? HourlyRate { get; set; }
public decimal? WeeklyFLS { get; set; }
public decimal? EmployeeSalaryByContract { get; set; }
public decimal? EmployeeSalaryByHours { get; set; }
public EmploymentType EmploymentType { get; set; }
public decimal DienstplanIst { get; set; }
public string AbsenceString { get; set; }
public decimal Resturlaub{ get; set; }
}
[DebuggerDisplay("{Date}: {MinutesTotal}")]
public class DayDetail
{
public DateTime Date { get; set; }
public DateTime? StartDateTime1 { get; set; }
public DateTime? EndDateTime1 { get; set; }
public DateTime? StartDateTime2 { get; set; }
public DateTime? EndDateTime2 { get; set; }
public DateTime? StartDateTime3 { get; set; }
public DateTime? EndDateTime3 { get; set; }
public DateTime? StartDateTime4 { get; set; }
public DateTime? EndDateTime4 { get; set; }
public decimal HoursSaturday { get; set; }
public decimal HoursSunday { get; set; }
public decimal HoursHoliday { get; set; }
public decimal HoursHoliday2 { get; set; }
public IList<AbsenceTime> AbsenceTimes { get; set; }
public decimal HoursInVacation { get; set; }
public decimal HoursSick { get; set; }
public decimal HoursOtherAbsenceTimes { get; set; }
decimal test = 0;
public decimal MinutesTotal
{
get { return test; }
set
{
if (Date == new DateTime(2024, 5, 1))
{
int test2 = 0;
}
test = value;
}
}
public String TimeInVacation { get; set; }
public String TimeSick { get; set; }
public String TimeOtherAbsenceTimes { get; set; }
public String TimeTotal { get; set; }
public decimal SollStunden { get; set; }
public String Custom1 { get; set; }
public String Custom2 { get; set; }
public String Custom3 { get; set; }
public String Custom4 { get; set; }
public String Custom5 { get; set; }
public String Custom6 { get; set; }
public String Custom7 { get; set; }
public String Custom8 { get; set; }
public String Custom9 { get; set; }
public String Custom10 { get; set; }
public IList<StundenkontoServiceRecord> ServiceRecords { get; set; }
public int? NightStart { get; set; }
public int? NightEnd { get; set; }
public int? MaxHoursUntilBreak { get; set; }
public decimal PauseInMinuten { get; set; }
public int? BreakMinutes { get; set; }
public int? MaxHoursUntilBreak2 { get; set; }
public int? BreakMinutes2 { get; set; }
public decimal SpecialHours { get; set; }
public FeiertagDC Feiertag { get; set; }
public bool IstFeiertag
{
get { return Feiertag != null; }
}
public bool IstSamstag
{
get { return Date.DayOfWeek == DayOfWeek.Saturday; }
}
public bool IstSonntag
{
get { return Date.DayOfWeek == DayOfWeek.Sunday; }
}
public IList<DateTimeSpan> ZusammenhaengendeZeitraeume { get; set; }
public String ZeitraeumeString
{
get
{
String str = "";
if (AbsenceTimes != null)
{
foreach (var at in AbsenceTimes)
{
if (at.AbsenceReason != null)
{
if (str.Length > 0)
{
str += ", ";
}
str += at.AbsenceReason.Description;
}
}
}
if (Feiertag != null && !String.IsNullOrEmpty(Feiertag.Name))
{
str = Feiertag.Name;
}
if (ZusammenhaengendeZeitraeume != null)
{
foreach (var dts in ZusammenhaengendeZeitraeume)
{
if (dts.StartDateTime != dts.EndDateTime)
{
if (str.Length > 0)
{
str += ", ";
}
str += String.Format("{0:HH:mm} - {1:HH:mm}", dts.StartDateTime, dts.EndDateTime);
}
}
}
return str;
}
}
}
public static EmployeeDetail CreateEmployeeDetail(Employee employee, Team team)
{
var employeeDetail = new EmployeeDetail
{
Teams = team == null ? DAOFactory.SearchDAO.FindTeamsOfEmployee(employee.Oid.Value) : new List<Team> { team },
Employee = employee,
LastName = employee.Person.LastName,
FirstName = employee.Person.FirstName,
FullName = $"{employee.Person.LastName}, {employee.Person.FirstName}"
};
return employeeDetail;
}
}
}