using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.DCEntityMapper; using BeWo.Service.Plugins; using BeWo.Service.ServiceImplementations; using BeWo.View.Navigation.Filter; using BeWoPlanerMobil.Models; using BeWoPlanerMobil.Service; using BeWoPlanerMobil.Util; using BS.Shared; using BS.Shared.Core; using BS.Shared.DataContracts; using BS.Shared.DataContracts.Compact; using BS.Shared.Extensions; using BS.Shared.Services; using DevExpress.XtraScheduler; using DevExpress.XtraScheduler.Compatibility; using DevExpress.XtraScheduler.Native; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Web.Mvc; using System.Windows.Forms; using static BeWoPlanerMobil.Util.MobileUtils; using static BS.Shared.ServiceRecordValidationResult; using FormCollection = System.Web.Mvc.FormCollection; using GoalRating = BeWoPlanerMobil.Util.GoalRating; using Image = System.Drawing.Image; using ServiceRecordDC = BS.Shared.DataContracts.ServiceRecordDC; /* * ToDo: Bug, wenn man auf "bearbeiten" bei einem Eintrag klickt, wird die Leistung nicht geladen * ToDo: Hat man vor dem Anlegen einer Mehrfachbuchung einen Hilfeplan ausgewählt, wird der nicht richtig nach dem Anlegen geladen und die Intervallauswahl ist nicht sichtbar. */ namespace BeWoPlanerMobil.Controllers { public class MainController : AbstractBaseController { private MainModel _Model; public MainModel Model { get { if(!MobileSessionFacade.IsUserLoggedIn()) { RedirectToActionPermanent("Index", "Login"); return null; } if(_Model is null) { _Model = new MainModel(); InitModel(_Model); InitViewModel(); } return _Model; } } private Dictionary _ParentGoals; private static readonly List _GoalTypes = new List { ValueListEntryType.SupportConceptGoalCategoryType, ValueListEntryType.SupportConceptIndividualGoalCategoryType }; private static readonly List _MeasureTypes = new List { ValueListEntryType.SupportConceptGoalType, ValueListEntryType.SupportConceptIndividualGoalType }; public void InitViewModel() { InitSettings(); //Load SupportConcepts if (Model.LoggedInEmployee?.EmployeeOid.HasValue ?? false) { Model.SupportConcepts = EmployeeService.GetActiveSupportConceptsForEmployee(Model.LoggedInEmployee.EmployeeOid, Model.SelectedSupportConceptFilter); } else { Model.SupportConcepts = new List(); } if (Model.ShowExpiredSupportConcepts == false) { Model.SupportConcepts = Model.SupportConcepts.Where(supportConcept => { var endDate = MainModel.GetEndDateOfSupportConcept(supportConcept); return endDate is null || endDate.Value >= DateTime.Now.Date; }).ToList(); } Model.GroupsOfPeople = EmployeeService.GetAllGroups(LoggedInEmployee.EmployeeOid).OrderBy(gop => gop.Name).ToList(); Model.Dokutypes = ValueListService.GetAllValueListEntrysByType(ValueListEntryType.DocumentType); if (Model.Dokutypes != null) { Model.Dokutypes = Model.Dokutypes.OrderBy(s => s.ValueListEntryOid).ToArray(); } //Load Employees if (Model.AllEmployees is null) { Model.AllEmployees = EmployeeService.GetAllActiveEmployeesCompact().OrderBy(e => e.LastName).ToList(); } if (Model.EmployeesForGroupAndMultiBooking is null) { Model.EmployeesForGroupAndMultiBooking = EmployeeService.GetAllCompactEmployees().Where(e => e.ActivationType == ActivationTypeId.Active).OrderBy(e => e.LastName).ToList(); } if (LoggedInUser.HasRight(UserRightType.ServiceRecord_AllowCreationForOtherEmployees)) { Model.Employees = Model.AllEmployees; } else if (LoggedInUser.HasRight(UserRightType.ServiceRecord_AllowCreationForOtherTeamMember) && Model.LoggedInEmployee.EmployeeOid != null) { Model.Employees = EmployeeService.GetAllTeamMember(LoggedInUser.Employee).Where(e => e.ActivationType == ActivationTypeId.Active).ToList(); } else { Model.Employees = new List { LoggedInUser.Employee }; } Model.Employees = Model.Employees.OrderBy(e => e.LastName).ThenBy(e => e.FirstName).ToList(); Model.SelectedConceptCostBearerRelations = new List(); Model.MultiBookingSelectedConceptCostBearerRelations = new List(); Model.GoalRatingTypes = OperationsService.GetAllRatingTypes().OrderBy(o => o.Position).ToList(); SetSelectedObjects(); } private void SetSelectedObjects() { Model.SelectedEmployee = Model.SelectedEmployeeOid.HasValue ? Model.AllEmployees.First(f => f.EmployeeOid.Equals(Model.SelectedEmployeeOid.Value)) : LoggedInUser.Employee; var isInList = Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SupportConceptListObjects.Exists(s => s.CostBearer2SupportConceptOid == Model.SelectedCostBearerSupportConceptOid); if (!Model.SelectedCostBearerSupportConceptOid.HasValue || !isInList) { if (Model.SelectedCostBearerSupportConceptOid.HasValue && !isInList) { Log.Info($"Model.SelectedCostBearerSupportConceptOid = {Model.SelectedCostBearerSupportConceptOid} is not in list !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); var sb = new StringBuilder(); foreach (var o in Model.SupportConceptListObjects) { if (sb.Length > 0) { sb.Append(", "); } sb.Append(o.CostBearer2SupportConceptOid); } Log.Info($"Model.SupportConceptListObjects Oids = {sb}"); } Model.SelectedCostBearer2SupportConceptRelListObject = Model.SupportConceptListObjects.FirstOrDefault(f => f.CostBearer2SupportConceptOid == -1) ?? Model.SupportConceptListObjects.First(); Model.SelectedCostBearerSupportConceptOid = -1; Model.HasAnyRatingTypes = Model.HasRightToRateGoals && OperationsService.GetAllRatingTypes().Any(); } else { Model.SelectedCostBearer2SupportConceptRelListObject = Model.SupportConceptListObjects.FirstOrDefault(f => f.CostBearer2SupportConceptOid == Model.SelectedCostBearerSupportConceptOid) ?? Model.SupportConceptListObjects.First(); } if (Model.SelectedSupportConceptOid.HasValue) { } if (Model.SelectedConceptCostBearerRelationOids.Count > 0) { Model.SelectedConceptCostBearerRelations = CustomerService.GetSupportConceptCostBearerRelationsById(Model.SelectedConceptCostBearerRelationOids); } Model.GroupBookingSelectedEmployees = Model.AllEmployees.Where(employee => Model.GroupBookingSelectedEmployeeOids.Contains(employee.EmployeeOid)).ToList(); Model.GroupBookingSelectedSupportConcepts = Model.SupportConcepts.Where(s => Model.GroupBookingSelectedSupportConceptOids.Contains(s.SupportConceptOid.Value)).ToList(); //Model.Group = Model.SupportConceptListObjectsForGroupBooking.Where(s => Model.GroupBookingSelectedSupportConceptOids.Contains(s.SupportConceptOid.Value)).ToList(); if (Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SelectedCostBearerSupportConceptOid != -1) { LoadSupportConceptThings(Model.SelectedCostBearerSupportConceptOid); LoadPaginatedServiceRecordsToModel(Model.CurrentPage); } if (Model.AllGoals != null) { Model.SelectedGoals = Model.AllGoals.Where(g => Model.SelectedGoalOids.Contains(g.ValueListEntryOid.Value)).ToList(); } } private void LoadSupportConceptThings(long? cb2ScOid) { LoadServiceCategoriesToModel(cb2ScOid); LoadGoals(); LoadTextModules(); } private void InitSettings() { //Mandator Settings Model.ShowBetrag = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowBetrag); Model.ShowMarker = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowMarker); Model.EinheitZeiterfassung = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.EinheitZeiterfassung); /* * Minuten: 0 * Stunden: 1 * Min & Std: 2 */ if (Model.EinheitZeiterfassung == 1) { Model.IsShowingDurationInHours = true; } Model.FilterGroupServiceCategories = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.FilterGroupServiceCategories); Model.SetStartTimeToEndTimeAfterSave = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.SetStartTimeToEndTimeAfterSave); Model.MokSettings = new MokSettings(); Model.MokSettings.SupportConceptExpirationLimitInMonths = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.HilfeplanAuslaufAuswahl, 3); Model.MokSettings.AnzTageZeiterfassErfolgt = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.AnzTageZeiterfassErfolgt); Model.MokSettings.MaxDaysEditServiceRecordsAllowed = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.MaxDaysEditServiceRecordsAllowed); Model.MokSettings.TimeUntilUILock = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.TimeUntilUILock); Model.MokSettings.ServiceRecordAllowChangeHours = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.ServiceRecordAllowChangeHours); Model.ShowServiceRecordInsertedOn = !UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.HideServiceRecordInsertedByAndInsertedOn); Model.ShowSignature = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowSignature) && Model.HasRightToProvideSingleSignature; Model.ShowDistanceField = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowDistanceFields); var settingsValue = GetSettingValue(Model.Mandator.Settings, SettingsKeys.IsServiceRecordNoticeMandatory); Model.IsServiceRecordNoticeMandatory = settingsValue is null || !settingsValue.Equals("0"); //User Settings var user = LoggedInUser; var userSettings = user?.Settings.FirstOrDefault(f => f.Type.Equals(SettingsType.ApplicationSettings))?.Value; Model.ShowExpiredSupportConcepts = UserSettingsUtils.GetSettingValueAsBool(userSettings, SettingsKeys.ShowExpiredSupportConcepts); Model.ShowOnlyOwnSupportConcepts = UserSettingsUtils.GetSettingValueAsBool(userSettings, SettingsKeys.ShowOnlyMySupportConcepts); Model.IsOnlyYearMonthVisible = UserSettingsUtils.GetSettingValueAsBool(userSettings, SettingsKeys.IsOnlyYearMonthVisible); Model.LastSelectedServiceRecordMonth = UserSettingsUtils.GetSettingValueAsDateTime(userSettings, SettingsKeys.LastSelectedServiceRecordMonth) ?? DateTime.Today; //int zeitraum; var serviceRecordTimeInterval = UserSettingsUtils.GetSettingValueAsEnum(userSettings, SettingsKeys.LastSelectedServiceRecordTimeInterval, ServiceRecordTimeInterval.LastWeek); Model.ServiceRecordTimeInterval = serviceRecordTimeInterval; if (serviceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen && (Model.SelectedZeitraum?.StartDate is null || Model.SelectedZeitraum.EndDate is null)) { var today = DateTime.Today; Model.SelectedZeitraum = new NullableDateTimeSpan(today.GetFirstOfMonth(), today); } Model.LastSelectedServiceRecordTimeIntervalDays = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.LastSelectedServiceRecordTimeIntervalDays); if (Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.Monatsauswahl) { Model.SelectedZeitraum = new NullableDateTimeSpan(Model.LastSelectedServiceRecordMonth.Date.GetFirstOfMonth(), Model.LastSelectedServiceRecordMonth.Date.GetLastOfMonth()); } CalculateSelectedDayCount(Model.LastSelectedServiceRecordTimeIntervalDays, Model.LastSelectedServiceRecordMonth, Model.SelectedZeitraum?.StartDate, Model.SelectedZeitraum?.EndDate, null); var customerFilter = MobileUserSettingsUtils.GetSettingValueAsEnum(userSettings, SettingsKeys.CustomerFilterInZeiterfassung, CustomerFilterEnum.MyCustomer); if (customerFilter != CustomerFilterEnum.MyCustomer && !Model.IsAllowedToSeeSupportConceptFilter) { customerFilter = CustomerFilterEnum.MyCustomer; } //if (Model.SelectedSupportConceptFilter == null) Model.SelectedSupportConceptFilter = customerFilter; Model.IsEndDateVisible = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.IsEndDateVisible); if (Model.IsZeiterfassungInStdMin) { var letzteZeiterfassungsdauer = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.LetzteZeiterfassungsDauer); Model.IsShowingDurationInHours = letzteZeiterfassungsdauer == 1; } } public void LoadTextModules() { Model.TextModules.Clear(); if (Model.SelectedServiceCategoryOid.HasValue && (Model.LoggedInEmployee?.EmployeeOid.HasValue ?? false)) { var allTextModules = OperationsService.GetTextModules(Model.HasRightToSeeGlobalTextModules, Model.LoggedInEmployee.EmployeeOid.Value, Model.HasRightToSeeGlobalTextModules, false); foreach (var tm in allTextModules.Where(textModule => textModule.IsParent == false)) { if (string.IsNullOrWhiteSpace(tm.Text)) { tm.Text = tm.Name; } } Model.AllTextModules = allTextModules.Where(tb => tb.TextModuleOid.HasValue).Select(tb => new TextbausteinDisplayItem(tb.Name, tb.Text, tb.Parent?.TextModuleOid, tb.TextModuleOid.Value, tb.IsExpanded)).ToList(); var x = allTextModules.Where( w => (w.ServiceCategory is null || w.ServiceCategory.ServiceCategoryOid == Model.SelectedServiceCategoryOid.Value) && !string.IsNullOrEmpty(w.Text) && (w.IsOnlyForEmployee && w.Employee.EmployeeOid.Equals(Model.LoggedInEmployee.EmployeeOid) || !w.IsOnlyForEmployee)).OrderBy(t => t.Text).ToList(); x.AddRangeIfElementsNotIn(BS.Shared.Core.Utils.GetParentTextModules(x)); var textModuleDisplayItems = x.Where(tb => tb.TextModuleOid.HasValue).Select(tb => new TextbausteinDisplayItem(tb.Name, tb.Text, tb.Parent?.TextModuleOid, tb.TextModuleOid.Value, tb.IsExpanded)).ToList(); foreach (var item in textModuleDisplayItems) { if (item.ParentOid is null) { continue; } var parent = textModuleDisplayItems.FirstOrDefault(p => p.Oid == item.ParentOid); parent?.Children.AddIfNotIn(item); } Model.TextModules = textModuleDisplayItems.Where(item => item.ParentOid is null).OrderBy(item => item.Name).ToList(); } } [Authorize] public ActionResult Main() { try { if(!MobileSessionFacade.IsUserLoggedIn() || Request.Browser.Browser.Equals("InternetExplorer")) { var isNewSession = Session.IsNewSession; if(isNewSession) { TempData[TempDataConstants.AutoEndOfSessionLogoutMessageKey] = "Sie wurden automatisch abgemeldet, da Ihre Session abgelaufen ist."; } return Logout(); } if(!Model.SessionInitialized) { Model.SessionInitialized = true; var mokSessionTimeout = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.MoKSessionTimeout, 20); Session.Timeout = mokSessionTimeout; Model.IsPasswordSecurityEnabled = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.IsPasswordSecurityActiv); if(Model.IsPasswordSecurityEnabled) { var tempDataValue = string.Empty; switch(MobileSessionFacade.PasswordStrength) { case 0: tempDataValue = "Sie benutzen ein sehr schwaches Passwort.

Bitte ändern Sie Ihr Passwort, indem Sie im Menü auf 'Password ändern' klicken."; break; case 1: tempDataValue = "Sie benutzen ein schwaches Passwort.

Bitte ändern Sie Ihr Passwort, indem Sie im Menü auf 'Password ändern' klicken."; break; } if(!string.IsNullOrEmpty(tempDataValue)) { TempData[TempDataConstants.ShowPwChPopupKey] = tempDataValue; } } } } catch(Exception e) { Log.Error(e.Message, e); } return View(Model); } [Authorize] private void UpdateSettings(string key, string value) { if(Model is null) { return; } var loggedInUser = LoggedInUser; if(loggedInUser?.UserOid is null) { return; } var userSettings = loggedInUser.Settings; UserSettingsUtils.SetSettingValue(SettingsType.ApplicationSettings, key, value, userSettings); UserService.UpdateUserSettings(loggedInUser.UserOid.Value, userSettings); } [HttpPost] [Authorize] public ActionResult SetShowExpiredSupportConcepts(FormCollection pCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } var newValue = "true,false" == pCollection[FormCollectionConstants.ShowExpiredSupportConceptsKey]; Model.ShowExpiredSupportConcepts = newValue; return UpdateApplicationSettings(SettingsKeys.ShowExpiredSupportConcepts, newValue ? "1" : "0"); } [HttpPost] public new ActionResult Logout() { return base.Logout(); } [Authorize] public string RateSelectedGoal(long? ratingTypeOid, long? goalOid) { if(Model is null || ratingTypeOid is null || goalOid is null || !Model.HasRightToRateGoals) { return LeerzeichenFuerGetMethoden; } var rating = Model.GoalRatingTypes.FirstOrDefault(ratingType => ratingType.RatingTypeOid == ratingTypeOid); var allGoals = new List(); if(Model.IsInGroupBookingMode) { var supportConcepts = Model.GroupBookingSelectedSupportConcepts; supportConcepts.DoForEach(sc => { allGoals.AddRangeIfElementsNotIn(sc.Goals); }); } else if(!Model.IsInGroupBookingMode) { allGoals = GetAllGoalsForSelectedSupportConcept(); } var goal = allGoals.FirstOrDefault(g => g.ValueListEntryOid?.Equals(goalOid.Value) ?? false); if(goal != null) { if(!Model.SelectedGoals.Any(a => a.ValueListEntryOid.HasValue && a.ValueListEntryOid.Value == goal.ValueListEntryOid)) { Model.SelectedGoals.AddIfNotIn(goal); } goal.RatingTypeOid = ratingTypeOid; var selectedGoal = Model.SelectedGoals.FirstOrDefault(a => a.ValueListEntryOid.HasValue && a.ValueListEntryOid.Value == goal.ValueListEntryOid); if(!(selectedGoal is null)) { selectedGoal.RatingTypeOid = ratingTypeOid; } } return SerializeObject(new GoalRating(rating?.DisplayName ?? string.Empty, goal?.ValueListEntryOid ?? 0)); } private List _AllGoals; private List GetAllGoalsForSelectedSupportConcept() { if(Model?.SelectedSupportConcept?.Goals is null) { return new List(); } if(_AllGoals is null) { _AllGoals = new List(Model.SelectedSupportConcept.Goals); } LoadParentGoals(Model.SelectedSupportConcept.Goals); return _AllGoals; } private void LoadParentGoals(IEnumerable goals) { var parentGoalOids = goals.Where(goal => goal.ParentOid.HasValue).Select(goal => goal.ParentOid.Value).Distinct().ToList(); var parentGoals = CustomerService.GetSupportConceptGoalParents(parentGoalOids); _AllGoals.AddRangeIfElementsNotIn(parentGoals); var nextParentGoalOids = parentGoals.Where(goal => goal.ParentOid.HasValue).Select(goal => goal.ParentOid.Value).Distinct().ToList(); if(nextParentGoalOids.Any()) { LoadParentGoals(parentGoals); } } private void LoadGoals() { try { if(Model is null) { return; } var selectedGoals = new List(); if(Model.IsInGroupBookingMode) { var supportConcepts = Model.GroupBookingSelectedSupportConcepts; supportConcepts.DoForEach(sc => { selectedGoals.AddRangeIfElementsNotIn(sc.Goals); }); } else { if(Model.SelectedCostBearerSupportConceptOid is null) { return; } var supportConcept = Model.SupportConcepts.FirstOrDefault(sc => sc.CostBearerRelations.Any(sc2Cb => sc2Cb.CostBearer2SupportConceptOid.HasValue && sc2Cb.CostBearer2SupportConceptOid.Value.Equals(Model.SelectedCostBearerSupportConceptOid.Value))); if(supportConcept is null) { Log.Info($"Hilfeplan von Bewilligung mit Oid {Model.SelectedCostBearerSupportConceptOid} nicht gefunden beim Laden der Ziele (LoadGoals)."); return; } Model.SelectedSupportConcept = supportConcept; selectedGoals = supportConcept.Goals; } var missingParents = selectedGoals.Where(w => w.ParentOid != null && false == selectedGoals.Any(a => a.ValueListEntryOid.Equals(w.ParentOid))).Select(s => s.ParentOid).ToList(); _ParentGoals = new Dictionary(); foreach(var oid in missingParents) { if(oid.HasValue) { LoadMissingParents(oid.Value); } } var allGoals = selectedGoals.Union(_ParentGoals.Values).ToList(); Model.AllGoals = allGoals; Model.GoalTree = BuildGoalTree(allGoals); } catch(Exception exception) { Log.Error(exception); } } private List BuildGoalTree(IReadOnlyCollection goals) { var ziele = goals.Where(w => _GoalTypes.Contains(w.Type)).OrderBy(s => s.DisplayName).ToList(); var massnahmen = goals.Where(w => _MeasureTypes.Contains(w.Type)).OrderBy(s => s.DisplayName).ToList(); var goalTree = new List(); var goalTreeDic = new Dictionary(); var goalsWithRating = Model.SelectedServiceRecord?.Goals?.Where(goal => goal.RatingTypeOid.HasValue).ToList() ?? new List(); var ratingTypes = OperationsService.GetRatingTypesByOids(goalsWithRating.Where(goal => goal.RatingTypeOid.HasValue).Select(goal => goal.RatingTypeOid.Value).Distinct().ToList()); foreach(var ziel in ziele) { if(ziel.ValueListEntryOid is null) { continue; } var treeItem = new GoalTreeItem(true, ziel.Type) { Children = new List(), Header = ziel.DisplayName ?? string.Empty, ParentOid = ziel.ParentOid, ValueListEntryOid = ziel.ValueListEntryOid }; goalTreeDic.Add(ziel.ValueListEntryOid.Value, treeItem); if(ziel.ParentOid is null) { goalTree.Add(treeItem); } } foreach(var zielMitEltern in goalTreeDic.Values.Where(zielMitEltern => zielMitEltern.ParentOid != null)) { if(zielMitEltern.ParentOid is null) { continue; } goalTreeDic[zielMitEltern.ParentOid.Value].Children.Add(zielMitEltern); } foreach(var ziel in massnahmen) { var ratingName = Model.HasAnyRatingTypes ? "Bewerten" : string.Empty; var goalWithRating = goalsWithRating.FirstOrDefault(g => g.ValueListEntryOid == ziel.ValueListEntryOid); if(Model.HasAnyRatingTypes && Model.IsInEditingMode && goalWithRating != null && ratingTypes.Any()) { var ratingType = ratingTypes.FirstOrDefault(rt => rt.RatingTypeOid == goalWithRating.RatingTypeOid); if(ratingType != null) { ratingName = ratingType.DisplayName; } } var kind = new GoalTreeItem(false, ziel.Type) { Children = new List(), Header = ziel.DisplayName ?? string.Empty, IsLeaf = true, ValueListEntryOid = ziel.ValueListEntryOid, RatingName = ratingName, ParentOid = ziel.ParentOid }; if(ziel.ParentOid is null || !goalTreeDic.ContainsKey(ziel.ParentOid.Value)) { continue; } kind.ParentOid = goalTreeDic[ziel.ParentOid.Value].ParentOid; goalTreeDic[ziel.ParentOid.Value].Children.Add(kind); } foreach(var item in goalTreeDic.Values.Where(item => item.Children.Count == 0)) { item.IsLeaf = true; } goalTree = goalTree.OrderBy(o => o.ValueListEntryOid).ToList(); foreach(var item in goalTree) { SortGoals(item); } return goalTree; } private static void SortGoals(GoalTreeItem goalTreeItem) { goalTreeItem.Children = goalTreeItem.Children.OrderBy(s => s.ValueListEntryOid).ToList(); foreach(var test in goalTreeItem.Children) { SortGoals(test); } } private void LoadMissingParents(long pParentOid) { while(true) { var parentDC = ValueListService.GetValueListEntryByOid(pParentOid); if(parentDC?.ValueListEntryOid is null) { continue; } if(!_ParentGoals.ContainsKey(parentDC.ValueListEntryOid.Value)) { _ParentGoals.Add(parentDC.ValueListEntryOid.Value, parentDC); if(parentDC.ParentOid != null) { pParentOid = parentDC.ParentOid.Value; continue; } } break; } } [Authorize] public string LoadStatistics(long oid) { try { if (Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var isLoaded = false; foreach(var supportConcept in Model.SupportConcepts) { if(supportConcept.CostBearerRelations.Any(supportConceptCostBearerRel => supportConceptCostBearerRel.CostBearer2SupportConceptOid == oid)) { isLoaded = true; } if(isLoaded) { break; } } if(!isLoaded) { return null; } var statisticsInfo = OperationsService.GetServiceRecordStatisticInfo(oid, DateTime.Now); var supportConceptStatisticsData = new SupportConceptStatisticsData(); if(statisticsInfo != null) { var count = 0; supportConceptStatisticsData.ShowDiagram = false; foreach(var period in statisticsInfo.PeriodStatisticInfos) { var statisticPeriod = new StatisticPeriod(); for(var i = 0; i < period.LeftValues.Length; i++) { var skipFirstHeader = count > 0 && i == 0; var left = period.LeftValues[i] ?? string.Empty; var right = period.RightValues[i] ?? string.Empty; var seperator = !string.IsNullOrWhiteSpace(left) && !string.IsNullOrWhiteSpace(right) ? "/" : string.Empty; var value = $"{left}{seperator}{right}"; var header = skipFirstHeader ? value : statisticsInfo.Header[i]; value = header == value ? string.Empty : value; statisticPeriod.Header2Values.AddIfNotIn(new Header2Values(header, value)); } supportConceptStatisticsData.StatisticPeriods.Add(statisticPeriod); count++; } } else { var supportConceptStatistics = OperationsService.CreateSupportConceptStatistics(oid, DateTime.Now); var provided = supportConceptStatistics.MinutesProvidedThisWeek / 60; var approved = supportConceptStatistics.MinutesApprovedPerWeek / 60; var freePerWeek = supportConceptStatistics.MinutesFreePerWeekAverage / 60; var providedTotal = supportConceptStatistics.MinutesProvidedTotalRounded / 60; var approvedTotal = supportConceptStatistics.MinutesApprovedTotal / 60; var freePerWeekTotal = (approvedTotal - providedTotal); decimal percentage = 0; if(approvedTotal > 0) { percentage = providedTotal / approvedTotal * 100; } if(percentage > 100) { percentage = 100; } supportConceptStatisticsData.Percentage = percentage; var statisticPeriod = new StatisticPeriod(); if(supportConceptStatistics.PeriodStatistics.Count != 1) { statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Bewilligungszeitraum:", "Gesamt")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Geleistet diese Woche/gesamt:", $"{provided:0.00}/{providedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Bewilligt pro Woche/gesamt:", $"{approved:0.00}/{approvedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Frei pro Woche(Ø)/gesamt:", $"{freePerWeek:0.00}/{freePerWeekTotal:0.00}")); supportConceptStatisticsData.StatisticPeriods.Add(statisticPeriod); } foreach(var periodStatistics in supportConceptStatistics.PeriodStatistics) { provided = periodStatistics.MinutesProvidedThisWeek / 60; approved = periodStatistics.MinutesApprovedPerWeek / 60; freePerWeek = periodStatistics.MinutesFreePerWeek / 60; providedTotal = periodStatistics.MinutesProvidedTotalRounded / 60; approvedTotal = periodStatistics.MinutesApprovedTotal / 60; freePerWeekTotal = (approvedTotal - providedTotal); var supportConceptApprovalPeriodSpan = periodStatistics.SupportConceptApprovalPeriod.Span; var minVal = DateTime.Now.AddYears(-50); var maxVal = DateTime.Now.AddYears(50); var sd = supportConceptApprovalPeriodSpan.StartDate; var ed = supportConceptApprovalPeriodSpan.EndDate; var start = sd > minVal && sd < maxVal ? $"{sd:dd.MM.yy} " : string.Empty; var end = ed > minVal && ed < maxVal ? $" {ed:dd.MM.yy}" : string.Empty; var span = $"{start}-{end}"; var serviceCategoryName = periodStatistics.SupportConceptApprovalPeriod.ServiceCategory != null ? periodStatistics.SupportConceptApprovalPeriod.ServiceCategory.Name + ":" : "Bewilligungszeitraum:"; statisticPeriod = new StatisticPeriod(); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values(serviceCategoryName, span)); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Geleistet diese Woche/gesamt:", $"{provided:0.00}/{providedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Bewilligt pro Woche/gesamt:", $"{approved:0.00}/{approvedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Frei pro Woche(Ø)/gesamt:", $"{freePerWeek:0.00}/{freePerWeekTotal:0.00}")); supportConceptStatisticsData.StatisticPeriods.Add(statisticPeriod); } } return SerializeObject(supportConceptStatisticsData); } catch (Exception e) { Log.Error(e.Message, e); return SerializeObject("Fehler 560"); } } [Authorize] public ActionResult SaveSignature(FormCollection formCollection) { var blob = formCollection[FormCollectionConstants.ServiceRecordSignatureBlobKey]; var date = DateTime.Parse(formCollection[FormCollectionConstants.ServiceRecordSignatureDateKey]); long.TryParse(formCollection[FormCollectionConstants.ServiceRecordSignatureRecordOidKey], out var serviceRecordOid); var serviceRecord = Model.ServiceRecords.FirstOrDefault(sr => sr.ServiceRecordOid.HasValue && sr.ServiceRecordOid.Value.Equals(serviceRecordOid)); if(serviceRecordOid < 1 || serviceRecord is null) { var message2Log = string.Empty; if(serviceRecordOid < 1) { message2Log = $"Einzelunterschrift konnte nicht gespeichert werden, da die ServiceRecordOid {serviceRecordOid} ungültig ist."; } else if(serviceRecord is null) { message2Log = "Einzelunterschrift konnte nicht gespeichert werden, da der Zeiterfassungseintrag im Model nicht gefunden werden konnte."; } Log.Error(message2Log); TempData[TempDataConstants.ErrorMessageKey] = "Beim Speichern der Unterschrift ist ein Fehler aufgetreten. Bitte wenden Sie sich an Ihren Administrator."; return RedirectToActionPermanent("Main", "Main"); } long? oid; using(var signatureBitmap = SignatureUtils.Base64StringToBitmap(blob.Split(',')[1])) { var isValid = SignatureUtils.ValidateSignature(signatureBitmap); if(!isValid) { TempData[TempDataConstants.ErrorMessageKey] = "Das Unterschriftenfeld darf nicht leer sein."; return RedirectToActionPermanent("Main", "Main"); } oid = OperationsService.InsertSignature(new SignatureDC { DataBild = blob, Zeitstempel = date, ServiceRecordOid = serviceRecordOid }).SignatureOid; } if(oid is null) { TempData[TempDataConstants.ErrorMessageKey] = "Beim Speichern der Unterschrift ist ein Fehler aufgetreten. Bitte wenden Sie sich an Ihren Administrator."; } else { TempData[TempDataConstants.InfoMessageKey] = $"Die Unterschrift von {serviceRecord.Customer} für den Eintrag vom {MainModel.GetServiceRecordTimeHeader(serviceRecord, false)} wurde erfolgreich gespeichert."; } return RedirectToActionPermanent("Main", "Main"); } [Authorize] public static string ApplyWatermark(string blob, string watermarkImagePath) { if(string.IsNullOrWhiteSpace(blob)) { return null; } var watermarkImage = Image.FromFile(watermarkImagePath); var signatureImage = SignatureUtils.Base64StringToBitmap(blob); var hasTransparentBackground = SignatureUtils.HasTransparentBackground(blob); if(hasTransparentBackground) { signatureImage = SignatureUtils.AddBackgroundToBitmap(signatureImage, Color.White); } var watermarker = new Watermarker(signatureImage); for(var y = 0; y < signatureImage.Height; y++) { for(var x = 0; x < signatureImage.Width; x++) { watermarker.Position = WatermarkPosition.Absolute; watermarker.PositionX = x; watermarker.PositionY = y; watermarker.Margin = new Padding(20); watermarker.Opacity = .1f; watermarker.TransparentColor = Color.White; watermarker.DrawImage(watermarkImage); x += watermarkImage.Width; } y += watermarkImage.Height; } return "data:image/png;base64," + SignatureUtils.ConvertImageToBase64String(watermarker.Image); } [Authorize] public string LoadCompleteTextbausteinByOid(long pTextbausteinOid) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var textModule = Model.AllTextModules.FirstOrDefault(f => f.Oid == pTextbausteinOid); return textModule is null ? null : string.IsNullOrWhiteSpace(textModule.Text) ? textModule.Name : textModule.Text; } [Authorize] public ActionResult LoadUpToDateTextModules() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("TextModulePartial"); } //Wird alles im InitViewModel gemacht: //Model.TextModules.Clear(); //if(Model.SelectedServiceCategoryOid.HasValue && (Model.LoggedInEmployee?.EmployeeOid.HasValue ?? false)) //{ // var allTextModules = OperationsService.GetTextModules(Model.HasRightToSeeGlobalTextModules, Model.LoggedInEmployee.EmployeeOid.Value, Model.HasRightToSeeGlobalTextModules, false); // foreach(var tm in allTextModules.Where(textModule => textModule.IsParent == false)) // { // if(string.IsNullOrWhiteSpace(tm.Text)) // { // tm.Text = tm.Name; // } // } // Model.AllTextModules = allTextModules.Where(tb => tb.TextModuleOid.HasValue).Select(tb => new TextbausteinDisplayItem(tb.Name, tb.Text, tb.Parent?.TextModuleOid, tb.TextModuleOid.Value, tb.IsExpanded)).ToList(); // var x = allTextModules.Where( // w => (w.ServiceCategory is null || w.ServiceCategory.ServiceCategoryOid == Model.SelectedServiceCategoryOid.Value) // && !string.IsNullOrEmpty(w.Text) // && (w.IsOnlyForEmployee && w.Employee.EmployeeOid.Equals(Model.LoggedInEmployee.EmployeeOid) || !w.IsOnlyForEmployee)).OrderBy(t => t.Text).ToList(); // x.AddRangeIfElementsNotIn(BS.Shared.Core.Utils.GetParentTextModules(x)); // var textModuleDisplayItems = x.Where(tb => tb.TextModuleOid.HasValue).Select(tb => new TextbausteinDisplayItem(tb.Name, tb.Text, tb.Parent?.TextModuleOid, tb.TextModuleOid.Value, tb.IsExpanded)).ToList(); // foreach(var item in textModuleDisplayItems) // { // if(item.ParentOid is null) // { // continue; // } // var parent = textModuleDisplayItems.FirstOrDefault(p => p.Oid == item.ParentOid); // parent?.Children.AddIfNotIn(item); // } // Model.TextModules = textModuleDisplayItems.Where(item => item.ParentOid is null).OrderBy(item => item.Name).ToList(); //} return PartialView("TextModulePartial", Model); } [HttpPost] [Authorize] public ActionResult CreateOrUpdateServiceRecord(FormCollection collection) { try { if(Model is null) { Log.Info($"Model ist null bei CreateOrUpdateServiceRecord; User: {LoggedInUser.UserOid} {LoggedInUser.LoginName} ({LoggedInUser.Employee})"); TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } // Falls ein Termin in die Zeiterfassung übernommen werden soll SchedulerAppointmentDC appointmentPrototype = null; if(Model.TransferringAppointmentOid.HasValue && Model.LoggedInEmployee.EmployeeOid.HasValue) { var app = DAOFactory.GenericDAO.LoadByID(Model.TransferringAppointmentOid.Value); appointmentPrototype = MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDC(app); } var marker = "on" == collection[FormCollectionConstants.MarkerKey]; string doku1; if(Model.Dokutypes != null && Model.Dokutypes.Length > 0) { doku1 = collection[FormCollectionConstants.Dokumentation1Key]; } else { doku1 = collection[FormCollectionConstants.Dokumentation6Key]; } decimal? betrag = null; var betragAsString = collection[FormCollectionConstants.BetragKey]?.Replace('.', ','); if(decimal.TryParse(betragAsString, out var betragAsDecimal)) { betrag = betragAsDecimal; } Log.Info($"CreateOrUpdateServiceRecord: datum:{collection[FormCollectionConstants.DateKey]}; start:{collection[FormCollectionConstants.StartKey]}; ende:{collection[FormCollectionConstants.EndKey]}; dauer:{collection[FormCollectionConstants.DurationKey]}; doku:{doku1}; aktion:{(Model.IsInEditingMode ? "Speichern" : "Anlegen")}"); if(string.IsNullOrEmpty(collection[FormCollectionConstants.DateKey])) { Log.Info($"CreateOrUpdateServiceRecord: Das Startdatum ist null. Breche das {(Model.IsInEditingMode ? "Speichern" : "Anlegen")} ab."); return View("Main", Model); } var distanz = collection[FormCollectionConstants.DistanceKey]; decimal? distanceInMeters = null; if(!string.IsNullOrEmpty(distanz)) { if(decimal.TryParse(distanz, out var parsedDistance)) { distanceInMeters = parsedDistance; } } var selectedCostbearerScRelOid = Model.SelectedCostBearerSupportConceptOid < 1 ? null : Model.SelectedCostBearerSupportConceptOid; var datum = Convert.ToDateTime(collection[FormCollectionConstants.DateKey]); var enddatum = datum; var endDateString = collection[FormCollectionConstants.EndDateKey]; if(endDateString?.Length > 0) { enddatum = Convert.ToDateTime(endDateString); } var start = collection[FormCollectionConstants.StartKey]; var ende = collection[FormCollectionConstants.EndKey]; var dauer = 0m; if(datum > enddatum) { enddatum = datum; } var durationAsString = collection[FormCollectionConstants.DurationKey]; durationAsString = durationAsString?.Replace('.', ','); if(!string.IsNullOrEmpty(durationAsString)) { decimal.TryParse(durationAsString, out dauer); } // Wenn die Dauer in Stunden ist if(Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1) { dauer *= 60m; } var doku2 = collection[FormCollectionConstants.Dokumentation2Key]?.RemoveUppercaseEsszett(); var doku3 = collection[FormCollectionConstants.Dokumentation3Key]?.RemoveUppercaseEsszett(); var doku4 = collection[FormCollectionConstants.Dokumentation4Key]?.RemoveUppercaseEsszett(); var doku5 = collection[FormCollectionConstants.Dokumentation5Key]?.RemoveUppercaseEsszett(); var zeitenFeld = new DateTime[2]; if(start == string.Empty && ende == string.Empty) { zeitenFeld[0] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1); if(enddatum == datum) { zeitenFeld[1] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer)); } else { zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer)); } } else { zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, Convert.ToDouble(dauer)) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, Convert.ToDouble(dauer)); } if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0]) { dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes; } if(Model.IsInEditingMode) { var selectedRecordOid = Model.SelectedServiceRecordOid ?? Model.SelectedServiceRecord.ServiceRecordOid; Model.NewServiceRecord = Model.GetServiceRecord(selectedRecordOid.Value); } if(Model.NewServiceRecord is null) { Log.Info("CreateOrUpdateServiceRecord: NewServiceRecord ist null. Breche ab."); return RedirectToActionPermanent("Main"); } Model.NewServiceRecord.IP = Request.UserHostAddress; Model.NewServiceRecord.Goals = Model.SelectedGoals; Model.NewServiceRecord.Start = zeitenFeld[0]; Model.NewServiceRecord.End = zeitenFeld[1]; Model.NewServiceRecord.Betrag = betrag; Model.NewServiceRecord.ServiceRecordType = marker ? ServiceRecordTypeId.Content : ServiceRecordTypeId.DefaultActivity; Model.NewServiceRecord.DistanceInMeter = null; Model.NewServiceRecord.DistanceInMeterDecimal = distanceInMeters; if(Model.LoggedInEmployee.EmployeeOid.HasValue) { if(!Model.IsInEditingMode) { Model.NewServiceRecord.Employee = Model.SelectedEmployee ?? LoggedInUser.Employee; } else { if(!(Model.SelectedEmployee is null)) { Model.NewServiceRecord.Employee = Model.SelectedEmployee; } } var sc = Model.SupportConcepts.FirstOrDefault(fod => fod.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && a.CostBearer2SupportConceptOid.Value.Equals(selectedCostbearerScRelOid))); if(!(sc is null)) { if(sc.SupportConceptOid.HasValue) { Model.NewServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(sc.SupportConceptOid.Value, Model.LoggedInEmployee.EmployeeOid); } Model.NewServiceRecord.Customer = sc.Customer; var cb2ScRel = sc.CostBearerRelations.First(f => f.CostBearer2SupportConceptOid.HasValue && f.CostBearer2SupportConceptOid.Equals(selectedCostbearerScRelOid)); Model.NewServiceRecord.CostBearer = cb2ScRel.CostBearer; var intervall = Model.NewServiceRecord.CostBearer.ActualMinuteIntervall; if(intervall > 0) { Model.NewServiceRecord.RoundedDuration = dauer % intervall != 0 ? dauer + (intervall - dauer % intervall) : dauer; } else { Model.NewServiceRecord.RoundedDuration = dauer; } Model.NewServiceRecord.CostBearer2SupportConceptOid = selectedCostbearerScRelOid; } else { Model.NewServiceRecord.RoundedDuration = dauer; } } Model.NewServiceRecord.DurationInStunden = Model.IsShowingDurationInHours ? ZeiterfassungsDauer.Stunden : ZeiterfassungsDauer.Minuten; Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; if(Model.IsEndDateVisible) { Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum; } Model.NewServiceRecord.Notice = string.IsNullOrEmpty(doku1) ? null : doku1?.RemoveUppercaseEsszett(); Model.NewServiceRecord.Notice2 = string.IsNullOrEmpty(doku2) ? null : doku2?.RemoveUppercaseEsszett(); Model.NewServiceRecord.Notice3 = string.IsNullOrEmpty(doku3) ? null : doku3?.RemoveUppercaseEsszett(); Model.NewServiceRecord.Notice4 = string.IsNullOrEmpty(doku4) ? null : doku4?.RemoveUppercaseEsszett(); Model.NewServiceRecord.Notice5 = string.IsNullOrEmpty(doku5) ? null : doku5?.RemoveUppercaseEsszett(); var serviceDescOid = 0L; if(!string.IsNullOrEmpty(collection[FormCollectionConstants.ServiceDescriptionKey])) { serviceDescOid = Convert.ToInt64(collection[FormCollectionConstants.ServiceDescriptionKey]); } else if(Model.SelectedServiceDescriptionOid.HasValue) { serviceDescOid = Model.SelectedServiceDescriptionOid.Value; } if(serviceDescOid > 0) { Model.NewServiceRecord.ServiceDescription = OperationsService.GetServiceDescription(serviceDescOid); } if(Model.NewServiceRecord.RoundedDuration == 0) { Model.NewServiceRecord.RoundedDuration = dauer; } Model.NewServiceRecord.IP = Request.UserHostAddress; Model.NewServiceRecord.InsertedOn = DateTime.Now; Model.NewServiceRecord.InsUser = MobileSessionFacade.EmployeeFullname; Model.NewServiceRecord.IsCreatedInMobileClient = true; if(Model.IsInGroupBookingMode && Model.GroupBookingSelectedSupportConcepts.Count > 1) { return Model.NewServiceRecord.ServiceRecordOid.HasValue ? SaveGroupBooking() : UpdateGroupBooking(); } if(!Model.IsInEditingMode) { var oidList = OperationsService.InsertNewServiceRecords(new List { Model.NewServiceRecord }); Model.LastCreatedServiceRecordOid = oidList[0]; if(Model.NewServiceRecord.CostBearer != null && Model.ShowSignature) { TempData[TempDataConstants.ShowSignatureSuggestionPopup] = true; } if(appointmentPrototype is object) { var isRecurring = !(appointmentPrototype.RecurrenceInfo is null); if(isRecurring && appointmentPrototype.Type != (int) AppointmentType.ChangedOccurrence) { var id = appointmentPrototype.RecurrenceIdReference; var recurrenceInfo = new RecurrenceInfo(); recurrenceInfo.FromXml(appointmentPrototype.RecurrenceInfo); var occurrenceCalculator = OccurrenceCalculator.CreateInstance(recurrenceInfo); var pattern = StaticAppointmentFactory.CreateAppointment(AppointmentType.Pattern); pattern.RecurrenceInfo.FromXml(appointmentPrototype.RecurrenceInfo); pattern.Start = pattern.RecurrenceInfo.Start; pattern.End = pattern.RecurrenceInfo.End; var occurrence = occurrenceCalculator.CalcOccurrences(new TimeInterval(appointmentPrototype.StartDate.Value, appointmentPrototype.EndDate.Value), pattern).FirstOrDefault(); if(!(occurrence is null)) { var index = occurrence.RecurrenceIndex; appointmentPrototype = SchedulerController.CloneAppointment(appointmentPrototype, $"", (int)AppointmentType.ChangedOccurrence); } else { appointmentPrototype = null; } } if(appointmentPrototype is object) { var serviceRecord = OperationsService.GetServiceRecordById(Model.LastCreatedServiceRecordOid); appointmentPrototype.ServiceRecordList.AddIfNotIn(serviceRecord); if(appointmentPrototype.SchedulerAppointmentOid.HasValue) { KalenderService.UpdateSchedulerAppointments(new List { appointmentPrototype }); } else { KalenderService.InsertSchedulerAppointments(new List { appointmentPrototype }); } } } } else { OperationsService.UpdateServiceRecords(new List { Model.NewServiceRecord }); } if(Model.SetStartTimeToEndTimeAfterSave) { var previousStartDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.Start : Model.NewServiceRecord?.Start; var previousEndDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.End : Model.NewServiceRecord?.End; if(!(previousStartDate is null) && !(previousEndDate is null)) { var duration = (previousEndDate - previousStartDate).Value.TotalMinutes; Model.NewStartDate = previousEndDate; Model.NewEndDate = previousEndDate.Value.AddMinutes(duration); } } Model.NewServiceRecord = new ServiceRecordDC(); } catch (Exception e) { Log.Error(e.Message, e); } ResetBookingMode(Model.IsInGroupBookingMode ? BookingMode.GroupBookingMode : BookingMode.SingleBookingMode); return ResetEditingMode(); } [Authorize] private ActionResult SaveGroupBooking() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } var employeeCount = Model.GroupBookingSelectedEmployees.Count; var personCount = Model.GroupBookingSelectedSupportConcepts.Count; var cb2ScOids = Model.GroupBookingSelectedCostbearerRelOids; var list = CalculateGroupBookingDuration(employeeCount, personCount, cb2ScOids); var newDCList = new List(); foreach(var dc in list) { foreach(var emp in Model.GroupBookingSelectedEmployees) { var newDC = CloneServiceRecord(dc); newDC.Employee = emp; newDC.InsertedOn = DateTime.Now; newDCList.Add(newDC); } } if(newDCList.Count > 0) { if(newDCList.Count == 1) { OperationsService.InsertNewServiceRecords(newDCList); } else { var groupDC = new ServiceRecordGroupDC { EmployeeCount = employeeCount, CustomerCount = personCount, StartDate = Model.NewServiceRecord.Start, EndDate = Model.NewServiceRecord.End, Notice = Model.NewServiceRecord.Notice?.RemoveUppercaseEsszett(), Notice2 = Model.NewServiceRecord.Notice2?.RemoveUppercaseEsszett(), Notice3 = Model.NewServiceRecord.Notice3?.RemoveUppercaseEsszett(), Notice4 = Model.NewServiceRecord.Notice4?.RemoveUppercaseEsszett(), Notice5 = Model.NewServiceRecord.Notice5?.RemoveUppercaseEsszett(), ServiceRecordList = newDCList }; if(Model.NewServiceRecord.GroupRoundedDuration != null) { groupDC.RoundedDuration = Model.NewServiceRecord.GroupRoundedDuration.Value; } groupDC = OperationsService.InsertNewServiceRecordGroup(groupDC); var serviceRecords = groupDC.ServiceRecordList; if(Model.TransferringAppointmentOid.HasValue && Model.LoggedInEmployee.EmployeeOid.HasValue) { var app = DAOFactory.GenericDAO.LoadByID(Model.TransferringAppointmentOid.Value); var appointment = MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDC(app); appointment.ServiceRecordList.AddRange(serviceRecords); KalenderService.UpdateSchedulerAppointments(new List { appointment }); } } } return ResetEditingMode(); } [Authorize] private ActionResult UpdateGroupBooking() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } var dc = Model.SelectedServiceRecord; var group = OperationsService.GetServiceRecordGroup(dc.GroupOid.Value); UpdateServiceRecordGroup(group); var employeeCount = Model.GroupBookingSelectedEmployees.Count; var customerCount = Model.GroupBookingSelectedSupportConcepts.Count; group.EmployeeCount = employeeCount; group.CustomerCount = customerCount; var roundDuration = true; var minuteInterval = 0; CompactOrganisationDC org = null; var cb2ScOids = new List(); foreach(var scdc in Model.GroupBookingSelectedSupportConcepts) { if(scdc.CostBearerRelations.Count > 0) { cb2ScOids.Add(scdc.CostBearerRelations.ElementAt(0).CostBearer2SupportConceptOid.Value); if(org is null) { org = scdc.CostBearerRelations.ElementAt(0).CostBearer; if(org != null) { minuteInterval = org.ActualMinuteIntervall; } } else { if(scdc.CostBearerRelations.ElementAt(0).CostBearer is null || !org.Equals(scdc.CostBearerRelations.ElementAt(0).CostBearer)) { roundDuration = false; } } } } var duration = (decimal) (Model.NewServiceRecord.End.Value - Model.NewServiceRecord.Start.Value).TotalMinutes; var lRoundedDuration = duration; decimal groupDuration; decimal roundedDuration; var gd = OperationsService.CalculateGroupDuration2(customerCount, employeeCount, duration, cb2ScOids.ToArray()); if(gd != null) { groupDuration = gd.TotalDuration; roundedDuration = gd.SingleDuration; } else { if(minuteInterval > 0 && roundDuration) { lRoundedDuration = duration % minuteInterval != 0 ? duration + (minuteInterval - duration % minuteInterval) : duration; } groupDuration = lRoundedDuration; roundedDuration = Math.Round(groupDuration / Model.GroupBookingSelectedSupportConcepts.Count, 0 , MidpointRounding.AwayFromZero); } Model.NewServiceRecord.RoundedDuration = roundedDuration; Model.NewServiceRecord.GroupRoundedDuration = groupDuration; group.Notice = Model.NewServiceRecord.Notice?.RemoveUppercaseEsszett(); group.Notice2 = Model.NewServiceRecord.Notice2?.RemoveUppercaseEsszett(); group.Notice3 = Model.NewServiceRecord.Notice3?.RemoveUppercaseEsszett(); group.Notice4 = Model.NewServiceRecord.Notice4?.RemoveUppercaseEsszett(); group.Notice5 = Model.NewServiceRecord.Notice5?.RemoveUppercaseEsszett(); group.RoundedDuration = groupDuration; group.StartDate = Model.NewServiceRecord.Start; group.EndDate = Model.NewServiceRecord.End; foreach(var item in group.ServiceRecordList) { item.Goals = Model.NewServiceRecord.Goals; item.Notice = Model.NewServiceRecord.Notice?.RemoveUppercaseEsszett(); item.Notice2 = Model.NewServiceRecord.Notice2?.RemoveUppercaseEsszett(); item.Notice3 = Model.NewServiceRecord.Notice3?.RemoveUppercaseEsszett(); item.Notice4 = Model.NewServiceRecord.Notice4?.RemoveUppercaseEsszett(); item.Notice5 = Model.NewServiceRecord.Notice5?.RemoveUppercaseEsszett(); item.End = Model.NewServiceRecord.End; item.Start = Model.NewServiceRecord.Start; item.RoundedDuration = roundedDuration; item.DistanceInMeterDecimal = Model.NewServiceRecord.DistanceInMeterDecimal; item.ServiceDescription = Model.NewServiceRecord.ServiceDescription; item.ServiceRecordFormat = Model.NewServiceRecord.ServiceRecordFormat; item.DurationInStunden = Model.NewServiceRecord.DurationInStunden; item.ServiceDescription = item.ServiceDescription ?? Model.NewServiceRecord.ServiceDescription; item.GroupEmployeeCount = group.EmployeeCount; item.GroupPersonCount = group.CustomerCount; item.GroupOid = Model.NewServiceRecord.GroupOid; item.GroupRoundedDuration = groupDuration; item.Betrag = Model.NewServiceRecord.Betrag; if(item.CostBearer != null && item.CostBearer.CostBearerOid is null && item.SupportConcept != null && item.SupportConcept.CostBearerList.Count > 0) { item.CostBearer.CostBearerOid = item.SupportConcept.CostBearerList[0].CostBearerOid; } } if(Model.NewServiceRecord.GroupOid.HasValue) { OperationsService.UpdateServiceRecordGroup(group); } Model.NewServiceRecord = null; Model.SelectedServiceRecord = null; Model.SelectedServiceRecordOid = null; Model.GroupBookingSelectedSupportConcepts = new List(); Model.GroupBookingSelectedEmployees = new List(); ResetBookingMode(BookingMode.SingleBookingMode); Model.IsInEditingMode = false; return ResetEditingMode(); } [Authorize] private IEnumerable CalculateGroupBookingDuration(int pEmployeeCount, int pCustomerCount, ICollection cb2ScOids) { var compactSupportConcepts = CustomerServiceImp.GetCompactSupportConcepts((from sc in Model.GroupBookingSelectedSupportConcepts where sc.SupportConceptOid != null select sc.SupportConceptOid.Value).ToList(), LoggedInUser.Employee.EmployeeOid); var nodes = (from supportConcept in Model.GroupBookingSelectedSupportConcepts let cb = supportConcept.CostBearerRelations.FirstOrDefault(f => cb2ScOids.Contains(f.CostBearer2SupportConceptOid.Value)) let sc = compactSupportConcepts.FirstOrDefault(f => f.SupportConceptOid == supportConcept.SupportConceptOid) where cb != null && sc != null select SupportConceptService.CreateFlatSupportConceptItem(sc, CustomerService.LoadOrganisationCompact(cb.CostBearer.OrganisationOid))).ToList(); var list = new List(); foreach(var node in nodes) { var sc = CloneServiceRecord(Model.NewServiceRecord); if(Model.NewServiceRecord.RoundedDuration == 0) { if(Model.NewServiceRecord.Start.HasValue && Model.NewServiceRecord.End.HasValue) { var minutes = Model.NewServiceRecord.End.Value.Subtract(Model.NewServiceRecord.Start.Value).TotalMinutes; Model.NewServiceRecord.RoundedDuration = (decimal)minutes; } } sc.GroupRoundedDuration = Model.NewServiceRecord.RoundedDuration; sc.CostBearer2SupportConceptOid = node.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.CostBearer2SupportConceptOid; sc.SupportConcept = node.SupportConceptTreeNodeDC.SupportConcept; sc.CostBearer = node.SupportConceptTreeNodeDC.CostBearer; sc.Customer = node.SupportConceptTreeNodeDC.Customer; sc.GroupEmployeeCount = pEmployeeCount; sc.GroupPersonCount = pCustomerCount; list.Add(sc); } var roundDuration = false; var minuteInterval = 0; string calcdId = null; var lastMinuteInterval = -1; if(Model.SelectedServiceDescriptionOid.HasValue && IsBillable(Model.SelectedServiceDescriptionOid.Value, Model.GetServiceDesctiptions())) { roundDuration = true; foreach(var org in from dc in Model.GroupBookingSelectedSupportConcepts where dc.CostBearerRelations.Count > 0 select dc.CostBearerRelations.First().CostBearer) { if(org != null) { minuteInterval = org.ActualMinuteIntervall; if(lastMinuteInterval == -1) { lastMinuteInterval = minuteInterval; calcdId = org.CostBearerID; } else if(lastMinuteInterval != minuteInterval) { roundDuration = false; } } else if(minuteInterval >= 0) { roundDuration = false; } else { minuteInterval = 0; } } } var duration = Model.NewServiceRecord.RoundedDuration; var totalDuration = duration; var groupDuration = OperationsService.CalculateGroupDuration2(pCustomerCount, pEmployeeCount, Model.NewServiceRecord.RoundedDuration, nodes.Select(s => s.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.CostBearer2SupportConceptOid.Value).ToArray()); if(groupDuration != null) { Model.NewServiceRecord.GroupRoundedDuration = groupDuration.TotalDuration; Model.NewServiceRecord.RoundedDuration = groupDuration.SingleDuration; } else { if(minuteInterval > 0 && roundDuration) { var calc = Calculations.GetInstance(calcdId); totalDuration = calc.GetRoundedDuration(minuteInterval, duration); } Model.NewServiceRecord.RoundedDuration = Math.Round(totalDuration / pCustomerCount, 0, MidpointRounding.AwayFromZero); Model.NewServiceRecord.GroupRoundedDuration = totalDuration; } return list; } private void UpdateServiceRecordGroup(ServiceRecordGroupDC pGroupDC) { var newCount = 0; foreach(var serviceRecord in pGroupDC.ServiceRecordList) { if(!serviceRecord.ServiceRecordOid.HasValue) { newCount++; } } if(newCount == pGroupDC.ServiceRecordList.Count) { return; } var dcsToChange = new List(); var oldSCs = new Dictionary(); var oldEmps = new Dictionary(); var newKeys = new Dictionary(); foreach(var sc in Model.GroupBookingSelectedSupportConcepts) { if(sc?.SupportConceptOid is null) { continue; } var costBearerRelation = Model.GroupBookingSelectionObject.SelectedRelations.FirstOrDefault(f => f.SupportConceptOid.HasValue && f.SupportConceptOid.Value.Equals(sc.SupportConceptOid.Value)); foreach(var emp in Model.GroupBookingSelectedEmployees) { var key = emp.EmployeeOid + "_" + sc.SupportConceptOid; if(costBearerRelation?.CostBearer2SupportConceptOid != null) { var costBearer2SupportConceptOid = sc.CostBearerRelations.ElementAt(0).CostBearer2SupportConceptOid; if(costBearer2SupportConceptOid != null) { key += "_" + costBearerRelation.CostBearer2SupportConceptOid.Value; } newKeys.Add(key, key); } } } foreach(var item in pGroupDC.ServiceRecordList) { var key = item.Employee.EmployeeOid + "_" + item.SupportConcept.SupportConceptOid; if(item.CostBearer2SupportConceptOid.HasValue) { key += "_" + item.CostBearer2SupportConceptOid.Value; } if(newKeys.ContainsKey(key)) { newKeys.Remove(key); } else { dcsToChange.Add(item); } if(!oldEmps.ContainsKey(item.Employee.EmployeeOid)) { oldEmps.Add(item.Employee.EmployeeOid, item.Employee); } if(!oldSCs.ContainsKey(item.SupportConcept.SupportConceptOid)) { oldSCs.Add(item.SupportConcept.SupportConceptOid, item.SupportConcept); } } if(newKeys.Count != 0 || dcsToChange.Count != 0) { if(newKeys.Count > 0) { foreach(var sc in Model.GroupBookingSelectedSupportConcepts) { foreach(var emp in Model.GroupBookingSelectedEmployees) { var key = emp.EmployeeOid + "_" + sc.SupportConceptOid; if(sc.CostBearerRelations != null && sc.CostBearerRelations.Count > 0) { key += "_" + sc.CostBearerRelations.ElementAt(0).CostBearer2SupportConceptOid; } if(!newKeys.ContainsKey(key)) { continue; } ServiceRecordDC newServiceRecord; if(dcsToChange.Count > 0) { newServiceRecord = dcsToChange[0]; dcsToChange.Remove(newServiceRecord); } else { newServiceRecord = CloneServiceRecord(Model.NewServiceRecord); pGroupDC.ServiceRecordList.Add(newServiceRecord); } newServiceRecord.Employee = emp; newServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(sc.SupportConceptOid.Value, null); newServiceRecord.CostBearer = sc.CostBearerRelations.ElementAt(0).CostBearer; newServiceRecord.Customer = sc.Customer; newServiceRecord.CostBearer2SupportConceptOid = sc.CostBearerRelations.ElementAt(0).CostBearer2SupportConceptOid; } } } foreach(var item in dcsToChange) { pGroupDC.ServiceRecordList.Remove(item); } } } [HttpPost] [Authorize] public ActionResult SelectSupportConcept(FormCollection formCollection) { try { if (Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } long? cb2ScOid = Convert.ToInt64(formCollection[FormCollectionConstants.CostBearer2SupportConceptOidKey]); Model.SelectedCostBearerSupportConceptOid = cb2ScOid; return RedirectToActionPermanent("Main");//ResetEditingMode(); } catch (Exception e) { Log.Error($"ERROR SelectSupportConcept: {e.Message}\n{e.StackTrace}"); throw; } } private void LoadServiceCategoriesToModel(long? cb2ScOid) { if(Model.Categories2Descriptions is null) { Model.Categories2Descriptions = new Dictionary>(); } Model.Categories2Descriptions.Clear(); //Model.SelectedServiceCategory = null; //Model.SelectedServiceCategoryOid = null; //Model.SelectedServiceDescription = null; //Model.SelectedServiceDescriptionOid = null; if (cb2ScOid is null && (Model.IsInGroupBookingMode || Model.IsInMultiBookingMode)) { Log.Info("Oid der Bewilligung ist null und der MoK befindet sich im Gruppen- oder Mehrfachbuchungsmodus"); var selectedSupportConcepts = Model.IsInGroupBookingMode ? Model.GroupBookingSelectedSupportConcepts : Model.IsInMultiBookingMode ? Model.MultiBookingSelectedSupportConcepts : new List(); // Alle ServiceDescriptions der ausgewählten Hilfepläne laden var nodes = OperationsService.GetSupportConceptTreeNodeDetailInfos(selectedSupportConcepts.Where(sc => sc.SupportConceptOid.HasValue).Select(sc => sc.SupportConceptOid.Value).ToList()); Model.Categories2Descriptions = CreateServiceCategory2ServiceDescription(nodes, true); SelectFirstServiceDescription(); return; } Model.SelectedCostBearerSupportConceptOid = cb2ScOid; Model.SelectedSupportConcept = Model.SupportConcepts.FirstOrDefault( supportConcept => supportConcept.CostBearerRelations.Any( supportConceptCostBearerRel => supportConceptCostBearerRel.CostBearer2SupportConceptOid.HasValue && supportConceptCostBearerRel.CostBearer2SupportConceptOid.Value.Equals(Model.SelectedCostBearerSupportConceptOid))); if(Model.SelectedSupportConcept != null) { Model.SelectedCostBearer2SupportConceptRelListObject = Model.SupportConceptListObjects.First(f => f.CostBearer2SupportConceptOid == cb2ScOid); var node = OperationsService.GetSupportConceptTreeNodeDetailInfo(Model.SelectedSupportConcept.Customer.CustomerOid, Model.SelectedSupportConcept.SupportConceptOid, Model.SelectedCostBearerSupportConceptOid); Model.Categories2Descriptions = CreateServiceCategory2ServiceDescription(new List { node }, false); } else if(cb2ScOid == -2) // Ohne Hilfeplan { var allServiceDescriptions = OperationsService.GetAllServiceDescriptions(); Model.SelectedCostBearer2SupportConceptRelListObject = Model.SupportConceptListObjects.First(f => f.CostBearer2SupportConceptOid == cb2ScOid); if(Model.Categories2Descriptions is null) { Model.Categories2Descriptions = new Dictionary>(); } else { Model.Categories2Descriptions.Clear(); } allServiceDescriptions.AsParallel().DoForEach(serviceDescription => { if(serviceDescription.Category.ActivationType == ActivationTypeId.Active && (!serviceDescription.Category.OhneHilfeplan.HasValue || serviceDescription.Category.OhneHilfeplan == AccountingvisibilityType.Beides || serviceDescription.Category.OhneHilfeplan == AccountingvisibilityType.NichtKlientenbezogen)) { Model.Categories2Descriptions.AddOrUpdateValueInDictionary(serviceDescription.Category, serviceDescription); } }); } else if(cb2ScOid == -1) // Hilfeplan Auswählen { Model.SelectedCostBearer2SupportConceptRelListObject = Model.SupportConceptListObjects.First(f => f.CostBearer2SupportConceptOid.Equals(cb2ScOid.ToString())); if(Model.Categories2Descriptions is null) { Model.Categories2Descriptions = new Dictionary>(); } else { Model.Categories2Descriptions.Clear(); } } // Ist der Klient abwesend, wird dies wie im FaC angezeigt if(Model.SelectedSupportConcept?.Customer?.AbsenceTimes?.Any() ?? false) { foreach(var absenceTime in Model.SelectedSupportConcept.Customer.AbsenceTimes) { if(absenceTime.Start.HasValue && DateTime.Now > absenceTime.Start.Value && (absenceTime.End is null || DateTime.Now < absenceTime.End.Value)) { Model.IsCustomerAbsence = true; Model.CustomerAbsenceInfo = $"{absenceTime.Reason.Description} von {absenceTime.Start:dd.MM.yyyy} bis {(absenceTime.End.HasValue ? absenceTime.End.Value.ToString("dd.MM.yyyy") : "unbekannt")}"; break; } Model.IsCustomerAbsence = false; Model.CustomerAbsenceInfo = null; } } else { Model.IsCustomerAbsence = false; Model.CustomerAbsenceInfo = null; } SelectFirstServiceDescription(); } private void SelectFirstServiceDescription() { if (Model?.Categories2Descriptions is null || Model.Categories2Descriptions.Count == 0) { UpdateSelectedServiceCategorieAndDescription(null, null); return; } //Nur, wenn Kategorie und Leistung null sind oder nicht in der Liste alle Kategorien enthalten sind, soll weiter unten die erste Leistung in der Liste gesetzt werden if (Model.SelectedServiceCategoryOid.HasValue && Model.SelectedServiceDescriptionOid.HasValue) { var cat = Model.Categories2Descriptions.Keys.Where(c => c.ServiceCategoryOid == Model.SelectedServiceCategoryOid).FirstOrDefault(); if (cat != null) { var desc = Model.Categories2Descriptions[cat].Where(d => d.ServiceDescriptionOid == Model.SelectedServiceDescriptionOid).FirstOrDefault(); if (desc != null) { //Setzte Objekte im Model, sonst wird unten die erste Leistung gesetzt Model.SelectedServiceCategory = cat; Model.SelectedServiceDescription = desc; return; } } } var firstServiceCategory2ServiceDescriptions = Model.Categories2Descriptions.OrderBy(c2d => c2d.Key.Position).ThenBy(c2d => c2d.Key.ServiceCategoryOid).FirstOrDefault(c2d => c2d.Value.Any()); if(firstServiceCategory2ServiceDescriptions.Key is null) { UpdateSelectedServiceCategorieAndDescription(null, null); return; } var serviceDescription = firstServiceCategory2ServiceDescriptions.Value.OrderBy(sd => sd.Position).ThenBy(sd => sd.ServiceDescriptionOid).First(); UpdateSelectedServiceCategorieAndDescription(serviceDescription.Category, serviceDescription); } private void UpdateSelectedServiceCategorieAndDescription(ServiceCategoryDC cat, ServiceDescriptionDC desc) { Model.SelectedServiceCategory = cat; Model.SelectedServiceDescription = desc; Model.SelectedServiceCategoryOid = Model.SelectedServiceCategory?.ServiceCategoryOid; Model.SelectedServiceDescriptionOid = Model.SelectedServiceDescription?.ServiceDescriptionOid; } private Dictionary> CreateServiceCategory2ServiceDescription(List nodes, bool isGroupBooking) { var result = new Dictionary>(); var firstNode = nodes.FirstOrDefault(); if(firstNode is null) { return result; } if(nodes.Count == 1) { firstNode.ServiceAccountings.DoForEach(serviceAccounting => result.AddOrUpdateValueInDictionary(serviceAccounting.ServiceDescription.Category, serviceAccounting.ServiceDescription)); } foreach(var serviceAccounting in firstNode.ServiceAccountings) { var serviceDescription = serviceAccounting.ServiceDescription; var serviceCategory = serviceDescription.Category; if(nodes.All(node => node.ServiceAccountings.Any(accounting => accounting.ServiceDescription.Equals(serviceDescription)))) { result.AddOrUpdateValueInDictionary(serviceCategory, serviceDescription); } } if(firstNode.ServiceAccountings.Count == 0 || result.Count == 0) { var allServiceDescriptions = OperationsService.GetAllServiceDescriptions().Where(sd => sd.Category.ActivationType == ActivationTypeId.Active && sd.ActivationType == ActivationTypeId.Active && sd.Category.OhneHilfeplan != AccountingvisibilityType.NichtKlientenbezogen).ToList(); foreach(var serviceDescription in allServiceDescriptions) { result.AddOrUpdateValueInDictionary(serviceDescription.Category, serviceDescription); } } return result.OrderBy(kvp => kvp.Key.Position).ToDictionary(category2Descriptions => category2Descriptions.Key, category2Descriptions => category2Descriptions.Value.OrderBy(serviceDescription => serviceDescription.Position).ToList()); } [HttpPost] [Authorize] public ActionResult DeleteServiceRecord(FormCollection formCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } Model.ServiceRecordOidToDelete = long.Parse(formCollection[FormCollectionConstants.ServiceRecordOidHolderKey]); if(Model.ServiceRecordOidToDelete != null && Model.ServiceRecordOidToDelete > 0 && LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.Equals(UserRightType.ServiceRecordView_Delete)))) { var serviceRecordDC = Model.ServiceRecords.FirstOrDefault(f => f.ServiceRecordOid != null && f.ServiceRecordOid.Value.Equals(Model.ServiceRecordOidToDelete)); var version = serviceRecordDC?.ServiceRecordVersion; if(version != null && Model.IsAllowedToDeleteServiceRecord(serviceRecordDC)) { OperationsService.DeleteServiceRecord(Model.ServiceRecordOidToDelete.Value, version.Value); Model.ServiceRecords = Model.ServiceRecords.Where(sr => sr.ServiceRecordOid != null && !sr.ServiceRecordOid.Value.Equals(serviceRecordDC.ServiceRecordOid)).ToList(); } } return ResetEditingMode(); } //[Authorize] //public ActionResult ReloadGoalRatings() //{ // if(Model is null) // { // TempData[TempDataConstants.DoLogoutKey] = true; // return PartialView("GoalRatingPopupContentPartial"); // } // return PartialView("GoalRatingPopupContentPartial", Model); //} [Authorize] public string UpdateGoals(string pGoalOids) { if (Model is null) { Logout(); return "0"; } var sc = Model.SelectedSupportConcept; if (!Model.IsInGroupBookingMode && sc is null) { return "0"; } if(string.IsNullOrEmpty(pGoalOids)) { Model.SelectedGoals.Clear(); return "0"; } var splitOids = pGoalOids.Trim(';').Split(';'); var selectedGoalOids = splitOids.Select(long.Parse).ToList(); var allGoals = new List(); if(Model.IsInGroupBookingMode) { var supportConcepts = Model.GroupBookingSelectedSupportConcepts; supportConcepts.DoForEach(supportConcept => { allGoals.AddRangeIfElementsNotIn(supportConcept.Goals); }); } else if(!Model.IsInGroupBookingMode) { allGoals = sc.Goals; } var parents = CustomerService.GetSupportConceptGoalParents(allGoals.Where(w => w.ParentOid.HasValue).Select(s => s.ParentOid.Value).ToList()); allGoals.AddRangeIfElementsNotIn(parents); var goals = allGoals.Where(w => w.ValueListEntryOid.HasValue && selectedGoalOids.Contains(w.ValueListEntryOid.Value)).ToList(); var stillSelectedGoals = Model.SelectedGoals.Where(s => goals.Any(a => a.ValueListEntryOid.HasValue && a.ValueListEntryOid.Value == s.ValueListEntryOid)).ToList(); Model.SelectedGoals = stillSelectedGoals; Model.SelectedGoals.AddRangeIfElementsNotIn(goals); Model.SelectedGoalOids = Model.SelectedGoals.Select(g => g.ValueListEntryOid.Value).ToList(); return Model.SelectedGoals?.Count.ToString() ?? "0"; } [Authorize] public string SetServiceDescription(long pServiceDescriptionOid) { if (Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var serviceDescription = OperationsService.GetServiceDescription(pServiceDescriptionOid); Model.SelectedServiceDescription = serviceDescription; Model.SelectedServiceDescriptionOid = pServiceDescriptionOid; return LeerzeichenFuerGetMethoden; } [HttpPost] [Authorize] public ActionResult LoadServiceRecords(FormCollection formCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } int.TryParse(formCollection["day-count-number"], out var dayCountNumber); var successfullStartParsing = DateTime.TryParse(formCollection["von"], out var parsedVon); var successfullEndParsing = DateTime.TryParse(formCollection["bis"], out var parsedBis); int.TryParse(formCollection["month-select"], out var month); int.TryParse(formCollection["year-select"], out var year); var lastSelectedServiceRecordMonth = new DateTime(year, month, 1); if(Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen) { if(!successfullStartParsing) { parsedVon = DateTime.Today.GetFirstOfMonth(); } if(!successfullEndParsing) { parsedBis = DateTime.Today; } if(parsedVon > parsedBis) { (parsedVon, parsedBis) = (parsedBis, parsedVon); } Model.SelectedZeitraum = new NullableDateTimeSpan(parsedVon, parsedBis); } var serviceRecordTimeInterval = (ServiceRecordTimeInterval) int.Parse(formCollection[FormCollectionConstants.RecordsKey]); Model.ServiceRecordTimeInterval = serviceRecordTimeInterval; CalculateSelectedDayCount(dayCountNumber, lastSelectedServiceRecordMonth, parsedVon, parsedBis, serviceRecordTimeInterval); return RedirectToActionPermanent("Main"); } [Authorize] public ActionResult LoadServiceRecordsNonPost(int dayCountNumber, string start, string end, int month, int year, int recordsKey) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("ServiceRecordListPartial"); } var lastSelectedServiceRecordMonth = new DateTime(year, month, 1); var isValidStart = DateTime.TryParse(start, out var parsedStart); var isValidEnd = DateTime.TryParse(end, out var parsedEnd); if(Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen) { if(!isValidStart) { parsedStart = DateTime.Today.GetFirstOfMonth(); } if(!isValidEnd) { parsedEnd = DateTime.Today; } if(parsedStart > parsedEnd) { (parsedStart, parsedEnd) = (parsedEnd, parsedStart); } Model.SelectedZeitraum = new NullableDateTimeSpan(parsedStart, parsedEnd); } var serviceRecordTimeInterval = (ServiceRecordTimeInterval) recordsKey; Model.ServiceRecordTimeInterval = serviceRecordTimeInterval; CalculateSelectedDayCount(dayCountNumber, lastSelectedServiceRecordMonth, parsedStart, parsedEnd, serviceRecordTimeInterval); if(Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SelectedCostBearerSupportConceptOid != -1) { LoadPaginatedServiceRecordsToModel(Model.CurrentPage); } return PartialView("ServiceRecordListPartial", Model); } private void CalculateSelectedDayCount(int? dayCountNumber, DateTime? lastSelectedServiceRecordMonth, DateTime? von, DateTime? bis, ServiceRecordTimeInterval? serviceRecordTimeInterval) { if(dayCountNumber is null) { dayCountNumber = 0; } if(lastSelectedServiceRecordMonth is null) { lastSelectedServiceRecordMonth = DateTime.Today.AddMonths(-1); } if(von is null || bis is null) { von = DateTime.Today.GetFirstOfMonth(); bis = DateTime.Today; } Model.SelectedDayCount = 0; switch(Model.ServiceRecordTimeInterval) { case ServiceRecordTimeInterval.LastWeek: Model.SelectedDayCount = 7; break; case ServiceRecordTimeInterval.LastMonth: Model.SelectedDayCount = 30; break; case ServiceRecordTimeInterval.Last3Month: Model.SelectedDayCount = 90; break; case ServiceRecordTimeInterval.XTage: Model.SelectedDayCount = dayCountNumber.Value; Model.LastSelectedServiceRecordTimeIntervalDays = dayCountNumber.Value; UpdateUserSettingsWithoutReload(SettingsKeys.LastSelectedServiceRecordTimeIntervalDays, dayCountNumber.ToString()); break; case ServiceRecordTimeInterval.Monatsauswahl: Model.LastSelectedServiceRecordMonth = lastSelectedServiceRecordMonth.Value; Model.SelectedDayCount = lastSelectedServiceRecordMonth.Value.Date.GetDaysInMonth(); Model.SelectedZeitraum = new NullableDateTimeSpan(lastSelectedServiceRecordMonth.Value.Date.GetFirstOfMonth(), lastSelectedServiceRecordMonth.Value.Date.GetLastOfMonth()); UpdateUserSettingsWithoutReload(SettingsKeys.LastSelectedServiceRecordMonth, lastSelectedServiceRecordMonth.Value.ToString("dd.MM.yyyy HH:mm:ss")); break; case ServiceRecordTimeInterval.ZeitraumWaehlen: Model.SelectedZeitraum = new NullableDateTimeSpan(von.Value, bis.Value); break; } if(serviceRecordTimeInterval is null) { return; } UpdateSettings(SettingsKeys.LastSelectedServiceRecordTimeInterval, ((int) serviceRecordTimeInterval.Value).ToString()); } [HttpPost] [Authorize] public ActionResult SelectRecordToEdit(FormCollection formCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } var oidString = formCollection[FormCollectionConstants.ServiceRecordOidHolder2Key]; var wasSuccessful = long.TryParse(oidString, out var serviceRecordOid); if(!wasSuccessful) { return RedirectToActionPermanent("Main"); } Model.SelectedServiceRecordOid = serviceRecordOid; var selectedServiceRecord = Model.GetServiceRecord(serviceRecordOid); if(selectedServiceRecord is null) { return RedirectToActionPermanent("Main"); } Model.SelectedServiceRecord = selectedServiceRecord; Model.SelectedServiceRecordOid = Model.SelectedServiceRecord?.ServiceRecordOid; Model.SelectedGoals = selectedServiceRecord.Goals; var selectedServiceDescription = selectedServiceRecord.ServiceDescription; var selectedServiceCategory = selectedServiceDescription.Category; Model.SelectedServiceDescriptionOid = selectedServiceDescription?.ServiceDescriptionOid; Model.SelectedServiceCategoryOid = selectedServiceCategory?.ServiceCategoryOid; Model.PreviouslySelectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid; Model.SelectedEmployeeOid = selectedServiceRecord.Employee?.EmployeeOid; Model.IsInEditingMode = true; Model.PreviouslySelectedSupportConceptOid = Model.SelectedSupportConcept?.SupportConceptOid; Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid; // Gruppenbuchung if(selectedServiceRecord.GroupOid.HasValue) { Model.IsInGroupBookingMode = true; Model.SelectedSupportConceptOid = null; Model.SelectedEmployeeOid = null; var group = OperationsService.GetServiceRecordGroup(selectedServiceRecord.GroupOid.Value); var employees = group.ServiceRecordList.Select(serviceRecord => serviceRecord.Employee).Distinct().ToList(); Model.GroupBookingSelectedEmployeeOids = employees.Select(e => e.EmployeeOid).ToList(); var cb2ScOids = group.ServiceRecordList.Where(w => w.CostBearer2SupportConceptOid.HasValue).Select(s => s.CostBearer2SupportConceptOid.Value).ToList(); //Model.SelectedConceptCostBearerRelations.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptCostBearerRelDCsByOids(cb2ScOids)); Model.SelectedConceptCostBearerRelationOids = cb2ScOids; //var selectedSupportConcepts = new List(); //selectedSupportConcepts.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptsById(group.ServiceRecordList.Select(s => s.SupportConcept.SupportConceptOid))); //Model.GroupBookingSelectedSupportConcepts = selectedSupportConcepts; Model.GroupBookingSelectedSupportConceptOids = group.ServiceRecordList.Select(s => s.SupportConcept.SupportConceptOid).ToList(); Model.SelectedServiceDescriptionOid = selectedServiceDescription?.ServiceDescriptionOid; Model.SelectedServiceCategoryOid = selectedServiceCategory?.ServiceCategoryOid; } return RedirectToActionPermanent("Main"); } [Authorize] public string GetSelectedRecordInformation() { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var result = LeerzeichenFuerGetMethoden; if(Model.SelectedServiceRecordOid.HasValue) { result = SerializeObject(Model.ServiceRecords.First(f => f.ServiceRecordOid == Model.SelectedServiceRecordOid)); } return result; } [Authorize] public string GetSelectedRecordInformationWithOid(long oid) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var serviceRecord = Model.ServiceRecords.FirstOrDefault(f => f.ServiceRecordOid.HasValue && f.ServiceRecordOid.Value.Equals(oid)) ?? OperationsService.GetServiceRecordById(oid); if(serviceRecord?.ServiceRecordOid is null) { return null; } var hasMonatsunterschrift = OperationsService.CheckForConfirmationReceiptSignatureForServiceRecord(serviceRecord.ServiceRecordOid.Value, SignatureType.Customer); var serviceRecord2Monatsunterschrift = new ServiceRecord2Monatsunterschrift(serviceRecord, hasMonatsunterschrift); return SerializeObject(serviceRecord2Monatsunterschrift); } [Authorize] [HttpPost] public ActionResult ValidateServiceRecord(FormCollection formCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } var inEditMode = Model.IsInEditingMode; var von = formCollection[FormCollectionConstants.DateKey]; var bis = formCollection[FormCollectionConstants.EndDateKey]; var start = formCollection[FormCollectionConstants.StartKey]; var end = formCollection[FormCollectionConstants.EndKey]; var durationRaw = formCollection[FormCollectionConstants.DurationKey]; var betragRaw = formCollection[FormCollectionConstants.BetragKey]; var distanceRaw = formCollection[FormCollectionConstants.DistanceKey]; var doku1 = formCollection[FormCollectionConstants.Dokumentation1Key]?.RemoveUppercaseEsszett(); var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key]?.RemoveUppercaseEsszett(); var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key]?.RemoveUppercaseEsszett(); var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key]?.RemoveUppercaseEsszett(); var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key]?.RemoveUppercaseEsszett(); var formId = formCollection[FormCollectionConstants.FormIdKey]; var markerRaw = formCollection[FormCollectionConstants.MarkerKey]; var marker = "on" == markerRaw; var serviceDescription = formCollection[FormCollectionConstants.ServiceDescriptionKey]; var startHoursDt = ConvertTimeStringToDateTime(start); var endHoursDt = ConvertTimeStringToDateTime(end); if(!DateTime.TryParse(von, out var startDate)) { startDate = DateTime.Now.Date; } if(!DateTime.TryParse(bis, out var endDate)) { endDate = DateTime.Now.Date; } var startDt = startDate.AddHours(startHoursDt.Hour).AddMinutes(startHoursDt.Minute); var endDt = endDate.AddHours(endHoursDt.Hour).AddMinutes(endHoursDt.Minute); var dauer = (int) (endDt - startDt).TotalMinutes; if(dauer == 0 || start == string.Empty && end == string.Empty) { startDt = startDt.AddSeconds(1); endDt = endDt.AddSeconds(1); } var checkServiceRecord = new ServiceRecordDC(); if(inEditMode) { checkServiceRecord = Model.ServiceRecords.FirstOrDefault(f => f.ServiceRecordOid.HasValue && f.ServiceRecordOid.Value.Equals(Model.SelectedServiceRecordOid)); } if(checkServiceRecord is null) { checkServiceRecord = new ServiceRecordDC(); } checkServiceRecord.ServiceRecordType = marker ? ServiceRecordTypeId.Content : ServiceRecordTypeId.DefaultActivity; checkServiceRecord.Notice = doku1; checkServiceRecord.Notice2 = doku2; checkServiceRecord.Notice3 = doku3; checkServiceRecord.Notice4 = doku4; checkServiceRecord.Notice5 = doku5; if(betragRaw is object && decimal.TryParse(betragRaw, out var betrag)) { checkServiceRecord.Betrag = betrag; } checkServiceRecord.Goals = Model.SelectedGoals; checkServiceRecord.Start = startDt; checkServiceRecord.End = endDt; checkServiceRecord.IP = Request.UserHostAddress; checkServiceRecord.ServiceDescription = OperationsService.GetServiceDescription(Model.SelectedServiceDescriptionOid.Value); checkServiceRecord.Employee = Model.SelectedEmployee ?? LoggedInUser.Employee; // Mitarbeiter ausgewählt und Einzelbuchung if(Model.SelectedEmployee != null && !Model.IsInGroupBookingMode && !Model.IsInMultiBookingMode) { var supportConcept = Model.SupportConcepts.FirstOrDefault(fod => fod.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && a.CostBearer2SupportConceptOid.Value.Equals(Model.SelectedCostBearerSupportConceptOid))); if(supportConcept != null) { if(supportConcept.SupportConceptOid != null) { checkServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(supportConcept.SupportConceptOid.Value, Model.LoggedInEmployee.EmployeeOid); } checkServiceRecord.Customer = supportConcept.Customer; var cb2ScRel = supportConcept.CostBearerRelations.First(f => f.CostBearer2SupportConceptOid.HasValue && f.CostBearer2SupportConceptOid.Equals(Model.SelectedCostBearerSupportConceptOid)); checkServiceRecord.CostBearer = cb2ScRel.CostBearer; var intervall = checkServiceRecord.CostBearer.ActualMinuteIntervall; if(intervall > 0) { checkServiceRecord.RoundedDuration = dauer % intervall != 0 ? dauer + (intervall - dauer % intervall) : dauer; } checkServiceRecord.CostBearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid; } } var mandator = MobileSessionFacade.Mandator; var maxDaysEditSRsAllowedString = GetSettingValue(mandator.Settings, SettingsKeys.MaxDaysEditServiceRecordsAllowed); var limitFuerZeiterfassungString = GetSettingValue(mandator.Settings, SettingsKeys.AnzTageZeiterfassErfolgt); if(!int.TryParse(maxDaysEditSRsAllowedString, out var maxDaysEditSRsAllowed)) { maxDaysEditSRsAllowed = 0; } if(!int.TryParse(limitFuerZeiterfassungString, out var limitFuerZeiterfassung)) { limitFuerZeiterfassung = 0; } if(LoggedInUser.HasRight(UserRightType.ServiceRecord_AllowEditAfterMaxDaysInNextMonth)) { maxDaysEditSRsAllowed = -1; } SupportConceptStatisticsDC stats = null; if(Model.SelectedCostBearerSupportConceptOid != null && Model.SelectedCostBearerSupportConceptOid > 0) { stats = OperationsService.CreateSupportConceptStatistics(Model.SelectedCostBearerSupportConceptOid.Value, DateTime.Now); } var employeeOids = new List { checkServiceRecord.Employee.EmployeeOid }; var validationResults = new List(); checkServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; if(Model.IsEndDateVisible) { checkServiceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum; } checkServiceRecord.DurationInStunden = Model.IsShowingDurationInHours ? ZeiterfassungsDauer.Stunden : ZeiterfassungsDauer.Minuten; string dateRangeString = null; // Gruppenbuchung if(Model.IsInGroupBookingMode) { ServiceRecordGroupDC serviceRecordGroup = null; if(checkServiceRecord.GroupOid.HasValue) { serviceRecordGroup = OperationsService.GetServiceRecordGroup(checkServiceRecord.GroupOid.Value); serviceRecordGroup.ServiceRecordList.DoForEach(sr => employeeOids.AddIfNotIn(sr.Employee.EmployeeOid)); } else { Model.GroupBookingSelectedEmployees.DoForEach(e => employeeOids.AddIfNotIn(e.EmployeeOid)); } var costBearer2SupportConceptOids = Model.SelectedConceptCostBearerRelations.Where(w => w.CostBearer2SupportConceptOid.HasValue).Select(s => s.CostBearer2SupportConceptOid.Value).ToList(); var relations = CustomerService.GetSupportConceptCostBearerRelationsById(costBearer2SupportConceptOids); var isNew = checkServiceRecord.ServiceRecordOid is null; if(isNew) { foreach(var rel in relations) { var sr = CloneServiceRecord(checkServiceRecord); sr.SupportConcept = rel.SupportConcept; sr.CostBearer = rel.CostBearer; sr.CostBearer2SupportConceptOid = rel.CostBearer2SupportConceptOid; sr.Customer = rel.SupportConcept?.Customer; var result = OperationsService.ValidateServiceRecord(sr, null, maxDaysEditSRsAllowed, employeeOids, costBearer2SupportConceptOids); dateRangeString = rel.DateRangeString; validationResults.AddIfNotIn(new ServiceRecord2Validation(sr, result, dateRangeString)); } } else if(serviceRecordGroup != null) { foreach(var serviceRecord in serviceRecordGroup.ServiceRecordList) { var sr = CloneServiceRecord(checkServiceRecord); sr.ServiceRecordOid = serviceRecord.ServiceRecordOid; sr.SupportConcept = serviceRecord.SupportConcept; sr.CostBearer = serviceRecord.CostBearer; sr.CostBearer2SupportConceptOid = serviceRecord.CostBearer2SupportConceptOid; sr.Customer = serviceRecord.SupportConcept?.Customer; var result = OperationsService.ValidateServiceRecord(sr, null, maxDaysEditSRsAllowed, employeeOids, costBearer2SupportConceptOids); var node = CreateFlatSupportConceptItem(CustomerService.LoadCompactSupportConceptDC(sr.SupportConcept.SupportConceptOid, Model.SelectedEmployee.EmployeeOid), null); dateRangeString = node?.SupportConceptTreeNodeDC != null ? node.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.DateRangeString : string.Empty; validationResults.AddIfNotIn(new ServiceRecord2Validation(sr, result, dateRangeString)); } } } // Einzelbuchung else if(!Model.IsInMultiBookingMode) { if(Model.SelectedSupportConcept != null) { var node = CreateFlatSupportConceptItem(CustomerService.LoadCompactSupportConceptDC(Model.SelectedSupportConcept.SupportConceptOid.Value, Model.SelectedEmployee.EmployeeOid), null); dateRangeString = node?.SupportConceptTreeNodeDC != null ? node.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.DateRangeString : ""; } var result = OperationsService.ValidateServiceRecord(checkServiceRecord, stats, maxDaysEditSRsAllowed, null, null); validationResults.AddIfNotIn(new ServiceRecord2Validation(checkServiceRecord, result, dateRangeString ?? "")); } // Mehrfachbuchung else if(Model.IsInMultiBookingMode && !Model.IsInGroupBookingMode) { employeeOids.AddRangeIfElementsNotIn(Model.MultiBookingSelectedEmployees.Select(e => e.EmployeeOid)); var cb2ScOids = Model.MultiBookingSelectedConceptCostBearerRelations.Where(w => w.CostBearer2SupportConceptOid.HasValue).Select(s => s.CostBearer2SupportConceptOid.Value).ToList(); var relations = CustomerService.GetSupportConceptCostBearerRelationsById(cb2ScOids); foreach(var costBearer2SupportConceptRel in relations) { dateRangeString = costBearer2SupportConceptRel.DateRangeString ?? string.Empty; var prototype = CloneServiceRecord(checkServiceRecord); prototype.Customer = costBearer2SupportConceptRel.SupportConcept.Customer; prototype.SupportConcept = costBearer2SupportConceptRel.SupportConcept; prototype.CostBearer = costBearer2SupportConceptRel.CostBearer; prototype.CostBearer2SupportConceptOid = costBearer2SupportConceptRel.CostBearer2SupportConceptOid; var organisation = CustomerService.LoadOrganisationCompact(costBearer2SupportConceptRel.CostBearer.OrganisationOid); if(!(organisation is null)) { var calculations = Calculations.GetInstance(organisation.CostBearerID); prototype.RoundedDuration = calculations.GetRoundedDuration(organisation, dauer); } var multiBookingValidationResults = OperationsService.ValidateServiceRecord(prototype, null, maxDaysEditSRsAllowed, employeeOids, cb2ScOids); validationResults.AddIfNotIn(new ServiceRecord2Validation(prototype, multiBookingValidationResults, dateRangeString)); } } var user = LoggedInUser; var allowOverlappingFls = user.HasRight(UserRightType.ServiceRecord_AllowCreateOverlappingFLS); var allowOverlappingFlsForEmployee = user.HasRight(UserRightType.ServiceRecord_AllowCreateOverlappingFLSForEmployee); var allowMoreFlsThanApproved = user.HasRight(UserRightType.ServiceRecord_AllowCreateMoreFLSThanApproved); var bookAfterSettlementInvoice = user.HasRight(UserRightType.BookServiceRecordAfterSettlementInvoice); var bookServiceRecordOutOfSupportConcept = user.HasRight(UserRightType.BookServiceRecordOutOfSupportConcept); var allowCreateAfterEmployeeSignature = user.HasRight(UserRightType.ServiceRecord_AllowCreateAfterEmployeeSignature); var allowEditAfterEmployeeSignature = user.HasRight(UserRightType.ServiceRecord_AllowEditAfterEmployeeSignature); var allowCreateAll = user.HasRight(UserRightType.CreateAll); var allowEditAll = user.HasRight(UserRightType.CreateAll); var newResult = new ValidationResult(); var exitLoop = false; if(Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any() && Model.SelectedGoals.Count == 0) { newResult.Message += "Es wurden keine Ziele zugeordnet.

