Das Recht Mitarbeiterabwesenheiten bearbeiten wird jetzt beachtet.

This commit is contained in:
2026-03-18 18:05:58 +01:00
parent 0d381136ad
commit 99e64f067d
14 changed files with 307 additions and 40 deletions

View File

@@ -713,6 +713,12 @@
<Content Include="Views\DevExpressScheduler\EmployeeMultiSelectPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\VerticalAppointmentTemplatePartial.cshtml" />
<Content Include="Views\DevExpressScheduler\HorizontalAppointmentTemplatePartial.cshtml" />
<Content Include="Views\DevExpressScheduler\AptFltEmployeesPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\AptFltCustomersPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\AptFltResourcesPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\AptFltEmployeePopupListPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\AptFltCustomerPopupListPartial.cshtml" />
<Content Include="Views\DevExpressScheduler\AptFltResourcePopupListPartial.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.config" />

View File

@@ -22,10 +22,10 @@ namespace BeWoPlanerMobil.Controllers
/*
* ToDo:
* 1. Filterung einbauen (Mitarbeiter, Klienten, Ressourcen, Privat, Aufgaben, Abwesenheiten)
* Das Filtern muss über den CustomCallback geschehen, damit die Termin-Liste aktualisiert wird.
* 2. "In die Zeiterfassung übertragen" und "Verfügbare Mitarbeiter prüfen" einbauen
* 3. Rechte implementieren!
* 4. Ressourcen-Farben einbauen -> Templates wie im DemoCenter benutzen
* 5. Übersetzungen
* 4. Übersetzungen
*/
public class DevExpressSchedulerController : AbstractBaseController
@@ -111,11 +111,11 @@ namespace BeWoPlanerMobil.Controllers
{
if(Model.LoggedInEmployee.EmployeeOid is null)
{
throw new Exception("Bei DevExpressSchedulerController.ReloadAppointments() ist die Oid des angemeldeten Benutzers ist wider Erwarten NULL!");
throw new Exception("Bei DevExpressSchedulerController.ReloadAppointments() ist die Oid des angemeldeten Benutzers wider Erwarten NULL!");
}
// ToDo: ausgewählte Ansicht laden und speichern!
//Model.ShowBetrag = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowBetrag);
var employeeOid = Model.LoggedInEmployee.EmployeeOid.Value;
var user = LoggedInUser;
var userSettings = user?.Settings.FirstOrDefault(f => f.Type.Equals(SettingsType.ApplicationSettings))?.Value;
@@ -127,7 +127,7 @@ namespace BeWoPlanerMobil.Controllers
var appointments = KalenderService.LoadFilteredAppointmentsMitAufgaben
(
Model.HasRightKalenderMitarbeitertermineAnsehen,
Model.LoggedInEmployee.EmployeeOid.Value,
employeeOid,
intervalStart,
intervalEnd,
new List<long>(),
@@ -141,9 +141,87 @@ namespace BeWoPlanerMobil.Controllers
true
);
var selectedCustomerOids = Model.PossibleCustomers.Select(s => s.CustomerOid).ToList();
var selectedEmployeeOids = Model.PossibleEmployees.Select(s => s.EmployeeOid).ToList();
var customerAbsenceTimes = KalenderService.GetAllActiveCustomersAbsenceTimesInInterval(intervalStart, intervalEnd, employeeOid, selectedCustomerOids);
var employeeAbsenceTimes = KalenderService.GetAllActiveEmployeeAbsenceTimesInInterval(intervalStart, intervalEnd, employeeOid, selectedEmployeeOids);
var allAbsenceTimes = new List<AbsenceTimeDC>();
allAbsenceTimes.AddRange(customerAbsenceTimes);
allAbsenceTimes.AddRange(employeeAbsenceTimes);
appointments.AddRange(ConvertAbsenceTimesToAppointments(allAbsenceTimes, Model.PossibleCustomers, Model.PossibleEmployees));
Model.Appointments = appointments;
}
private List<SchedulerAppointmentDC> ConvertAbsenceTimesToAppointments(List<AbsenceTimeDC> absenceTimes, List<CompactCustomerDC> allCustomers, List<CompactEmployeeDC> allEmployees)
{
var appointments = new List<SchedulerAppointmentDC>();
foreach(var absenceTime in absenceTimes)
{
var subject = $"{absenceTime.Reason.Description}";
var employee = absenceTime.EmployeeOid.HasValue ? allEmployees.FirstOrDefault(f => f.EmployeeOid == absenceTime.EmployeeOid.Value) : null;
var customer = absenceTime.CustomerOid.HasValue ? allCustomers.FirstOrDefault(f => f.CustomerOid == absenceTime.CustomerOid.Value) : null;
var allDay = absenceTime.IsAllDay;
var isEmployeeAbsenceTime = absenceTime.EmployeeOid.HasValue;
IFilterableDC dc = employee;
var originator = employee;
if(false == isEmployeeAbsenceTime)
{
dc = customer;
originator = EmployeeService.FindCompactEmployeeByFullname(absenceTime.InsUser);
}
if(false == dc is null)
{
subject += $" ({dc.SimpleDescription})";
}
var absenceTimeEnd = absenceTime.End;
var end = absenceTime.End ?? DateTime.MaxValue;
var isMultipleDayAbsenceTime = absenceTime.End is null || absenceTime.Start.Value.Date != absenceTime.End.Value.Date;
if(isMultipleDayAbsenceTime && allDay && end != DateTime.MaxValue)
{
absenceTimeEnd = end.AddDays(1);
}
if(originator is null)
{
originator = LoggedInUser.Employee;
}
var appointment = new SchedulerAppointmentDC
{
AbsenceReason = absenceTime.Reason,
AllDay = true,
Description = absenceTime.Notice,
StartDate = absenceTime.Start,
EndDate = absenceTimeEnd,
ActivationType = ActivationTypeId.Active,
FormerAbsenceTimeOid = absenceTime.AbsenceTimeOid,
Originator = originator,
Subject = subject,
Krankheitsmeldung = absenceTime.KrankheitsMeldung
};
if(false == customer is null && employee is null)
{
appointment.CustomerList = new List<CompactCustomerDC> { customer };
}
appointments.Add(appointment);
}
return appointments;
}
[Authorize]
public ActionResult DevExpressScheduler()
{
@@ -366,5 +444,31 @@ namespace BeWoPlanerMobil.Controllers
return PartialView("SchedulerPagePartial", Model);
}
[Authorize]
public ActionResult SelectAllEmployeesForFiltering()
{
Model.SelectedEmployeesForFiltering = Model.PossibleEmployees.Select(employee => employee.EmployeeOid).ToList();
return PartialView("AptFltEmployeePopupListPartial");
}
[Authorize]
public ActionResult SelectAllCustomersForFiltering()
{
Model.SelectedCustomersForFiltering = Model.PossibleCustomers.Select(customer => customer.CustomerOid).ToList();
return PartialView("AptFltCustomerPopupListPartial");
}
[Authorize]
public ActionResult SelectAllResourcesForFiltering()
{
Model.SelectedResourcesForFiltering = Model.PossibleResources.Where(resource => resource.ResourceOid.HasValue).Select(resource => resource.ResourceOid.Value).ToList();
return PartialView("AptFltResourcePopupListPartial");
}
}
}

