using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; using System.Windows.Forms; using BeWo.Data.Entities; 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; 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 _Zieltypen = new List { ValueListEntryType.SupportConceptGoalCategoryType, ValueListEntryType.SupportConceptIndividualGoalCategoryType }; private static readonly List _Massnahmentypen = new List { ValueListEntryType.SupportConceptGoalType, ValueListEntryType.SupportConceptIndividualGoalType }; private MandatorDC GetMandator() { var mandator = (MandatorDC) HttpContext.Session["mandator"]; if(!(mandator is null)) { return mandator; } mandator = OperationsService.GetMandator(); HttpContext.Session["mandator"] = mandator; return mandator; } [Authorize] public ActionResult Main() { try { if(!MobileSessionFacade.IsUserLoggedIn() || Request.Browser.Browser.Equals("InternetExplorer")) { var isNewSession = Session.IsNewSession; if(isNewSession) { TempData["ein_schluessel"] = "Sie wurden automatisch abgemeldet, da Ihre Session abgelaufen ist."; } return Logout(); } if(Model.Mandator is null) { Model.Mandator = GetMandator(); 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["show_pw_change_popup"] = tempDataValue; } } 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.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); AbstractModel.ShowServiceRecordInsertedOn = !UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.HideServiceRecordInsertedByAndInsertedOn); Model.ShowSignature = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.ShowSignature) && AbstractModel.HasRightToProvideSingleSignature; #if DEBUG //Model.ShowSignature = true; #endif Model.GroupsOfPeople = EmployeeService.GetAllGroups(GetUser().Employee.EmployeeOid).OrderBy(gop => gop.Name).ToList(); if (!Model.IsInEditingMode) { Model.SelectedGoals.Clear(); } Model.ShowDistanceField = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.ShowDistanceFields); Model.Dokutypes = ValueListService.GetAllValueListEntrysByType(ValueListEntryType.DocumentType); if(!(Model.Dokutypes is 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().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); } 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 //if(!(Model?.SupportConcepts is null)) { 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.ServiceCategories is null) { Model.ServiceCategories = new List(); } 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; } Model.IsServiceRecordNoticeMandatory = UserSettingsUtils.GetSettingValueAsBool(mandatorSettings, SettingsKeys.IsServiceRecordNoticeMandatory); var isInList = !(Model.SelectedSupportConceptListObject is null) && Model.SupportConceptListObjects.Contains(Model.SelectedSupportConceptListObject); if(Model.SelectedSupportConceptListObject is null || !isInList) { if(!(Model.SelectedSupportConceptListObject is null) && !isInList) { Log.Info($"Model.SelectedSupportConceptListObject.Oid = {Model.SelectedSupportConceptListObject.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.SelectedSupportConceptListObject = 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) { LoadRecordsToModel(); } 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); } [Authorize] private void SaveServiceRecordTimeIntervalToSession(ServiceRecordTimeInterval serviceRecordTimeInterval) { if(Model is null) { return; } Session[SessionConstants.ServiceRecordTimeIntervalKey] = serviceRecordTimeInterval; } [Authorize] private ServiceRecordTimeInterval LoadServiceRecordTimeIntervalFromSession() { if(Model is null) { return ServiceRecordTimeInterval.LastWeek; } if(Session[SessionConstants.ServiceRecordTimeIntervalKey] is ServiceRecordTimeInterval serviceRecordTimeInterval) { return serviceRecordTimeInterval; } SaveServiceRecordTimeIntervalToSession(ServiceRecordTimeInterval.LastWeek); return ServiceRecordTimeInterval.LastWeek; } [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; } if(!Model.IsInGroupBookingMode) { var rating = Model.GoalRatingTypes.FirstOrDefault(ratingType => ratingType.RatingTypeOid == ratingTypeOid); var allGoals = GetAllGoalsForSelectedSupportConcept(); var goal = allGoals.FirstOrDefault(g => g.ValueListEntryOid?.Equals(goalOid.Value) ?? false); if(!(goal is null) && Model.SelectedGoals.Any(a => a.ValueListEntryOid.HasValue && a.ValueListEntryOid.Value == goal.ValueListEntryOid)) { 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)); } return null; } 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); } } [HttpPost] [Authorize] public ActionResult SetShowExpiredSupportConcepts(FormCollection pCollection) { if(Model is null) { return Logout(); } var newValue = "true,false" == pCollection[FormCollectionConstants.ShowExpiredSupportConceptsKey]; Model.ShowExpiredSupportConcepts = newValue; return UpdateApplicationSettings(SettingsKeys.ShowExpiredSupportConcepts, newValue ? "1" : "0"); } [HttpPost] public new ActionResult Logout() { return base.Logout(); } [Authorize] public void LoadGoals() { if((!Model.CostBearer2SupportConceptOid.HasValue || Model.CostBearer2SupportConceptOid.Value > 0) && Model.SelectedSupportConcept is null) { Logout(); } 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; var 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); } private List BuildGoalTree(IReadOnlyCollection goals) { var ziele = goals.Where(w => _Zieltypen.Contains(w.Type)).OrderBy(s => s.DisplayName).ToList(); var massnahmen = goals.Where(w => _Massnahmentypen.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.Where(z => z.ValueListEntryOid.HasValue)) { var treeItem = new GoalTreeItem { 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)) { 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 { Children = new List(), Header = ziel.DisplayName ?? string.Empty, IsLeaf = true, ValueListEntryOid = ziel.ValueListEntryOid, RatingName = ratingName}; 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) { if(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(!_ParentGoals.ContainsKey(parentDC.ValueListEntryOid.Value)) { _ParentGoals.Add(parentDC.ValueListEntryOid.Value, parentDC); if(parentDC.ParentOid != null) { pParentOid = parentDC.ParentOid.Value; continue; } } break; } } [Authorize] public string LoadStatistics(long oid) { try { if (Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var isLoaded = false; foreach(var supportConcept in Model.SupportConcepts) { if(supportConcept.CostBearerRelations.Any(supportConceptCostBearerRel => supportConceptCostBearerRel.CostBearer2SupportConceptOid == oid)) { isLoaded = true; } if(isLoaded) { break; } } if(!isLoaded) { return null; } var statisticsInfo = OperationsService.GetServiceRecordStatisticInfo(oid, DateTime.Now); var supportConceptStatisticsData = new SupportConceptStatisticsData(); if(statisticsInfo != null) { var count = 0; supportConceptStatisticsData.ShowDiagram = false; foreach(var period in statisticsInfo.PeriodStatisticInfos) { var statisticPeriod = new StatisticPeriod(); for(var i = 0; i < period.LeftValues.Length; i++) { var skipFirstHeader = count > 0 && i == 0; var left = period.LeftValues[i] ?? string.Empty; var right = period.RightValues[i] ?? string.Empty; var seperator = !string.IsNullOrWhiteSpace(left) && !string.IsNullOrWhiteSpace(right) ? "/" : string.Empty; var value = $"{left}{seperator}{right}"; var header = skipFirstHeader ? value : statisticsInfo.Header[i]; value = header == value ? string.Empty : value; statisticPeriod.Header2Values.AddIfNotIn(new Header2Values(header, value)); } supportConceptStatisticsData.StatisticPeriods.Add(statisticPeriod); count++; } } else { var supportConceptStatistics = OperationsService.CreateSupportConceptStatistics(oid, DateTime.Now); var provided = supportConceptStatistics.MinutesProvidedThisWeek / 60; var approved = supportConceptStatistics.MinutesApprovedPerWeek / 60; var freePerWeek = supportConceptStatistics.MinutesFreePerWeekAverage / 60; var providedTotal = supportConceptStatistics.MinutesProvidedTotalRounded / 60; var approvedTotal = supportConceptStatistics.MinutesApprovedTotal / 60; var freePerWeekTotal = (approvedTotal - providedTotal); decimal percentage = 0; if(approvedTotal > 0) { percentage = providedTotal / approvedTotal * 100; } if(percentage > 100) { percentage = 100; } supportConceptStatisticsData.Percentage = percentage; var statisticPeriod = new StatisticPeriod(); if(supportConceptStatistics.PeriodStatistics.Count != 1) { statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Bewilligungszeitraum:", "Gesamt")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Geleistet diese Woche/gesamt:", $"{provided:0.00}/{providedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Bewilligt pro Woche/gesamt:", $"{approved:0.00}/{approvedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Frei pro Woche(Ø)/gesamt:", $"{freePerWeek:0.00}/{freePerWeekTotal:0.00}")); supportConceptStatisticsData.StatisticPeriods.Add(statisticPeriod); } foreach(var periodStatistics in supportConceptStatistics.PeriodStatistics) { provided = periodStatistics.MinutesProvidedThisWeek / 60; approved = periodStatistics.MinutesApprovedPerWeek / 60; freePerWeek = periodStatistics.MinutesFreePerWeek / 60; providedTotal = periodStatistics.MinutesProvidedTotalRounded / 60; approvedTotal = periodStatistics.MinutesApprovedTotal / 60; freePerWeekTotal = (approvedTotal - providedTotal); var supportConceptApprovalPeriodSpan = periodStatistics.SupportConceptApprovalPeriod.Span; var minVal = DateTime.Now.AddYears(-50); var maxVal = DateTime.Now.AddYears(50); var sd = supportConceptApprovalPeriodSpan.StartDate; var ed = supportConceptApprovalPeriodSpan.EndDate; var start = sd > minVal && sd < maxVal ? $"{sd:dd.MM.yy} " : string.Empty; var end = ed > minVal && ed < maxVal ? $" {ed:dd.MM.yy}" : string.Empty; var span = $"{start}-{end}"; var serviceCategoryName = periodStatistics.SupportConceptApprovalPeriod.ServiceCategory != null ? periodStatistics.SupportConceptApprovalPeriod.ServiceCategory.Name + ":" : "Bewilligungszeitraum:"; statisticPeriod = new StatisticPeriod(); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values(serviceCategoryName, span)); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Geleistet diese Woche/gesamt:", $"{provided:0.00}/{providedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Bewilligt pro Woche/gesamt:", $"{approved:0.00}/{approvedTotal:0.00}")); statisticPeriod.Header2Values.AddIfNotIn(new Header2Values("Frei pro Woche(Ø)/gesamt:", $"{freePerWeek:0.00}/{freePerWeekTotal:0.00}")); supportConceptStatisticsData.StatisticPeriods.Add(statisticPeriod); } } return SerializeObject(supportConceptStatisticsData); } catch (Exception e) { Log.Error(e.Message, e); return SerializeObject("Fehler 560"); } } [Authorize] public string SaveUnterschrift(string blob, string timeStamp, long? serviceRecordOid) { try { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } using(var signatureBitmap = SignatureUtils.Base64StringToBitmap(blob.Split(',')[1])) { var isValid = SignatureUtils.ValidateSignature(signatureBitmap); if(!isValid) { return SerializeObject("Das Unterschriftenfeld darf nicht leer sein."); } var date = DateTime.Parse(timeStamp); OperationsService.InsertSignature(new SignatureDC { DataBild = blob, Zeitstempel = date, ServiceRecordOid = serviceRecordOid }); } return LeerzeichenFuerGetMethoden; } catch(Exception e) { Log.Error(e.Message, e); return SerializeObject("Fehler 540"); } } [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 LoadServiceCategories(long pServiceCategoryOid) { if (Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } try { var scm = Model.ServiceCategories.FirstOrDefault(s => s.ServiceCategoryOid.HasValue && s.ServiceCategoryOid.Value == pServiceCategoryOid); if (scm != null) { Model.SelectedServiceCategoryOid = scm.ServiceCategoryOid; } return SerializeObject(scm != null ? scm.ServiceDescriptions.OrderBy(serviceDescription => serviceDescription.Position).ToList() : new List()); } catch(Exception exception) { Debug.WriteLine(exception); throw; } } [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) { return Logout(); } 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) { return Logout(); } 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]; } 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 != null) { 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]; if(marker) { Model.NewServiceRecord.ServiceRecordType = ServiceRecordTypeId.Content; } 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() { 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["AppointmentListItem"] 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() { 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.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; 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) { foreach(var emp in Model.GroupBookingSelectedEmployees) { var key = emp.EmployeeOid + "_" + sc.SupportConceptOid; if(sc.CostBearerRelations != null && sc.CostBearerRelations.Count > 0) { var costBearer2SupportConceptOid = sc.CostBearerRelations.ElementAt(0).CostBearer2SupportConceptOid; if(costBearer2SupportConceptOid != null) { key += "_" + 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) { return Logout(); } long? cb2ScOid = Convert.ToInt64(formCollection[FormCollectionConstants.CostBearer2SupportConceptOidKey]); Log.Info($"SelectSupportConcept: {cb2ScOid}"); LoadSupportConceptThings(cb2ScOid); return ResetEditingMode(); } catch (Exception e) { Log.Error($"ERROR SelectSupportConcept: {e.Message}\n{e.StackTrace}"); throw; } } private void LoadServiceCategoriesToModel(long? cb2ScOid) { if (cb2ScOid is null) { Log.Info("cb2ScOid is null !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); } if (cb2ScOid is null && Model.IsInGroupBookingMode) { Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); return; } Model.CostBearer2SupportConceptOid = cb2ScOid; Model.SelectedSupportConcept = Model.SupportConcepts.FirstOrDefault( f => f.CostBearerRelations.Any( a => a.CostBearer2SupportConceptOid.HasValue && a.CostBearer2SupportConceptOid.Value.Equals(Model.CostBearer2SupportConceptOid))); if(Model.SelectedSupportConcept != null) { Model.SelectedSupportConceptListObject = Model.SupportConceptListObjects.First(f => long.Parse(f.CostBearer2SupportConceptOid) == cb2ScOid); var details = OperationsService.GetSupportConceptTreeNodeDetailInfo(Model.SelectedSupportConcept.Customer.CustomerOid, Model.SelectedSupportConcept.SupportConceptOid, Model.CostBearer2SupportConceptOid); Model.ServiceCategories = details.ServiceAccountings.Count > 0 ? CreateServiceCategoryModels(details.ServiceAccountings.Select(sa => sa.ServiceDescription).ToList()) : CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); Model.ServiceCategories = Model.ServiceCategories.Where(c => !c.OhneHilfeplan.HasValue || c.OhneHilfeplan.Value == AccountingvisibilityType.Beides || c.OhneHilfeplan.Value == AccountingvisibilityType.NurKlientenbezogen).ToList(); } else if(cb2ScOid == -2) { Model.SelectedSupportConceptListObject = Model.SupportConceptListObjects.First(f => f.CostBearer2SupportConceptOid.Equals(cb2ScOid.ToString())); Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); Model.ServiceCategories = Model.ServiceCategories.Where(c => !c.OhneHilfeplan.HasValue || c.OhneHilfeplan.Value == AccountingvisibilityType.Beides || c.OhneHilfeplan.Value == AccountingvisibilityType.NichtKlientenbezogen).ToList(); } else if(cb2ScOid == -1) { Model.SelectedSupportConceptListObject = Model.SupportConceptListObjects.First(f => f.CostBearer2SupportConceptOid.Equals(cb2ScOid.ToString())); Model.ServiceCategories.Clear(); } else { Log.Info("Model.SelectedSupportConcept is null !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); } if (Model.SelectedSupportConceptListObject is null || Model.SelectedSupportConceptListObject.CostBearer2SupportConceptOid == "-1") { Log.Info($"LoadServiceCategoriesToModel() Model.SelectedSupportConceptListObject is null {Model.SelectedSupportConceptListObject is null}, Model.SelectedSupportConceptListObject.CostBearer2SupportConceptOid == {Model.SelectedSupportConceptListObject?.CostBearer2SupportConceptOid}"); } if (Model.ServiceCategories != null) { Model.ServiceCategories = Model.ServiceCategories.OrderBy(serviceCategory => serviceCategory.Position).ToList(); } } [HttpPost] [Authorize] public ActionResult DeleteServiceRecord(FormCollection formCollection) { if (Model is null) { 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 string UpdateGoals(string pGoalOids) { if (Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var sc = Model.SelectedSupportConcept; if (sc is null) { return LeerzeichenFuerGetMethoden; } if(string.IsNullOrEmpty(pGoalOids)) { Model.SelectedGoals.Clear(); return LeerzeichenFuerGetMethoden; } var splitOids = pGoalOids.Trim(';').Split(';'); var selectedGoalOids = splitOids.Select(long.Parse).ToList(); var 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(); // ToDo: Hier liegt der Bug! // ToDo: vorhandene Bewertungen beachten! var stillSelectedGoals = Model.SelectedGoals.Where(s => goals.Any(a => a.ValueListEntryOid.HasValue && a.ValueListEntryOid.Value == s.ValueListEntryOid)).ToList(); Model.SelectedGoals = stillSelectedGoals; Model.SelectedGoals.AddRangeIfElementsNotIn(goals); //Model.SelectedGoals = goals; return LeerzeichenFuerGetMethoden; } [Authorize] public string SetServiceDescription(long pServiceDescriptionOid) { if (Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } Model.SelectedServiceDescriptionOid = pServiceDescriptionOid; return LeerzeichenFuerGetMethoden; } [HttpPost] [Authorize] public ActionResult LoadServiceRecords(FormCollection formCollection) { if(Model is null) { 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"); } 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(); 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()); } private void LoadRecordsToModel() { if(Model?.Employee?.EmployeeOid is null) { Logout(); return; } Model.ServiceRecords = new List(); if(Model.CostBearer2SupportConceptOid.HasValue && Model.CostBearer2SupportConceptOid.Value == -1) { return; } var records = new List(); if(Model.SelectedZeitraum?.StartDate is null || Model.SelectedZeitraum.EndDate is null) { Model.SelectedZeitraum = new NullableDateTimeSpan(DateTime.Today.GetFirstOfMonth(), DateTime.Today); } var selectedDayCount = (long?) (Model.SelectedDayCount == 0 ? null : (int?) Model.SelectedDayCount); // 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.GetEmployeesServiceRecordsWithStartEndDate(Model.Employee.EmployeeOid.Value, Model.SelectedZeitraum.StartDate.Value, Model.SelectedZeitraum.EndDate.Value).ToList() : OperationsService.GetEmployeesServiceRecords2(Model.Employee.EmployeeOid.Value, selectedDayCount).ToList(); } else { records = Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen || Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.Monatsauswahl ? //Zeitraum oder Monat gewählt OperationsService.GetCustomerServiceRecordsWithStartEndDate(Model.SelectedSupportConcept.Customer.CustomerOid, Model.CostBearer2SupportConceptOid.Value, Model.SelectedZeitraum.StartDate.Value, Model.SelectedZeitraum.EndDate.Value) : OperationsService.FindServiceRecordsForLastDays(Model.CostBearer2SupportConceptOid, Model.SelectedDayCount, Model.Employee.EmployeeOid.Value).ToList(); } 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); } Model.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(); } [HttpPost] [Authorize] public ActionResult SelectRecordToEdit(FormCollection formCollection) { if(Model is null) { 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; Model.SelectedServiceDescriptionOid = selectedServiceRecord.ServiceDescription.ServiceDescriptionOid; Model.SelectedServiceCategoryOid = selectedServiceRecord.ServiceDescription.Category.ServiceCategoryOid; Model.PreviouslySelectedEmployee = Model.SelectedEmployee; Model.SelectedEmployee = selectedServiceRecord.Employee; Model.IsInEditingMode = true; Model.PreviouslySelectedSupportConcept = Model.SelectedSupportConcept; if (selectedServiceRecord.GroupOid.HasValue) { Model.IsInGroupBookingMode = true; Model.SelectedSupportConcept = null; Model.SelectedEmployee = null; Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); 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; } 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] public string CheckRights(string von, string bis, bool inEditMode, string dateString, string startString, string endString) { if (Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } Log.Info($"CheckRights: von:{von};bis:{bis};inEditMode:{inEditMode};dateString:{dateString};startString:{startString};endString:{endString}"); var startHoursDt = ConvertTimeStringToDateTime(startString); var endHoursDt = ConvertTimeStringToDateTime(endString); 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); if (startDt > endDt) { return "StartGreaterEnd"; } var dauer = (int)(endDt - startDt).TotalMinutes; if (dauer == 0) { 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.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; if (Model.SelectedEmployee != null && !Model.IsInGroupBookingMode && !Model.IsInMultiBookingMode) { var sc = Model.SupportConcepts.FirstOrDefault(fod => fod.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && a.CostBearer2SupportConceptOid.Value.Equals(Model.CostBearer2SupportConceptOid))); if (sc != null) { if (sc.SupportConceptOid != null) { checkServiceRecord.SupportConcept = CustomerService.LoadCompactSupportConceptDC(sc.SupportConceptOid.Value, Model.Employee.EmployeeOid); } checkServiceRecord.Customer = sc.Customer; var cb2ScRel = sc.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 = GetMandator(); 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; 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; 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; 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)); } } } 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.ValidateServiceRecordEntry(checkServiceRecord, stats, maxDaysEditSRsAllowed, checkServiceRecord.GroupOid.HasValue, employeeOids); validationResults.Add(new ServiceRecord2Validation(checkServiceRecord, result, dateRangeString ?? "")); } 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 + "' 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 + " existiert bereits ein Eintrag von " + vr.EmployeeName + " (" + vr.Message + ").