"; newResult.KannTrotzdemGespeichertWerden = true; exitLoop = false; } foreach(var sr2V in validationResults) { if(exitLoop) { break; } foreach(var vr in sr2V.ValidationResults) { if(exitLoop) { break; } switch(vr.ResultType) { case ServiceRecordOverlapping: newResult.Message = $"An dem gewählten Datum {von:dd.MM.yyyy} existiert bereits ein Eintrag ({vr.Message} bei Klient/in {vr.CustomerName}).

"; newResult.KannTrotzdemGespeichertWerden = allowOverlappingFls; exitLoop = !allowOverlappingFls; break; case EmployeeOverlapping: newResult.Message += $"An dem gewählten Datum {von:dd.MM.yyyy} existiert bereits ein Eintrag von {vr.EmployeeName} ({vr.Message}).

"; newResult.KannTrotzdemGespeichertWerden = allowOverlappingFlsForEmployee; exitLoop = !allowOverlappingFlsForEmployee; break; case OutsideOfSupportConcept: newResult.Message += $"Das gewählte Datum {von:dd.MM.yyyy} liegt außerhalb des Zeitraumes des gewählten Hilfeplans ({sr2V.HilfePlanZeitraum}).

"; newResult.KannTrotzdemGespeichertWerden = bookServiceRecordOutOfSupportConcept; exitLoop = !bookServiceRecordOutOfSupportConcept; break; case ApprovedFLSOverspending: var klient = "diesen Hilfeplan"; if(!string.IsNullOrEmpty(vr.CustomerName)) { klient = "Klient/in " + vr.CustomerName; } var msg = "Die für " + klient + " genehmigten FLS (" + vr.ApprovedHours + ") werden mit diesem Eintrag überschritten. (" + vr.HoursNew + ")."; newResult.Message += msg + "

