using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Web.Mvc; using System.Windows.Forms; 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 Newtonsoft.Json; using static BS.Shared.ServiceRecordValidationResult; using FormCollection = System.Web.Mvc.FormCollection; 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 == 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 == null) { mandator = OperationsService.GetMandator(); HttpContext.Session["mandator"] = mandator; } return mandator; } [Authorize] public ActionResult Main() { try { if(!MobileSessionFacade.IsUserLoggedIn() || Request.Browser.Browser.Equals("InternetExplorer") || !AbstractModel.HasRightToSeeServiceRecords) { var isNewSession = Session.IsNewSession; if(isNewSession) { TempData["ein_schluessel"] = "Sie wurden automatisch abgemeldet, da Ihre Session abgelaufen ist."; } return Logout(); } Model.ShowExpiredSupportConcepts = GetUserSettingValue("ShowExpiredSupportConcepts") == "1"; Model.ShowOnlyOwnSupportConcepts = GetUserSettingValue("ShowOnlyMySupportConcepts") == "1"; var customerFilterRaw = GetUserSettingValue("CustomerFilterInZeiterfassung"); if(!Enum.TryParse(customerFilterRaw, out CustomerFilterEnum customerFilter)) { customerFilter = CustomerFilterEnum.MyCustomer; } Model.SelectedSupportConceptFilter = customerFilter; var mandator = GetMandator(); var supportConceptExpirationLimitInMonths = GetSettingValue(mandator.Settings, "HilfeplanAuslaufAuswahl"); var anzTageZeiterfassErfolgt = GetSettingValue(mandator.Settings, "AnzTageZeiterfassErfolgt"); var maxDaysEditServiceRecordsAllowed = GetSettingValue(mandator.Settings, "MaxDaysEditServiceRecordsAllowed"); BS.Shared.Settings.ApplicationSettings.SupportConceptExpirationLimitInMonths = supportConceptExpirationLimitInMonths == null ? 3 : int.Parse(supportConceptExpirationLimitInMonths); BS.Shared.Settings.ApplicationSettings.AnzTageZeiterfassErfolgt = anzTageZeiterfassErfolgt == null ? 0 : int.Parse(anzTageZeiterfassErfolgt); BS.Shared.Settings.ApplicationSettings.MaxDaysEditServiceRecordsAllowed = maxDaysEditServiceRecordsAllowed == null ? 0 : int.Parse(maxDaysEditServiceRecordsAllowed); var timeUntilUILock = GetSettingValue(mandator.Settings, "TimeUntilUILock"); BS.Shared.Settings.ApplicationSettings.TimeUntilUILock = timeUntilUILock == null ? 0 : int.Parse(timeUntilUILock); var unter = GetSettingValue(mandator.Settings, "ShowSignature"); Model.ShowSignature = unter == "1"; #if DEBUG Model.ShowSignature = true; #endif Model.GroupsOfPeople = EmployeeService.GetAllGroups(GetUser().Employee.EmployeeOid); if (!Model.IsInEditingMode) { Model.SelectedGoals.Clear(); } Model.ShowDistanceField = "1" == GetSettingValue(mandator.Settings, "ShowDistanceFields"); Model.Dokutypes = ValueListService.GetAllValueListEntrysByType(ValueListEntryType.DocumentType); if (Model.Dokutypes != null) { Model.Dokutypes = Model.Dokutypes.OrderBy(s => s.ValueListEntryOid).ToArray(); } if(MainModel.AllEmployees == null) { MainModel.AllEmployees = EmployeeService.GetAllActiveEmployeesCompact().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 }; } if(Model?.Employee?.EmployeeOid.HasValue ?? false) { Model.SupportConcepts = EmployeeService.GetActiveSupportConceptsForEmployee(Model.Employee.EmployeeOid, Model.SelectedSupportConceptFilter); } else { Model.SupportConcepts = new List(); } if(!Model.ShowExpiredSupportConcepts) { Model.SupportConcepts = Model.SupportConcepts.Where(supportConcept => { var endDate = MainModel.GetEndDateOfSupportConcept(supportConcept); return endDate == null || endDate.Value >= DateTime.Now.Date; }).ToList(); } if(Model.ServiceCategories == null) { Model.ServiceCategories = new List(); } if(Model.SelectedConceptCostBearerRelations == null) { Model.SelectedConceptCostBearerRelations = new List(); } if (Model.SelectedEmployee == null) { Model.SelectedEmployee = MobileSessionFacade.LoggedInCompactEmployee; } var isServiceRecordNoticeMandatorySetting = GetSettingValue(mandator.Settings, "IsServiceRecordNoticeMandatory"); if (isServiceRecordNoticeMandatorySetting != null && isServiceRecordNoticeMandatorySetting == "0") { Model.IsServiceRecordNoticeMandatory = false; } else { Model.IsServiceRecordNoticeMandatory = true; } var isInList = Model.SelectedSupportConceptListObject != null && Model.SupportConceptListObjects.Contains(Model.SelectedSupportConceptListObject); if(Model.SelectedSupportConceptListObject == null || !isInList) { Model.SelectedSupportConceptListObject = Model.SupportConceptListObjects.FirstOrDefault(f => f.CostBearer2SupportConceptOid == "-1") ?? Model.SupportConceptListObjects.First(); Model.CostBearer2SupportConceptOid = -1; } if(Model.CostBearer2SupportConceptOid != null) { LoadRecordsToModel(); } var endtime = GetSettingValue(mandator.Settings, "IsEndDateVisible"); Model.IsEndDateVisible = Equals(endtime, "1"); var isDurationMinHoursSwitchableSetting = GetSettingValue(mandator.Settings, "IsZeiterfassungInStdMin"); Model.IsZeiterfassungInStdMin = Equals(isDurationMinHoursSwitchableSetting, "1"); } catch (Exception e) { Log.Error(e.Message, e); } return View(Model); } [HttpPost] [Authorize] public ActionResult SetShowExpiredSupportConcepts(FormCollection pCollection) { if (Model == null) { return Logout(); } var newValue = "true,false" == pCollection[FormCollectionConstants.ShowExpiredSupportConceptsKey]; Model.ShowExpiredSupportConcepts = newValue; return UpdateSettings("ShowExpiredSupportConcepts", newValue ? "1" : "0"); } [Authorize] public ActionResult UpdateSettings(string pKey, string pValue) { if (Model == null) { return Logout(); } var userSettings = GetUser().Settings; UserSettingsUtils.SetSettingValue(SettingsType.ApplicationSettings, pKey, pValue, userSettings); UserService.UpdateUserSettings(GetUser().UserOid.Value, userSettings); return RedirectToAction("Main"); } [HttpPost] public new ActionResult Logout() { return base.Logout(); } [Authorize] public string LoadGoalTreeItems() { if (!Model.CostBearer2SupportConceptOid.HasValue || Model.CostBearer2SupportConceptOid.Value > 0 || Model.SelectedSupportConcept == null) { return null; } var goals = Model.SelectedSupportConcept.Goals; var missingParentElements = goals.Where(w => w.ParentOid.HasValue && !goals.Any(a => a.ValueListEntryOid.Equals(w.ParentOid))).Select(s => s.ParentOid).ToList(); _ParentGoals = new Dictionary(); foreach (var oid in missingParentElements) { LoadMissingParents(oid.Value); } goals.AddRangeIfElementsNotIn(_ParentGoals.Values); var ziele = goals.Where(w => _Zieltypen.Contains(w.Type)).OrderBy(s => s.TypeDescription).ToList(); var massnahmen = goals.Where(w => _Massnahmentypen.Contains(w.Type)).OrderBy(s => s.TypeDescription).ToList(); var parentItems = goals.Where(w => w.ValueListEntryOid.HasValue && goals.Any(a => a.ParentOid.HasValue && a.ParentOid.Equals(w.ValueListEntryOid))).ToList(); var goalTree = new List(); var goalTreeDic = new Dictionary(); foreach (var ziel in ziele.Where(ziel => ziel.ValueListEntryOid.HasValue)) { var treeItem = new BootstrapTreeViewItem(ziel.TypeDescription, ziel.ParentOid, ziel.ValueListEntryOid.Value, parentItems.Contains(ziel)); goalTreeDic.Add(ziel.ValueListEntryOid.Value, treeItem); if (ziel.ParentOid == null) { goalTree.Add(treeItem); } } foreach (var zielMitEltern in goalTreeDic.Values.Where(w => w.ParentOid != null)) { goalTreeDic[zielMitEltern.ParentOid.Value].Nodes.Add(zielMitEltern); } foreach (var ziel in massnahmen) { var node = new BootstrapTreeViewItem(ziel.TypeDescription, ziel.ParentOid, ziel.ValueListEntryOid.Value, parentItems.Contains(ziel)); if (ziel.ParentOid != null && goalTreeDic.ContainsKey(ziel.ParentOid.Value)) { node.ParentOid = goalTreeDic[ziel.ParentOid.Value].ParentOid; goalTreeDic[ziel.ParentOid.Value].Nodes.Add(node); } } return JsonConvert.SerializeObject(goalTree, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); } [Authorize] public string LoadGoals() { if((!Model.CostBearer2SupportConceptOid.HasValue || Model.CostBearer2SupportConceptOid.Value > 0) && Model.SelectedSupportConcept == null) { Logout(); return null; } var supportConcept = Model.SupportConcepts.FirstOrDefault(sc => sc.CostBearerRelations.Any(sc2Cb => sc2Cb.CostBearer2SupportConceptOid.HasValue && sc2Cb.CostBearer2SupportConceptOid.Value.Equals(Model.CostBearer2SupportConceptOid.Value))); if (supportConcept == null) { return null; } 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) { LoadMissingParents(oid.Value); } var goalTree = BuildGoalTree(selectedGoals.Union(_ParentGoals.Values).ToList()); return SerializeObject(goalTree); } private static List BuildGoalTree(IReadOnlyCollection goals) { var ziele = goals.Where(w => _Zieltypen.Contains(w.Type)).OrderBy(s => s.TypeDescription).ToList(); var massnahmen = goals.Where(w => _Massnahmentypen.Contains(w.Type)).OrderBy(s => s.TypeDescription).ToList(); var goalTree = new List(); var goalTreeDic = new Dictionary(); foreach(var ziel in ziele) { var treeItem = new GoalTreeItem { Children = new List(), Header = ziel.TypeDescription, ParentOid = ziel.ParentOid, ValueListEntryOid = ziel.ValueListEntryOid }; goalTreeDic.Add(ziel.ValueListEntryOid.Value, treeItem); if(ziel.ParentOid == null) { goalTree.Add(treeItem); } } foreach(var zielMitEltern in goalTreeDic.Values.Where(w => w.ParentOid != null)) { goalTreeDic[zielMitEltern.ParentOid.Value].Children.Add(zielMitEltern); } foreach(var ziel in massnahmen) { var kind = new GoalTreeItem { Children = new List(), Header = ziel.TypeDescription, IsLeaf = true, ValueListEntryOid = ziel.ValueListEntryOid }; if(ziel.ParentOid != null && goalTreeDic.ContainsKey(ziel.ParentOid.Value)) { 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; } } return goalTree; } 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; } } private static string GetUserSettingValue(string key) { var user = MobileSessionFacade.LoggedInUser; var settings = user?.SettingList.FirstOrDefault(f => f.Type.Equals(SettingsType.ApplicationSettings)); return settings != null ? GetSettingValue(settings.Value, key) : null; } [Authorize] public string LoadStatistics(long oid) { try { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } var supportConceptStatistics = OperationsService.CreateSupportConceptStatistics(oid, DateTime.Now); if (supportConceptStatistics.PeriodStatistics != null && supportConceptStatistics.PeriodStatistics.Count == 1) { } return SerializeObject(supportConceptStatistics); } 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 == 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"); } } 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 == null) { Logout(); return _LeerzeichenFuerGetMethoden; } try { var scm = Model?.ServiceCategories.FirstOrDefault(s => 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 LoadTextbausteineForServiceCategory(long pServiceCategoryOid) { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } try { if (!MobileSessionFacade.CheckForUserRight(UserRightType.TextbausteineNurEigeneAnsehen) && !MobileSessionFacade.CheckForUserRight(UserRightType.TextbausteineAlleAnsehen)) { return _LeerzeichenFuerGetMethoden; } var textbausteine = OperationsService.GetAllTextModules(); foreach (var tm in textbausteine) { if (string.IsNullOrWhiteSpace(tm.Text)) { tm.Text = tm.Name; } } if(!MobileSessionFacade.CheckForUserRight(UserRightType.TextbausteineAlleAnsehen)) { textbausteine = textbausteine.Where(w => w.Employee.EmployeeOid == Model.Employee.EmployeeOid && w.IsOnlyForEmployee).ToList(); } Model.Textbausteine = textbausteine.Where(w => (w.ServiceCategory == null || w.ServiceCategory.ServiceCategoryOid == pServiceCategoryOid) && !String.IsNullOrEmpty(w.Text)).ToList(); Model.Textbausteine.AddRangeIfElementsNotIn(Utils.GetParentTextModules(Model.Textbausteine)); var newItems = Model.Textbausteine.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 newItems) { if(item.ParentOid != null) { var parent = newItems.FirstOrDefault(p => p.Oid == item.ParentOid); parent?.Children.AddIfNotIn(item); } } var test = newItems.Where(item => item.ParentOid == null).ToList(); if(test.Count == 0) { return _LeerzeichenFuerGetMethoden; } _TextModuleTreeHtml = "
"; foreach(var item in test) { BuildTextModuleTreeBranch(item); } _TextModuleTreeHtml += "
"; return _TextModuleTreeHtml; } catch(Exception exception) { Debug.WriteLine(exception); throw; } } private string _TextModuleTreeHtml = ""; private void BuildTextModuleTreeBranch(TextbausteinDisplayItem textModuleItem) { if(textModuleItem.IsParent) { _TextModuleTreeHtml += $"" + $"" + $"{textModuleItem.Name}" + "" + $"
"; foreach(var child in textModuleItem.Children) { BuildTextModuleTreeBranch(child); } _TextModuleTreeHtml += "
"; } else { _TextModuleTreeHtml += $"{textModuleItem.Name}"; } } [Authorize] public string LoadCompleteTextbausteinByOid(long pTextbausteinOid) { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } var textModule = Model.Textbausteine.FirstOrDefault(f => f.TextModuleOid.HasValue && f.TextModuleOid.Value == pTextbausteinOid); return textModule == null ? null : string.IsNullOrWhiteSpace(textModule.Text) ? textModule.Name : textModule.Text; } [HttpPost] [Authorize] public ActionResult CreateOrUpdateServiceRecord(FormCollection collection) { try { if(Model == null) { return Logout(); } 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]; var distanceInMeters = 0; if(!string.IsNullOrEmpty(distanz)) { if(int.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 = 0; if(datum > enddatum) { enddatum = datum; } if(!string.IsNullOrEmpty(collection[FormCollectionConstants.DurationKey])) { int.TryParse(collection[FormCollectionConstants.DurationKey], out dauer); } var doku2 = collection[FormCollectionConstants.Dokumentation2Key]; var doku3 = collection[FormCollectionConstants.Dokumentation3Key]; var doku4 = collection[FormCollectionConstants.Dokumentation4Key]; var doku5 = collection[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(dauer); } else { zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(dauer); } } else { zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, dauer) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, 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 = OperationsService.GetServiceRecordById(selectedRecordOid.Value); } if(Model.NewServiceRecord == null) { return RedirectToActionPermanent("Main"); } Model.NewServiceRecord.IP = Request.UserHostAddress; Model.NewServiceRecord.Goals = Model.SelectedGoals; Model.NewServiceRecord.Start = zeitenFeld[0]; Model.NewServiceRecord.End = zeitenFeld[1]; Model.NewServiceRecord.DistanceInMeter = distanceInMeters; if(Model.Employee.EmployeeOid != null) { if(!Model.IsInEditingMode) { Model.NewServiceRecord.Employee = Model.SelectedEmployee ?? MobileSessionFacade.LoggedInCompactEmployee; } else { if(Model.SelectedEmployee != 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 != null) { if(sc.SupportConceptOid != null) { 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 = ZeiterfassungsDauer.Minuten; Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; 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(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.SelectedSupportConcepts.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[FormCollectionConstants.ShowSignatureSuggestionPopup] = true; } } else { OperationsService.UpdateServiceRecords(new List { Model.NewServiceRecord }); } Model.NewServiceRecord = new ServiceRecordDC(); if(selectedCostbearerSCRelOid.HasValue) { Model.ServiceRecords = OperationsService.FindServiceRecordsForLastDays(selectedCostbearerSCRelOid, Model.Zeitraum, Model.Employee.EmployeeOid).ToList(); } } catch (Exception e) { Log.Error(e.Message, e); } ResetGroupBookingMode(Model.IsInGroupBookingMode); return ResetEditingMode(); } private ActionResult SaveGroupBooking() { var employeeCount = Model.SelectedEmployees.Count; var personCount = Model.SelectedSupportConcepts.Count; var cb2ScOids = (from scDc in Model.SelectedSupportConcepts where scDc.CostBearerRelations != null && scDc.CostBearerRelations.Count > 0 let costBearer2SupportConceptOid = scDc.CostBearerRelations[0].CostBearer2SupportConceptOid where costBearer2SupportConceptOid != null select costBearer2SupportConceptOid.Value).ToList(); var list = CalculateGroupBookingDuration(employeeCount, personCount, cb2ScOids); var newDCList = new List(); foreach(var dc in list) { foreach(var emp in Model.SelectedEmployees) { var newDC = CloneServiceRecordForGroupBooking(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, Notice2 = Model.NewServiceRecord.Notice2, Notice3 = Model.NewServiceRecord.Notice3, Notice4 = Model.NewServiceRecord.Notice4, Notice5 = Model.NewServiceRecord.Notice5, ServiceRecordList = newDCList }; if(Model.NewServiceRecord.GroupRoundedDuration != null) { groupDC.RoundedDuration = Model.NewServiceRecord.GroupRoundedDuration.Value; } OperationsService.InsertNewServiceRecordGroup(groupDC); } } return ResetEditingMode(); } private ActionResult UpdateGroupBooking() { var dc = Model.SelectedServiceRecord; var group = OperationsService.GetServiceRecordGroup(dc.GroupOid.Value); UpdateServiceRecordGroup(group); var employeeCount = Model.SelectedEmployees.Count; var customerCount = Model.SelectedSupportConcepts.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.SelectedSupportConcepts) { if(scdc.CostBearerRelations.Count > 0) { cb2ScOids.Add(scdc.CostBearerRelations.ElementAt(0).CostBearer2SupportConceptOid.Value); if(org == null) { org = scdc.CostBearerRelations.ElementAt(0).CostBearer; if(org != null) { minuteInterval = org.ActualMinuteIntervall; } } else { if(scdc.CostBearerRelations.ElementAt(0).CostBearer == 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.SelectedSupportConcepts.Count, 0 , MidpointRounding.AwayFromZero); } Model.NewServiceRecord.RoundedDuration = roundedDuration; Model.NewServiceRecord.GroupRoundedDuration = groupDuration; group.Notice = Model.NewServiceRecord.Notice; group.Notice2 = Model.NewServiceRecord.Notice2; group.Notice3 = Model.NewServiceRecord.Notice3; group.Notice4 = Model.NewServiceRecord.Notice4; group.Notice5 = Model.NewServiceRecord.Notice5; group.RoundedDuration = groupDuration; group.StartDate = Model.NewServiceRecord.Start; group.EndDate = Model.NewServiceRecord.End; foreach(var item in group.ServiceRecordList) { item.Notice = Model.NewServiceRecord.Notice; item.Notice2 = Model.NewServiceRecord.Notice2; item.Notice3 = Model.NewServiceRecord.Notice3; item.Notice4 = Model.NewServiceRecord.Notice4; item.Notice5 = Model.NewServiceRecord.Notice5; item.End = Model.NewServiceRecord.End; item.Start = Model.NewServiceRecord.Start; item.RoundedDuration = roundedDuration; item.DistanceInMeter = Model.NewServiceRecord.DistanceInMeter; 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 == 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.SelectedSupportConcepts = new List(); Model.SelectedEmployees = new List(); ResetGroupBookingMode(false); Model.IsInEditingMode = false; return ResetEditingMode(); } private IEnumerable CalculateGroupBookingDuration(int pEmployeeCount, int pCustomerCount, ICollection cb2ScOids) { var compactSupportConcepts = CustomerServiceImp.GetCompactSupportConcepts((from sc in Model.SelectedSupportConcepts where sc.SupportConceptOid != null select sc.SupportConceptOid.Value).ToList(), GetUser().Employee.EmployeeOid); var nodes = (from supportConcept in Model.SelectedSupportConcepts 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 = CloneServiceRecordForGroupBooking(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.SelectedSupportConcepts 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.SelectedSupportConcepts) { foreach(var emp in Model.SelectedEmployees) { 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.SelectedSupportConcepts) { foreach(var emp in Model.SelectedEmployees) { 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 = CloneServiceRecordForGroupBooking(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) { if(Model == null) { return Logout(); } long? cb2ScOid = Convert.ToInt64(formCollection[FormCollectionConstants.CostBearer2SupportConceptOidKey]); LoadServiceCategoriesToModel(cb2ScOid); Model.Zeitraum = 7; LoadRecordsToModel(); LoadGoalTreeItems(); return ResetEditingMode(); } private void LoadServiceCategoriesToModel(long? cb2ScOid) { if(cb2ScOid == 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(); } if(Model.ServiceCategories != null) { Model.ServiceCategories = Model.ServiceCategories.OrderBy(serviceCategory => serviceCategory.Position).ToList(); } } [HttpPost] [Authorize] public ActionResult DeleteServiceRecord(FormCollection formCollection) { if (Model == 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) { 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"); } public string UpdateGoals(string pGoalOids) { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } var sc = Model.SelectedSupportConcept; if (sc == 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 goals = sc.Goals.Where(w => w.ValueListEntryOid.HasValue && selectedGoalOids.Contains(w.ValueListEntryOid.Value)).ToList(); Model.SelectedGoals = goals; return _LeerzeichenFuerGetMethoden; } public string SetServiceDescription(long pServiceDescriptionOid) { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } Model.SelectedServiceDescriptionOid = pServiceDescriptionOid; return _LeerzeichenFuerGetMethoden; } [HttpPost] [Authorize] public ActionResult LoadServiceRecords(FormCollection formCollection) { if (Model == null) { return Logout(); } var zeitraum = int.Parse(formCollection[FormCollectionConstants.RecordsKey]); if (zeitraum < 0) { zeitraum = 7; } Model.Zeitraum = zeitraum; LoadRecordsToModel(); return RedirectToActionPermanent("Main"); } private void LoadRecordsToModel() { if (Model == null) { Logout(); return; } if (Model.Zeitraum < 0 || Model.CostBearer2SupportConceptOid.HasValue && Model.CostBearer2SupportConceptOid.Value == -1) { Model.ServiceRecords = new List(); return; } var records = OperationsService.FindServiceRecordsForLastDays(Model.CostBearer2SupportConceptOid < 1 ? null : Model.CostBearer2SupportConceptOid, Model.Zeitraum, Model.Employee.EmployeeOid); 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 == null) { return Logout(); } var oidString = formCollection[FormCollectionConstants.ServiceRecordOidHolder2Key]; var wasSuccessful = long.TryParse(oidString, out var serviceRecordOid); if (!wasSuccessful) { RedirectToActionPermanent("Main"); } Model.SelectedServiceRecordOid = serviceRecordOid; var selectedServiceRecord = OperationsService.GetServiceRecordById(serviceRecordOid); 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.SelectedEmployees = 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.SelectedSupportConcepts = selectedSupportConcepts; } return RedirectToActionPermanent("Main"); } public string GetSelectedRecordInformation() { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } var result = _LeerzeichenFuerGetMethoden; if (Model.SelectedServiceRecordOid.HasValue) { result = SerializeObject(Model.ServiceRecords.First(f => f.ServiceRecordOid == Model.SelectedServiceRecordOid)); } return result; } public string GetSelectedRecordInformationWithOid(long oid) { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } LoadRecordsToModel(); return SerializeObject(Model.ServiceRecords.First(f => f.ServiceRecordOid == oid)); } [Authorize] public string CheckRights(string von, string bis, bool inEditMode, string dateString, string startString, string endString) { if (Model == 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 == 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) { 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, "MaxDaysEditServiceRecordsAllowed"); var limitFuerZeiterfassungString = GetSettingValue(mandator.Settings, "AnzTageZeiterfassErfolgt"); var isSuccessful1 = int.TryParse(maxDaysEditSRsAllowedString, out var maxDaysEditSRsAllowed); if (!isSuccessful1) { maxDaysEditSRsAllowed = 0; } var isSuccessful2 = int.TryParse(limitFuerZeiterfassungString, out var limitFuerZeiterfassung); if(!isSuccessful2) { 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 employees = new List {checkServiceRecord.Employee.EmployeeOid}; var validationResults = new List(); checkServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; checkServiceRecord.DurationInStunden = ZeiterfassungsDauer.Minuten; string dateRangeString = null; if(Model.IsInGroupBookingMode) { if (checkServiceRecord.GroupOid.HasValue) { var serviceRecordGroup = OperationsService.GetServiceRecordGroup(checkServiceRecord.GroupOid.Value); serviceRecordGroup.ServiceRecordList.DoForEach(sr => employees.AddIfNotIn(sr.Employee.EmployeeOid)); } else { Model.SelectedEmployees.DoForEach(e => employees.AddIfNotIn(e.EmployeeOid)); } var cb2ScOids = Model.SelectedConceptCostBearerRelations.Where(w => w.CostBearer2SupportConceptOid.HasValue).Select(s => s.CostBearer2SupportConceptOid.Value).ToList(); var relations = CustomerService.GetSupportConceptCostBearerRelationsById(cb2ScOids); foreach (var rel in relations) { var sr = CloneServiceRecordForGroupBooking(checkServiceRecord); sr.SupportConcept = rel.SupportConcept; sr.CostBearer = rel.CostBearer; sr.CostBearer2SupportConceptOid = rel.CostBearer2SupportConceptOid; var result = OperationsService.ValidateServiceRecord(sr, null, maxDaysEditSRsAllowed, employees, cb2ScOids); dateRangeString = rel.DateRangeString; validationResults.Add(new ServiceRecord2Validation(sr, result, dateRangeString)); } } else { 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, employees); validationResults.Add(new ServiceRecord2Validation(checkServiceRecord, result, 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ö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 = false; break; case HasEmployeeSignature: if(checkServiceRecord.ServiceRecordOid.HasValue) { if(!allowEditAll && !allowEditAfterEmployeeSignature) { newResult.Message += "Sie können den Eintrag nicht speichern, da bereits eine Mitarbeiterunterschrift geleistet wurde.

"; exitLoop = true; newResult.KannTrotzdemGespeichertWerden = false; } else { newResult.Message += "Es existiert bereits eine Mitarbeiterunterschrift. Möchten Sie trotzdem speichern?

"; exitLoop = false; newResult.KannTrotzdemGespeichertWerden = true; } } else { if(!allowCreateAll && !allowCreateAfterEmployeeSignature) { newResult.Message += "Sie können den Eintrag nicht speichern, da bereits eine Mitarbeiterunterschrift geleistet wurde.

"; exitLoop = true; newResult.KannTrotzdemGespeichertWerden = false; } else { newResult.Message += "Es existiert bereits eine Mitarbeiterunterschrift. Möchten Sie trotzdem speichern?

"; exitLoop = false; newResult.KannTrotzdemGespeichertWerden = true; } } break; } } } 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 == null) { Logout(); return _LeerzeichenFuerGetMethoden; } var isSuccessful = long.TryParse(serviceRecordOidString, out var serviceRecordOid); if(!isSuccessful) { return "Error"; } var newResult = new ValidationResult(); var serviceRecord = OperationsService.GetServiceRecordById(serviceRecordOid); 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) { var exitLoop = false; foreach(var result in validationResultList) { switch(result.ResultType) { case Custom: newResult.KannTrotzdemGespeichertWerden = true; newResult.Message += "Dieser Eintrag wurde bereits unterschrieben.
Möchten Sie ihn trotzdem löschen?

"; break; case HasEmployeeSignature: if(!allowDeleteAll && !allowDeleteAfterEmployeeSignature) { exitLoop = true; newResult.KannTrotzdemGespeichertWerden = false; newResult.Message += "Sie können den Eintrag nicht löschen, da bereits eine Mitarbeiterunterschrift geleistet wurde.

"; } else { newResult.KannTrotzdemGespeichertWerden = true; newResult.Message += "Es existiert bereits eine Mitarbeiterunterschrift.
Möchten Sie ihn trotzdem löschen?

"; } break; } if(exitLoop) { break; } } 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}); } public string SetServiceRecordEmployee(long employeeOid) { try { if (Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } Model.SelectedEmployee = MainModel.AllEmployees.First(f => f.EmployeeOid.Equals(employeeOid)); return _LeerzeichenFuerGetMethoden; } catch (Exception e) { Log.Info("Error in SetServiceRecordEmployee:"); Log.Error(e.Message, e); if (MainModel.AllEmployees == null) { Log.Info("Weitere Infos: AllEmployees = null!"); } else { Log.Info($"Weitere Infos: AllEmployees enthält {MainModel.AllEmployees.Count} Elemente: "); var stringBuilder = new StringBuilder(); foreach (var ce in MainModel.AllEmployees) { if (stringBuilder.Length > 0) { stringBuilder.Append(","); } stringBuilder.Append(ce.EmployeeOid); } Log.Info(stringBuilder.ToString()); } throw e; } } 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("PreselectCustomer", "Customer", new {Model.SelectedSupportConcept.Customer.CustomerOid}); } if(Model?.SelectedSupportConcept == 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.IsAllowedToSeeBills ? RedirectToActionPermanent("InitReports", "Report") : RedirectToMain(); } public ActionResult RedirectToMain() { return RedirectToActionPermanent("Main", "Main"); } [Authorize] public ActionResult RedirectToDevelopment() { #if DEBUG return RedirectToActionPermanent("Development", "Development"); #endif return RedirectToMain(); } // Gruppenbuchungen [HttpPost] [Authorize] public ActionResult SetGroupBookingMode(FormCollection pFormCollection) { if (Model == null) { return Logout(); } var isInGroupBookingMode = "true,false" == pFormCollection[FormCollectionConstants.IsInGroupBookingModeKey]; ResetGroupBookingMode(isInGroupBookingMode); return RedirectToAction("Main"); } /// /// Setzt die getroffenen Auswahlen zurück /// /// /// Wenn true, wird davon ausgegangen, dass man von der Einzelbuchung in eine Gruppenbuchung wechselt und es wird sich der vorher ausgewählte Mitarbeiter und Hilfeplan gemerkt. /// Bei false wird davon ausgegangen, dass man von der Gruppenbuchung in eine Einzelbuchung wechselt und der vorher ausgewählte Mitarbeiter und Hilfeplan wird automatisch ausgewählt. private void ResetGroupBookingMode(bool pIsInGroupBookingMode) { if (Model == null) { Logout(); return; } Model.IsInGroupBookingMode = pIsInGroupBookingMode; if (pIsInGroupBookingMode) { Model.PreviouslySelectedEmployee = Model.SelectedEmployee; Model.PreviouslySelectedSupportConcept = Model.SelectedSupportConcept; Model.SelectedSupportConcept = null; Model.SelectedEmployee = null; Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); Model.SelectedEmployees.AddIfNotIn(MobileSessionFacade.LoggedInCompactEmployee); Model.IsInEditingMode = false; Model.SelectedServiceRecord = null; } else { Model.SelectedEmployee = Model.PreviouslySelectedEmployee; Model.SelectedSupportConcept = Model.PreviouslySelectedSupportConcept; Model.ServiceCategories.Clear(); Model.SelectedCostbearerRelOids.Clear(); Model.SelectedEmployees.Clear(); Model.SelectedSupportConcepts.Clear(); Model.SelectedConceptCostBearerRelations.Clear(); Model.SelectedEmployee = MobileSessionFacade.LoggedInCompactEmployee; 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(); } } } [HttpPost] [Authorize] public ActionResult ResetEditingMode() { if (Model == null) { return Logout(); } Model.NewServiceRecord = new ServiceRecordDC(); Model.SelectedServiceRecord = null; Model.IsInEditingMode = false; Model.SelectedSupportConcepts.Clear(); Model.SelectedConceptCostBearerRelations.Clear(); Model.SelectedCostbearerRelOids.Clear(); Model.SelectedGroupOfPeopleOids.Clear(); Model.SelectedEmployees = new List { MobileSessionFacade.LoggedInCompactEmployee }; Model.SelectedEmployee = MobileSessionFacade.LoggedInCompactEmployee; //Model.ServiceCategories = CreateServiceCategoryModels(OperationsService.GetAllServiceDescriptions()); LoadServiceCategoriesToModel(Model.CostBearer2SupportConceptOid); var serviceDescriptions = Model.GetServiceDesctiptions(); if (Model.ServiceCategories.Any() && serviceDescriptions.Any()) { var firstServiceDescription = serviceDescriptions.First(); Model.SelectedServiceDescriptionOid = firstServiceDescription.ServiceDescriptionOid; Model.SelectedServiceCategoryOid = firstServiceDescription.Category.ServiceCategoryOid; } return RedirectToActionPermanent("Main"); } [Authorize] public string AddSupportConceptCostBearerRelationsToGroupBooking(string pRelOids, string pGroupOids) { if(Model == 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.SelectedGroupOfPeopleOids.Clear(); rawGroupOids.DoForEach(s => { var group = Model.GroupsOfPeople.FirstOrDefault(f => f.GroupOfPeopleOid.HasValue && f.GroupOfPeopleOid.Value.Equals(long.Parse(s))); if(group == null) { return; } groups.AddIfNotIn(group); group.SupportConceptList.DoForEach(f => relOids.AddRangeIfElementsNotIn(f.CostBearerRelOids)); }); Model.SelectedSupportConcepts.Clear(); Model.SelectedCostbearerRelOids.Clear(); Model.SelectedCostbearerRelOids.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.SelectedSupportConcepts.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.SelectedGroupOfPeopleOids.AddIfNotIn(groupOid); } else if (Model.SelectedGroupOfPeopleOids.Contains(groupOid)) { Model.SelectedGroupOfPeopleOids.Remove(groupOid); } } return SerializeObject(Model.GroupBookingSelectionObject); } [Authorize] public string RemoveSupportConceptCostBearerRelationFromGroupBooking(string pRelOid) { if(Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } long.TryParse(pRelOid, out var supportConceptCostBearerRelationOid); var supportConcept = Model.SelectedSupportConcepts.FirstOrDefault(f => f.CostBearerRelations.Any(a => a.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid)); var relation = Model.SelectedConceptCostBearerRelations.FirstOrDefault(f => f.CostBearer2SupportConceptOid == supportConceptCostBearerRelationOid); Model.SelectedSupportConcepts.Remove(supportConcept); Model.SelectedConceptCostBearerRelations.Remove(relation); var selectedGroups = Model.GroupsOfPeople.Where(group => group.GroupOfPeopleOid.HasValue && Model.SelectedGroupOfPeopleOids.Contains(group.GroupOfPeopleOid.Value)).ToList(); var groups = selectedGroups.Where(group => group.SupportConceptList.All(a => Model.SelectedSupportConcepts.Where(w => w.SupportConceptOid.HasValue).Select(s => s.SupportConceptOid.Value).Contains(a.SupportConceptOid))); Model.SelectedGroupOfPeopleOids = groups.Where(group => group.GroupOfPeopleOid.HasValue).Select(group => group.GroupOfPeopleOid.Value).ToList(); return SerializeObject(Model.GroupBookingSelectionObject); } [Authorize] public string AddEmployeesToGroupBooking(string pEmployeeOids) { if(Model == null) { Logout(); return _LeerzeichenFuerGetMethoden; } if(string.IsNullOrEmpty(pEmployeeOids)) { Model.SelectedEmployees.Clear(); return JsonConvert.SerializeObject(Model.SelectedEmployees.Count); } var rawEmployeeOids = pEmployeeOids.Split(','); var oids = new List(); rawEmployeeOids.DoForEach(s => oids.AddIfNotIn(long.Parse(s))); var employees = Model.Employees.Where(w => oids.Contains(w.EmployeeOid)); Model.SelectedEmployees.Clear(); Model.SelectedEmployees.AddRangeIfElementsNotIn(employees); return JsonConvert.SerializeObject(Model.SelectedEmployees.Count); } [HttpPost] [Authorize] public ActionResult LoadSignatureImage(FormCollection pFormCollection) { if(Model == null) { return Logout(); } var isParsingSuccessful2 = long.TryParse(pFormCollection[FormCollectionConstants.ServiceRecordOidHolder2Key], out var serviceRecordOid); var isParsingSuccessful = long.TryParse(pFormCollection[FormCollectionConstants.SignatureOidHolderKey], out var signatureOid); if(isParsingSuccessful && isParsingSuccessful2) { var signatureServiceRecord = Model.ServiceRecords.FirstOrDefault(serviceRecord => serviceRecord.ServiceRecordOid.Equals(serviceRecordOid)); Model.SignatureServiceRecordHeader = MainModel.GetServiceRecordTimeHeader(signatureServiceRecord, false); Model.SignatureImage = OperationsService.GetSignature(signatureOid).DataBild; Model.SignatureImage = ApplyWatermark(Model.SignatureImage, Server.MapPath("../Content/images/bewoplaner_logo_big.png")); } return RedirectToActionPermanent("Main"); } [Authorize] public string ResetSignatureImage() { if(Model == null) { return _LeerzeichenFuerGetMethoden; } Model.SignatureImage = null; Model.SignatureServiceRecordHeader = null; return _LeerzeichenFuerGetMethoden; } [HttpPost] [Authorize] public ActionResult CreateGroupBooking(FormCollection formCollection) { try { if(Model == null) { return Logout(); } if(Model.SelectedConceptCostBearerRelations.Count == 1) { var cb2ScOids = (from scDc in Model.SelectedSupportConcepts 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"); } } string doku1; if(Model.Dokutypes != null && Model.Dokutypes.Length > 0) { doku1 = formCollection[FormCollectionConstants.Dokumentation1Key]; } else { doku1 = formCollection[FormCollectionConstants.Dokumentation6Key]; } Log.Info($"CreateServiceRecord: datum:{formCollection[FormCollectionConstants.DateKey]}; start:{formCollection[FormCollectionConstants.StartKey]}; ende:{formCollection[FormCollectionConstants.EndKey]}; dauer:{formCollection[FormCollectionConstants.DurationKey]}; doku:{doku1}; aktion:{formCollection[FormCollectionConstants.HiddenInputKey]}"); if(string.IsNullOrEmpty(formCollection[FormCollectionConstants.DateKey])) { return View("Main", Model); } var distanz = formCollection[FormCollectionConstants.DistanceKey]; var distanceInMeters = 0; if(!string.IsNullOrEmpty(distanz)) { if(int.TryParse(distanz, out var parsedDistance)) { distanceInMeters = parsedDistance; } } var selectedCostbearerScRelOid = 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 = 0; if(datum > enddatum) { enddatum = datum; } if(!string.IsNullOrEmpty(formCollection[FormCollectionConstants.DurationKey])) { int.TryParse(formCollection[FormCollectionConstants.DurationKey], out dauer); } 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(dauer); } else { zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(dauer); } } else { zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, dauer) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, dauer); } if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0]) { dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes; } if(Model.NewServiceRecord == null) { return RedirectToActionPermanent("Main"); } Model.NewServiceRecord.IP = Request.UserHostAddress; Model.NewServiceRecord.Goals = Model.SelectedGoals; Model.NewServiceRecord.Start = zeitenFeld[0]; Model.NewServiceRecord.End = zeitenFeld[1]; Model.NewServiceRecord.DistanceInMeter = distanceInMeters; if(Model.Employee.EmployeeOid != null) { if(Model.SelectedEmployee != 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 != null) { if(sc.SupportConceptOid != null) { 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 = ZeiterfassungsDauer.Minuten; Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; 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.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.SelectedSupportConcepts.Count > 1) { return SaveGroupBooking(); } var oidList = OperationsService.InsertNewServiceRecords(new List { Model.NewServiceRecord }); Model.ServiceRecordOid = oidList[0]; Model.NewServiceRecord = new ServiceRecordDC(); } catch(Exception e) { Log.Error(e.Message, e); } return ResetEditingMode(); } // Wird zum Bearbeiten von Gruppenbuchungen benutzt [HttpPost] [Authorize] public ActionResult EditServiceRecord(FormCollection formCollection) { if(Model == null) { return Logout(); } try { string doku1; if(Model.Dokutypes != null && Model.Dokutypes.Length > 0) { doku1 = formCollection[FormCollectionConstants.Dokumentation1Key]; } else { doku1 = formCollection[FormCollectionConstants.Dokumentation6Key]; } Log.Info($"EditServiceRecord: datum:{formCollection[FormCollectionConstants.DateKey]}; start:{formCollection[FormCollectionConstants.StartKey]}; ende:{formCollection[FormCollectionConstants.EndKey]}; dauer:{formCollection[FormCollectionConstants.DurationKey]}; doku:{doku1}; aktion:Speichern"); if(string.IsNullOrEmpty(formCollection[FormCollectionConstants.DateKey])) { return View("Main", Model); } var distanz = formCollection[FormCollectionConstants.DistanceKey]; var distanceInMeters = 0; if(!string.IsNullOrEmpty(distanz)) { if(int.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 = 0; if(datum > enddatum) { enddatum = datum; } if(!string.IsNullOrEmpty(formCollection[FormCollectionConstants.DurationKey])) { int.TryParse(formCollection[FormCollectionConstants.DurationKey], out dauer); } 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(dauer); } else { zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(dauer); } } else { zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, dauer) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, dauer); } if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0]) { dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes; } var selectedRecordOid = Model.SelectedServiceRecordOid ?? Model.SelectedServiceRecord.ServiceRecordOid; Model.NewServiceRecord = OperationsService.GetServiceRecordById(selectedRecordOid.Value); if(Model.NewServiceRecord == null) { return RedirectToActionPermanent("Main"); } Model.NewServiceRecord.IP = Request.UserHostAddress; Model.NewServiceRecord.Goals = Model.SelectedGoals; Model.NewServiceRecord.Start = zeitenFeld[0]; Model.NewServiceRecord.End = zeitenFeld[1]; Model.NewServiceRecord.DistanceInMeter = distanceInMeters; if(Model.Employee.EmployeeOid != null) { if(Model.SelectedEmployee != 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 != null) { if(sc.SupportConceptOid != null) { 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 = ZeiterfassungsDauer.Minuten; Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung; 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.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.SelectedSupportConcepts.Count > 1) { return UpdateGroupBooking(); } OperationsService.UpdateServiceRecords(new List { Model.NewServiceRecord }); Model.NewServiceRecord = new ServiceRecordDC(); if(selectedCostbearer2SupportConceptRelOid.HasValue) { Model.ServiceRecords = OperationsService.FindServiceRecordsForLastDays(selectedCostbearer2SupportConceptRelOid, Model.Zeitraum, Model.Employee.EmployeeOid).ToList(); } } catch(Exception e) { Log.Error(e.Message, e); } return ResetEditingMode(); } [HttpPost] public ActionResult LogOutAfterSessionTimeout() { Logout(); return RedirectToActionPermanent("Index", "Login", new { isSessionTimedOut = true}); } [HttpPost] [Authorize] public ActionResult SetSupportConceptFilter(FormCollection formCollection) { if(Model == null) { return Logout(); } var selectedSupportConceptFilter = formCollection[nameof(Model.SelectedSupportConceptFilter)]; if(!Enum.TryParse(selectedSupportConceptFilter, out CustomerFilterEnum customerFilter)) { customerFilter = CustomerFilterEnum.MyCustomer; } UpdateSettings("CustomerFilterInZeiterfassung", customerFilter.ToString()); return RedirectToActionPermanent("Main"); } } }