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))
{