"; newResult.KannTrotzdemGespeichertWerden = allowMoreFlsThanApproved; exitLoop = !allowMoreFlsThanApproved; break; case OutOfEditLimit: newResult.Message += "Sie k&oml;nnen keine neuen Leistungen für den " + von + " dokumentieren, da bereits der " + maxDaysEditSRsAllowed + ". des nachfolgenden Monats überschritten ist.

"; exitLoop = true; newResult.KannTrotzdemGespeichertWerden = false; break; case Error: newResult.Message += "Beim Speichern ist ein Fehler aufgetreten.

"; exitLoop = true; newResult.KannTrotzdemGespeichertWerden = false; break; case SettlementInvoiceAlreadyExisting: var klient2 = "diesen Hilfeplan"; if(!string.IsNullOrEmpty(vr.CustomerName)) { klient2 = "Klient/in " + vr.CustomerName; } newResult.KannTrotzdemGespeichertWerden = bookAfterSettlementInvoice; exitLoop = !bookAfterSettlementInvoice; if(bookAfterSettlementInvoice) { newResult.Message += "Es existiert bereits eine Spitzabrechnung für " + klient2 + ". Um diesen Eintrag zu berücksichtigen, muss eventuell eine neue Spitzabrechnung erstellt werden.

"; } else { newResult.Message += "Sie können den Eintrag nicht bearbeiten, da bereits eine Spitzabrechnung für " + klient2 + "