View File

@@ -13,6 +13,7 @@ namespace BeWoPlanerMobil.Models
{
public class AbstractModel
{
public bool HasRightToEditEmployeeAbsenceTimes => CheckRight(UserRightType.Employee_AllowEditAbsenceTimes);
public bool IsDeleteBtnVisible => CheckRight(UserRightType.ServiceRecordView_Delete);
public bool IsAllowedToSeeScheduler => LoggedInUser != null && CheckRight(UserRightType.KalenderAnsehen) || CheckRight(UserRightType.ViewAll);

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Web.Mvc;
using BeWo.View.Navigation.Filter;
using BeWoPlanerMobil.Controllers;
using BeWoPlanerMobil.Service;
using BeWoPlanerMobil.Util;
using BS.Shared;
using BS.Shared.DataContracts;
@@ -13,6 +14,8 @@ namespace BeWoPlanerMobil.Models
{
public class CustomerModel : AbstractModel, ISignable, IAbsenceTimeModel, IDocumentsModel
{
public bool HasRightToEdit => HasRightToEditCustomers;
public bool HasRightToDelete => HasRightToEditCustomers;
public long? ObjectOid => SelectedCustomerOid;
public TableID ObjectTid => TableID.Customer;
public string HtmlPrefix => "customer";

View File

@@ -66,5 +66,23 @@ namespace BeWoPlanerMobil.Models
return null;
}
public List<long> SelectedEmployeesForFiltering
{
get => DevExpressSchedulerSessionModel.SelectedEmployeesForFiltering;
set => DevExpressSchedulerSessionModel.SelectedEmployeesForFiltering = value;
}
public List<long> SelectedCustomersForFiltering
{
get => DevExpressSchedulerSessionModel.SelectedCustomersForFiltering;
set => DevExpressSchedulerSessionModel.SelectedCustomersForFiltering = value;
}
public List<long> SelectedResourcesForFiltering
{
get => DevExpressSchedulerSessionModel.SelectedResourcesForFiltering;
set => DevExpressSchedulerSessionModel.SelectedResourcesForFiltering = value;
}
}
}

View File

@@ -10,6 +10,10 @@ namespace BeWoPlanerMobil.Models
public List<long> SelectedResourceOids { get; set; }
public SchedulerViewType CurrentSchedulerViewType { get; set; }
public List<long> SelectedEmployeesForFiltering { get; set; }
public List<long> SelectedCustomersForFiltering { get; set; }
public List<long> SelectedResourcesForFiltering { get; set; }
public override void ResetValues()
{
base.ResetValues();
@@ -17,6 +21,9 @@ namespace BeWoPlanerMobil.Models
SelectedCustomerOids = null;
SelectedEmployeeOids = null;
SelectedResourceOids = null;
SelectedEmployeesForFiltering = null;
SelectedCustomersForFiltering = null;
SelectedResourcesForFiltering = null;
}
}
}

