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 BeWo.Service.Plugins; using BeWo.Service.ServiceImplementations; using BeWo.View.Navigation.Filter; using BeWoPlanerMobil.Models; using BeWoPlanerMobil.Service; using BeWoPlanerMobil.Util; using static BeWoPlanerMobil.Util.MobileUtils; 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 Newtonsoft.Json; 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; using BeWo.Data.Entities; /* * 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(((MainModel) Session[ModelSessionConstants.MainModelKey])?.Employee is null) { _Model = new MainModel { Employee = MobileSessionFacade.LoggedInEmployee }; Session[ModelSessionConstants.MainModelKey] = _Model; } else { _Model = (MainModel) Session[ModelSessionConstants.MainModelKey]; } 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 }; [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.Mandator is null) { Model.Mandator = MobileSessionFacade.Mandator; 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; } } Model.ShowBetrag = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowBetrag); Model.ShowMarker = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowMarker); } var mandatorSettings = Model.Mandator.Settings; Model.EinheitZeiterfassung = UserSettingsUtils.GetSettingValueAsInteger(mandatorSettings, SettingsKeys.EinheitZeiterfassung); if(Model.EinheitZeiterfassung == 1) { Model.IsShowingDurationInHours = true; } Model.FilterGroupServiceCategories = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.FilterGroupServiceCategories); Model.SetStartTimeToEndTimeAfterSave = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.SetStartTimeToEndTimeAfterSave); var user = GetUser(); 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); InitializeInterval(userSettings); var customerFilter = MobileUserSettingsUtils.GetSettingValueAsEnum(userSettings, SettingsKeys.CustomerFilterInZeiterfassung, CustomerFilterEnum.MyCustomer); if(customerFilter != CustomerFilterEnum.MyCustomer && !AbstractModel.IsAllowedToSeeSupportConceptFilter) { customerFilter = CustomerFilterEnum.MyCustomer; } Model.SelectedSupportConceptFilter = customerFilter; BS.Shared.Settings.ApplicationSettings.SupportConceptExpirationLimitInMonths = UserSettingsUtils.GetSettingValueAsInteger(mandatorSettings, SettingsKeys.HilfeplanAuslaufAuswahl, 3); BS.Shared.Settings.ApplicationSettings.AnzTageZeiterfassErfolgt = UserSettingsUtils.GetSettingValueAsInteger(mandatorSettings, SettingsKeys.AnzTageZeiterfassErfolgt); BS.Shared.Settings.ApplicationSettings.MaxDaysEditServiceRecordsAllowed = UserSettingsUtils.GetSettingValueAsInteger(mandatorSettings, SettingsKeys.MaxDaysEditServiceRecordsAllowed); BS.Shared.Settings.ApplicationSettings.TimeUntilUILock = UserSettingsUtils.GetSettingValueAsInteger(mandatorSettings, SettingsKeys.TimeUntilUILock); BS.Shared.Settings.ApplicationSettings.ServiceRecordAllowChangeHours = UserSettingsUtils.GetSettingValueAsInteger(mandatorSettings, SettingsKeys.ServiceRecordAllowChangeHours); AbstractModel.ShowServiceRecordInsertedOn = !UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.HideServiceRecordInsertedByAndInsertedOn); Model.ShowSignature = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.ShowSignature) && AbstractModel.HasRightToProvideSingleSignature; Model.GroupsOfPeople = EmployeeService.GetAllGroups(GetUser().Employee.EmployeeOid).OrderBy(gop => gop.Name).ToList(); Model.ShowDistanceField = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.ShowDistanceFields); Model.Dokutypes = ValueListService.GetAllValueListEntrysByType(ValueListEntryType.DocumentType); if(Model.Dokutypes != null) { Model.Dokutypes = Model.Dokutypes.OrderBy(s => s.ValueListEntryOid).ToArray(); } 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 (MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreationForOtherEmployees)) { Model.Employees = EmployeeService.GetAllActiveEmployeesCompact(); } else if(MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreationForOtherTeamMember) && Model.Employee?.EmployeeOid != null) { Model.Employees = EmployeeService.GetAllTeamMember(MobileSessionFacade.LoggedInCompactEmployee).Where(e => e.ActivationType == ActivationTypeId.Active).ToList(); } else { Model.Employees = new List { MobileSessionFacade.LoggedInCompactEmployee }; } Model.Employees = Model.Employees.OrderBy(e => e.LastName).ThenBy(e => e.FirstName).ToList(); if(Model.Employee?.EmployeeOid.HasValue ?? false) { Model.SupportConcepts = EmployeeService.GetActiveSupportConceptsForEmployee(Model.Employee.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(); } if(Model.SelectedConceptCostBearerRelations is null) { Model.SelectedConceptCostBearerRelations = new List(); } if(Model.MultiBookingSelectedConceptCostBearerRelations is null) { Model.MultiBookingSelectedConceptCostBearerRelations = new List(); } if(Model.SelectedEmployee is null) { Model.SelectedEmployee = MobileSessionFacade.LoggedInCompactEmployee; } var settingsValue = GetSettingValue(mandatorSettings, SettingsKeys.IsServiceRecordNoticeMandatory); Model.IsServiceRecordNoticeMandatory = settingsValue is null || !settingsValue.Equals("0"); var isInList = !(Model.SelectedCostBearer2SupportConceptRelListObject is null) && Model.SupportConceptListObjects.Contains(Model.SelectedCostBearer2SupportConceptRelListObject); if(Model.SelectedCostBearer2SupportConceptRelListObject is null || !isInList) { if(!(Model.SelectedCostBearer2SupportConceptRelListObject is null) && !isInList) { Log.Info($"Model.SelectedSupportConceptListObject.Oid = {Model.SelectedCostBearer2SupportConceptRelListObject.CostBearer2SupportConceptOid} 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.CostBearer2SupportConceptOid = -1; Model.HasAnyRatingTypes = AbstractModel.HasRightToRateGoals && OperationsService.GetAllRatingTypes().Any(); } if(!(Model.CostBearer2SupportConceptOid is null) && Model.CostBearer2SupportConceptOid != -1) { LoadPaginatedServiceRecordsToModel(Model.CurrentPage); } Model.IsEndDateVisible = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.IsEndDateVisible); if(Model.IsZeiterfassungInStdMin) { var letzteZeiterfassungsdauer = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.LetzteZeiterfassungsDauer); Model.IsShowingDurationInHours = letzteZeiterfassungsdauer == 1; } } catch(Exception e) { Log.Error(e.Message, e); } return View(Model); } [Authorize] private void InitializeInterval(string userSettings) { 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); } [Authorize] private void UpdateSettings(string key, string value) { if(Model is null) { return; } var loggedInUser = GetUser(); 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(); } #region Ziele und Maßnahmen [Authorize] public void LoadGoalRatings() { if(Model is null || !AbstractModel.HasRightToRateGoals) { return; } var ratingTypes = OperationsService.GetAllRatingTypes().OrderBy(o => o.Position); ; Model.GoalRatingTypes = ratingTypes.ToList(); } [Authorize] public string RateSelectedGoal(long? ratingTypeOid, long? goalOid) { if(Model is null || ratingTypeOid is null || goalOid is null || !AbstractModel.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); } } [Authorize] public 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.CostBearer2SupportConceptOid is null) { return; } var supportConcept = Model.SupportConcepts.FirstOrDefault(sc => sc.CostBearerRelations.Any(sc2Cb => sc2Cb.CostBearer2SupportConceptOid.HasValue && sc2Cb.CostBearer2SupportConceptOid.Value.Equals(Model.CostBearer2SupportConceptOid.Value))); if(supportConcept is null) { 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.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; } } #endregion [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"); } Model.TextModules.Clear(); if(Model.SelectedServiceCategoryOid.HasValue && (Model.Employee?.EmployeeOid.HasValue ?? false)) { var allTextModules = OperationsService.GetTextModules(AbstractModel.HasRightToSeeGlobalTextModules, Model.Employee.EmployeeOid.Value, AbstractModel.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.Employee.EmployeeOid) || !w.IsOnlyForEmployee)).OrderBy(t => t.Text).ToList(); x.AddRangeIfElementsNotIn(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) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } // Falls ein Termin in die Zeiterfassung übernommen werden soll AppointmentListItem appointmentListItemPrototype = null; if(TempData[TempDataConstants.AppointmentListItemKey] is AppointmentListItem appointmentListItem && Model.Employee.EmployeeOid.HasValue) { appointmentListItemPrototype = appointmentListItem; } 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])) { 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.CostBearer2SupportConceptOid < 1 ? null : Model.CostBearer2SupportConceptOid; 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) { 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.Employee.EmployeeOid.HasValue) { if(!Model.IsInEditingMode) { Model.NewServiceRecord.Employee = Model.SelectedEmployee ?? MobileSessionFacade.LoggedInCompactEmployee; } 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.Employee.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.LoggedInEmployee.FirstName} {MobileSessionFacade.LoggedInEmployee.LastName}"; 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.ServiceRecordOid = oidList[0]; if(Model.NewServiceRecord.CostBearer != null && Model.ShowSignature) { TempData[TempDataConstants.ShowSignatureSuggestionPopup] = true; } if(!(appointmentListItemPrototype is null)) { var appointment = appointmentListItemPrototype.SchedulerAppointment; var isRecurring = !(appointment.RecurrenceInfo is null); if(isRecurring && appointment.Type != (int) AppointmentType.ChangedOccurrence) { var id = appointment.RecurrenceIdReference; var recurrenceInfo = new RecurrenceInfo(); recurrenceInfo.FromXml(appointment.RecurrenceInfo); var occurrenceCalculator = OccurrenceCalculator.CreateInstance(recurrenceInfo); var pattern = StaticAppointmentFactory.CreateAppointment(AppointmentType.Pattern); pattern.RecurrenceInfo.FromXml(appointment.RecurrenceInfo); pattern.Start = pattern.RecurrenceInfo.Start; pattern.End = pattern.RecurrenceInfo.End; var occurrence = occurrenceCalculator.CalcOccurrences(new TimeInterval(appointment.StartDate.Value, appointment.EndDate.Value), pattern).FirstOrDefault(); if(!(occurrence is null)) { var index = occurrence.RecurrenceIndex; appointment = SchedulerController.CloneAppointment(appointment, $"", (int)AppointmentType.ChangedOccurrence); } else { appointment = null; } } if(!(appointment is null)) { var serviceRecord = OperationsService.GetServiceRecordById(Model.ServiceRecordOid); appointment.ServiceRecordList.AddIfNotIn(serviceRecord); if(appointment.SchedulerAppointmentOid.HasValue) { KalenderService.UpdateSchedulerAppointments(new List { appointment }); } else { KalenderService.InsertSchedulerAppointments(new List { appointment }); } } } } 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(TempData[TempDataConstants.AppointmentListItemKey] is AppointmentListItem appointmentListItem && Model.Employee.EmployeeOid.HasValue) { var appointment = appointmentListItem.SchedulerAppointment; 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.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(), GetUser().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.SelectedCostBearerSupportConceptRelOid = cb2ScOid; LoadSupportConceptThings(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 is null) { return; } if(Model.Categories2Descriptions is null) { Model.Categories2Descriptions = new Dictionary>(); } Model.Categories2Descriptions.Clear(); Model.SelectedServiceCategory = null; Model.SelectedServiceDescription = null; if(cb2ScOid is null && (Model.IsInGroupBookingMode || Model.IsInMultiBookingMode)) { 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.CostBearer2SupportConceptOid = cb2ScOid; Model.SelectedSupportConcept = Model.SupportConcepts.FirstOrDefault( supportConcept => supportConcept.CostBearerRelations.Any( supportConceptCostBearerRel => supportConceptCostBearerRel.CostBearer2SupportConceptOid.HasValue && supportConceptCostBearerRel.CostBearer2SupportConceptOid.Value.Equals(Model.CostBearer2SupportConceptOid))); if(Model.SelectedSupportConcept != null) { Model.SelectedCostBearer2SupportConceptRelListObject = Model.SupportConceptListObjects.First(f => long.Parse(f.CostBearer2SupportConceptOid) == cb2ScOid); var node = OperationsService.GetSupportConceptTreeNodeDetailInfo(Model.SelectedSupportConcept.Customer.CustomerOid, Model.SelectedSupportConcept.SupportConceptOid, Model.CostBearer2SupportConceptOid); 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.Equals(cb2ScOid.ToString())); 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|| Model.SelectedServiceDescription != null || Model.SelectedServiceCategory != null) { 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) { return; } var serviceDescription = firstServiceCategory2ServiceDescriptions.Value.OrderBy(sd => sd.Position).ThenBy(sd => sd.ServiceDescriptionOid).First(); Model.SelectedServiceDescription = serviceDescription; Model.SelectedServiceCategory = serviceDescription.Category; } 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 && MobileSessionFacade.LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.RightType.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 && MainModel.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(); } } ResetEditingMode(); return RedirectToActionPermanent("Main"); } [Authorize] public ActionResult ReloadGoalRatings() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return PartialView("GoalRatingPopupContentPartial"); } LoadGoalRatings(); 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); 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; 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.CostBearer2SupportConceptOid.HasValue && Model.CostBearer2SupportConceptOid != -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.SelectedGoals = selectedServiceRecord.Goals; var selectedServiceDescription = selectedServiceRecord.ServiceDescription; var selectedServiceCategory = selectedServiceDescription.Category; Model.SelectedServiceDescription = selectedServiceDescription; Model.SelectedServiceCategory = selectedServiceCategory; Model.PreviouslySelectedEmployee = Model.SelectedEmployee; Model.SelectedEmployee = selectedServiceRecord.Employee; Model.IsInEditingMode = true; Model.PreviouslySelectedSupportConcept = Model.SelectedSupportConcept; Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.CostBearer2SupportConceptOid; // Gruppenbuchung if(selectedServiceRecord.GroupOid.HasValue) { Model.IsInGroupBookingMode = true; Model.SelectedSupportConcept = null; Model.SelectedEmployee = null; var group = OperationsService.GetServiceRecordGroup(selectedServiceRecord.GroupOid.Value); var employees = group.ServiceRecordList.Select(serviceRecord => serviceRecord.Employee).Distinct().ToList(); Model.GroupBookingSelectedEmployees = employees; var cb2ScOids = group.ServiceRecordList.Where(w => w.CostBearer2SupportConceptOid.HasValue).Select(s => s.CostBearer2SupportConceptOid.Value).ToList(); Model.SelectedConceptCostBearerRelations.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptCostBearerRelDCsByOids(cb2ScOids)); var selectedSupportConcepts = new List(); selectedSupportConcepts.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptsById(group.ServiceRecordList.Select(s => s.SupportConcept.SupportConceptOid))); Model.GroupBookingSelectedSupportConcepts = selectedSupportConcepts; LoadServiceCategoriesToModel(null); Model.SelectedServiceDescription = selectedServiceDescription; Model.SelectedServiceCategory = selectedServiceCategory; LoadGoals(); } 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 ?? MobileSessionFacade.LoggedInCompactEmployee; // 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.CostBearer2SupportConceptOid))); if(supportConcept != null) { if(supportConcept.SupportConceptOid != null) { checkServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(supportConcept.SupportConceptOid.Value, Model.Employee.EmployeeOid); } checkServiceRecord.Customer = supportConcept.Customer; var cb2ScRel = supportConcept.CostBearerRelations.First(f => f.CostBearer2SupportConceptOid.HasValue && f.CostBearer2SupportConceptOid.Equals(Model.CostBearer2SupportConceptOid)); 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.CostBearer2SupportConceptOid; } } 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(MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowEditAfterMaxDaysInNextMonth)) { maxDaysEditSRsAllowed = -1; } SupportConceptStatisticsDC stats = null; if(Model.CostBearer2SupportConceptOid != null && Model.CostBearer2SupportConceptOid > 0) { stats = OperationsService.CreateSupportConceptStatistics(Model.CostBearer2SupportConceptOid.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.Add(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.Add(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.Add(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.Add(new ServiceRecord2Validation(prototype, multiBookingValidationResults, dateRangeString)); } } var allowOverlappingFls = MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreateOverlappingFLS); var allowOverlappingFlsForEmployee = MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreateOverlappingFLSForEmployee); var allowMoreFlsThanApproved = MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreateMoreFLSThanApproved); var bookAfterSettlementInvoice = MobileSessionFacade.CheckForUserRight(UserRightType.BookServiceRecordAfterSettlementInvoice); var bookServiceRecordOutOfSupportConcept = MobileSessionFacade.CheckForUserRight(UserRightType.BookServiceRecordOutOfSupportConcept); var allowCreateAfterEmployeeSignature = MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreateAfterEmployeeSignature); var allowEditAfterEmployeeSignature = MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowEditAfterEmployeeSignature); var allowCreateAll = MobileSessionFacade.CheckForUserRight(UserRightType.CreateAll); var allowEditAll = MobileSessionFacade.CheckForUserRight(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(!MobileSessionFacade.CheckForUserRight(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 Anliegen 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; } 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.Employee.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)); 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 AbstractModel.HasRightToViewQuittierungsbelege ? RedirectToActionPermanent("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(); } TempData[TempDataConstants.IsInTransferModeKey] = null; TempData[TempDataConstants.AppointmentListItemKey] = null; 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.PreviouslySelectedEmployee = Model.SelectedEmployee; Model.PreviouslySelectedSupportConcept = Model.SelectedSupportConcept; Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.CostBearer2SupportConceptOid; Model.SelectedSupportConcept = null; Model.CostBearer2SupportConceptOid = null; Model.SelectedEmployee = null; LoadServiceCategoriesToModel(null); Model.GroupBookingSelectedEmployees.AddIfNotIn(MobileSessionFacade.LoggedInCompactEmployee); Model.IsInEditingMode = false; Model.SelectedServiceRecord = null; } if(bookingMode == BookingMode.MultiBookingMode) { ResetGroupBookingMode(); Model.PreviouslySelectedEmployee = Model.SelectedEmployee; Model.PreviouslySelectedSupportConcept = Model.SelectedSupportConcept; Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.CostBearer2SupportConceptOid; Model.SelectedSupportConcept = null; Model.CostBearer2SupportConceptOid = null; Model.SelectedEmployee = null; LoadServiceCategoriesToModel(null); Model.MultiBookingSelectedEmployees.AddIfNotIn(MobileSessionFacade.LoggedInCompactEmployee); Model.IsInEditingMode = false; Model.SelectedServiceRecord = null; Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedEmployees.Clear(); Model.GroupBookingSelectedSupportConcepts.Clear(); Model.SelectedConceptCostBearerRelations.Clear(); } if(bookingMode == BookingMode.SingleBookingMode) { ResetMultiBookingMode(); Model.SelectedEmployee = Model.PreviouslySelectedEmployee ?? MobileSessionFacade.LoggedInCompactEmployee; if(Model.PreviouslySelectedSupportConcept is object) { Model.SelectedSupportConcept = Model.PreviouslySelectedSupportConcept; Model.CostBearer2SupportConceptOid = Model.PreviouslySelectedCostbearer2SupportConceptOid; } ResetGroupBookingMode(); } LoadSupportConceptThings(Model.CostBearer2SupportConceptOid); //LoadGoals(); } private void ResetMultiBookingMode() { Model.Categories2Descriptions.Clear(); Model.MultiBookingSelectedConceptCostBearerRelations.Clear(); Model.MultiBookingSelectedEmployees.Clear(); Model.MultiBookingSelectedGroupOfPeopleOids.Clear(); Model.MultiBookingSelectedCostbearerRelOids.Clear(); Model.MultiBookingSelectedSupportConcepts.Clear(); Model.MultiBookingSupportConceptListObjects.Clear(); } private void ResetGroupBookingMode() { Model.Categories2Descriptions.Clear(); Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedEmployees.Clear(); Model.GroupBookingSelectedSupportConcepts.Clear(); Model.SelectedConceptCostBearerRelations.Clear(); } [HttpPost] [Authorize] public ActionResult ResetSingleBookingForm() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } ResetBookingMode(BookingMode.SingleBookingMode); LoadServiceCategoriesToModel(Model.SelectedCostBearerSupportConceptRelOid); 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.PreviouslySelectedSupportConcept != null && Model.SelectedSupportConcept is null) { Model.SelectedSupportConcept = Model.PreviouslySelectedSupportConcept; Model.CostBearer2SupportConceptOid = Model.PreviouslySelectedCostbearer2SupportConceptOid; } ResetModel(); return View("Main", Model); } [HttpPost] [Authorize] public ActionResult ResetEditingMode() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } ResetModel(); return RedirectToActionPermanent("Main"); } [Authorize] [HttpPost] public ActionResult ResetTransferMode() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } ResetModel(); return RedirectToScheduler(); } [Authorize] private void ResetModel() { if(Model is null) { return; } TempData[TempDataConstants.AppointmentListItemKey] = null; TempData[TempDataConstants.IsInTransferModeKey] = null; TempData[TempDataConstants.AfterValidationStateKey] = null; Model.NewServiceRecord = new ServiceRecordDC(); Model.SelectedServiceRecord = null; Model.IsInEditingMode = false; Model.GroupBookingSelectedSupportConcepts.Clear(); Model.SelectedConceptCostBearerRelations.Clear(); Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedGroupOfPeopleOids.Clear(); Model.GroupBookingSelectedEmployees = new List { MobileSessionFacade.LoggedInCompactEmployee }; Model.SelectedEmployee = MobileSessionFacade.LoggedInCompactEmployee; Model.IsInMultiBookingMode = false; Model.MultiBookingSelectedCostbearerRelOids.Clear(); Model.MultiBookingSelectedEmployees.Clear(); Model.MultiBookingSelectedConceptCostBearerRelations.Clear(); Model.MultiBookingSelectedEmployees = new List { MobileSessionFacade.LoggedInCompactEmployee }; Model.MultiBookingSelectedGroupOfPeopleOids.Clear(); Model.MultiBookingSelectedSupportConcepts.Clear(); Model.SelectedGoals.Clear(); Model.SelectedServiceCategory = null; Model.SelectedServiceDescription = null; LoadServiceCategoriesToModel(Model.CostBearer2SupportConceptOid); } [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); } } 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; } 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(); 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); 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.CostBearer2SupportConceptOid = 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.CostBearer2SupportConceptOid < 1 ? null : Model.CostBearer2SupportConceptOid; // 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.Employee.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.Employee.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.LoggedInEmployee.FirstName} {MobileSessionFacade.LoggedInEmployee.LastName}"; 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 is null) && !(previousEndDate is null)) { 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; } [Authorize] public void LoadSupportConceptThings(long? cb2ScOid) { if(Model is null) { Logout(); return; } LoadServiceCategoriesToModel(cb2ScOid); LoadGoalRatings(); LoadGoals(); } /// /// Bereitet die Übernahme eines Termins in die Zeiterfassung vor. Wird im SchedulerController aufgerufen. /// /// [Authorize] public ActionResult PrepareServiceRecordInsert() { if(Model is null) { TempData[TempDataConstants.DoLogoutKey] = true; return Logout(); } if(TempData[TempDataConstants.AppointmentListItemKey] is AppointmentListItem appointmentListItem && Model.Employee.EmployeeOid.HasValue) { TempData[TempDataConstants.IsInTransferModeKey] = true; var appointment = appointmentListItem.SchedulerAppointment; 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.Employee.EmployeeOid.Value); } var notice = appointment.Description; var customerService = PluginLoader.FindClass(); var supportConcepts = customerService.GetAllActiveSupportConceptCostbearer(false, true, Model.Employee.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.Employee.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 => { if(long.TryParse(sclo.CostBearer2SupportConceptOid, out var costBearer2SupportConceptRelOid)) { availableRelOids.AddIfNotIn(costBearer2SupportConceptRelOid); } }); 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(); } } TempData[TempDataConstants.AppointmentListItemKey] = appointmentListItem; } 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(); } TempData[TempDataConstants.IsInTransferModeKey] = null; TempData[TempDataConstants.AppointmentListItemKey] = 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.CostBearer2SupportConceptOid < 1 ? null : Model.CostBearer2SupportConceptOid; 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.LoggedInEmployee.FirstName} {MobileSessionFacade.LoggedInEmployee.LastName}", 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() || MobileSessionFacade.LoggedInUserDC.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(MobileSessionFacade.LoggedInUser.Oid.Value, oldPassword, newPassword); if(!(checkResult is null)) { TempData[TempDataConstants.PwChErrKey] = checkResult; return RedirectToActionPermanent("Main"); } } var userName = MobileSessionFacade.LoggedInUserDC.LoginName; var userVersion = MobileSessionFacade.LoggedInUserDC.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.Employee.EmployeeOid.Value; // Ohne Hilfeplan if(Model.CostBearer2SupportConceptOid is null || Model.CostBearer2SupportConceptOid < 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.CostBearer2SupportConceptOid.Value, Model.SelectedZeitraum.StartDate.Value, Model.SelectedZeitraum.EndDate.Value, firstResult, Model.MaxResults, out totalServiceRecords) : OperationsService.FindServiceRecordsForLastDaysPaginated(Model.CostBearer2SupportConceptOid, Model.SelectedDayCount, Model.Employee?.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 = serviceRecordOids2GoalHeaders; Model.ServiceRecords = serviceRecords; } [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; } 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) { 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; } } }