using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using BeWo.Data; using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.DCEntityMapper; using BS.Shared.DataContracts; using BS.Shared.DataContracts.Compact; using BS.Shared.Extensions; using Utils = BeWo.Service.Core.Utils; namespace BeWo.Report.ReportObjects { public class KalenderRO : AbstractBeWoReportObject { public string PrintingEmployee { get; set; } public List Appointments { get; set; } public List KalenderTageSortiert { get; set; } public Dictionary Wochen { get; set; } public string PrintingDate => DateTime.Now.ToShortDateString(); public List SelectedDates { get; set; } public List AbsenceTimeOids { get; set; } = new List(); public static KalenderRO Create(IEnumerable appointmentOids, long? employeeOid, IEnumerable serientermine, IEnumerable selectedDates, IEnumerable mehrtaegigeTermine) { var appointments = DAOFactory.GenericDAO.LoadByIDs(appointmentOids); var employeeName = DAOFactory.GenericDAO.GetByID(employeeOid.Value).Person.FirstNameLastName; var kalendertage = new HashSet(); var wochen = new Dictionary(); var recurringAppointments = CreateRecurringAppointments(serientermine); var mapper = new SchedulerAppointmentDC_SchedulerAppointment(); var recurringSchedulerAppointments = mapper.MapToNewEntities(recurringAppointments); var mehrtaegigeSchedulerAppointments = mapper.MapToNewEntities(mehrtaegigeTermine); appointments.AddRange(mehrtaegigeSchedulerAppointments); appointments.AddRange(recurringSchedulerAppointments); appointments = appointments.Where(w => w.StartDate != null && selectedDates.Any(a => a.CompareShortDates(w.StartDate.Value))).OrderBy(o => o.StartDate).ToList(); // ganztägige Termine beachten foreach (var app in appointments) { var datum = app.StartDate.Value.ToString("dd. MMMM yyyy"); if (!kalendertage.Any(k => k.Datum.Equals(datum))) { kalendertage.Add(new KalenderTag(new List {new AppointmentStruct {Appointment = DAOFactory.GenericDAO.Unproxy(app)}})); } else { var kt = kalendertage.First(f => f.Datum.Equals(datum)); kt.Termine.Add(new AppointmentStruct { Appointment = DAOFactory.GenericDAO.Unproxy(app) }); } } Calendar calendar = new GregorianCalendar(); foreach (var kalendertag in kalendertage) { var wt = calendar.GetWeekOfYear(kalendertag.Date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); if (wochen.ContainsKey(wt)) { wochen[wt].AddDayToWeek(kalendertag); } else { wochen.Add(wt, new KalenderWoche(wt, kalendertag)); } } return new KalenderRO { Appointments = appointments, PrintingEmployee = employeeName, KalenderTageSortiert = kalendertage.ToList().OrderBy(o=>o.Date).ToList(), Wochen = wochen, SelectedDates = selectedDates.ToList() }; } public static KalenderRO CreateWithAbsenceTimes(IEnumerable appointmentOids, long? employeeOid, IEnumerable serientermine, IList selectedDates, IEnumerable mehrtaegigeTermine, List absenceTimeOids) { var appointments = DAOFactory.GenericDAO.LoadByIDs(appointmentOids); var employeeName = DAOFactory.GenericDAO.GetByID(employeeOid.Value).Person.FirstNameLastName; var kalendertage = new HashSet(); var wochen = new Dictionary(); var absenceTimes = MapperFactory.AbsenceTimeDC_AbsenceTime.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs(absenceTimeOids)); var absenceTimeEmployees = MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs(absenceTimes.Where(at => at.EmployeeOid.HasValue).Select(at => at.EmployeeOid.Value))); var absenceTimeCustomers = MapperFactory.CompactCustomerDC_Customer.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs(absenceTimes.Where(at => at.CustomerOid.HasValue).Select(at => at.CustomerOid.Value))); var mehrtaegigeAbwesenheiten = GenerateSeveralDaysAbsenceTimeAppointments(absenceTimes.Where(absenceTime => absenceTime.Start.HasValue && (absenceTime.End is null || absenceTime.Start.Value.GetDayNumberBetweenTwoDates(absenceTime.End.Value) > 0)).ToList(), selectedDates.ToList(), absenceTimeEmployees, absenceTimeCustomers); var eintagsabwesenheiten = ConvertSingleDayAbsenceTimes(absenceTimes.Where(w => w.Start.HasValue && w.End.HasValue && w.Start.Value.GetDayNumberBetweenTwoDates(w.End.Value) == 0).ToList(), selectedDates.ToList()); var recurringAppointments = CreateRecurringAppointments(serientermine); var mapper = new SchedulerAppointmentDC_SchedulerAppointment(); var recurringSchedulerAppointments = mapper.MapToNewEntities(recurringAppointments); var mehrtaegigeSchedulerAppointments = mapper.MapToNewEntities(mehrtaegigeTermine); appointments.AddRange(mapper.MapToNewEntities(eintagsabwesenheiten)); appointments.AddRange(mapper.MapToNewEntities(mehrtaegigeAbwesenheiten)); appointments.AddRange(mehrtaegigeSchedulerAppointments); appointments.AddRange(recurringSchedulerAppointments); appointments = appointments.Where(w => w.StartDate.HasValue && selectedDates.Any(a => a.CompareShortDates(w.StartDate.Value))).OrderBy(o => o.StartDate).ToList(); // Die KalenderTag-Objekte werden aus SchedulerAppointments erstellt CreateKalendertage(kalendertage, appointments); CreateKalenderwochen(wochen, kalendertage); return new KalenderRO { Appointments = appointments, PrintingEmployee = employeeName, KalenderTageSortiert = kalendertage.ToList().OrderBy(o => o.Date).ToList(), Wochen = wochen, SelectedDates = selectedDates.ToList(), AbsenceTimeOids = absenceTimeOids }; } public static List GenerateSeveralDaysAbsenceTimeAppointments(List absenceTimes, List selectedDates, List employees, List customers) { var intervalEnd = selectedDates[0]; var intervalStart = selectedDates[0]; foreach(var date in selectedDates) { if(date > intervalEnd) { intervalEnd = date; } if(date < intervalStart) { intervalStart = date; } } var result = new List(); foreach(var absenceTime in absenceTimes) { if(absenceTime.Start is null) { continue; } if(absenceTime.End is null) { absenceTime.End = intervalEnd.AddDays(1); } var employee = employees.FirstOrDefault(e => e.EmployeeOid.Equals(absenceTime.EmployeeOid)); var customer = customers.FirstOrDefault(c => c.CustomerOid.Equals(absenceTime.CustomerOid)); var isAllDayAbsenceTime = absenceTime.Start.Value.IsTimeZero() && absenceTime.End.Value.IsTimeZero(); // Bei einem Tag gibt die Funktion 0 zurück! var dayCount = absenceTime.Start.Value.GetDayNumberBetweenTwoDates(absenceTime.End.Value) + 1; if(dayCount > 31) { dayCount = 31; } if(dayCount > 0) { if(isAllDayAbsenceTime) { for(var i = 0; i < dayCount; i++) { var startDate = new DateTime(absenceTime.Start.Value.AddDays(i).Year, absenceTime.Start.Value.AddDays(i).Month, absenceTime.Start.Value.AddDays(i).Day); var endDate = new DateTime(absenceTime.Start.Value.AddDays(i + 1).Year, absenceTime.Start.Value.AddDays(i + 1).Month, absenceTime.Start.Value.AddDays(i + 1).Day); if(startDate < intervalStart || startDate > intervalEnd) { continue; } result.Add(CreateAppointmentFromAbsenceTime(startDate, endDate, absenceTime, employee, customer)); } } else { for(var i = 0; i < dayCount; i++) { DateTime startDate; DateTime endDate; if(i == 0) { startDate = absenceTime.Start.Value; endDate = new DateTime(absenceTime.Start.Value.AddDays(1).Year, absenceTime.Start.Value.AddDays(1).Month, absenceTime.Start.Value.AddDays(1).Day); } else if(i == dayCount - 1) { startDate = new DateTime(absenceTime.End.Value.Year, absenceTime.End.Value.Month, absenceTime.End.Value.Day); endDate = absenceTime.End.Value; } else { startDate = new DateTime(absenceTime.Start.Value.AddDays(i).Year, absenceTime.Start.Value.AddDays(i).Month, absenceTime.Start.Value.AddDays(i).Day); endDate = new DateTime(absenceTime.Start.Value.AddDays(i + 1).Year, absenceTime.Start.Value.AddDays(i + 1).Month, absenceTime.Start.Value.AddDays(i + 1).Day); } if(startDate < intervalStart || startDate > intervalEnd) { continue; } result.Add(CreateAppointmentFromAbsenceTime(startDate, endDate, absenceTime, employee, customer)); } } } } return result; } private static SchedulerAppointmentDC CreateAppointmentFromAbsenceTime(DateTime start, DateTime end, AbsenceTimeDC absenceTime, CompactEmployeeDC employee, CompactCustomerDC customer) { if(employee is null && customer is null) { throw new ArgumentNullException(nameof(employee), "employee und customer dürfen nicht beide null sein!"); } var isCustomerAbsenceTime = employee is null; var originator = MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(DAOFactory.SearchDAO.FindEmployeeByFullname(absenceTime.InsUser)); if(originator is null) { if(isCustomerAbsenceTime) { var user = LoggedInUserOperationContextExt.Current?.User != null ? LoggedInUserOperationContextExt.Current.User : SessionFacade.LoggedInUser; if(user?.Employee is null) { return null; } originator = MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(user.Employee); } else { originator = employee; } } var simpleDescription = isCustomerAbsenceTime ? customer.SimpleDescription : employee.SimpleDescription; var isAllDay = start.IsTimeZero() && end.IsTimeZero(); var appointment = new SchedulerAppointmentDC { AllDay = isAllDay, StartDate = start, EndDate = end, Originator = originator, Subject = $"{absenceTime.Reason} ({simpleDescription})" }; #if DEBUG appointment.Subject = $"({(isCustomerAbsenceTime ? "K" : "M")}{absenceTime.AbsenceTimeOid}) {absenceTime.Reason} ({simpleDescription})"; #endif return appointment; } public static List CreateRecurringAppointments(IEnumerable serientermine) { var recurringAppointments = serientermine.ToList(); var recurrenceIds2Appointments = new Dictionary>(); var test = recurringAppointments.Where(w => !(w.RecurrenceInfo is null)).Select(s => s.RecurrenceInfo).ToList(); foreach(var recurrenceInfo in test) { var id = Utils.GetRecurrenceIdFromRecurrenceInfo(recurrenceInfo); if(!recurrenceIds2Appointments.ContainsKey(id)) { recurrenceIds2Appointments.Add(id, new List()); } } foreach(var kvp in recurrenceIds2Appointments) { kvp.Value.AddRange(DAOFactory.SearchDAO.FindDeletedRecurrencesByRecurrenceId(kvp.Key).ToList()); } foreach(var kvp in recurrenceIds2Appointments) { foreach(var appointment in kvp.Value) { var start = appointment.StartDate; var end = appointment.EndDate; var theOneToDelete = recurringAppointments.FirstOrDefault(w => w.RecurrenceInfo.Contains(kvp.Key) && w.StartDate == start && w.EndDate == end); if(!(theOneToDelete is null)) { recurringAppointments.Remove(theOneToDelete); } } } return recurringAppointments; } public static void CreateKalendertage(HashSet kalendertage, List appointments) { foreach(var app in appointments) { if(app.StartDate is null) { continue; } var datum = app.StartDate.Value.ToString("dd. MMMM yyyy"); if(!kalendertage.Any(k => k.Datum.Equals(datum))) { kalendertage.Add(new KalenderTag(new List { new AppointmentStruct { Appointment = DAOFactory.GenericDAO.Unproxy(app) } })); } else { var kt = kalendertage.First(f => f.Datum.Equals(datum)); kt.Termine.Add(new AppointmentStruct { Appointment = DAOFactory.GenericDAO.Unproxy(app) }); } } } public static void CreateKalenderwochen(Dictionary weeks, HashSet kalendertage) { Calendar calendar = new GregorianCalendar(); foreach(var kalendertag in kalendertage) { var weekOfYear = calendar.GetWeekOfYear(kalendertag.Date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); if(weeks.ContainsKey(weekOfYear)) { weeks[weekOfYear].AddDayToWeek(kalendertag); } else { weeks.Add(weekOfYear, new KalenderWoche(weekOfYear, kalendertag)); } } } /// /// Konvertiert AbsenceTimeDCs in SchedulerAppointmentDCs von eintägigen Abwesenheiten. /// /// Die eintägiten Abwesenheiten. /// Zeitraum der ausgedruckt werden soll. /// public static List ConvertSingleDayAbsenceTimes(List absenceTimes, List selectedDates) { var result = new List(); var lastDate = selectedDates[0]; foreach(var date in selectedDates) { if(date < lastDate) { lastDate = date; } } var employees = MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs(absenceTimes.Where(absenceTime => absenceTime.EmployeeOid.HasValue).Select(absenceTime => absenceTime.EmployeeOid.Value))); var customers = MapperFactory.CompactCustomerDC_Customer.MapToNewDCs(DAOFactory.GenericDAO.LoadByIDs(absenceTimes.Where(absenceTime => absenceTime.CustomerOid.HasValue).Select(absenceTime => absenceTime.CustomerOid.Value))); foreach(var absenceTime in absenceTimes) { var appointment = ConvertAbsenceTimeToAppointment(absenceTime, lastDate, employees, customers); if(!(appointment is null)) { result.Add(appointment); } } return result; } public static SchedulerAppointmentDC ConvertAbsenceTimeToAppointment(AbsenceTimeDC absenceTime, DateTime intervalEnd, List employees, List customers) { if(absenceTime.Start is null) { return null; } var employee = absenceTime.EmployeeOid.HasValue ? employees.FirstOrDefault(emp => emp.EmployeeOid == absenceTime.EmployeeOid.Value) : null; var customer = absenceTime.CustomerOid.HasValue ? customers.FirstOrDefault(cus => cus.CustomerOid == absenceTime.CustomerOid.Value) : null; var isEmployeeAbsenceTime = !(employee is null); var originator = MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(DAOFactory.SearchDAO.FindEmployeeByFullname(absenceTime.InsUser)); if(isEmployeeAbsenceTime && originator is null) { originator = employee; } if(!isEmployeeAbsenceTime && originator is null) { var user = LoggedInUserOperationContextExt.Current?.User != null ? LoggedInUserOperationContextExt.Current.User : SessionFacade.LoggedInUser; if(user?.Employee is null) { return null; } originator = MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(user.Employee); } var lastNameCommaFirstName = isEmployeeAbsenceTime ? employee.SimpleDescription : customer?.SimpleDescription; var endDate = intervalEnd; if(absenceTime.End.HasValue) { endDate = absenceTime.End.Value; } var isAllDay = absenceTime.Start.Value.IsTimeZero() && endDate.IsTimeZero(); var appointment = new SchedulerAppointmentDC { AllDay = isAllDay, StartDate = absenceTime.Start.Value, EndDate = endDate, Originator = originator, Subject = $"{absenceTime.Reason} ({lastNameCommaFirstName})" }; #if DEBUG appointment.Subject = $"({(isEmployeeAbsenceTime ? "M" : "K")}{absenceTime.AbsenceTimeOid}) {absenceTime.Reason} ({lastNameCommaFirstName})"; #endif return appointment; } } public class KalenderWoche { public KalenderTag Montag { get; set; } public KalenderTag Dienstag { get; set; } public KalenderTag Mittwoch { get; set; } public KalenderTag Donnerstag { get; set; } public KalenderTag Freitag { get; set; } public KalenderTag Samstag { get; set; } public KalenderTag Sonntag { get; set; } public int Wochennummer { get; set; } public KalenderWoche(int wochennummer, KalenderTag kalenderTag) { Wochennummer = wochennummer; var eWt = kalenderTag.Date.FirstDateOfWeek(wochennummer); Montag = new KalenderTag(new List()) { Datum = eWt.ToShortDateString(), Date = eWt }; Dienstag = new KalenderTag(new List()) { Datum = eWt.AddDays(1).ToShortDateString(), Date = eWt.AddDays(1) }; Mittwoch = new KalenderTag(new List()) { Datum = eWt.AddDays(2).ToShortDateString(), Date = eWt.AddDays(2) }; Donnerstag = new KalenderTag(new List()) { Datum = eWt.AddDays(3).ToShortDateString(), Date = eWt.AddDays(3) }; Freitag = new KalenderTag(new List()) { Datum = eWt.AddDays(4).ToShortDateString(), Date = eWt.AddDays(4) }; Samstag = new KalenderTag(new List()) { Datum = eWt.AddDays(5).ToShortDateString(), Date = eWt.AddDays(5) }; Sonntag = new KalenderTag(new List()) { Datum = eWt.AddDays(6).ToShortDateString(), Date = eWt.AddDays(6) }; AddDayToWeek(kalenderTag); } public void AddDayToWeek(KalenderTag day) { switch (day.Date.DayOfWeek) { case DayOfWeek.Monday: Montag = day; break; case DayOfWeek.Tuesday: Dienstag = day; break; case DayOfWeek.Wednesday: Mittwoch = day; break; case DayOfWeek.Thursday: Donnerstag = day; break; case DayOfWeek.Friday: Freitag = day; break; case DayOfWeek.Saturday: Samstag = day; break; case DayOfWeek.Sunday: Sonntag = day; break; } } } public class KalenderTag { public string Datum { get; set; } public DateTime Date { get; set; } public List Termine { get; set; } public KalenderTag(List termine) { Termine = termine; Datum = termine.Count > 0 ? termine.First().Appointment.StartDate.Value.ToString("dd. MMMM yyyy") : string.Empty; if (termine.Count > 0) { var d = termine.First().Appointment.StartDate.Value; Date = new DateTime(d.Year, d.Month, d.Day); } } } public struct AppointmentStruct { public string VonBisString { get { var result = string.Empty; if (Appointment.AllDay) { result = "Ganztägig"; } else { result = Appointment.StartDate.HasValue ? $"{Appointment.StartDate.Value.ToShortTimeString()} - {Appointment.EndDate.Value.ToShortTimeString()}" : string.Empty; } return result; } } public string SubjectLocationString => !string.IsNullOrEmpty(Appointment.Location) ? $"{Appointment.Subject} ({Appointment.Location})" : Appointment.Subject; public SchedulerAppointment Appointment { get; set; } } }