"; } break; case FristAbgelaufen: var intervall = "einem Tag"; if(limitFuerZeiterfassung != 1) { intervall = "" + limitFuerZeiterfassung + " Tagen"; } if(!LoggedInUser.HasRight(UserRightType.ServiceRecordAllowEditAfterMindays)) { if(limitFuerZeiterfassung == 1) { newResult.Message += $"Sie können keine neuen Leistungen für den {von} dokumentieren, da die Zeiterfassung innerhalb von einem Tag erfolgen muss.

"; } else { newResult.Message += $"Sie können keine neuen Leistungen für den {von} dokumentieren, da die Zeiterfassung innerhalb von {intervall} erfolgen muss.

"; } newResult.KannTrotzdemGespeichertWerden = false; exitLoop = true; } break; case Custom: newResult.Message += vr.Message + "

"; exitLoop = true; newResult.KannTrotzdemGespeichertWerden = vr.Allow; break; case SignatureExists: var klient3 = "diesem Hilfeplan"; if(!string.IsNullOrEmpty(vr.CustomerName)) { klient3 = "Klient " + vr.CustomerName; } newResult.Message += $"Für den ausgewählten Zeitraum existiert bereits eine Monatsunterschrift bei {klient3}, die mit dem Anlegen dieses Eintrags verfällt und neu geleistet werden muss.

