From d6c2952c2f0b993614cd25de480fb23716255f1e Mon Sep 17 00:00:00 2001 From: Kojo Date: Mon, 3 Aug 2026 10:39:33 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Neues=20Benutzerrecht=20"Mitarbeiter=20Abwe?= =?UTF-8?q?senheiten=20l=C3=B6schen=20nach=20Ablauf"=20-=20Serveranteil=20?= =?UTF-8?q?ToDoOID=3D1328370181?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Data/Security/UserRightHelper.cs | 7 +++++++ .../CustomerServiceImp.cs | 19 ++++++++++++++++++- .../OperationsServiceImp.cs | 18 ++++++++++++++++-- Shared/BeWoEntityEnums.cs | 1 + Shared/Core/EnumTranslations.cs | 2 ++ Shared/DataContracts/AbsenceTimeDC.cs | 2 ++ 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Data/Security/UserRightHelper.cs b/Data/Security/UserRightHelper.cs index 57af77f48..5043ccdd7 100644 --- a/Data/Security/UserRightHelper.cs +++ b/Data/Security/UserRightHelper.cs @@ -193,6 +193,8 @@ namespace BeWo.Data.Security return "3.30"; if (isRightVersion331(r)) return "3.31"; + if (isRightVersion332(r)) + return "3.32"; return BASE_VERSION; } @@ -252,5 +254,10 @@ namespace BeWo.Data.Security || r == UserRightType.Customer_DeleteMedication; } + private static bool isRightVersion332(UserRightType r) + { + return r == UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry; + } + } } diff --git a/Service/ServiceImplementations/CustomerServiceImp.cs b/Service/ServiceImplementations/CustomerServiceImp.cs index 5ed56b8ec..8ef2fb5bc 100644 --- a/Service/ServiceImplementations/CustomerServiceImp.cs +++ b/Service/ServiceImplementations/CustomerServiceImp.cs @@ -1569,7 +1569,24 @@ namespace BeWo.Service.ServiceImplementations { try { - ServiceLogic.SetActivationType(pOid2Version, ActivationTypeId.Deleted); + var user = GetLoggedInUser(); + if (!UserRightHelper.UserHasRight(user, UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry)) + { + var forbiddenOids = DAOFactory.GenericDAO.LoadByIDs(pOid2Version.Keys) + .Where(a => a.EmployeeOid != null && a.End.HasValue && a.End.Value.Date < DateTime.Today) + .Select(a => a.Oid.Value) + .ToList(); + + foreach (var oid in forbiddenOids) + { + pOid2Version.Remove(oid); + } + } + + if (pOid2Version.Count > 0) + { + ServiceLogic.SetActivationType(pOid2Version, ActivationTypeId.Deleted); + } } catch (Exception e) { diff --git a/Service/ServiceImplementations/OperationsServiceImp.cs b/Service/ServiceImplementations/OperationsServiceImp.cs index 9215779a4..6f02e5b03 100644 --- a/Service/ServiceImplementations/OperationsServiceImp.cs +++ b/Service/ServiceImplementations/OperationsServiceImp.cs @@ -3,6 +3,7 @@ using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Data.ICD10; using BeWo.Data.ICF; +using BeWo.Data.Security; using BeWo.Data.Utils; using BeWo.Service.AI; using BeWo.Service.Configuration; @@ -4391,8 +4392,15 @@ namespace BeWo.Service.ServiceImplementations { //ServiceLogic.SetActivationType(pOid2Version, ActivationTypeId.Deleted); - var lOriginals = DAOFactory.GenericDAO.LoadByIDs(pOid2Version.Select(e => e.Key)).Where(e => e.SystemEntryID == null).ToList(); - DAOFactory.GenericDAO.Delete(lOriginals); + var abwesenheiten = DAOFactory.GenericDAO.LoadByIDs(pOid2Version.Select(e => e.Key)).Where(e => e.SystemEntryID == null).ToList(); + + var user = SecurityUtils.GetLoggedInUser(); + if (!UserRightHelper.UserHasRight(user, UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry)) + { + abwesenheiten = abwesenheiten.Where(a => a.EmployeeOid == null || !a.End.HasValue || a.End.Value.Date >= DateTime.Today).ToList(); + } + + DAOFactory.GenericDAO.Delete(abwesenheiten); } catch (Exception e) { @@ -6876,6 +6884,12 @@ namespace BeWo.Service.ServiceImplementations { try { + var user = SecurityUtils.GetLoggedInUser(); + if (absenceTimeDC.IsInThePast && !UserRightHelper.UserHasRight(user, UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry)) + { + throw new InvalidOperationException("Sie haben nicht das Recht, bereits vergangene Abwesenheiten zu löschen."); + } + var emp = DAOFactory.GenericDAO.GetByID(absenceTimeDC.EmployeeOid.Value); emp.AbsenceTimes.Remove(emp.AbsenceTimes.First(a => a.Oid == absenceTimeDC.AbsenceTimeOid)); DAOFactory.GenericDAO.Update(emp); diff --git a/Shared/BeWoEntityEnums.cs b/Shared/BeWoEntityEnums.cs index 539db34d0..28d9f78e7 100644 --- a/Shared/BeWoEntityEnums.cs +++ b/Shared/BeWoEntityEnums.cs @@ -463,6 +463,7 @@ namespace BS.Shared Employee_AllowViewOwnTeam = 20006, Employee_AllowEditAbsenceTimes = 20007, Employee_AllowEditOvertimes = 20008, + Employee_AllowDeleteAbsenceTimesAfterExpiry = 20009, Employee_ViewNotizen = 20010, Employee_EditNotizen = 20011, diff --git a/Shared/Core/EnumTranslations.cs b/Shared/Core/EnumTranslations.cs index edadf4387..8445c1784 100644 --- a/Shared/Core/EnumTranslations.cs +++ b/Shared/Core/EnumTranslations.cs @@ -747,6 +747,7 @@ namespace BS.Shared.Core dict.Add(UserRightType.Employee_ViewNotizen, Translator.Translate("MitarbeiterSingular") + " Notizen ansehen"); dict.Add(UserRightType.Employee_EditNotizen, Translator.Translate("MitarbeiterSingular") + " Notizen bearbeiten"); dict.Add(UserRightType.Employee_DeleteNotizen, Translator.Translate("MitarbeiterSingular") + " Notizen löschen"); + dict.Add(UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry, Translator.Translate("MitarbeiterSingular") + " Abwesenheiten löschen nach Ablauf"); dict.Add(UserRightType.OrganisationView_Create, Translator.Translate("Organisationen anlegen")); dict.Add(UserRightType.OrganisationView_Delete, Translator.Translate("Organisationen löschen")); @@ -909,6 +910,7 @@ namespace BS.Shared.Core dict.Add(UserRightType.KalenderRessourcentermineAndererAendern, "Termine mit Ressourcen anderer " + Translator.Translate("MitarbeiterPlural") + " ändern"); dict.Add(UserRightType.KalenderInZeiterfassungUebernehmen, Translator.Translate("Termine in Zeiterfassung übernehmen")); dict.Add(UserRightType.KalenderInAbwesenheitenUebernehmen, Translator.Translate("Termine in Abwesenheiten übernehmen")); + dict.Add(UserRightType.KalenderRessourcenDoppeltBuchen, Translator.Translate("Ressourcen doppelt buchen")); dict.Add(UserRightType.TextbausteineAlleAnsehen, Translator.Translate("Textbausteine ansehen (allgemeine)")); dict.Add(UserRightType.TextbausteineNurEigeneAnsehen, Translator.Translate("Textbausteine ansehen (eigene)")); dict.Add(UserRightType.TextbausteineAlleBearbeiten, Translator.Translate("Textbausteine bearbeiten (allgemeine)")); diff --git a/Shared/DataContracts/AbsenceTimeDC.cs b/Shared/DataContracts/AbsenceTimeDC.cs index 421712735..df04aa0d0 100644 --- a/Shared/DataContracts/AbsenceTimeDC.cs +++ b/Shared/DataContracts/AbsenceTimeDC.cs @@ -38,6 +38,8 @@ namespace BS.Shared.DataContracts [DataMember] public string BackgroundColor { get; set; } + public bool IsInThePast => End.HasValue && End.Value.Date < DateTime.Today; + public bool IsAllDay { get From 913b51b58b32404323dc11c21d4c7403540f968f Mon Sep 17 00:00:00 2001 From: Kojo Date: Mon, 3 Aug 2026 10:40:39 +0200 Subject: [PATCH 2/5] =?UTF-8?q?Neues=20Benutzerrecht=20"Mitarbeiter=20Abwe?= =?UTF-8?q?senheiten=20l=C3=B6schen=20nach=20Ablauf"=20-=20FaC-Anteil=20To?= =?UTF-8?q?DoOID=3D1328370181?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewModel/EmployeeAbsenceTimeListVM.cs | 23 ++++++++++++++++++- BeWo/View/Detail/AbsenceTimesView.xaml.cs | 21 ++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/BeWo/Scheduler/ViewModel/EmployeeAbsenceTimeListVM.cs b/BeWo/Scheduler/ViewModel/EmployeeAbsenceTimeListVM.cs index 693571af9..d8c34cab6 100644 --- a/BeWo/Scheduler/ViewModel/EmployeeAbsenceTimeListVM.cs +++ b/BeWo/Scheduler/ViewModel/EmployeeAbsenceTimeListVM.cs @@ -1,11 +1,14 @@ using System.Collections.Generic; using System.Linq; +using System.Windows; using System.Windows.Media; using BS.Shared; using BS.Shared.DataContracts; using BS.Shared.DataContracts.Compact; +using BS.Shared.Translation; +using BeWo.Core; using BeWo.ServiceProxy; using BeWo.Scheduler.Resources; using BeWo.Scheduler.View; @@ -151,7 +154,25 @@ namespace BeWo.Scheduler.ViewModel protected override void DeleteAppointments(IEnumerable dcList) { - ServiceFacade.DoCustomerServiceAsync(s => s.DeactivateAbsenceTimes(dcList.ToDictionary(dc => dc.AbsenceTimeOid != null ? dc.AbsenceTimeOid.Value : 0, + var lDcList = dcList.ToList(); + + if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry)) + { + var pastAbsenceTimes = lDcList.Where(dc => dc.IsInThePast).ToList(); + if (pastAbsenceTimes.Count > 0) + { + lDcList = lDcList.Except(pastAbsenceTimes).ToList(); + MessageBox.Show(Translator.Translate("Sie besitzen nicht das Benutzerrecht, bereits vergangene Mitarbeiter-Abwesenheiten zu löschen."), + "BeWo Planer", MessageBoxButton.OK, MessageBoxImage.Warning); + } + } + + if (lDcList.Count == 0) + { + return; + } + + ServiceFacade.DoCustomerServiceAsync(s => s.DeactivateAbsenceTimes(lDcList.ToDictionary(dc => dc.AbsenceTimeOid != null ? dc.AbsenceTimeOid.Value : 0, dc => dc.AbsenceTimeVersion != null ? dc.AbsenceTimeVersion.Value : 0))); } diff --git a/BeWo/View/Detail/AbsenceTimesView.xaml.cs b/BeWo/View/Detail/AbsenceTimesView.xaml.cs index d0d3d276c..807036e79 100644 --- a/BeWo/View/Detail/AbsenceTimesView.xaml.cs +++ b/BeWo/View/Detail/AbsenceTimesView.xaml.cs @@ -7,6 +7,7 @@ using BeWo.Core.Commands; using BeWo.ServiceProxy; using BeWo.ViewModel; using BeWo.ViewModel.ListViewModel; +using BS.Shared; using BS.Shared.Extensions; using BS.Shared.Translation; using DependencyObject = System.Windows.DependencyObject; @@ -139,9 +140,27 @@ namespace BeWo.View.Detail private void RemoveAbsenceTime() { - AbsenceTimes?.VMList.Remove(DataGridAbsenceTimes.GetCurrentValue()); + var absenceTime = DataGridAbsenceTimes.GetCurrentValue(); + if (absenceTime == null) + { + return; + } + + if (IsAbsenceTimeInThePast(absenceTime) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry)) + { + MessageBox.Show(Translator.Translate("Sie haben nicht das Benutzerrecht, bereits vergangene Mitarbeiter-Abwesenheiten zu löschen."), + "BeWo Planer", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + AbsenceTimes?.VMList.Remove(absenceTime); BeWoWpfUtils.RefreshDXGrid(DataGridAbsenceTimes); } + private static bool IsAbsenceTimeInThePast(AbsenceTimeVM absenceTime) + { + return absenceTime.End.HasValue && absenceTime.End.Value.Date < DateTime.Today; + } + } } From 2379ba2bd6e964ff182f797bc22cd9a9e4ea63bc Mon Sep 17 00:00:00 2001 From: Kojo Date: Mon, 3 Aug 2026 10:41:29 +0200 Subject: [PATCH 3/5] =?UTF-8?q?Neues=20Benutzerrecht=20"Mitarbeiter=20Abwe?= =?UTF-8?q?senheiten=20l=C3=B6schen=20nach=20Ablauf"=20-=20MoK-Anteil,=20t?= =?UTF-8?q?o=20be=20tested=20ToDoOID=3D1328370181?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/EmployeeController.cs | 6 ++++++ BeWoPlanerMobil/Models/CustomerModel.cs | 2 ++ BeWoPlanerMobil/Models/EmployeeModel.cs | 19 ++++++++++++++++++- BeWoPlanerMobil/Models/IAbsenceTimeModel.cs | 1 + .../Views/Shared/AbsenceTimePartial.cshtml | 6 +++--- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/BeWoPlanerMobil/Controllers/EmployeeController.cs b/BeWoPlanerMobil/Controllers/EmployeeController.cs index 6313b2734..5be5c3840 100644 --- a/BeWoPlanerMobil/Controllers/EmployeeController.cs +++ b/BeWoPlanerMobil/Controllers/EmployeeController.cs @@ -268,6 +268,12 @@ namespace BeWoPlanerMobil.Controllers ViewData["AbsenceTimeError"] = "Beim Löschen der Abwesenheit ist ein Fehler aufgetreten!

Bitte wenden Sie sich an Ihren Administrator."; } + if(absenceTime2Delete != null && !Model.CanDeleteAbsenceTime(absenceTime2Delete)) + { + ViewData["AbsenceTimeError"] = "Sie haben nicht das Benutzerrecht, bereits vergangene Mitarbeiter-Abwesenheiten zu löschen."; + return PartialView("AbsenceTimePartial", Model); + } + var employee = Model.SelectedEmployee; employee.AbsenceTimes.Remove(absenceTime2Delete); diff --git a/BeWoPlanerMobil/Models/CustomerModel.cs b/BeWoPlanerMobil/Models/CustomerModel.cs index 4a8f3ce42..0e03a6343 100644 --- a/BeWoPlanerMobil/Models/CustomerModel.cs +++ b/BeWoPlanerMobil/Models/CustomerModel.cs @@ -16,6 +16,8 @@ namespace BeWoPlanerMobil.Models { public bool HasRightToEdit => HasRightToEditCustomers; public bool HasRightToDelete => HasRightToEditCustomers; + + public bool CanDeleteAbsenceTime(AbsenceTimeDC absenceTime) => HasRightToDelete; public long? ObjectOid => SelectedCustomerOid; public TableID ObjectTid => TableID.Customer; public string HtmlPrefix => "customer"; diff --git a/BeWoPlanerMobil/Models/EmployeeModel.cs b/BeWoPlanerMobil/Models/EmployeeModel.cs index c33cb4a4d..1a2e67f50 100644 --- a/BeWoPlanerMobil/Models/EmployeeModel.cs +++ b/BeWoPlanerMobil/Models/EmployeeModel.cs @@ -1,4 +1,5 @@ -using BS.Shared.DataContracts; +using BS.Shared; +using BS.Shared.DataContracts; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Web.Mvc; @@ -9,6 +10,22 @@ namespace BeWoPlanerMobil.Models { public bool HasRightToEdit => HasRightToEditEmployeeAbsenceTimes; public bool HasRightToDelete => HasRightToEditEmployeeAbsenceTimes; + + public bool CanDeleteAbsenceTime(AbsenceTimeDC absenceTime) + { + if (!HasRightToDelete) + { + return false; + } + + if (absenceTime.IsInThePast) + { + return CheckRight(UserRightType.Employee_AllowDeleteAbsenceTimesAfterExpiry); + } + + return true; + } + public string HtmlPrefix => "employee"; public EmployeeSessionModel EmployeeSessionModel => SessionModel as EmployeeSessionModel; diff --git a/BeWoPlanerMobil/Models/IAbsenceTimeModel.cs b/BeWoPlanerMobil/Models/IAbsenceTimeModel.cs index 9471cd7fa..41bdc7ad1 100644 --- a/BeWoPlanerMobil/Models/IAbsenceTimeModel.cs +++ b/BeWoPlanerMobil/Models/IAbsenceTimeModel.cs @@ -16,5 +16,6 @@ namespace BeWoPlanerMobil.Models long? AbsenteeOid { get; } bool HasRightToEdit { get; } bool HasRightToDelete { get; } + bool CanDeleteAbsenceTime(AbsenceTimeDC absenceTime); } } diff --git a/BeWoPlanerMobil/Views/Shared/AbsenceTimePartial.cshtml b/BeWoPlanerMobil/Views/Shared/AbsenceTimePartial.cshtml index 4893fd78c..ee2901150 100644 --- a/BeWoPlanerMobil/Views/Shared/AbsenceTimePartial.cshtml +++ b/BeWoPlanerMobil/Views/Shared/AbsenceTimePartial.cshtml @@ -85,7 +85,7 @@

- @if(Model.HasRightToEdit || Model.HasRightToDelete) + @if(Model.HasRightToEdit || Model.CanDeleteAbsenceTime(absenceTime)) {
@@ -97,8 +97,8 @@
} - - @if(Model.HasRightToDelete) + + @if(Model.CanDeleteAbsenceTime(absenceTime)) {