"; newResult.KannTrotzdemGespeichertWerden = allowOverlappingFLSForEmployee; exitLoop = !allowOverlappingFLSForEmployee; break; case OutsideOfSupportConcept: newResult.Message += "Das gewählte Datum " + von.Substring(0, 10) + " 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"; } newResult.Message += "Sie können keine neuen Leistungen für den " + von + " dokumentieren, da die Zeiterfassung innerhalb von " + intervall + " erfolgen muss.

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

"; exitLoop = true; newResult.KannTrotzdemGespeichertWerden = vr.Allow; break; case SignatureExists: newResult.Message += vr.Message + "

"; 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 ? "
Möchten Sie trotzdem speichern?

" : "
Speichern nicht möglich.

"; } Model.NewServiceRecord = new ServiceRecordDC(); return SerializeObject(newResult); } [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 allowDeleteAfterEmployeeSignature = MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowDeleteAfterEmployeeSignature); var allowDeleteAll = MobileSessionFacade.CheckForUserRight(UserRightType.CreateAll); 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 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; } // 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(); } // Gruppenbuchungen [HttpPost] [Authorize] public ActionResult SetGroupBookingMode(FormCollection pFormCollection) { if (Model is null) { 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.SelectedSupportConcept = null; Model.SelectedEmployee = null; Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); 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.SelectedSupportConcept = null; Model.SelectedEmployee = null; Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); 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; Model.SelectedSupportConcept = Model.PreviouslySelectedSupportConcept; ResetGroupBookingMode(); if (Model.SelectedSupportConcept != null) { var details = OperationsService.GetSupportConceptTreeNodeDetailInfo(Model.SelectedSupportConcept.Customer.CustomerOid, Model.SelectedSupportConcept.SupportConceptOid, Model.CostBearer2SupportConceptOid); Model.ServiceCategories = details.ServiceAccountings.Count > 0 ? CreateServiceCategoryModels(details.ServiceAccountings.Select(sa => sa.ServiceDescription).ToList()) : CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); Model.ServiceCategories = Model.ServiceCategories.Where(c => !c.OhneHilfeplan.HasValue || c.OhneHilfeplan.Value == AccountingvisibilityType.Beides || c.OhneHilfeplan.Value == AccountingvisibilityType.NurKlientenbezogen).ToList(); } else if (Model.CostBearer2SupportConceptOid == -2) { Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); Model.ServiceCategories = Model.ServiceCategories.Where(c => !c.OhneHilfeplan.HasValue || c.OhneHilfeplan.Value == AccountingvisibilityType.Beides || c.OhneHilfeplan.Value == AccountingvisibilityType.NichtKlientenbezogen).ToList(); } } } private void ResetMultiBookingMode() { Model.ServiceCategories.Clear(); Model.MultiBookingSelectedConceptCostBearerRelations.Clear(); Model.MultiBookingSelectedEmployees.Clear(); Model.MultiBookingSelectedGroupOfPeopleOids.Clear(); Model.MultiBookingSelectedCostbearerRelOids.Clear(); Model.MultiBookingSelectedSupportConcepts.Clear(); Model.MultiBookingSupportConceptListObjects.Clear(); } private void ResetGroupBookingMode() { Model.ServiceCategories.Clear(); Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedEmployees.Clear(); Model.GroupBookingSelectedSupportConcepts.Clear(); Model.SelectedConceptCostBearerRelations.Clear(); } [HttpPost] [Authorize] public ActionResult ResetEditingMode() { if(Model is null) { return Logout(); } ResetModel(); return RedirectToActionPermanent("Main"); } [Authorize] [HttpPost] public ActionResult ResetTransferMode() { if(Model is null) { return Logout(); } ResetModel(); return RedirectToScheduler(); } [Authorize] private void ResetModel() { if(Model is null) { return; } TempData[TempDataConstants.AppointmentListItemKey] = null; TempData[TempDataConstants.IsInTransferModeKey] = 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(); LoadServiceCategoriesToModel(Model.CostBearer2SupportConceptOid); var serviceDescriptions = Model.GetServiceDesctiptions(); if(!Model.ServiceCategories.Any() || !serviceDescriptions.Any()) { return; } var firstServiceDescription = serviceDescriptions.First(); Model.SelectedServiceDescriptionOid = firstServiceDescription.ServiceDescriptionOid; Model.SelectedServiceCategoryOid = firstServiceDescription.Category.ServiceCategoryOid; } [Authorize] public string AddSupportConceptCostBearerRelationsToGroupBooking(string pRelOids, string pGroupOids) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var rawRelOids = string.IsNullOrEmpty(pRelOids) ? new string[0] : pRelOids.Split(','); var rawGroupOids = string.IsNullOrEmpty(pGroupOids) ? new string[0] : pGroupOids.Split(','); var relOids = new List(); var groups = new List(); rawRelOids.DoForEach(s => relOids.AddIfNotIn(long.Parse(s))); Model.GroupBookingSelectedGroupOfPeopleOids.Clear(); rawGroupOids.DoForEach(s => { var group = Model.GroupsOfPeople.FirstOrDefault(f => f.GroupOfPeopleOid.HasValue && f.GroupOfPeopleOid.Value.Equals(long.Parse(s))); if(group is null) { return; } groups.AddIfNotIn(group); group.SupportConceptList.DoForEach(f => relOids.AddRangeIfElementsNotIn(f.CostBearerRelOids)); }); Model.GroupBookingSelectedSupportConcepts.Clear(); Model.GroupBookingSelectedCostbearerRelOids.Clear(); Model.GroupBookingSelectedCostbearerRelOids.AddRangeIfElementsNotIn(relOids); var selectedSupportConcepts = Model.SupportConcepts.Where(w => w != null && w.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && relOids.Contains(a.CostBearer2SupportConceptOid.Value))).ToList(); var groupCostBearerRelations = CustomerService.GetSupportConceptCostBearerRelationsById(relOids); 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(relOids.ContainsItems(groupRelOids)) { Model.GroupBookingSelectedGroupOfPeopleOids.AddIfNotIn(groupOid); } else if(Model.GroupBookingSelectedGroupOfPeopleOids.Contains(groupOid)) { Model.GroupBookingSelectedGroupOfPeopleOids.Remove(groupOid); } } return SerializeObject(Model.GroupBookingSelectionObject); } [Authorize] public string RemoveSupportConceptCostBearerRelationFromGroupBooking(string pRelOid) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } long.TryParse(pRelOid, out var supportConceptCostBearerRelationOid); var supportConcept = Model.GroupBookingSelectedSupportConcepts.FirstOrDefault(f => f.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid)); var relation = Model.SelectedConceptCostBearerRelations.FirstOrDefault(f => f.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid); Model.GroupBookingSelectedSupportConcepts.Remove(supportConcept); Model.SelectedConceptCostBearerRelations.Remove(relation); 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(); return SerializeObject(Model.GroupBookingSelectionObject); } [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) { 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) { return Logout(); } try { if(!Model.IsInEditingMode) { if(Model.SelectedConceptCostBearerRelations.Count == 1) { var cb2ScOids = (from scDc in Model.GroupBookingSelectedSupportConcepts where scDc.CostBearerRelations != null && scDc.CostBearerRelations.Count > 0 let costBearer2SupportConceptOid = scDc.CostBearerRelations[0].CostBearer2SupportConceptOid where costBearer2SupportConceptOid != null select costBearer2SupportConceptOid.Value).ToList(); var cb2ScOidsCount = cb2ScOids.Count; if(cb2ScOidsCount == 1) { Model.CostBearer2SupportConceptOid = cb2ScOids[0]; } else { return RedirectToActionPermanent("Main"); } } } 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); } var marker = "on" == formCollection[FormCollectionConstants.MarkerKey]; 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 != null) { 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); } // Wenn die Dauer in Stunden ist if(Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1) { dauer *= 60m; } var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key]; var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key]; var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key]; var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key]; 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]; if(marker) { Model.NewServiceRecord.ServiceRecordType = ServiceRecordTypeId.Content; } Model.NewServiceRecord.DistanceInMeterDecimal = distanceInMeters; if(Model.Employee.EmployeeOid.HasValue) { 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(selectedCostbearer2SupportConceptRelOid))); 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(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); //LoadRecordsToModel(); LoadGoalRatings(); LoadGoals(); } /// /// Bereitet die Übernahme eines Termins in die Zeiterfassung vor. Wird im SchedulerController aufgerufen. /// /// [Authorize] public ActionResult PrepareServiceRecordInsert() { if(Model is null) { 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); var serviceCategory = Model.ServiceCategories.FirstOrDefault(); var serviceDescription = serviceCategory?.ServiceDescriptions.FirstOrDefault(); if(!(serviceDescription is null)) { Model.SelectedServiceCategoryOid = serviceDescription.Category.ServiceCategoryOid; var serviceRecord = CreateServiceRecordFromScratch(start.Value, end.Value, null, Model.SelectedEmployee, notice); serviceRecord.ServiceDescription = serviceDescription; Model.SelectedServiceRecord = serviceRecord; } } // Einzelbuchung else 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(); LoadSupportConceptThings(costBearer2SupportConcept?.CostBearer2SupportConceptOid ?? -2); var serviceCategory = Model.ServiceCategories.FirstOrDefault(); var serviceDescription = serviceCategory?.ServiceDescriptions.FirstOrDefault(); serviceRecord.CostBearer = costBearer2SupportConcept?.CostBearer; serviceRecord.CostBearer2SupportConceptOid = costBearer2SupportConcept?.CostBearer2SupportConceptOid; serviceRecord.ServiceDescription = serviceDescription; if(!(serviceDescription is 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.ServiceCategories.FirstOrDefault()?.ServiceDescriptions.FirstOrDefault() }; 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(); 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; } } 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) { 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] [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]; 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 != null) { 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) }; 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 AddSupportConceptCostBearerRelationsToMultiBooking(string pRelOids, string pGroupOids) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } var rawRelOids = string.IsNullOrEmpty(pRelOids) ? Array.Empty() : pRelOids.Split(','); var rawGroupOids = string.IsNullOrEmpty(pGroupOids) ? Array.Empty() : pGroupOids.Split(','); var relOids = new List(); var groups = new List(); rawRelOids.DoForEach(s => relOids.AddIfNotIn(long.Parse(s))); Model.MultiBookingSelectedGroupOfPeopleOids.Clear(); rawGroupOids.DoForEach(s => { var group = Model.GroupsOfPeople.FirstOrDefault(f => f.GroupOfPeopleOid.HasValue && f.GroupOfPeopleOid.Value.Equals(long.Parse(s))); if(group is null) { return; } groups.AddIfNotIn(group); group.SupportConceptList.DoForEach(f => relOids.AddRangeIfElementsNotIn(f.CostBearerRelOids)); }); Model.MultiBookingSelectedSupportConcepts.Clear(); Model.MultiBookingSelectedCostbearerRelOids.Clear(); Model.MultiBookingSelectedCostbearerRelOids.AddRangeIfElementsNotIn(relOids); var selectedSupportConcepts = Model.SupportConcepts.Where(w => w != null && w.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid.HasValue && relOids.Contains(a.CostBearer2SupportConceptOid.Value))).ToList(); var multiBookingCostBearerRelations = CustomerService.GetSupportConceptCostBearerRelationsById(relOids); Model.MultiBookingSelectedConceptCostBearerRelations.Clear(); Model.MultiBookingSelectedConceptCostBearerRelations.AddRangeIfElementsNotIn(multiBookingCostBearerRelations); 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(relOids.ContainsItems(groupRelOids)) { Model.MultiBookingSelectedGroupOfPeopleOids.AddIfNotIn(groupOid); } else if(Model.MultiBookingSelectedGroupOfPeopleOids.Contains(groupOid)) { Model.MultiBookingSelectedGroupOfPeopleOids.Remove(groupOid); } } return SerializeObject(Model.MultiBookingSelectionObject); } [Authorize] public string RemoveSupportConceptCostBearerRelationFromMultiBooking(string pRelOid) { if(Model is null) { Logout(); return LeerzeichenFuerGetMethoden; } long.TryParse(pRelOid, out var supportConceptCostBearerRelationOid); var supportConcept = Model.MultiBookingSelectedSupportConcepts.FirstOrDefault(f => f.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid)); var relation = Model.MultiBookingSelectedConceptCostBearerRelations.FirstOrDefault(f => f.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid); Model.MultiBookingSelectedSupportConcepts.Remove(supportConcept); Model.MultiBookingSelectedConceptCostBearerRelations.Remove(relation); 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(); return SerializeObject(Model.MultiBookingSelectionObject); } [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); } [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) { return Logout(); } var oldPassword = formCollection["old-password"]; var newPassword = formCollection["new-password"]; var passwordConfirmation = formCollection["confirm-new-password"]; if(false == newPassword.Equals(passwordConfirmation)) { TempData["passwd-change-error"] = "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["passwd-change-error"] = checkResult; return RedirectToActionPermanent("Main"); } } var userName = MobileSessionFacade.LoggedInUserDC.LoginName; var userVersion = MobileSessionFacade.LoggedInUserDC.UserVersion.Value; UserService.ChangePassword(userName, userVersion, oldPassword, newPassword); return RedirectToActionPermanent("Main"); } [Authorize] public string ProvokeJsonError() { return "lkasdjf lkjasdlkf jjasldfljk ajksldf "; } } public class ServiceRecord2Monatsunterschrift { public ServiceRecordDC ServiceRecord { get; } public bool HasMonatsunterschrift { get; } public ServiceRecord2Monatsunterschrift(ServiceRecordDC serviceRecord, bool hasMonatsunterschrift) { ServiceRecord = serviceRecord; HasMonatsunterschrift = hasMonatsunterschrift; } } }