"; exitLoop = false; newResult.KannTrotzdemGespeichertWerden = true; break; } } } var signatureValidationResult = OperationsService.CheckForExistingSignature(checkServiceRecord); if(signatureValidationResult != null && newResult.KannTrotzdemGespeichertWerden) { newResult.Message += $"
{signatureValidationResult.Message}

"; } if(!string.IsNullOrEmpty(newResult.Message)) { newResult.Message += newResult.KannTrotzdemGespeichertWerden ? newResult.Message.Contains("Möchten Sie trotzdem speichern?") ? string.Empty : "
Möchten Sie trotzdem speichern?

" : "
Speichern nicht möglich.

"; Model.SelectedServiceRecord = checkServiceRecord; } Model.NewServiceRecord = new ServiceRecordDC(); if(newResult?.Message != null) { TempData[TempDataServiceRecordValidationKey] = newResult; TempData[TempDataFormIdKey] = formId; } else { var formCollection2 = new FormCollection { [FormCollectionConstants.DateKey] = von, [FormCollectionConstants.EndDateKey] = bis, [FormCollectionConstants.StartKey] = start, [FormCollectionConstants.EndKey] = end, [FormCollectionConstants.DurationKey] = durationRaw, [FormCollectionConstants.DistanceKey] = distanceRaw, [FormCollectionConstants.BetragKey] = betragRaw, [FormCollectionConstants.MarkerKey] = markerRaw, [FormCollectionConstants.ServiceDescriptionKey] = serviceDescription, [FormCollectionConstants.Dokumentation1Key] = doku1, [FormCollectionConstants.Dokumentation2Key] = doku2, [FormCollectionConstants.Dokumentation3Key] = doku3, [FormCollectionConstants.Dokumentation4Key] = doku4, [FormCollectionConstants.Dokumentation5Key] = doku5, [FormCollectionConstants.Dokumentation6Key] = Model.Dokutypes != null && Model.Dokutypes.Length == 0 ? doku1 : null }; TempData[TempDataConstants.AfterValidationStateKey] = null; if(Model.IsInGroupBookingMode) { return CreateOrUpdateGroupBooking(formCollection2); } return Model.IsInMultiBookingMode ? CreateMultiBooking(formCollection2) : CreateOrUpdateServiceRecord(formCollection2); } if(decimal.TryParse(distanceRaw, out var distanceInMeters) && Model.SelectedServiceRecord != null) { Model.SelectedServiceRecord.DistanceInMeterDecimal = distanceInMeters; } if(decimal.TryParse(durationRaw, out var duration) && Model.SelectedServiceRecord != null && Model.SelectedServiceRecord.RoundedDuration == 0) { Model.SelectedServiceRecord.RoundedDuration = Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1 ? duration * 60 : duration; } Model.SelectedServiceRecordOid = Model.SelectedServiceRecord?.ServiceRecordOid; TempData[TempDataConstants.AfterValidationStateKey] = true; return View("Main", Model); } [Authorize] public string ValidateServiceRecordDeletion(string serviceRecordOidString) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var isSuccessful = long.TryParse(serviceRecordOidString, out var serviceRecordOid); if(!isSuccessful) { return "Error"; } var newResult = new ValidationResult(); var serviceRecord = Model.GetServiceRecord(serviceRecordOid); if(serviceRecord is null) { return LeerzeichenFuerGetMethoden; } var validationResultList = OperationsService.ValidateServiceRecordDeletion(serviceRecord, Model.LoggedInEmployee.EmployeeOid.Value); if(validationResultList.Count > 0) { foreach(var result in validationResultList) { switch(result.ResultType) { case Custom: newResult.KannTrotzdemGespeichertWerden = true; newResult.Message += RemoveConfirmationFromValidationResultMessage(result.Message) + "