View File

@@ -7,6 +7,8 @@ namespace BeWoPlanerMobil.Models
{
public class EmployeeModel : AbstractModel, IAbsenceTimeModel
{
public bool HasRightToEdit => HasRightToEditEmployeeAbsenceTimes;
public bool HasRightToDelete => HasRightToEditEmployeeAbsenceTimes;
public string HtmlPrefix => "employee";
public EmployeeSessionModel EmployeeSessionModel => SessionModel as EmployeeSessionModel;

View File

@@ -14,5 +14,7 @@ namespace BeWoPlanerMobil.Models
Dictionary<string, bool> Collapsibles2IsShown { get; set; }
List<SelectListItem> AbsenceReasonItems { get; }
long? AbsenteeOid { get; }
bool HasRightToEdit { get; }
bool HasRightToDelete { get; }
}
}

View File

@@ -1,11 +1,4 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using BeWo.Report.DefaultReports;
using BeWoPlanerMobil.Models;
using BS.Shared;
using BS.Shared.Core;
@@ -15,6 +8,14 @@ using BS.Shared.Extensions;
using BS.Shared.Services;
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using static System.Int32;
using static System.String;

View File

@@ -137,6 +137,96 @@
}
</script>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle m-1" type="button" data-toggle="dropdown">
Filtern
</button>
<div class="dropdown-menu">
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="only-my-own-appointments-cb2">
<label class="form-check-label" for="only-my-own-appointments-cb2">Nur meine Termine</label>
</div>
</form>
</div>
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="only-private-appointments-cb2">
<label class="form-check-label" for="only-private-appointments-cb2">Nur private Termine</label>
</div>
</form>
</div>
<div class="dropdown-divider"></div>
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="employee-colors-cb2">
<label class="form-check-label" for="employee-colors-cb2">Mitarbeiterfarben</label>
</div>
</form>
</div>
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="absence-times-cb2">
<label class="form-check-label" for="absence-times-cb2">Abwesenheiten</label>
</div>
</form>
</div>
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="tasks-cb2">
<label class="form-check-label" for="tasks-cb2">Aufgaben</label>
</div>
</form>
</div>
<div class="dropdown-divider"></div>
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="only-employees-cb2">
<label class="form-check-label" for="only-employees-cb2">Nur Mitarbeiter</label>
</div>
</form>
</div>
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="only-customers-cb2">
<label class="form-check-label" for="only-customers-cb2">Nur Klienten</label>
</div>
</form>
</div>
<div class="dropdown-item">
<form class="form-inline">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="only-resources-cb2">
<label class="form-check-label" for="only-resources-cb2">Nur Ressourcen</label>
</div>
</form>
</div>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item">
<i class="fas fa-user text-bewo-employee"></i>
Mitarbeiter
<span class="badge badge-bewo-employee">0</span>
</a>
<a href="#" class="dropdown-item">
<i class="fas fa-user text-bewo-customers"></i>
Klienten
<span class="badge badge-bewo-customers">0</span>
</a>
<a href="#" class="dropdown-item">
<i class="fas fa-cubes text-bewo-resource"></i>
Ressourcen
<span class="badge badge-bewo-resource">0</span>
</a>
</div>
</div>
@using(Html.BeginForm())
{
<div id="scheduler-container">

View File

@@ -1,5 +1,4 @@
@using BeWoPlanerMobil.Models
@using BeWoPlanerMobil.Util
@using BeWoPlanerMobil.Util
@using BS.Shared.Extensions
@model BeWoPlanerMobil.Models.SchedulerModel

View File

@@ -75,30 +75,40 @@
<div class="card w-100">
<div class="card-header" onclick="cardHeaderClick2(this)">
<div class="row">
<div class="col-sm-auto mr-auto">
<div class="input-group">
<div class="input-group-prepend">
<i class="fas fa-chevron-down h-100 text-bewo-customer-card-header chevron-identifier-class"></i>
</div>
<p class="form-control text-bewo-customer-card-header border-0 bg-transparent" style="user-select: none !important;">
@absenceTime.Start.Value.GetIntervalDescription(absenceTime.End)
</p>
</div>
</div>
<div class="col-sm-auto">
<div class="btn-toolbar justify-content-between">
<div class="btn-group pr-1" role="group">
<button class="btn btn-primary" type="button" onclick="selectAbsenceTime(@absenceTime.AbsenceTimeOid)">
<span class="fas fa-edit mr-0 pr-0"></span>
</button>
</div>
<div class="btn-group" role="group">
<button class="btn btn-danger" type="button" onclick="deleteAbsenceTime(@absenceTime.AbsenceTimeOid, '@absenceTime.Start.Value.GetIntervalDescription(absenceTime.End)')">
<span class="fas fa-trash mr-0 pr-0"></span>
</button>
</div>
</div>
</div>
<div class="col-sm-auto mr-auto">
<div class="input-group">
<div class="input-group-prepend">
<i class="fas fa-chevron-down h-100 text-bewo-customer-card-header chevron-identifier-class"></i>
</div>
<p class="form-control text-bewo-customer-card-header border-0 bg-transparent" style="user-select: none !important;">
@absenceTime.Start.Value.GetIntervalDescription(absenceTime.End)
</p>
</div>
</div>
@if(Model.HasRightToEdit || Model.HasRightToDelete)
{
<div class="col-sm-auto">
<div class="btn-toolbar justify-content-between">
@if(Model.HasRightToEdit)
{
<div class="btn-group pr-1" role="group">
<button class="btn btn-primary" type="button" onclick="selectAbsenceTime(@absenceTime.AbsenceTimeOid)">
<span class="fas fa-edit mr-0 pr-0"></span>
</button>
</div>
}
@if(Model.HasRightToDelete)
{
<div class="btn-group" role="group">
<button class="btn btn-danger" type="button" onclick="deleteAbsenceTime(@absenceTime.AbsenceTimeOid, '@absenceTime.Start.Value.GetIntervalDescription(absenceTime.End)')">
<span class="fas fa-trash mr-0 pr-0"></span>
</button>
</div>
}
</div>
</div>
}
</div>
</div>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, $"{Model.HtmlPrefix}-absence-time-{absenceTime.AbsenceTimeOid}")" id="customer-absence-time-@absenceTime.AbsenceTimeOid">

View File

@@ -38,6 +38,26 @@ namespace BS.Shared.DataContracts
[DataMember]
public string BackgroundColor { get; set; }
public bool IsAllDay
{
get
{
if(End is null && Start is null || (End != null && Start is null))
{
return false;
}
var start = Start.Value;
var end = End.HasValue == false ? DateTime.MaxValue : End.Value;
return start.Hour == 0 &&
start.Minute == 0 &&
start.Second == 0 &&
(end == DateTime.MaxValue || end.Hour == 0 &&
end.Minute == 0 &&
end.Second == 0);
}
}
public override bool Equals(object obj)
{

View File

@@ -162,6 +162,10 @@ namespace BS.Shared.DataContracts
[DataMember]
public List<ServiceRecordDC> ServiceRecordList { get; set; }
public long? FormerAbsenceTimeOid { get; set; }
public DateTime? Krankheitsmeldung { get; set; }
public AbsenceReasonDC AbsenceReason { get; set; }
public override bool Equals(object obj)
{
if (!(obj is SchedulerAppointmentDC schedulerAppointmentDC))