From 3e9f656d14b30ccdd2fb7e2ab6b3e55fb07bf07a Mon Sep 17 00:00:00 2001 From: Lyndon Date: Fri, 22 Dec 2017 18:09:52 -0400 Subject: [PATCH 1/3] Die Termine werden jetzt wieder korrekt gedruckt. --- Data/Access/SearchDAO.cs | 204 +++++++++--------- Report/ReportObjects/KalenderRO.cs | 64 ++++-- Service/Core/Utils.cs | 43 ++++ Service/Service.csproj | 3 + .../ResourceServiceImp.cs | 68 +++++- 5 files changed, 265 insertions(+), 117 deletions(-) diff --git a/Data/Access/SearchDAO.cs b/Data/Access/SearchDAO.cs index 46b2652ce..2a087ed68 100644 --- a/Data/Access/SearchDAO.cs +++ b/Data/Access/SearchDAO.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; - +using System.Text.RegularExpressions; using BeWo.Data.Entities; using BS.Shared.Extensions; @@ -1170,7 +1170,8 @@ namespace BeWo.Data.Access return c.List().Count > 0; } - public bool OverlappingAppointmentsExist(DateTime start, DateTime end, IEnumerable employees, IEnumerable customers, IEnumerable resources, long originator, long? appointmentOid, string recurrenceId = "", int occurrenceIndex = 0) + //TODO: Hier vielleicht die neue CreateRecurrenceCriteria-Methode benutzen? + public bool OverlappingAppointmentsExist(DateTime start, DateTime end, IEnumerable employees, IEnumerable customers, IEnumerable resources, long originator, long? appointmentOid, string recurrenceId = "", int occurrenceIndex = 0) { var criteria = CreateCriteria() .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active)) @@ -1275,8 +1276,7 @@ namespace BeWo.Data.Access var recId = GetSpecificValueFromRecurrenceInfo(a.RecurrenceInfo, a.RecurrenceInfo.IndexOf("Id=\"") + 4); var index = GetSpecificValueFromRecurrenceInfo(a.RecurrenceInfo, a.RecurrenceInfo.IndexOf("Index=\"") + 7); - int intIndex; - Int32.TryParse(index, out intIndex); + int.TryParse(index, out var intIndex); return !(recurrenceId.Equals(recId) && occurrenceIndex == intIndex); }); @@ -1286,65 +1286,33 @@ namespace BeWo.Data.Access var oidList = new List(); foreach (var appointment in schedulerAppointments) { - oidList.AddRange(appointment.EmployeeList.Select(rel => (rel.ParticipationAnswer != ParticipationAnswer.Absage && rel.Employee.Oid != null) ? rel.Employee.Oid.Value : 0)); + oidList.AddRange(appointment.EmployeeList.Select(rel => rel.ParticipationAnswer != ParticipationAnswer.Absage && rel.Employee.Oid != null ? rel.Employee.Oid.Value : 0)); } var emp = oidList.Intersect(employees).Any(); - var cus = schedulerAppointments.Any(app => app.CustomerList.Select(c => c.Oid != null ? c.Oid.Value : 0).Intersect(customers).Any()); - var res = schedulerAppointments.Any(app => app.ResourceList.Select(r => r.Oid != null ? r.Oid.Value : 0).Intersect(resources).Any()); + var cus = schedulerAppointments.Any(app => app.CustomerList.Select(c => c.Oid ?? 0).Intersect(customers).Any()); + var res = schedulerAppointments.Any(app => app.ResourceList.Select(r => r.Oid ?? 0).Intersect(resources).Any()); var ori = schedulerAppointments.Any(app => app.Originator.Oid.HasValue && app.Originator.Oid.Value == originator && (app.EmployeeList.Count == 0 || app.EmployeeList.Any(a => a.Employee.Oid.HasValue && a.Employee.Oid.Value == originator))); return emp || cus || res || ori; } - public IEnumerable GetAllActiveAppointmentsForEmployeeInInterval(DateTime start, DateTime end, long pEmployeeOid) + public IEnumerable GetAllActiveAppointmentsForEmployeeInInterval(DateTime start, DateTime end, long pEmployeeOid) { - var detachedCriteria = DetachedCriteria.For() - .Add(Restrictions.And(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", pEmployeeOid), - Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Absage)))); - detachedCriteria.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment)); - - var recurrenceBetween = string.Format("'{0:yyyy-MM-dd} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", start, SchedulerAppointment.PropertyName_RecurrenceInfo); - var hasResources = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM resource2newschapp)"; - var criteria = CreateCriteria() - .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active)) - .Add(Restrictions.Or( - Restrictions.And( - Restrictions.Not(Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "Range", MatchMode.Anywhere)), - Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "OccurrenceCount=\"10\"", MatchMode.Anywhere)), - Restrictions.Or( - Restrictions.Or( - Restrictions.And(Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end), Restrictions.Ge(SchedulerAppointment.PropertyName_EndDate, start)), - Restrictions.And(Restrictions.IsNotNull(SchedulerAppointment.PropertyName_RecurrenceInfo), Expression.Sql(new SqlString(recurrenceBetween)))), - Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Type, 3), Expression.Sql(new SqlString(recurrenceBetween)))))) + var criteria = CreateRecurrenceCriteria(start, end) .Add(Restrictions.Or( Expression.Sql(new SqlString(hasResources)), - Restrictions.Or( - Restrictions.Eq(SchedulerAppointment.PropertyName_Originator + ".Oid", pEmployeeOid), - Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria)))); + CreateOwnAppointmentsCriteria(pEmployeeOid))); return criteria.List(); } public IEnumerable GetAllActiveAppointmentsInInterval(DateTime start, DateTime end) { - var recurrenceBetween = string.Format("'{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", start.ToString("yyyy-MM-dd"), SchedulerAppointment.PropertyName_RecurrenceInfo); - - var criteria = CreateCriteria() - .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active)) - .Add(Restrictions.Or( - Restrictions.And(Restrictions.Not(Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "Range", MatchMode.Anywhere)), - Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "OccurrenceCount=\"10\"", MatchMode.Anywhere)), - Restrictions.Or( - Restrictions.Or( - Restrictions.And(Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end), Restrictions.Ge(SchedulerAppointment.PropertyName_EndDate, start)), - Restrictions.And(Restrictions.IsNotNull(SchedulerAppointment.PropertyName_RecurrenceInfo), Expression.Sql(new SqlString(recurrenceBetween)))), - Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Type, 3), Expression.Sql(new SqlString(recurrenceBetween)))))); - - return criteria.List(); + return CreateRecurrenceCriteria(start, end).List(); } private static string GetSpecificValueFromRecurrenceInfo(string str, int startIndex) @@ -1431,14 +1399,15 @@ namespace BeWo.Data.Access return c.List(); } - // Veraltet + // Veraltet. Wird nicht mehr benutzt public IEnumerable FindAppointmentsForPrintingForEmployee(long employeeOid, List selectedDates, List userRights) { - var abfrage = string.Format("SELECT Oid FROM newschedulerappointment WHERE IsActive = 1 AND "); + var abfrage = "SELECT Oid FROM newschedulerappointment WHERE IsActive = 1 AND "; var or = string.Empty; foreach (var d in selectedDates) { + // TODO: RecurrenceInfo hat nicht immer ein Enddatum or += string.Format("StartDate LIKE '{0}%' OR RecurrenceInfo IS NOT NULL AND '{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", d.ToString("yyyy-MM-dd"), SchedulerAppointment.PropertyName_RecurrenceInfo); if (selectedDates.IndexOf(d) < selectedDates.Count - 1) { @@ -1487,30 +1456,21 @@ namespace BeWo.Data.Access Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, ParticipationAnswer.Absage)))); detachedCriteria.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment)); - var recurrenceBetween = String.Format("'{0} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", - start.ToString("yyyy-MM-dd"), - SchedulerAppointment.PropertyName_RecurrenceInfo); + var hasResources = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM resource2newschapp)"; - var hasResources = String.Format("{0} IN (SELECT newschappoid FROM resource2newschapp)", BeWoEntityBase.PropertyName_Oid); + var detachedCriteria2 = DetachedCriteria.For() + .SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment)); - var criteria = CreateCriteria() - .Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active)) - .Add(Restrictions.Or( - Restrictions.And( - Restrictions.Not(Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "Range", MatchMode.Anywhere)), - Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, "OccurrenceCount=\"10\"", MatchMode.Anywhere)), - Restrictions.Or( - Restrictions.Or( - Restrictions.And(Restrictions.Lt(SchedulerAppointment.PropertyName_StartDate, end), Restrictions.Ge(SchedulerAppointment.PropertyName_EndDate, start)), - Restrictions.And(Restrictions.IsNotNull(SchedulerAppointment.PropertyName_RecurrenceInfo), Expression.Sql(new SqlString(recurrenceBetween)))), - Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Type, 3), Expression.Sql(new SqlString(recurrenceBetween)))))) - .Add(Restrictions.Or( + var ownAppointmentCriterion = Restrictions.Or( + Restrictions.And(Restrictions.In(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", pEmployeeOids), Subqueries.PropertyNotIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria2)), + Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria)); + + var criteria = CreateRecurrenceCriteria(start, end) + .Add(Restrictions.Or( Expression.Sql(new SqlString(hasResources)), - Restrictions.Or( - Restrictions.In(SchedulerAppointment.PropertyName_Originator + ".Oid", pEmployeeOids), - Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria)))); + ownAppointmentCriterion)); - return criteria.List(); + return criteria.List(); } public IEnumerable FilterEmployeesWithAppointments(List pEmployeeOids, DateTime pStartTime, DateTime pEndTime) @@ -2329,25 +2289,10 @@ namespace BeWo.Data.Access if (pEmployeeOid.HasValue) { - var detachedCriteria = DetachedCriteria.For() - .Add(Restrictions.And( - Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", pEmployeeOid), - Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, - ParticipationAnswer.Absage)))); - detachedCriteria.SetProjection( - Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment)); - - var detachedCriteria2 = DetachedCriteria.For() - .SetProjection( - Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment)); - - ownAppointmentCriterion = Restrictions.Or( - Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Originator + ".Oid", pEmployeeOid), Subqueries.PropertyNotIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria2)), - Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria)); - + ownAppointmentCriterion = CreateOwnAppointmentsCriteria(pEmployeeOid.Value); } - if (pPrivateAppointmentsOnly) + if(pPrivateAppointmentsOnly) { mainCriteria.Add(Restrictions.Eq(SchedulerAppointment.PropertyName_IsPrivate, true)); } @@ -2393,7 +2338,6 @@ namespace BeWo.Data.Access } } - var blah = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM customer2newschapp WHERE customeroid IN ({list}))"; customerCriterion = Expression.Sql(blah); } @@ -2416,16 +2360,15 @@ namespace BeWo.Data.Access var blah = $"{BeWoEntityBase.PropertyName_Oid} IN (SELECT newschappoid FROM resource2newschapp WHERE resourceoid IN ({list}))"; resourceCriterion = Expression.Sql(blah); } - - var listOfCriterias = new List() + // AND {SchedulerAppointment.PropertyName_RecurrenceInfo} IS NOT NULL AND {SchedulerAppointment.PropertyName_RecurrenceInfo} NOT LIKE '%Index%' + var listOfCriterias = new List { employeeCriterion, customerCriterion, resourceCriterion }; - - if (!pHasRightToSeeAllEmployeeAppointments) + if (!pHasRightToSeeAllEmployeeAppointments && pSelectedEmployees.Count == 0) { mainCriteria.Add(ownAppointmentCriterion); } @@ -2440,7 +2383,55 @@ namespace BeWo.Data.Access { mainCriteria.Add(orCriteria); } - return mainCriteria.List(); + + var appointments = mainCriteria.List(); + + var exceptionalRecurrenceInfos = appointments.Where(w => w.RecurrenceInfo != null && w.Type == 3).ToList(); + + var exceptionIds = new List(); + var regex = new Regex("(Id=\\\"[a-z0-9-]+\\\")"); + foreach(var appointment in exceptionalRecurrenceInfos) + { + var match = regex.Match(appointment.RecurrenceInfo); + if(match.Success) + { + var value = match.Value; + var actualId = value.Split("\""); + if(actualId.Count > 1) + { + var id = actualId[1]; + + if(!appointments.Any(w => w.RecurrenceInfo != null && w.RecurrenceInfo.Contains(id) && w.Type == 1)) + { + exceptionIds.Add(appointment.Oid.Value); + } + } + } + } + + var exceptionsToModify = appointments.Where(w => w.Oid.HasValue && exceptionIds.Contains(w.Oid.Value)).ToList(); + + foreach(var exception in exceptionsToModify) + { + var replacingAppointment = new SchedulerAppointment + { + Oid = exception.Oid.Value * -1, + Version = 1, + Type = 4, + RecurrenceInfo = exception.RecurrenceInfo, + Originator = exception.Originator, + EmployeeList = exception.EmployeeList, + CustomerList = exception.CustomerList, + ResourceList = exception.ResourceList + }; + + exception.RecurrenceInfo = null; + exception.Type = 0; + + appointments.Add(replacingAppointment); + } + + return appointments; } private static ICriterion CreateOrCriteria(IReadOnlyCollection criterionList) @@ -2453,14 +2444,7 @@ namespace BeWo.Data.Access { if (c != null) { - if (orCriterion == null) - { - orCriterion = c; - } - else - { - orCriterion = Restrictions.Or(orCriterion, c); - } + orCriterion = orCriterion == null ? c : Restrictions.Or(orCriterion, c); } } } @@ -2468,6 +2452,25 @@ namespace BeWo.Data.Access return orCriterion; } + private static ICriterion CreateOwnAppointmentsCriteria(long pEmployeeOid) + { + var detachedCriteria = DetachedCriteria.For() + .Add(Restrictions.And( + Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", pEmployeeOid), + Restrictions.Not(Restrictions.Eq(Employee2SchedulerAppointment.PropertyName_ParticipationAnswer, + ParticipationAnswer.Absage)))); + detachedCriteria.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment)); + + var detachedCriteria2 = DetachedCriteria.For() + .SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment)); + + ICriterion ownAppointmentCriterion = Restrictions.Or( + Restrictions.And(Restrictions.Eq(SchedulerAppointment.PropertyName_Originator + ".Oid", pEmployeeOid), Subqueries.PropertyNotIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria2)), + Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria)); + + return ownAppointmentCriterion; + } + private ICriteria CreateRecurrenceCriteria(DateTime start, DateTime end) { var recurrenceBetween = string.Format("'{0:yyyy-MM-dd} 00:00:00' BETWEEN STR_TO_DATE(SUBSTRING({1}, 24, 19), '%m/%d/%Y %H:%i:%s') AND STR_TO_DATE(SUBSTRING({1}, 50, 19), '%m/%d/%Y %H:%i:%s')", start, SchedulerAppointment.PropertyName_RecurrenceInfo); @@ -2495,5 +2498,14 @@ namespace BeWo.Data.Access return criteria; } + + public IList FindDeletedRecurrencesByRecurrenceId(string pRecurrenceId) + { + var c = CreateCriteria() + .Add(Restrictions.Like(SchedulerAppointment.PropertyName_RecurrenceInfo, pRecurrenceId, MatchMode.Anywhere)) + .Add(Restrictions.Eq(SchedulerAppointment.PropertyName_Type, 4)); + + return c.List(); + } } } diff --git a/Report/ReportObjects/KalenderRO.cs b/Report/ReportObjects/KalenderRO.cs index 5c51bf0aa..f44e3f20b 100644 --- a/Report/ReportObjects/KalenderRO.cs +++ b/Report/ReportObjects/KalenderRO.cs @@ -2,9 +2,12 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; + using BeWo.Data.Access; using BeWo.Data.Entities; +using BeWo.Service.Core; using BeWo.Service.DCEntityMapper; + using BS.Shared.DataContracts; using BS.Shared.Extensions; @@ -16,22 +19,57 @@ namespace BeWo.Report.ReportObjects public List Appointments { get; set; } public List KalenderTageSortiert { get; set; } public Dictionary Wochen { get; set; } - public String PrintingDate { get { return DateTime.Now.ToShortDateString(); } } + public string PrintingDate => DateTime.Now.ToShortDateString(); - public static KalenderRO Create(IEnumerable appointmentOids, long? employeeOid, IEnumerable serientermine, IEnumerable selectedDates, IEnumerable mehrtaegigeTermine) + 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 = serientermine.ToList(); + + var recurrenceIds2Appointments = new Dictionary>(); + var test = recurringAppointments.Where(w => w.RecurrenceInfo != 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 != null) + { + recurringAppointments.Remove(theOneToDelete); + } + } + } var mapper = new SchedulerAppointmentDC_SchedulerAppointment(); - var objekte = mapper.MapToNewEntities(serientermine); + var objekte = mapper.MapToNewEntities(recurringAppointments); var objekte2 = mapper.MapToNewEntities(mehrtaegigeTermine); appointments.AddRange(objekte2); appointments.AddRange(objekte); - appointments = appointments.Where(w => (w.StartDate != null && selectedDates.Any(a => a.CompareShortDates(w.StartDate.Value)))).OrderBy(o => o.StartDate).ToList(); + 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) @@ -54,6 +92,7 @@ namespace BeWo.Report.ReportObjects foreach (var kTag in kalenderTage) { var wt = c.GetWeekOfYear(kTag.Date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); + if (wochen.ContainsKey(wt)) { wochen[wt].AddDayToWeek(kTag); @@ -154,7 +193,7 @@ namespace BeWo.Report.ReportObjects { get { - var result = String.Empty; + var result = string.Empty; if (Appointment.AllDay) { @@ -162,23 +201,16 @@ namespace BeWo.Report.ReportObjects } else { - result = Appointment.StartDate.HasValue ? String.Format("{0} - {1}", Appointment.StartDate.Value.ToShortTimeString(), Appointment.EndDate.Value.ToShortTimeString()) : string.Empty; + result = Appointment.StartDate.HasValue ? $"{Appointment.StartDate.Value.ToShortTimeString()} - {Appointment.EndDate.Value.ToShortTimeString()}" + : string.Empty; } return result; } } - public string SubjectLocationString - { - get - { - if (!String.IsNullOrEmpty(Appointment.Location)) - return String.Format("{0} ({1})", Appointment.Subject, Appointment.Location); - return Appointment.Subject; - } - } + public string SubjectLocationString => !string.IsNullOrEmpty(Appointment.Location) ? $"{Appointment.Subject} ({Appointment.Location})" : Appointment.Subject; - public SchedulerAppointment Appointment { get; set; } + public SchedulerAppointment Appointment { get; set; } } } \ No newline at end of file diff --git a/Service/Core/Utils.cs b/Service/Core/Utils.cs index 508280e7c..3b5d930ed 100644 --- a/Service/Core/Utils.cs +++ b/Service/Core/Utils.cs @@ -15,6 +15,7 @@ using BeWo.Data.Entities; using BeWo.Service.ServiceContracts; using BeWo.Data; using BS.Shared; +using BS.Shared.Extensions; namespace BeWo.Service.Core { @@ -225,5 +226,47 @@ namespace BeWo.Service.Core } return false; } + + public static string GetRecurrenceIdFromRecurrenceInfo(string pRecurrenceInfo) + { + var regex = new Regex("(Id=\\\"[a-z0-9-]+\\\")"); + + var match = regex.Match(pRecurrenceInfo); + if(match.Success) + { + var value = match.Value; + var actualId = value.Split("\""); + if(actualId.Count > 1) + { + return actualId[1]; + } + } + + return null; + } + + public static string GetRecurrenceIndexFromRecurrenceInfo(string pRecurrenceInfo) + { + if(!pRecurrenceInfo.Contains("Index")) + { + return null; + } + + var regex = new Regex("(Index=\\\"\\d+\\\")"); + + var match = regex.Match(pRecurrenceInfo); + if(match.Success) + { + var value = match.Value; + var actualIndex = value.Split("\""); + + if(actualIndex.Count > 1) + { + return actualIndex[1]; + } + } + + return null; + } } } \ No newline at end of file diff --git a/Service/Service.csproj b/Service/Service.csproj index eb0994477..2eb2f567d 100644 --- a/Service/Service.csproj +++ b/Service/Service.csproj @@ -81,6 +81,9 @@ ..\Lib\Castle.DynamicProxy2.dll + + False + diff --git a/Service/ServiceImplementations/ResourceServiceImp.cs b/Service/ServiceImplementations/ResourceServiceImp.cs index 2a874b08a..0a891b2b8 100644 --- a/Service/ServiceImplementations/ResourceServiceImp.cs +++ b/Service/ServiceImplementations/ResourceServiceImp.cs @@ -696,6 +696,34 @@ namespace BeWo.Service.ServiceImplementations var lOriginals = DAOFactory.GenericDAO.LoadByIDs(pSchedulerAppointments.Select(b => b.SchedulerAppointmentOid.Value)); var allegleich = true; + + var test = pSchedulerAppointments.Where(w => w.SchedulerAppointmentOid.HasValue && lOriginals.Any(a => a.Oid.HasValue && + a.Oid.Value == w.SchedulerAppointmentOid.Value && a.RecurrenceInfo != null && + w.RecurrenceInfo == null)) + .ToList(); + + if(test.Count > 0) + { + var originalAppointments = lOriginals.Where(w => w.Oid.HasValue && test.Select(s => s.SchedulerAppointmentOid.Value).Contains(w.Oid.Value)).ToList(); + + foreach(var modifiedException in test) + { + var original = originalAppointments.FirstOrDefault(f => f.Oid.Value == modifiedException.SchedulerAppointmentOid.Value); + + if(original == null) + { + continue; + } + + if(modifiedException.Type != 4) + { + modifiedException.Type = original.Type; + } + + modifiedException.RecurrenceInfo = original.RecurrenceInfo; + } + } + // Die geänderten Anwesenheiten updaten und die entfernten löschen foreach (var item in pSchedulerAppointments) { @@ -808,8 +836,33 @@ namespace BeWo.Service.ServiceImplementations { try { + var lOriginals = DAOFactory.GenericDAO.LoadByIDs(pOid2Version.Keys); + + if(lOriginals.Count > 0 && lOriginals.Any(a => a.Type == 3 && a.Oid.HasValue && pOid2Version.Keys.Contains(a.Oid.Value))) + { + var originalsToUpdate = lOriginals.Where(w => w.Type == 3 && w.Oid.HasValue && pOid2Version.Keys.Contains(w.Oid.Value)).ToList(); + foreach(var original in originalsToUpdate) + { + original.Type = 4; + } + + DAOFactory.GenericDAO.Update(originalsToUpdate); + + var updatedAppointments = DAOFactory.GenericDAO.LoadByIDs(originalsToUpdate.Select(s => s.Oid.Value)); + + foreach(var appointment in updatedAppointments) + { + if(appointment.Oid.HasValue && appointment.Version.HasValue && pOid2Version.ContainsKey(appointment.Oid.Value)) + { + pOid2Version.Remove(appointment.Oid.Value); + } + } + } + foreach (var kvp in pOid2Version) - ServiceLogic.SetActivationType(new Dictionary { { kvp.Key, kvp.Value } }, ActivationTypeId.Deleted); + { + ServiceLogic.SetActivationType(new Dictionary { { kvp.Key, kvp.Value } }, ActivationTypeId.Deleted); + } return GetSchedulerAppointmentsById(pOid2Version.Keys); } @@ -985,8 +1038,8 @@ namespace BeWo.Service.ServiceImplementations } //Man hat nur Customer und/oder Resourcen ausgewählt, dann dürfen die eigenen nicht angezeigt werden if ((pSelectedEmployees == null || pSelectedEmployees.Count == 0) && - ((pSelectedCustomer != null && pSelectedCustomer.Count > 0) || - (pSelectedResources != null && pSelectedResources.Count > 0))) + (pSelectedCustomer != null && pSelectedCustomer.Count > 0 || + pSelectedResources != null && pSelectedResources.Count > 0)) { ownerOid = null; } @@ -996,8 +1049,13 @@ namespace BeWo.Service.ServiceImplementations ownerOid = pEmployeeOid; } - //rausnehmen, sonst werden termine nicht gezeigt, bei denen man owner und kein Employee ausgewählt wurde - pSelectedEmployees?.Remove(pEmployeeOid); + if(!(!pHasRightToSeeAllEmployeeAppointments && pSelectedEmployees != null && pSelectedEmployees.Count == 1 && pSelectedEmployees.Contains(pEmployeeOid))) + { + //rausnehmen, sonst werden termine nicht gezeigt, bei denen man owner und kein Employee ausgewählt wurde. + //wird nicht rausgenommen, wenn man die termine anderer mitarbeiter nicht sehen darf und "nur meine termine" ausgewählt hat. + //sonst werden die filter mit and und nicht mit or verknüpft. + pSelectedEmployees?.Remove(pEmployeeOid); + } if(pPrivateAppointmentsOnly && (pSelectedEmployees == null || pSelectedEmployees.Count == 0) && (pSelectedCustomer == null || pSelectedCustomer.Count == 0) && (pSelectedResources == null || pSelectedResources.Count == 0) && !(pSelectedEmployees == null || pSelectedEmployees.Count == 0) && (pSelectedCustomer != null && pSelectedCustomer.Count > 0 || From 7fcb146d13241711771925874d0dacbd6b284a15 Mon Sep 17 00:00:00 2001 From: Lyndon Date: Tue, 2 Jan 2018 18:47:59 -0400 Subject: [PATCH 2/3] =?UTF-8?q?Textbausteine=20haben=20jetzt=20ein=20Konte?= =?UTF-8?q?xtmen=C3=BC=20und=20Textbausteinkategorien?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BeWo/Core/TextModuleTreeItem.cs | 1 - BeWo/View/Detail/CustomerView.xaml | 4 +- BeWo/View/Detail/ServiceRecordView2.xaml.cs | 7 +- BeWo/View/Detail/TextModuleView.xaml | 2 +- BeWo/View/Detail/TextbausteinView.xaml | 244 ++++++++++++++------ BeWo/View/Detail/TextbausteinView.xaml.cs | 59 ++++- 6 files changed, 226 insertions(+), 91 deletions(-) diff --git a/BeWo/Core/TextModuleTreeItem.cs b/BeWo/Core/TextModuleTreeItem.cs index d69e6e935..a3fa8e4fd 100644 --- a/BeWo/Core/TextModuleTreeItem.cs +++ b/BeWo/Core/TextModuleTreeItem.cs @@ -15,7 +15,6 @@ namespace BeWo.Core private bool _IsExpanded; - public TextModuleVM TextModuleVM { get; set; } public string ItemName diff --git a/BeWo/View/Detail/CustomerView.xaml b/BeWo/View/Detail/CustomerView.xaml index 4c143b020..1030d7b63 100644 --- a/BeWo/View/Detail/CustomerView.xaml +++ b/BeWo/View/Detail/CustomerView.xaml @@ -96,9 +96,9 @@ + ItemsSource="{Binding Path=UngueltigeVerordnungen}" CustomColumnSort="Grid_medikamentenverordnungshistorie_OnCustomColumnSort"> - + diff --git a/BeWo/View/Detail/ServiceRecordView2.xaml.cs b/BeWo/View/Detail/ServiceRecordView2.xaml.cs index c11b97e39..b67d79740 100644 --- a/BeWo/View/Detail/ServiceRecordView2.xaml.cs +++ b/BeWo/View/Detail/ServiceRecordView2.xaml.cs @@ -83,10 +83,7 @@ namespace BeWo.View.Detail private int lastPosition; - public static double DocumentationTextBoxFontSize - { - get { return BeWoApp.AppSettings.DocumentationFontSize; } - } + public static double DocumentationTextBoxFontSize => BeWoApp.AppSettings.DocumentationFontSize; public ServiceRecordView2(ServiceRecordListVM pViewModel, long? startSupportConceptOid) { @@ -3430,7 +3427,7 @@ namespace BeWo.View.Detail rootGrid2.Children.Add(stackPanel); tbv.root.Header = string.Empty; - var window = new BeWoWindow(tbv) { Width = 514, Height = 400, rootGroupBox = { Header = "Textbausteine" } }; + var window = new BeWoWindow(tbv) { Width = 914, Height = 600, rootGroupBox = { Header = "Textbausteine" } }; speichernBtn.Click += (o, args) => { diff --git a/BeWo/View/Detail/TextModuleView.xaml b/BeWo/View/Detail/TextModuleView.xaml index 714787b15..ec9a352cb 100644 --- a/BeWo/View/Detail/TextModuleView.xaml +++ b/BeWo/View/Detail/TextModuleView.xaml @@ -11,7 +11,7 @@ VerticalAlignment="Stretch" Focusable="True"> - + diff --git a/BeWo/View/Detail/TextbausteinView.xaml b/BeWo/View/Detail/TextbausteinView.xaml index 55b7e6c60..3bcde7389 100644 --- a/BeWo/View/Detail/TextbausteinView.xaml +++ b/BeWo/View/Detail/TextbausteinView.xaml @@ -11,9 +11,24 @@ VerticalAlignment="Stretch" Focusable="True"> - + + + + + + + + + + + + + + + + @@ -21,6 +36,7 @@ + @@ -46,78 +62,164 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeWo/View/Detail/TextbausteinView.xaml.cs b/BeWo/View/Detail/TextbausteinView.xaml.cs index 301007a87..49e08cc96 100644 --- a/BeWo/View/Detail/TextbausteinView.xaml.cs +++ b/BeWo/View/Detail/TextbausteinView.xaml.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Windows; +using System.Windows.Controls; using System.Windows.Data; using BeWo.Core; @@ -25,7 +26,7 @@ namespace BeWo.View.Detail public TextModuleListVM ViewModel { - get { return _ViewModel; } + get => _ViewModel; set { @@ -34,15 +35,9 @@ namespace BeWo.View.Detail } } - public override bool IsDirty - { - get { return ViewModel != null && ViewModel.IsDirty; } - } + public override bool IsDirty => ViewModel != null && ViewModel.IsDirty; - internal override DependencyObject ValidationOnSaveRootElement - { - get { return AddTextbausteinButton; } - } + internal override DependencyObject ValidationOnSaveRootElement => AddTextbausteinButton; private bool isInAdministrationView; @@ -112,8 +107,8 @@ namespace BeWo.View.Detail private void DeleteButton_Click(object sender, RoutedEventArgs e) { - ViewModel.VMList.Remove(datagrid_textbausteine.GetCurrentValue()); - BeWoWpfUtils.RefreshDXGrid(datagrid_textbausteine); + ViewModel.VMList.Remove(DatagridTextbausteine.GetCurrentValue()); + BeWoWpfUtils.RefreshDXGrid(DatagridTextbausteine); } private void ButtonAddTextbaustein_Click(object sender, RoutedEventArgs e) @@ -151,8 +146,50 @@ namespace BeWo.View.Detail return isOwn && hasRight2EditOwn || hasRight2EditAll; } + return false; } + + // TODO: Merken, ob die Textmodulkategorie aufgeklappt ist. + // TODO: Speichern und Schließen statt der bisherigen Lösung. + private void ContextMenuTextModules_Click(object sender, RoutedEventArgs e) + { + if(e.OriginalSource is MenuItem twi) + { + var selectedItem = TreeListControl.SelectedItem as TextModuleVM; + + ViewModel.NewVM.IsParent = twi.Header.Equals("Neue Textbausteinkategorie"); + ViewModel.NewVM.IsOnlyForEmployee = true; + + if(selectedItem != null) + { + ViewModel.NewVM.Parent = selectedItem; + } + + ViewModel.AddNewVMToList(false); + Save(); + } + } + + private void ContextMenuTextModules_Opened(object sender, RoutedEventArgs e) + { + if (e.OriginalSource is ContextMenu menu) + { + var textModule = TreeListControl.SelectedItem as TextModuleVM; + + foreach (var menuitem in menu.Items.OfType().Select(item => item)) + { + if(textModule == null || !textModule.IsParent) + { + menuitem.IsEnabled = false; + } + else + { + menuitem.IsEnabled = true; + } + } + } + } } public class IsOnlyForEmployeeRightsConverter : IValueConverter From 19c596dfe10de5acbd6d6823c1db594de0b6ad33 Mon Sep 17 00:00:00 2001 From: Lyndon Date: Fri, 5 Jan 2018 19:13:18 -0400 Subject: [PATCH 3/3] Textbausteine... --- BeWo/View/Detail/ServiceRecordView2.xaml.cs | 42 ++--- BeWo/View/Detail/SupportConceptView.xaml | 8 +- BeWo/View/Detail/TextModuleView.xaml.cs | 2 +- BeWo/View/Detail/TextbausteinView.xaml | 156 +++++------------- BeWo/View/Detail/TextbausteinView.xaml.cs | 156 ++++++++++++------ .../ListViewModel/TextModuleListVM.cs | 1 + BeWo/ViewModel/TextModuleVM.cs | 64 ++++--- BeWo/ViewModel/VMFactory.cs | 1 + Data/Entities/TextModule.cs | 49 +++--- Data/Entities/Textbaustein.cs | 85 +++++++--- Data/Mappings/TextModule.hbm.xml | 1 + Data/Mappings/Textbaustein.hbm.xml | 7 +- Model/Changes_2018_01_03.txt | 1 + .../DCEntityMapper/TextModuleDC_TextModule.cs | 40 ++--- .../ClientPartials/TextModuleDC.cs | 15 +- Shared/DataContracts/TextModuleDC.cs | 5 +- 16 files changed, 326 insertions(+), 307 deletions(-) create mode 100644 Model/Changes_2018_01_03.txt diff --git a/BeWo/View/Detail/ServiceRecordView2.xaml.cs b/BeWo/View/Detail/ServiceRecordView2.xaml.cs index b67d79740..fce726a68 100644 --- a/BeWo/View/Detail/ServiceRecordView2.xaml.cs +++ b/BeWo/View/Detail/ServiceRecordView2.xaml.cs @@ -3379,50 +3379,28 @@ namespace BeWo.View.Detail { var tbv = new TextbausteinView(x) { Background = FindResource("ApplicationBackground") as LinearGradientBrush }; - var rootGrid2 = (Grid)tbv.root.Content; - var zielGrid = (Grid)rootGrid2.Children[0]; - var cb = new CheckBox - { - Content = "Nur für mich sichtbar", - Margin = new Thickness(3), - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Center - }; - - if (BeWoApp.LoggedOnUser.HasRight(UserRightType.TextbausteineNurEigeneBearbeiten) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.TextbausteineAlleBearbeiten)) - { - cb.IsEnabled = false; - } - - var IsOnlyForEmployeeBinding = new Binding("NewVM.IsOnlyForEmployee") { Source = tbv.ViewModel, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }; - BindingOperations.SetBinding(cb, ToggleButton.IsCheckedProperty, IsOnlyForEmployeeBinding); - - Grid.SetColumn(cb, 0); - Grid.SetRow(cb, 2); - Grid.SetColumnSpan(cb, 4); - - zielGrid.Children.Add(cb); + var rootGrid2 = (Grid) tbv.root.Content; var stackPanel = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right }; var speichernBtn = new Button { - Content = "Speichern und schließen", + Content = "Speichern", HorizontalAlignment = HorizontalAlignment.Right, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center }; - var abbrechenBtn = new Button + var schliessenBtn = new Button { - Content = "Abbrechen", + Content = "Schließen", HorizontalAlignment = HorizontalAlignment.Right, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center }; stackPanel.Children.Add(speichernBtn); - stackPanel.Children.Add(abbrechenBtn); + stackPanel.Children.Add(schliessenBtn); Grid.SetRow(stackPanel, 2); rootGrid2.Children.Add(stackPanel); @@ -3432,13 +3410,13 @@ namespace BeWo.View.Detail speichernBtn.Click += (o, args) => { tbv.Focus(); - if (x.IsDirty || x.VMList.Any(vm => vm.IsDirty)) + if(x.IsDirty || x.VMList.Any(vm => vm.IsDirty)) + { tbv.Save(() => { textbausteineSearchView.ServiceCategoryOid = textbausteineSearchView.ServiceCategoryOid; }); - - window.Close(); + } }; - abbrechenBtn.Click += (o, args) => + schliessenBtn.Click += (o, args) => { tbv.Focus(); tbv.DoSaveCheck(); @@ -3446,6 +3424,8 @@ namespace BeWo.View.Detail window.Close(); }; + window.WindowStartupLocation = WindowStartupLocation.CenterScreen; + window.Show(); })); } diff --git a/BeWo/View/Detail/SupportConceptView.xaml b/BeWo/View/Detail/SupportConceptView.xaml index 95eef130c..765c92b28 100644 --- a/BeWo/View/Detail/SupportConceptView.xaml +++ b/BeWo/View/Detail/SupportConceptView.xaml @@ -503,10 +503,10 @@ Height="23"/>