"; break; } } if(newResult.Message?.Length > 0) { newResult.Message += "Möchten Sie ihn trotzdem löschen?

"; } return SerializeObject(newResult); } return serviceRecord.GroupOid != null ? SerializeObject(new ValidationResult{KannTrotzdemGespeichertWerden = true, Message = "ACHTUNG, wenn Sie fortfahren, löschen Sie die gesamte Gruppenbuchung.
Wenn Sie nur einzelne Klienten aus der Gruppe entfernen möchten, editieren Sie die Gruppe und entfernen den Klienten aus der Liste der Hilfepläne.
Sind Sie sicher, dass Sie den gesamten Gruppeneintrag löschen möchten?

" }) : SerializeObject(new ValidationResult {KannTrotzdemGespeichertWerden = true, Message = null}); } private static string RemoveConfirmationFromValidationResultMessage(string resultMessage) { if(resultMessage is null) { return string.Empty; } var confirmation = "Möchten Sie ihn trotzdem löschen?"; if(resultMessage.Contains(confirmation)) { var length = resultMessage.Length - confirmation.Length; if(length > 0) { resultMessage = resultMessage.Substring(0, length); } } return resultMessage; } [Authorize] public string SetServiceRecordEmployee(long employeeOid) { try { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } Model.SelectedEmployee = Model.AllEmployees.First(f => f.EmployeeOid.Equals(employeeOid)); Model.SelectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid; return Model.SelectedEmployee?.DetailDescription ?? LeerzeichenFuerGetMethoden; } catch(Exception e) { Log.Info("Error in SetServiceRecordEmployee:"); Log.Error(e.Message, e); if(Model?.AllEmployees is null) { Log.Info("Weitere Infos: Model oder AllEmployees = null!"); } else { Log.Info($"Weitere Infos: AllEmployees enthält {Model.AllEmployees.Count} Elemente: "); var stringBuilder = new StringBuilder(); foreach (var ce in Model.AllEmployees) { if (stringBuilder.Length > 0) { stringBuilder.Append(","); } stringBuilder.Append(ce.EmployeeOid); } Log.Info(stringBuilder.ToString()); } throw e; } } [Authorize] public string CheckToken(string token) { if(token != null && token.Equals("abcd")) { return SerializeObject("localhost;demo"); } return LeerzeichenFuerGetMethoden; } #region Menü // Menünavigation [Authorize] public ActionResult RedirectToScheduler() { return RedirectToActionPermanent("Scheduler", "Scheduler"); } [Authorize] public ActionResult RedirectToCustomer() { if(Model?.SelectedSupportConcept?.Customer?.Oid.HasValue ?? false) { return RedirectToActionPermanent("Customer", "Customer", new { id = Model.SelectedSupportConcept.Customer.Oid }); } //if(Model?.SelectedSupportConcept is null && (CustomerModel)Session[ModelSessionConstants.CustomerModelKey] != null) //{ // var customerModel = (CustomerModel) Session[ModelSessionConstants.CustomerModelKey]; // customerModel.SelectedCustomerOid = null; // customerModel.SelectedCustomer = null; //} return RedirectToActionPermanent("Customer", "Customer"); } [Authorize] public ActionResult RedirectToReportView() { return Model.HasRightToViewQuittierungsbelege ? RedirectToAction("InitReports", "Report") : RedirectToMain(); } [Authorize] public ActionResult RedirectToReportViewer() { return RedirectToActionPermanent("ReportViewer", "ReportViewer"); } public ActionResult RedirectToMain() { return RedirectToActionPermanent("Main", "Main"); } [Authorize] public ActionResult RedirectToDevExpressScheduler() { #if DEBUG return RedirectToActionPermanent("DevExpressScheduler", "DevExpressScheduler"); #endif return RedirectToMain(); } [Authorize] public ActionResult RedirectToDebuggingTools() { #if DEBUG return RedirectToActionPermanent("DebuggingTools", "DebuggingTools"); #endif return RedirectToMain(); } #endregion // Gruppenbuchungen [HttpPost] [Authorize] public ActionResult SetGroupBookingMode(FormCollection pFormCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } Model.TransferringAppointmentOid = null; Model.IsInTransferMode = false; var bookingMode = "true,false" == pFormCollection[FormCollectionConstants.IsInGroupBookingModeKey] ? BookingMode.GroupBookingMode : BookingMode.SingleBookingMode; ResetBookingMode(bookingMode); return RedirectToAction("Main"); } /// /// Setzt die getroffenen Auswahlen zurück /// /// /// Einzelbuchung, Gruppenbuchung oder Mehrfachbuchung wie im FaC /// private void ResetBookingMode(BookingMode bookingMode) { if(Model is null) { Logout(); return; } ResetModel(); Model.IsInGroupBookingMode = bookingMode == BookingMode.GroupBookingMode; Model.IsInMultiBookingMode = bookingMode == BookingMode.MultiBookingMode; if(bookingMode == BookingMode.GroupBookingMode) { ResetMultiBookingMode(); Model.PreviouslySelectedEmployeeOid = Model.SelectedEmployeeOid; Model.PreviouslySelectedSupportConceptOid = Model.SelectedSupportConceptOid; Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid; Model.SelectedSupportConceptOid = null; Model.SelectedCostBearerSupportConceptOid = null; Model.SelectedEmployeeOid = null; Model.GroupBookingSelectedEmployeeOids.AddIfNotIn(LoggedInUser.Employee.EmployeeOid); Model.IsInEditingMode = false; Model.SelectedServiceRecordOid = null; } if(bookingMode == BookingMode.MultiBookingMode) { ResetGroupBookingMode(); Model.PreviouslySelectedEmployeeOid = Model.SelectedEmployeeOid; Model.PreviouslySelectedSupportConceptOid = Model.SelectedSupportConceptOid; Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid; Model.SelectedSupportConceptOid = null; Model.SelectedCostBearerSupportConceptOid = null; Model.SelectedEmployeeOid = null; Model.MultiBookingSelectedEmployeeOids.AddIfNotIn(LoggedInUser.Employee.EmployeeOid); Model.IsInEditingMode = false; Model.SelectedServiceRecordOid = null; } if(bookingMode == BookingMode.SingleBookingMode) { ResetMultiBookingMode(); Model.SelectedEmployeeOid = Model.PreviouslySelectedEmployeeOid ?? LoggedInUser.Employee.EmployeeOid; if (Model.PreviouslySelectedSupportConceptOid.HasValue) { Model.SelectedSupportConceptOid = Model.PreviouslySelectedSupportConceptOid; } if (Model.PreviouslySelectedCostbearer2SupportConceptOid.HasValue) { Model.SelectedCostBearerSupportConceptOid = Model.PreviouslySelectedCostbearer2SupportConceptOid; } ResetGroupBookingMode(); } Model.SelectedSupportConceptOid = Model.SelectedSupportConcept?.SupportConceptOid; Model.SelectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid; Model.SelectedServiceRecordOid = Model.SelectedServiceRecord?.ServiceRecordOid; } private void ResetMultiBookingMode() { Model.Categories2Descriptions.Clear(); Model.MultiBookingSelectedConceptCostBearerRelations.Clear(); Model.MultiBookingSelectedEmployeeOids.Clear(); Model.MultiBookingSelectedGroupOfPeopleOids.Clear(); Model.MultiBookingSelectedCostbearerRelOids.Clear(); Model.MultiBookingSelectedSupportConceptOids.Clear(); Model.MultiBookingSupportConceptListObjects.Clear(); } private void ResetGroupBookingMode() { Model.Categories2Descriptions.Clear(); Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedEmployeeOids.Clear(); Model.GroupBookingSelectedSupportConceptOids.Clear(); Model.SelectedConceptCostBearerRelationOids.Clear(); } [HttpPost] [Authorize] public ActionResult ResetSingleBookingForm() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } ResetBookingMode(BookingMode.SingleBookingMode); //LoadServiceCategoriesToModel(Model.SelectedCostBearerSupportConceptOid); return View("Main", Model); } [HttpPost] [Authorize] public ActionResult ResetGroupBookingForm() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; } ResetBookingMode(BookingMode.GroupBookingMode); return View("Main", Model); } [HttpPost] [Authorize] public ActionResult ResetMultiBookingForm() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } if(Model.PreviouslySelectedSupportConceptOid != null && Model.SelectedSupportConceptOid is null) { Model.SelectedSupportConceptOid = Model.PreviouslySelectedSupportConceptOid; Model.SelectedCostBearerSupportConceptOid = Model.PreviouslySelectedCostbearer2SupportConceptOid; } ResetModel(); return View("Main", Model); } [HttpPost] [Authorize] public ActionResult ResetEditingMode() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } ResetModel(); Model.TransferringAppointmentOid = null; Model.IsInTransferMode = false; return RedirectToActionPermanent("Main"); } [Authorize] [HttpPost] public ActionResult ResetTransferMode() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } Model.TransferringAppointmentOid = null; Model.IsInTransferMode = false; ResetModel(); return RedirectToScheduler(); } [Authorize] private void ResetModel() { if(Model is null) { return; } TempData[TempDataConstants.AfterValidationStateKey] = null; Model.NewServiceRecord = new ServiceRecordDC(); Model.SelectedServiceRecordOid = null; Model.IsInEditingMode = false; Model.SelectedEmployeeOid = LoggedInUser.Employee.EmployeeOid; Model.SelectedConceptCostBearerRelationOids.Clear(); Model.GroupBookingSelectedSupportConceptOids.Clear(); Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedGroupOfPeopleOids.Clear(); Model.GroupBookingSelectedEmployeeOids = new List { LoggedInUser.Employee.EmployeeOid }; Model.IsInMultiBookingMode = false; Model.MultiBookingSelectedCostbearerRelOids.Clear(); Model.MultiBookingSelectedEmployeeOids = new List { LoggedInUser.Employee.EmployeeOid }; Model.MultiBookingSelectedGroupOfPeopleOids.Clear(); Model.MultiBookingSelectedSupportConceptOids.Clear(); Model.SelectedGoalOids.Clear(); Model.SelectedServiceCategoryOid = null; Model.SelectedServiceDescriptionOid = null; //LoadServiceCategoriesToModel(Model.SelectedCostBearerSupportConceptOid); //Model.MainSessionModel.ResetValues(); } [Authorize] public ActionResult AddScCbRelsToGroupBooking(string[] relOids, string[] groupOids) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("GroupBookingScCbRelList"); } var singleRels = new List(); var groupRels = new List(); var groups = new List(); if(groupOids is null) { groupOids = Array.Empty(); } if(relOids is null) { relOids = Array.Empty(); } relOids.DoForEach(relOid => { if(long.TryParse(relOid, out var singleRelOid)) { singleRels.AddIfNotIn(singleRelOid); } }); groupOids.DoForEach(groupOid => { if(long.TryParse(groupOid, out var g)) { groupRels.AddIfNotIn(g); } }); Model.GroupBookingSelectedGroupOfPeopleOids.Clear(); groupRels.DoForEach(groupOid => { var group = Model.GroupsOfPeople.FirstOrDefault(f => f.GroupOfPeopleOid.HasValue && f.GroupOfPeopleOid.Value.Equals(groupOid)); if(group is null) { return; } groups.AddIfNotIn(group); group.SupportConceptList.DoForEach(f => singleRels.AddRangeIfElementsNotIn(f.CostBearerRelOids)); }); Model.GroupBookingSelectedSupportConcepts.Clear(); Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedCostbearerRelOids.AddRangeIfElementsNotIn(singleRels); var selectedSupportConcepts = CustomerService.GetSupportConceptsByCostbearer2SupportConceptRelOids(singleRels); var groupCostBearerRelations = CustomerService.GetSupportConceptCostBearerRelationsById(singleRels); Model.SelectedConceptCostBearerRelations.Clear(); Model.SelectedConceptCostBearerRelations.AddRangeIfElementsNotIn(groupCostBearerRelations); Model.GroupBookingSelectedSupportConcepts.AddRangeIfElementsNotIn(selectedSupportConcepts); foreach(var gruppe in groups.Where(g => g.GroupOfPeopleOid.HasValue)) { var groupRelOids = new List(); gruppe.SupportConceptList.ForEach(f => groupRelOids.AddRange(f.CostBearerRelOids)); if(!gruppe.GroupOfPeopleOid.HasValue) { continue; } var groupOid = gruppe.GroupOfPeopleOid.Value; if(singleRels.ContainsItems(groupRelOids)) { Model.GroupBookingSelectedGroupOfPeopleOids.AddIfNotIn(groupOid); } else if(Model.GroupBookingSelectedGroupOfPeopleOids.Contains(groupOid)) { Model.GroupBookingSelectedGroupOfPeopleOids.Remove(groupOid); } } Model.SelectedConceptCostBearerRelationOids = Model.SelectedConceptCostBearerRelations.Select(s => s.CostBearer2SupportConceptOid.Value).ToList(); Model.GroupBookingSelectedSupportConceptOids = Model.GroupBookingSelectedSupportConcepts.Select(s => s.SupportConceptOid.Value).ToList(); return PartialView("GroupBookingScCbRelList", Model); } [Authorize] public ActionResult RemoveSupportConceptCostbearerRel(string relOid) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("GroupBookingSelectionPartial"); } if(!long.TryParse(relOid, out var supportConceptCostBearerRelationOid)) { return PartialView("GroupBookingSelectionPartial", Model); } var supportConcept2Remove = Model.GroupBookingSelectedSupportConcepts.FirstOrDefault(f => f.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid)); var relation2Remove = Model.SelectedConceptCostBearerRelations.FirstOrDefault(f => f.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid); if(supportConcept2Remove?.SupportConceptOid.HasValue ?? false) { var supportConcepts = Model.GroupBookingSelectedSupportConcepts.Where(supportConcept => supportConcept.SupportConceptOid.HasValue && supportConcept.SupportConceptOid.Value.Equals(supportConcept2Remove.SupportConceptOid.Value) == false).ToList(); // Ziele, die bei den verbleibenden Hilfeplänen nicht vorhanden sind, werden aus der Auswahl entfernt. var remainingGoals = new List(); foreach(var supportConcept in supportConcepts) { foreach(var goal in supportConcept.Goals) { remainingGoals.AddIfNotIn(goal); } } Model.SelectedGoals = Model.SelectedGoals.Where(goal => remainingGoals.Contains(goal)).ToList(); } Model.GroupBookingSelectedSupportConcepts.Remove(supportConcept2Remove); Model.SelectedConceptCostBearerRelations.Remove(relation2Remove); var selectedGroups = Model.GroupsOfPeople.Where(group => group.GroupOfPeopleOid.HasValue && Model.GroupBookingSelectedGroupOfPeopleOids.Contains(group.GroupOfPeopleOid.Value)).ToList(); var groups = selectedGroups.Where(group => group.SupportConceptList.All(a => Model.GroupBookingSelectedSupportConcepts.Where(w => w.SupportConceptOid.HasValue).Select(s => s.SupportConceptOid.Value).Contains(a.SupportConceptOid))); Model.GroupBookingSelectedGroupOfPeopleOids = groups.Where(group => group.GroupOfPeopleOid.HasValue).Select(group => group.GroupOfPeopleOid.Value).ToList(); LoadServiceCategoriesToModel(null); if(Model.SelectedServiceCategory != null && !Model.Categories2Descriptions.Keys.Contains(Model.SelectedServiceCategory)) { var firstCategory2ServiceDescriptions = Model.Categories2Descriptions.FirstOrDefault(); var firstServiceCategory = firstCategory2ServiceDescriptions.Key; var firstServiceDescription = firstCategory2ServiceDescriptions.Value?.FirstOrDefault(); Model.SelectedServiceCategory = firstServiceCategory; Model.SelectedServiceDescription = firstServiceDescription; } Model.SelectedGoalOids = Model.SelectedGoals.Select(g => g.ValueListEntryOid.Value).ToList(); Model.GroupBookingSelectedSupportConceptOids = Model.GroupBookingSelectedSupportConcepts.Select(g => g.SupportConceptOid.Value).ToList(); Model.SelectedConceptCostBearerRelationOids = Model.SelectedConceptCostBearerRelations.Select(g => g.CostBearer2SupportConceptOid.Value).ToList(); Model.SelectedServiceCategoryOid = Model.SelectedServiceCategory?.ServiceCategoryOid; Model.SelectedServiceDescriptionOid = Model.SelectedServiceDescription?.ServiceDescriptionOid; return PartialView("GroupBookingSelectionPartial", Model); } [Authorize] public ActionResult ReloadGroupBookingForm() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; } else { LoadServiceCategoriesToModel(null); } return PartialView("GroupBookingSelectionPartial", Model); } [Authorize] public string AddEmployeesToGroupBooking(string pEmployeeOids) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } if(string.IsNullOrEmpty(pEmployeeOids)) { Model.GroupBookingSelectedEmployees.Clear(); Model.GroupBookingSelectedEmployeeOids.Clear(); return JsonConvert.SerializeObject(Model.GroupBookingSelectedEmployees.Count); } var rawEmployeeOids = pEmployeeOids.Split(','); var oids = new List(); rawEmployeeOids.DoForEach(s => oids.AddIfNotIn(long.Parse(s))); var employees = Model.EmployeesForGroupAndMultiBooking.Where(w => oids.Contains(w.EmployeeOid)); Model.GroupBookingSelectedEmployees.Clear(); Model.GroupBookingSelectedEmployees.AddRangeIfElementsNotIn(employees); Model.GroupBookingSelectedEmployeeOids = Model.GroupBookingSelectedEmployees.Select(e => e.EmployeeOid).ToList(); return JsonConvert.SerializeObject(Model.GroupBookingSelectedEmployees.Count); } [Authorize] public string GetSignatureImage(long serviceRecordOid, long signatureOid) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var signatureServiceRecord = Model.GetServiceRecord(serviceRecordOid); var signatureServiceRecordHeader = MainModel.GetServiceRecordTimeHeader(signatureServiceRecord, false); var signatureImage = OperationsService.GetSignature(signatureOid).DataBild; return signatureServiceRecordHeader + ";" + ApplyWatermark(signatureImage, Server.MapPath("../Content/images/bewoplaner_by_ownsoft_logo_mok.png")); } [HttpPost] public ActionResult LogOutAfterSessionTimeout() { Logout(); return RedirectToActionPermanent("Index", "Login", new { isSessionTimedOut = true}); } [HttpPost] [Authorize] public ActionResult SetSupportConceptFilter(FormCollection formCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } var selectedSupportConceptFilter = formCollection[nameof(Model.SelectedSupportConceptFilter)]; if(!Enum.TryParse(selectedSupportConceptFilter, out CustomerFilterEnum customerFilter)) { customerFilter = CustomerFilterEnum.MyCustomer; } UpdateApplicationSettings(SettingsKeys.CustomerFilterInZeiterfassung, customerFilter.ToString()); return RedirectToActionPermanent("Main"); } [Authorize] [HttpPost] public ActionResult CreateOrUpdateGroupBooking(FormCollection formCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } try { if(!Model.IsInEditingMode) { if(Model.GroupBookingSelectedCostbearerRelOids.Count == 1) { Model.SelectedCostBearerSupportConceptOid = Model.GroupBookingSelectedCostbearerRelOids.FirstOrDefault(); } } else { var selectedRecordOid = Model.SelectedServiceRecordOid ?? Model.SelectedServiceRecord.ServiceRecordOid; Model.NewServiceRecord = OperationsService.GetServiceRecordById(selectedRecordOid.Value); } string doku1; if(Model.Dokutypes != null && Model.Dokutypes.Length > 0) { doku1 = formCollection[FormCollectionConstants.Dokumentation1Key]; } else { doku1 = formCollection[FormCollectionConstants.Dokumentation6Key]; } // Wenn kein Datum angegeben wurde, wird die Main-Seite geladen und abgebrochen if(string.IsNullOrEmpty(formCollection[FormCollectionConstants.DateKey])) { return View("Main", Model); } // Marker var marker = "on" == formCollection[FormCollectionConstants.MarkerKey]; decimal? betrag = null; var betragAsString = formCollection[FormCollectionConstants.BetragKey]?.Replace('.', ','); if(decimal.TryParse(betragAsString, out var betragAsDecimal)) { betrag = betragAsDecimal; } // Distanz var distanz = formCollection[FormCollectionConstants.DistanceKey]; decimal? distanceInMeters = null; if(!string.IsNullOrEmpty(distanz)) { if(decimal.TryParse(distanz, out var parsedDistance)) { distanceInMeters = parsedDistance; } } // Kostenträger-Hilfeplan-Relation var selectedCostbearer2SupportConceptRelOid = Model.SelectedCostBearerSupportConceptOid < 1 ? null : Model.SelectedCostBearerSupportConceptOid; // Datumsteil des Startdatums var datum = Convert.ToDateTime(formCollection[FormCollectionConstants.DateKey]); // Enddatum wird der gleiche Tag wie vom Start var enddatum = datum; // Es wird geprüft, ob es das Enddatumsfeld gibt (das haben nicht alle Kunden) var endDateString = formCollection[FormCollectionConstants.EndDateKey]; if(endDateString?.Length > 0) { enddatum = Convert.ToDateTime(endDateString); } // Start- und Endzeit zur Dauerberechnung var start = formCollection[FormCollectionConstants.StartKey]; var ende = formCollection[FormCollectionConstants.EndKey]; var dauer = 0m; if(datum > enddatum) { enddatum = datum; } var durationAsString = formCollection[FormCollectionConstants.DurationKey]; durationAsString = durationAsString.Replace('.', ','); if(!string.IsNullOrEmpty(durationAsString)) { decimal.TryParse(durationAsString, out dauer); } // Wenn die Dauer in Stunden ist if(Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1) { dauer *= 60m; } // Dokumentation var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key]; var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key]; var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key]; var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key]; // Ziele und Maßnahmen // Start- und Endstrings werden in DateTime-Objekte konvertiert var zeitenFeld = new DateTime[2]; if(start == string.Empty && ende == string.Empty) { zeitenFeld[0] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1); if(enddatum == datum) { zeitenFeld[1] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer)); } else { zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer)); } } else { zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, Convert.ToDouble(dauer)) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, Convert.ToDouble(dauer)); } if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0]) { dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes; } if(Model.NewServiceRecord is null) { return RedirectToActionPermanent("Main"); } Model.NewServiceRecord.IP = Request.UserHostAddress; Model.NewServiceRecord.Goals = Model.SelectedGoals; Model.NewServiceRecord.Start = zeitenFeld[0]; Model.NewServiceRecord.End = zeitenFeld[1]; Model.NewServiceRecord.Betrag = betrag; if(marker) { Model.NewServiceRecord.ServiceRecordType = ServiceRecordTypeId.Content; } Model.NewServiceRecord.DistanceInMeterDecimal = distanceInMeters; if(Model.LoggedInEmployee.EmployeeOid.HasValue) { if(Model.SelectedEmployee != null) { Model.NewServiceRecord.Employee = Model.SelectedEmployee; } var supportConcept = Model.SupportConcepts.FirstOrDefault(fod => fod.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && a.CostBearer2SupportConceptOid.Value.Equals(selectedCostbearer2SupportConceptRelOid))); if(supportConcept != null) { if(supportConcept.SupportConceptOid.HasValue) { Model.NewServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(supportConcept.SupportConceptOid.Value, Model.LoggedInEmployee.EmployeeOid); } Model.NewServiceRecord.Customer = supportConcept.Customer; var cb2ScRel = supportConcept.CostBearerRelations.First(f => f.CostBearer2SupportConceptOid.HasValue && f.CostBearer2SupportConceptOid.Equals(selectedCostbearer2SupportConceptRelOid)); Model.NewServiceRecord.CostBearer = cb2ScRel.CostBearer; var intervall = Model.NewServiceRecord.CostBearer.ActualMinuteIntervall; if(intervall > 0) { Model.NewServiceRecord.RoundedDuration = dauer % intervall != 0 ? dauer + (intervall - dauer % intervall) : dauer; } else { Model.NewServiceRecord.RoundedDuration = dauer; } Model.NewServiceRecord.CostBearer2SupportConceptOid = selectedCostbearer2SupportConceptRelOid; } else { Model.NewServiceRecord.RoundedDuration = dauer; } } Model.NewServiceRecord.DurationInStunden = Model.IsZeiterfassungInStdMin ? ZeiterfassungsDauer.Stunden : ZeiterfassungsDauer.Minuten; Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; if(Model.IsEndDateVisible) { Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum; } Model.NewServiceRecord.Notice = string.IsNullOrEmpty(doku1) ? null : doku1; Model.NewServiceRecord.Notice2 = string.IsNullOrEmpty(doku2) ? null : doku2; Model.NewServiceRecord.Notice3 = string.IsNullOrEmpty(doku3) ? null : doku3; Model.NewServiceRecord.Notice4 = string.IsNullOrEmpty(doku4) ? null : doku4; Model.NewServiceRecord.Notice5 = string.IsNullOrEmpty(doku5) ? null : doku5; var serviceDescOid = 0L; if(!string.IsNullOrEmpty(formCollection[FormCollectionConstants.ServiceDescriptionKey])) { serviceDescOid = Convert.ToInt64(formCollection[FormCollectionConstants.ServiceDescriptionKey]); } else if(Model.SelectedServiceDescriptionOid.HasValue) { serviceDescOid = Model.SelectedServiceDescriptionOid.Value; } if(serviceDescOid > 0) { Model.NewServiceRecord.ServiceDescription = OperationsService.GetServiceDescription(serviceDescOid); } if(Model.NewServiceRecord.RoundedDuration == 0) { Model.NewServiceRecord.RoundedDuration = dauer; } Model.NewServiceRecord.InsertedOn = DateTime.Now; Model.NewServiceRecord.InsUser = MobileSessionFacade.EmployeeFullname; Model.NewServiceRecord.IsCreatedInMobileClient = true; if(Model.SetStartTimeToEndTimeAfterSave) { var previousStartDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.Start : Model.NewServiceRecord?.Start; var previousEndDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.End : Model.NewServiceRecord?.End; if(previousStartDate.HasValue && previousEndDate.HasValue) { var duration = (previousEndDate - previousStartDate).Value.TotalMinutes; Model.NewStartDate = previousEndDate; Model.NewEndDate = previousEndDate.Value.AddMinutes(duration); } } return Model.IsInEditingMode ? UpdateGroupBooking() : SaveGroupBooking(); } catch(Exception exception) { Log.Error(exception.Message, exception); } return ResetEditingMode(); } [Authorize] public string ToggleDurationUnit(bool isInHoursMode) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } Model.IsShowingDurationInHours = isInHoursMode; UpdateUserSettingsWithoutReload(SettingsKeys.LetzteZeiterfassungsDauer, Model.IsShowingDurationInHours ? "1" : "0"); return LeerzeichenFuerGetMethoden; } /// /// Bereitet die Übernahme eines Termins in die Zeiterfassung vor. Wird im SchedulerController aufgerufen. /// /// Main.cshtml [Authorize] public ActionResult PrepareServiceRecordInsert() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } Model.TransferringAppointmentOid = TempData[TempDataConstants.AppointmentOidKey] as long?; if(Model.TransferringAppointmentOid.HasValue && Model.LoggedInEmployee.EmployeeOid.HasValue) { var app = DAOFactory.GenericDAO.LoadByID(Model.TransferringAppointmentOid.Value); var appointment = MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDC(app); var start = appointment.StartDate; var end = appointment.EndDate; var customerOids = appointment.CustomerList.Select(customer => customer.CustomerOid).ToList(); var employeeOids = appointment.EmployeeList.Select(e2a => e2a.Employee.EmployeeOid).ToList(); if(appointment.AllDay && start.HasValue && end.HasValue) { start = start.Value.MergeDateWithHoursMinutesSeconds(0, 0, 1); end = end.Value.MergeDateWithHoursMinutesSeconds(0, 0, 1); } if(employeeOids.Count == 0) { employeeOids.Add(Model.LoggedInEmployee.EmployeeOid.Value); } var notice = appointment.Description; var customerService = PluginLoader.FindClass(); var supportConcepts = customerService.GetAllActiveSupportConceptCostbearer(false, true, Model.LoggedInEmployee.EmployeeOid.Value); supportConcepts = supportConcepts.Where(sc => customerOids.Contains(sc.Customer.CustomerOid) && sc.StartDate.HasValue && sc.EndDate.HasValue && start.Value.AreInBetweenDates(end.Value, sc.StartDate.Value, sc.EndDate.Value)).ToList(); var supportConceptList = new List(); foreach(var customerOid in customerOids) { var supportConcept = supportConcepts.FirstOrDefault(sc => sc.Customer.CustomerOid.Equals(customerOid)); if(supportConcept is null) { continue; } supportConceptList.AddIfNotIn(supportConcept); } // Ohne Hilfeplan if(supportConceptList.Count == 0) { ResetBookingMode(BookingMode.SingleBookingMode); Model.SelectedEmployee = Model.AllEmployees.FirstOrDefault(e => e.EmployeeOid.Equals(Model.LoggedInEmployee.EmployeeOid.Value)); LoadSupportConceptThings(-2); if(Model.SelectedServiceDescription != null) { Model.SelectedServiceCategory = Model.SelectedServiceDescription.Category; var serviceRecord = CreateServiceRecordFromScratch(start.Value, end.Value, null, Model.SelectedEmployee, notice); serviceRecord.ServiceDescription = Model.SelectedServiceDescription; Model.SelectedServiceRecord = serviceRecord; } } // Einzelbuchung else { var availableRelOids = new List(); Model.SupportConceptListObjects.DoForEach(sclo => { availableRelOids.AddIfNotIn(sclo.CostBearer2SupportConceptOid); }); if(supportConceptList.Count == 1 && employeeOids.Count == 1) { ResetBookingMode(BookingMode.SingleBookingMode); Model.SelectedEmployee = Model.AllEmployees.FirstOrDefault(e => e.EmployeeOid.Equals(employeeOids.FirstOrDefault())); var compactSupportConcept = supportConceptList.First(); var supportConcept = Model.SupportConcepts.FirstOrDefault(f => f.SupportConceptOid.HasValue && f.SupportConceptOid.Value.Equals(compactSupportConcept.SupportConceptOid)); var serviceRecord = CreateServiceRecordFromScratch(start.Value, end.Value, supportConcept?.Customer, Model.SelectedEmployee, notice); var costBearer2SupportConcept = supportConcept?.CostBearerRelations.FirstOrDefault(cbRel => cbRel.CostBearer2SupportConceptOid.HasValue && availableRelOids.Contains(cbRel.CostBearer2SupportConceptOid.Value)); LoadSupportConceptThings(costBearer2SupportConcept?.CostBearer2SupportConceptOid ?? -2); serviceRecord.CostBearer = costBearer2SupportConcept?.CostBearer; serviceRecord.CostBearer2SupportConceptOid = costBearer2SupportConcept?.CostBearer2SupportConceptOid; serviceRecord.ServiceDescription = Model.SelectedServiceDescription; if(Model.SelectedServiceDescription != null) { Model.SelectedServiceRecord = serviceRecord; } } else // Gruppenbuchung { ResetBookingMode(BookingMode.GroupBookingMode); Model.GroupBookingSelectedEmployees = Model.AllEmployees.Where(w => employeeOids.Contains(w.EmployeeOid)).ToList(); var roundedDuration = (int) ((end - start)?.TotalMinutes ?? 0); Model.SelectedServiceRecord = new ServiceRecordDC() { Start = start, End = end, RoundedDuration = roundedDuration, Notice = notice, ServiceDescription = Model.GetSelectedOrFirstServiceDescription() }; var supportConceptsForGroupBooking = Model.SupportConcepts.Where(sc => sc.SupportConceptOid.HasValue && supportConceptList.Any(csc => csc.SupportConceptOid.Equals(sc.SupportConceptOid.Value))).ToList(); var costBearer2SupportConceptOids = new List(); var costBearer2SupportConcepts = new List(); foreach(var supportConcept in supportConceptsForGroupBooking) { var costBearer2SupportConcept = supportConcept?.CostBearerRelations.FirstOrDefault(cbRel => cbRel.CostBearer2SupportConceptOid.HasValue && availableRelOids.Contains(cbRel.CostBearer2SupportConceptOid.Value)); if(costBearer2SupportConcept?.CostBearer2SupportConceptOid is null) { continue; } costBearer2SupportConceptOids.AddIfNotIn(costBearer2SupportConcept.CostBearer2SupportConceptOid.Value); costBearer2SupportConcepts.AddIfNotIn(costBearer2SupportConcept); } if(costBearer2SupportConceptOids.Any()) { Model.GroupBookingSelectedCostbearerRelOids = costBearer2SupportConceptOids; Model.SelectedConceptCostBearerRelations = costBearer2SupportConcepts; Model.GroupBookingSelectedSupportConcepts = supportConceptsForGroupBooking; } LoadServiceCategoriesToModel(null); LoadGoals(); } } Model.SelectedServiceRecordOid = Model.SelectedServiceRecord?.ServiceRecordOid; Model.TransferringAppointmentOid = appointment.SchedulerAppointmentOid; Model.IsInTransferMode = true; } return View("Main", Model); } private ServiceRecordDC CreateServiceRecordFromScratch(DateTime start, DateTime end, CompactCustomerDC customer, CompactEmployeeDC employee, string notice) { var serviceRecord = new ServiceRecordDC { Employee = employee, Customer = customer, Notice = notice?.RemoveUppercaseEsszett(), InsertedOn = DateTime.Now, InsUser = employee?.ToString(), IsCreatedInMobileClient = true }; if(start.Date != end.Date) { serviceRecord.Start = end; serviceRecord.End = end; serviceRecord.RoundedDuration = 0; } else { serviceRecord.Start = start; serviceRecord.End = end; serviceRecord.RoundedDuration = (decimal)end.Subtract(start).TotalMinutes; } if(Model.IsEndDateVisible) { serviceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum; } else if(Model.IsOnlyYearMonthVisible) { serviceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitMonatJahr; } else { serviceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; } serviceRecord.DurationInStunden = Model.IsShowingDurationInHours ? ZeiterfassungsDauer.Stunden : ZeiterfassungsDauer.Minuten; return serviceRecord; } [HttpPost] [Authorize] public ActionResult DeleteSignature(FormCollection formCollection) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } try { if(long.TryParse(formCollection["sr-signature-to-del-oid"], out var signatureOid) && long.TryParse(formCollection["sr-sig-to-del-record-oid"], out var serviceRecordOid)) { OperationsService.DeleteSignature(signatureOid, serviceRecordOid); } } catch(Exception exception) { Log.Error(exception.Message, exception); } return RedirectToActionPermanent("Main"); } #region Mehrfachbuchung [Authorize] public ActionResult ReloadMultiBookingForm() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; } else { LoadServiceCategoriesToModel(null); } return PartialView("MultiBookingSelectionPartial", Model); } [Authorize] public ActionResult AddScCbRelsToMultiBooking(string[] relOids, string[] groupOids) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("MultiBookingScCbRelList"); } var singleRels = new List(); var groupRels = new List(); var groups = new List(); if(groupOids is null) { groupOids = Array.Empty(); } if(relOids is null) { relOids = Array.Empty(); } relOids.DoForEach(relOid => { if(long.TryParse(relOid, out var singleRelOid)) { singleRels.AddIfNotIn(singleRelOid); } }); groupOids.DoForEach(groupOid => { if(long.TryParse(groupOid, out var g)) { groupRels.AddIfNotIn(g); } }); Model.MultiBookingSelectedGroupOfPeopleOids.Clear(); groupRels.DoForEach(groupOid => { var group = Model.GroupsOfPeople.FirstOrDefault(f => f.GroupOfPeopleOid.HasValue && f.GroupOfPeopleOid.Value.Equals(groupOid)); if(group is null) { return; } groups.AddIfNotIn(group); group.SupportConceptList.DoForEach(f => singleRels.AddRangeIfElementsNotIn(f.CostBearerRelOids)); }); Model.MultiBookingSelectedSupportConcepts.Clear(); Model.MultiBookingSelectedCostbearerRelOids.Clear(); Model.MultiBookingSelectedCostbearerRelOids.AddRangeIfElementsNotIn(singleRels); var selectedSupportConcepts = CustomerService.GetSupportConceptsByCostbearer2SupportConceptRelOids(singleRels); var groupCostBearerRelations = CustomerService.GetSupportConceptCostBearerRelationsById(singleRels); Model.MultiBookingSelectedConceptCostBearerRelations.Clear(); Model.MultiBookingSelectedConceptCostBearerRelations.AddRangeIfElementsNotIn(groupCostBearerRelations); Model.MultiBookingSelectedSupportConcepts.AddRangeIfElementsNotIn(selectedSupportConcepts); foreach(var gruppe in groups.Where(g => g.GroupOfPeopleOid.HasValue)) { var groupRelOids = new List(); gruppe.SupportConceptList.ForEach(f => groupRelOids.AddRange(f.CostBearerRelOids)); if(!gruppe.GroupOfPeopleOid.HasValue) { continue; } var groupOid = gruppe.GroupOfPeopleOid.Value; if(singleRels.ContainsItems(groupRelOids)) { Model.MultiBookingSelectedGroupOfPeopleOids.AddIfNotIn(groupOid); } else if(Model.MultiBookingSelectedGroupOfPeopleOids.Contains(groupOid)) { Model.MultiBookingSelectedGroupOfPeopleOids.Remove(groupOid); } } return PartialView("MultiBookingScCbRelList", Model); } [Authorize] public ActionResult RemoveSupportConceptCostbearerRelFromMultiBooking(string relOid) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("MultiBookingSelectionPartial"); } if(!long.TryParse(relOid, out var supportConceptCostBearerRelationOid)) { return PartialView("MultiBookingSelectionPartial", Model); } var supportConcept2Remove = Model.MultiBookingSelectedSupportConcepts.FirstOrDefault(f => f.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid)); var relation2Remove = Model.MultiBookingSelectedConceptCostBearerRelations.FirstOrDefault(f => f.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid); if(supportConcept2Remove?.SupportConceptOid.HasValue ?? false) { var supportConcepts = Model.MultiBookingSelectedSupportConcepts.Where(supportConcept => supportConcept.SupportConceptOid.HasValue && supportConcept.SupportConceptOid.Value.Equals(supportConcept2Remove.SupportConceptOid.Value) == false).ToList(); // Ziele, die bei den verbleibenden Hilfeplänen nicht vorhanden sind, werden aus der Auswahl entfernt. var remainingGoals = new List(); foreach(var supportConcept in supportConcepts) { foreach(var goal in supportConcept.Goals) { remainingGoals.AddIfNotIn(goal); } } Model.SelectedGoals = Model.SelectedGoals.Where(goal => remainingGoals.Contains(goal)).ToList(); } Model.MultiBookingSelectedSupportConcepts.Remove(supportConcept2Remove); Model.MultiBookingSelectedConceptCostBearerRelations.Remove(relation2Remove); var selectedGroups = Model.GroupsOfPeople.Where(group => group.GroupOfPeopleOid.HasValue && Model.MultiBookingSelectedGroupOfPeopleOids.Contains(group.GroupOfPeopleOid.Value)).ToList(); var groups = selectedGroups.Where(group => group.SupportConceptList.All(a => Model.MultiBookingSelectedSupportConcepts.Where(w => w.SupportConceptOid.HasValue).Select(s => s.SupportConceptOid.Value).Contains(a.SupportConceptOid))); Model.MultiBookingSelectedGroupOfPeopleOids = groups.Where(group => group.GroupOfPeopleOid.HasValue).Select(group => group.GroupOfPeopleOid.Value).ToList(); LoadServiceCategoriesToModel(null); if(Model.SelectedServiceCategory != null && !Model.Categories2Descriptions.Keys.Contains(Model.SelectedServiceCategory)) { var firstCategory2ServiceDescriptions = Model.Categories2Descriptions.FirstOrDefault(); var firstServiceCategory = firstCategory2ServiceDescriptions.Key; var firstServiceDescription = firstCategory2ServiceDescriptions.Value.FirstOrDefault(); Model.SelectedServiceCategory = firstServiceCategory; Model.SelectedServiceDescription = firstServiceDescription; } return PartialView("MultiBookingSelectionPartial", Model); } [Authorize] [HttpPost] public ActionResult SetMultiBookingMode(FormCollection formCollection) { if(Model is null) { return Logout(); } Model.IsInTransferMode = false; Model.TransferringAppointmentOid = null; try { var isInMultiBookingMode = "true,false" == formCollection[FormCollectionConstants.IsInMultiBookingModeKey]; Model.IsInMultiBookingMode = isInMultiBookingMode; ResetBookingMode(isInMultiBookingMode ? BookingMode.MultiBookingMode : BookingMode.SingleBookingMode); } catch(Exception exception) { Log.Error(exception.Message, exception); } return RedirectToAction("Main"); } [Authorize] [HttpPost] public ActionResult CreateMultiBooking(FormCollection formCollection) { if(Model is null) { return Logout(); } try { string doku1; if(Model.Dokutypes != null && Model.Dokutypes.Length > 0) { doku1 = formCollection[FormCollectionConstants.Dokumentation1Key]?.RemoveUppercaseEsszett(); } else { doku1 = formCollection[FormCollectionConstants.Dokumentation6Key]?.RemoveUppercaseEsszett(); } // Wenn kein Datum angegeben wurde, wird die Main-Seite geladen und abgebrochen if(string.IsNullOrEmpty(formCollection[FormCollectionConstants.DateKey])) { return View("Main", Model); } var marker = "on" == formCollection[FormCollectionConstants.MarkerKey]; decimal? betrag = null; var betragAsString = formCollection[FormCollectionConstants.BetragKey]?.Replace('.', ','); if(decimal.TryParse(betragAsString, out var betragAsDecimal)) { betrag = betragAsDecimal; } var distanz = formCollection[FormCollectionConstants.DistanceKey]; decimal? distanceInMeters = null; if(!string.IsNullOrEmpty(distanz)) { if(decimal.TryParse(distanz, out var parsedDistance)) { distanceInMeters = parsedDistance; } } var selectedCostbearer2SupportConceptRelOid = Model.SelectedCostBearerSupportConceptOid < 1 ? null : Model.SelectedCostBearerSupportConceptOid; var datum = Convert.ToDateTime(formCollection[FormCollectionConstants.DateKey]); var enddatum = datum; var endDateString = formCollection[FormCollectionConstants.EndDateKey]; if(endDateString?.Length > 0) { enddatum = Convert.ToDateTime(endDateString); } var start = formCollection[FormCollectionConstants.StartKey]; var ende = formCollection[FormCollectionConstants.EndKey]; var dauer = 0m; if(datum > enddatum) { enddatum = datum; } var durationAsString = formCollection[FormCollectionConstants.DurationKey]; durationAsString = durationAsString.Replace('.', ','); if(!string.IsNullOrEmpty(durationAsString)) { decimal.TryParse(durationAsString, out dauer); } if(Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1) { dauer *= 60m; } var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key]?.RemoveUppercaseEsszett(); var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key]?.RemoveUppercaseEsszett(); var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key]?.RemoveUppercaseEsszett(); var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key]?.RemoveUppercaseEsszett(); var zeitenFeld = new DateTime[2]; if(start == string.Empty && ende == string.Empty) { zeitenFeld[0] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1); if(enddatum == datum) { zeitenFeld[1] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer)); } else { zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer)); } } else { zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, Convert.ToDouble(dauer)) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, Convert.ToDouble(dauer)); } if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0]) { dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes; } var serviceRecordsToInsert = new List(); if(Model.MultiBookingSelectedConceptCostBearerRelations.Any() && Model.MultiBookingSelectedEmployees.Any()) { foreach(var sc2cbRel in Model.MultiBookingSelectedConceptCostBearerRelations) { var roundedDuration = dauer; var organisation = CustomerService.LoadOrganisationCompact(sc2cbRel.CostBearer.OrganisationOid); if(!(organisation is null)) { var calculations = Calculations.GetInstance(organisation.CostBearerID); roundedDuration = calculations.GetRoundedDuration(organisation, dauer); } // ToDo: Validierungsergebnisse treten mehrfach auf foreach(var employee in Model.MultiBookingSelectedEmployees) { var newServiceRecord = new ServiceRecordDC { IP = Request.UserHostAddress, Start = zeitenFeld[0], End = zeitenFeld[1], DistanceInMeterDecimal = distanceInMeters, RoundedDuration = roundedDuration, SupportConcept = sc2cbRel.SupportConcept, CostBearer2SupportConceptOid = sc2cbRel.CostBearer2SupportConceptOid, CostBearer = sc2cbRel.CostBearer, DurationInStunden = Model.IsShowingDurationInHours ? ZeiterfassungsDauer.Stunden : ZeiterfassungsDauer.Minuten, Customer = sc2cbRel.SupportConcept.Customer, Notice = doku1 ?? string.Empty, Notice2 = doku2 ?? string.Empty, Notice3 = doku3 ?? string.Empty, Notice4 = doku4 ?? string.Empty, Notice5 = doku5 ?? string.Empty, InsertedOn = DateTime.Now, InsUser = MobileSessionFacade.EmployeeFullname, IsCreatedInMobileClient = true, Employee = employee, ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung, ServiceDescription = OperationsService.GetServiceDescription(Model.SelectedServiceDescriptionOid.Value), Betrag = betrag }; if(marker) { newServiceRecord.ServiceRecordType = ServiceRecordTypeId.Content; } if(Model.IsEndDateVisible) { newServiceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum; } serviceRecordsToInsert.Add(newServiceRecord); } } OperationsService.InsertNewServiceRecords(serviceRecordsToInsert); } } catch(Exception exception) { Log.Error(exception.Message, exception); } return ResetEditingMode(); } [Authorize] public string AddEmployeesToMultiBooking(string pEmployeeOids) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } if(string.IsNullOrEmpty(pEmployeeOids)) { Model.MultiBookingSelectedEmployees.Clear(); return JsonConvert.SerializeObject(Model.MultiBookingSelectedEmployees.Count); } var rawEmployeeOids = pEmployeeOids.Split(','); var oids = new List(); rawEmployeeOids.DoForEach(s => oids.AddIfNotIn(long.Parse(s))); var employees = Model.EmployeesForGroupAndMultiBooking.Where(w => oids.Contains(w.EmployeeOid)); Model.MultiBookingSelectedEmployees.Clear(); Model.MultiBookingSelectedEmployees.AddRangeIfElementsNotIn(employees); return JsonConvert.SerializeObject(Model.MultiBookingSelectedEmployees.Count); } // Veraltet [Authorize] public string MultiBookingHasSelectedSupportConcepts() { try { return JsonConvert.SerializeObject(Model.MultiBookingSelectedConceptCostBearerRelations.Any()); } catch(Exception exception) { Log.Error(exception.Message, exception); } return JsonConvert.SerializeObject(false); } [Authorize] public string MultiBookingHasSelectedEmployees() { try { return JsonConvert.SerializeObject(Model.MultiBookingSelectedEmployees.Any()); } catch(Exception exception) { Log.Error(exception.Message, exception); } return JsonConvert.SerializeObject(false); } #endregion [HttpPost] [Authorize] public ActionResult ChangePassword(FormCollection formCollection) { if(Model is null || !MobileSessionFacade.IsUserLoggedIn() || LoggedInUser.UserVersion is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } var oldPassword = formCollection["old-password"]; var newPassword = formCollection["new-password"]; var passwordConfirmation = formCollection["confirm-new-password"]; if(false == newPassword.Equals(passwordConfirmation)) { TempData[TempDataConstants.PwChErrKey] = "Die Passwörter stimmen nicht überein!"; return RedirectToActionPermanent("Main"); } var passwordUtils = new PasswordUtils(); if(passwordUtils.EvaluatePasswordStrength(newPassword) < 2) { var checkResult = UserService.CheckPassword(LoggedInUser.UserOid.Value, oldPassword, newPassword); if(!(checkResult is null)) { TempData[TempDataConstants.PwChErrKey] = checkResult; return RedirectToActionPermanent("Main"); } } var userName = LoggedInUser.LoginName; var userVersion = LoggedInUser.UserVersion.Value; UserService.ChangePassword(userName, userVersion, oldPassword, newPassword); return RedirectToActionPermanent("Main"); } #region ServiceRecord-Pagination [Authorize] public ActionResult LoadServiceRecordPage(int selectedPage) { if(Model.SelectedZeitraum?.StartDate is null || Model.SelectedZeitraum.EndDate is null) { Model.SelectedZeitraum = new NullableDateTimeSpan(DateTime.Today.GetFirstOfMonth(), DateTime.Today); } LoadPaginatedServiceRecordsToModel(selectedPage); return PartialView("ServiceRecordListPartial", Model); } private void LoadPaginatedServiceRecordsToModel(int selectedPage) { var records = new List(); if(selectedPage < 1) { selectedPage = 1; } var selectedDayCount = (long?) (Model.SelectedDayCount == 0 ? null : (int?) Model.SelectedDayCount); Model.CurrentPage = selectedPage; int totalServiceRecords; var firstResult = (selectedPage - 1) * Model.MaxResults; var selectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid ?? Model.LoggedInEmployee.EmployeeOid.Value; // Ohne Hilfeplan if(Model.SelectedCostBearerSupportConceptOid is null || Model.SelectedCostBearerSupportConceptOid < 1) { records = Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen || Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.Monatsauswahl ? //Zeitraum oder Monat gewählt OperationsService.GetEmployeesServiceRecordsWithStartEndDatePaginated(selectedEmployeeOid, Model.SelectedZeitraum.StartDate.Value, Model.SelectedZeitraum.EndDate.Value, firstResult, Model.MaxResults, out totalServiceRecords).ToList() : OperationsService.GetEmployeesServiceRecords2Paginated(selectedEmployeeOid, selectedDayCount, firstResult, Model.MaxResults, out totalServiceRecords).ToList(); } else { records = Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen || Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.Monatsauswahl ? //Zeitraum oder Monat gewählt OperationsService .GetCustomerServiceRecordsWithStartEndDatePaginated( Model.SelectedSupportConcept.Customer.CustomerOid, Model.SelectedCostBearerSupportConceptOid.Value, Model.SelectedZeitraum.StartDate.Value, Model.SelectedZeitraum.EndDate.Value, firstResult, Model.MaxResults, out totalServiceRecords) : OperationsService.FindServiceRecordsForLastDaysPaginated(Model.SelectedCostBearerSupportConceptOid, Model.SelectedDayCount, Model.LoggedInEmployee?.EmployeeOid, firstResult, Model.MaxResults, out totalServiceRecords).ToList(); } var pages = Math.DivRem(totalServiceRecords, Model.MaxResults, out var remainder); if(remainder > 0) { pages++; } Model.ServiceRecordCount = totalServiceRecords; Model.ServiceRecordPageCount = pages; var recordsOhneDuplikate = new List(); foreach(var r in records.Where(r => !recordsOhneDuplikate.Any(a => a.GroupOid.HasValue && a.GroupOid.Value.Equals(r.GroupOid)))) { recordsOhneDuplikate.Add(r); } var serviceRecords = recordsOhneDuplikate.Where(serviceRecord => serviceRecord.Start.HasValue && serviceRecord.End.HasValue) .OrderBy(serviceRecord => serviceRecord.Start.Value.Date) .ThenBy(serviceRecord => serviceRecord.Start.Value.Hour) .ThenBy(serviceRecord => serviceRecord.Start.Value.Minute) .ThenBy(serviceRecord => serviceRecord.End.Value.Date) .ThenBy(serviceRecord => serviceRecord.End.Value.Hour) .ThenBy(serviceRecord => serviceRecord.End.Value.Minute) .ThenByDescending(serviceRecord => serviceRecord.InsertedOn.Value).ToList(); var serviceRecordOids2GoalHeaders = new Dictionary>(); var goalOids = new List(); //var measures = new List(); serviceRecords.DoForEach(serviceRecord => { //measures.AddRangeIfElementsNotIn(serviceRecord.Goals); goalOids.AddRangeIfElementsNotIn(serviceRecord.Goals.Where(goal => goal.ParentOid.HasValue).Select(goal => goal.ParentOid.Value)); }); var goalCategories = ValueListService.GetGoalCategoriesByOids(goalOids); //serviceRecords.DoForEach(serviceRecord => //{ // if(serviceRecord.ServiceRecordOid is null) // { // return; // } // serviceRecord.Goals.OrderBy(vle => $"{vle.Abbreviation}-{vle.TypeDescription}").DoForEach(goal => // { // var goalCategory = goalCategories.FirstOrDefault(g => g.ValueListEntryOid.HasValue && goal.ValueListEntryOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ValueListEntryOid.Value) || (g.ValueListEntryOid.HasValue && goal.ParentOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ParentOid.Value))); // if(goalCategory != null) // { // serviceRecordOids2GoalHeaders.AddOrUpdateValueInDictionary(serviceRecord.ServiceRecordOid.Value, new List { goalCategory.DisplayName }); // } // }); //}); Model.ServiceRecordOids2GoalHeader = GetServiceRecordOids2GoalHeaders(serviceRecords, goalCategories); Model.ServiceRecords = serviceRecords; } [Authorize] public static Dictionary> GetServiceRecordOids2GoalHeaders(List serviceRecords, List goalCategories) { var serviceRecordOids2GoalHeaders = new Dictionary>(); serviceRecords.DoForEach(serviceRecord => { if(serviceRecord.ServiceRecordOid is null) { return; } serviceRecord.Goals.OrderBy(vle => $"{vle.Abbreviation}-{vle.TypeDescription}").DoForEach(goal => { var goalCategory = goalCategories.FirstOrDefault(g => g.ValueListEntryOid.HasValue && goal.ValueListEntryOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ValueListEntryOid.Value) || (g.ValueListEntryOid.HasValue && goal.ParentOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ParentOid.Value))); if(goalCategory != null) { serviceRecordOids2GoalHeaders.AddOrUpdateValueInDictionary(serviceRecord.ServiceRecordOid.Value, new List { goalCategory.DisplayName }); } }); }); return serviceRecordOids2GoalHeaders; } [Authorize] public ActionResult GoToFirstPage() { return LoadServiceRecordPage(1); } [Authorize] public ActionResult GoToLastPage() { return LoadServiceRecordPage(Model.ServiceRecordPageCount); } #endregion #region Einmal-Link für die Unterschrift [Authorize] public ActionResult GenerateOneTimeLinkForSignature(long serviceRecordOid) { var token = BeWo.Service.Security.SecurityUtils.CreateExternalSignatureToken(serviceRecordOid); var server = "https://" + LoginController.GetServerFromTenant(MobileSessionFacade.Tenant); #if DEBUG server = "http://" + GetLocalIPAddress() + "/BeWoPlanerMobil"; #endif var link = $"{server}/ExternalSignature/ExternalSignature/{token}"; Model.OneTimeLink = link; var serviceRecord = Model.GetServiceRecord(serviceRecordOid); var hilfeplan = Model.SelectedCostBearer2SupportConceptRelListObject.NameAndDateOfBirth + " | " + Model.SelectedCostBearer2SupportConceptRelListObject.SupportConceptTimeSpan; var leistung = serviceRecord.ServiceDescription.Name; var kategorie = serviceRecord.ServiceDescription.Category; var employee = $"{serviceRecord.Employee.FirstName} {serviceRecord.Employee.LastName}"; var datumUhrzeit = MainModel.GetServiceRecordTimeString(serviceRecord); Model.OneTimeLinkText = $"Hilfeplan: {hilfeplan}
Kategorie: {kategorie}
Leistung: {leistung}
Mitarbeiter: {employee}
Datum / Uhrzeit: {datumUhrzeit}

"; Model.ShareDetails = $"Unterschrift für erbrachte Leistung am {datumUhrzeit}"; return PartialView("OneTimeLinkCreationPartial", Model); } [Authorize] public ActionResult CancelLinkCreation() { Model.OneTimeLink = null; Model.OneTimeLinkText = null; Model.ShareDetails = null; return PartialView("OneTimeLinkCreationPartial", Model); } #endregion private static string GetLocalIPAddress() { var host = Dns.GetHostEntry(Dns.GetHostName()); foreach(var ip in host.AddressList) { if(ip.AddressFamily == AddressFamily.InterNetwork) { return ip.ToString(); } } throw new Exception("No network adapters with an IPv4 address in the system!"); } [Authorize] public ActionResult ReloadGoals() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; } LoadGoals(); return PartialView("GoalTreePartial", Model); } [Authorize] public ActionResult SetSelectedServiceCategory(string categoryOidStr) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("Category2ServiceDescriptionPartial"); } if(long.TryParse(categoryOidStr, out var categoryOid)) { Model.SelectedServiceCategory = Model.Categories2Descriptions.FirstOrDefault(f => f.Key?.ServiceCategoryOid != null && f.Key.ServiceCategoryOid.Value.Equals(categoryOid)).Key; Model.SelectedServiceDescription = null; if(Model.SelectedServiceCategory is null) { return PartialView("Category2ServiceDescriptionPartial", Model); } var selectedServiceDescription = Model.Categories2Descriptions[Model.SelectedServiceCategory].OrderBy(sd => sd.Position).ThenBy(sd => sd.ServiceDescriptionOid).FirstOrDefault(); Model.SelectedServiceDescription = selectedServiceDescription; Model.SelectedServiceCategoryOid = Model.SelectedServiceCategory?.ServiceCategoryOid; Model.SelectedServiceDescriptionOid = Model.SelectedServiceDescription?.ServiceDescriptionOid; } return PartialView("Category2ServiceDescriptionPartial", Model); } [Authorize] public string CheckSession() { return (Model is null).ToString(); } [HttpPost] public ActionResult ZombieLogout() { #if DEBUG TempData[TempDataConstants.ErrorMessageKey] = "Der Browser wurde aus der Versenkung zurückgeholt und das Model ist jetzt null!"; #endif return base.Logout(); } [Authorize] public override string SaveCollapsibleStatus(bool isOpen, string identifier) { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return LeerzeichenFuerGetMethoden; } Model.Collapsibles2IsShown[identifier] = isOpen; return LeerzeichenFuerGetMethoden; } } public class ServiceRecord2Monatsunterschrift { public ServiceRecordDC ServiceRecord { get; } public bool HasMonatsunterschrift { get; } public ServiceRecord2Monatsunterschrift(ServiceRecordDC serviceRecord, bool hasMonatsunterschrift) { ServiceRecord = serviceRecord; HasMonatsunterschrift = hasMonatsunterschrift; } } }