Files
BeWoPlaner/BeWoPlanerMobil/Controllers/MainController.cs

5964 lines
255 KiB
C#
Raw Normal View History

2026-05-11 12:42:57 +02:00
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.AI;
using BeWo.Service.DCEntityMapper;
2023-02-23 11:48:41 +01:00
using BeWo.Service.Plugins;
using BeWo.View.Navigation.Filter;
2016-06-27 01:45:38 +02:00
using BeWoPlanerMobil.Models;
using BeWoPlanerMobil.Service;
using BeWoPlanerMobil.Util;
2016-06-27 01:45:38 +02:00
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.Extensions;
using BS.Shared.Services;
using DevExpress.XtraScheduler;
using DevExpress.XtraScheduler.Compatibility;
using Newtonsoft.Json;
using System;
2026-03-30 00:07:52 +02:00
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Web.Mvc;
using System.Windows.Forms;
2026-05-11 12:42:57 +02:00
using NHibernate;
using static BeWoPlanerMobil.Util.MobileUtils;
using static BS.Shared.ServiceRecordValidationResult;
using FormCollection = System.Web.Mvc.FormCollection;
using GoalRating = BeWoPlanerMobil.Util.GoalRating;
using Image = System.Drawing.Image;
using ServiceRecordDC = BS.Shared.DataContracts.ServiceRecordDC;
/*
* ToDo: Bug, wenn man auf "bearbeiten" bei einem Eintrag klickt, wird die Leistung nicht geladen
* ToDo: Hat man vor dem Anlegen einer Mehrfachbuchung einen Hilfeplan ausgewählt, wird der nicht richtig nach dem Anlegen geladen und die Intervallauswahl ist nicht sichtbar.
*/
2016-06-27 01:45:38 +02:00
namespace BeWoPlanerMobil.Controllers
{
public class MainController : SignableController
2016-06-27 01:45:38 +02:00
{
2026-03-30 00:07:52 +02:00
// Speichert den Status externer Aufrufe (callId -> Callback-Daten)
private static readonly ConcurrentDictionary<string, string> _externalCallResults = new ConcurrentDictionary<string, string>();
// Speichert optionale Statusmeldungen für laufende externe Aufrufe (callId -> Statustext)
private static readonly ConcurrentDictionary<string, string> _externalCallStatusMessages = new ConcurrentDictionary<string, string>();
// Speichert das Aufnametoken für laufende externe Aufrufe (callId -> Token)
private static readonly ConcurrentDictionary<string, AiVoiceDataDC> _externalCallTokens = new ConcurrentDictionary<string, AiVoiceDataDC>();
public MainController()
{
int test = 0;
}
private MainModel _Model;
public bool SkipModelInitialization { get; set; }
public bool SkipServiceRecordInitialization { get; set; }
2025-12-03 18:31:50 +01:00
2016-06-27 01:45:38 +02:00
public MainModel Model
{
get
{
if(!MobileSessionFacade.IsUserLoggedIn())
2016-06-27 01:45:38 +02:00
{
RedirectToActionPermanent("Index", "Login");
return null;
}
if(_Model is null)
2016-06-27 01:45:38 +02:00
{
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
2025-06-11 22:56:25 +02:00
_Model = new MainModel();
InitModel(_Model);
if (!SkipModelInitialization)
{
InitViewModel();
}
sw.Stop();
System.Diagnostics.Debug.WriteLine($"MainModel Initialisierung in: {sw.ElapsedMilliseconds} ms");
2016-06-27 01:45:38 +02:00
}
return _Model;
2016-06-27 01:45:38 +02:00
}
}
private Dictionary<long, ValueListEntryDC> _ParentGoals;
2016-06-27 01:45:38 +02:00
private static readonly List<ValueListEntryType> _GoalTypes = new List<ValueListEntryType> { ValueListEntryType.SupportConceptGoalCategoryType, ValueListEntryType.SupportConceptIndividualGoalCategoryType };
private static readonly List<ValueListEntryType> _MeasureTypes = new List<ValueListEntryType> { ValueListEntryType.SupportConceptGoalType, ValueListEntryType.SupportConceptIndividualGoalType };
2016-06-27 01:45:38 +02:00
2025-10-09 12:56:32 +02:00
public void InitViewModel(bool forceReload = false)
2025-06-11 22:56:25 +02:00
{
InitSettings();
2020-08-04 12:45:46 +02:00
2025-10-09 12:56:32 +02:00
CreateModelSupportConceptListObjects(forceReload);
2025-06-11 22:56:25 +02:00
Model.GroupsOfPeople = EmployeeService.GetAllGroups(LoggedInEmployee.EmployeeOid).OrderBy(gop => gop.Name).ToList();
Model.Dokutypes = ValueListService.GetAllValueListEntrysByType(ValueListEntryType.DocumentType);
2025-07-18 19:37:01 +02:00
if(Model.Dokutypes != null)
2025-06-11 22:56:25 +02:00
{
Model.Dokutypes = Model.Dokutypes.OrderBy(s => s.ValueListEntryOid).ToArray();
}
//Load Employees
2025-07-18 19:37:01 +02:00
if(Model.AllEmployees is null)
2025-06-11 22:56:25 +02:00
{
Model.AllEmployees = EmployeeService.GetAllCompactEmployees().Where(e => e.ActivationType == ActivationTypeId.Active).OrderBy(e => e.LastName).ToList();
2025-06-11 22:56:25 +02:00
}
2025-07-18 19:37:01 +02:00
if(Model.EmployeesForGroupAndMultiBooking is null)
2025-06-11 22:56:25 +02:00
{
Model.EmployeesForGroupAndMultiBooking = Model.AllEmployees;
2025-06-11 22:56:25 +02:00
}
2025-07-18 19:37:01 +02:00
if(LoggedInUser.HasRight(UserRightType.ServiceRecord_AllowCreationForOtherEmployees))
2025-06-11 22:56:25 +02:00
{
Model.Employees = Model.AllEmployees;
}
2025-07-18 19:37:01 +02:00
else if(LoggedInUser.HasRight(UserRightType.ServiceRecord_AllowCreationForOtherTeamMember) && Model.LoggedInEmployee.EmployeeOid != null)
2025-06-11 22:56:25 +02:00
{
Model.Employees = EmployeeService.GetAllTeamMember(LoggedInUser.Employee).Where(e => e.ActivationType == ActivationTypeId.Active).ToList();
}
else
{
Model.Employees = new List<CompactEmployeeDC> { LoggedInUser.Employee };
}
Model.Employees = Model.Employees.OrderBy(e => e.LastName).ThenBy(e => e.FirstName).ToList();
Model.GroupBookingSelectedCostBearerSupportConcepts = new List<SupportConceptCostBearerRelDC>();
2025-06-11 22:56:25 +02:00
Model.GoalRatingTypes = OperationsService.GetAllRatingTypes().OrderBy(o => o.Position).ToList();
SetSelectedObjects();
}
public void CreateModelSupportConceptListObjects(bool forceReload)
{
//Load SupportConcepts
2025-07-18 19:37:01 +02:00
if(Model.SupportConceptListObjects is null || Model.SupportConceptListObjects.Count == 0 || forceReload || (Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SelectedCostBearerSupportConceptOid.Value != -1))
{
2025-07-18 19:37:01 +02:00
if(Model.LoggedInEmployee?.EmployeeOid.HasValue ?? false)
{
var customerService = PluginLoader.FindClass<CustomerService>();
var test = customerService.GetAllActiveSupportConceptCostbearer(false, true, Model.LoggedInEmployee.EmployeeOid.Value);
Model.SupportConcepts = test;
}
else
{
Model.SupportConcepts = new List<CompactSupportConceptDC>();
}
2025-07-18 19:37:01 +02:00
if(Model.ShowExpiredSupportConcepts == false)
{
2025-07-18 19:37:01 +02:00
Model.SupportConcepts = Model.SupportConcepts.Where(sc => sc.EndDate is null || sc.EndDate.Value >= DateTime.Now.Date).ToList();
}
if (Model.SelectedSupportConceptFilter == CustomerFilterEnum.MyCustomer)
{
Model.SupportConcepts = Model.SupportConcepts.Where(sc => sc.IsRelatedToEmployee).ToList();
}
else if (Model.SelectedSupportConceptFilter == CustomerFilterEnum.TeamCustomer)
{
Model.SupportConcepts = Model.SupportConcepts.Where(sc => sc.Customer.IsRelatedToTeam).ToList();
}
foreach (var supportConcept in Model.SupportConcepts)
{
2025-07-18 19:37:01 +02:00
if(supportConcept.Goals is null)
{
2025-07-18 19:37:01 +02:00
supportConcept.Goals = new List<ValueListEntryDC>();
}
}
//Einfachbuchung
var allCostBearerRelationsSingleBooking = new List<MokSupportConceptListObject> {
new MokSupportConceptListObject(-1, -1, false, false, false, false)
{
NameAndDateOfBirth = "Hilfeplan auswählen"
},
new MokSupportConceptListObject(-2, -2, false, false, false, false)
{
NameAndDateOfBirth = "Ohne Hilfeplan"
}};
if (Model.IsInEditingMode && Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SelectedCostBearerSupportConceptOid.Value > 0)
{
allCostBearerRelationsSingleBooking.RemoveAt(allCostBearerRelationsSingleBooking.Count - 1); // Verhindert, dass man Klienten Buchungen ausversehen zu Buchungen ohne Hilfeplan machen kann.
}
var allCostBearerRelationsMultiBooking = new List<MokSupportConceptListObject>();
BS.Shared.Settings.ApplicationSettings.SupportConceptExpirationLimitInMonths = Model.MokSettings.SupportConceptExpirationLimitInMonths;
foreach (var sc in Model.SupportConcepts.OrderBy(sc => sc.Customer.LastName))
{
foreach (var cb in sc.CostBearerList)
{
2025-07-18 19:37:01 +02:00
var customerName = $"{sc.Customer.SimpleDescription} {(sc.Customer.DateOfBirth.HasValue ? "*" + sc.Customer.DateOfBirth.Value.ToString("dd.MM.yyyy") : string.Empty)}";
var scNameSingle = $"{cb.Bezeichnung} {sc.StartDate?.ToShortDateString().Remove(6, 2) ?? string.Empty}-{sc.EndDate?.ToShortDateString().Remove(6, 2) ?? string.Empty} {cb.OrganisationName}"; // {Model.GetIsNotApproved(sc)}";
scNameSingle = sc.CostBearer;
allCostBearerRelationsMultiBooking.Add(new MokSupportConceptListObject(sc.SupportConceptOid, sc.CostBearerRelOids[0], sc.IsAboutToExpire, sc.ExpiresIn3MonthOrLess, sc.IsArchived, sc.IsDeleted)
{
NameAndDateOfBirth = customerName,
SupportConceptTimeSpan = scNameSingle
});
}
}
allCostBearerRelationsSingleBooking.AddRange(allCostBearerRelationsMultiBooking);
Model.SupportConceptListObjects = allCostBearerRelationsSingleBooking;
Model.SupportConceptListObjectsForGroupBooking = allCostBearerRelationsMultiBooking;
}
if (Model.SupportConceptListObjectsForGroupBooking == null && Model.SupportConceptListObjects != null)
{
Model.SupportConceptListObjectsForGroupBooking = Model.SupportConceptListObjects.Where(s => s.CostBearer2SupportConceptOid > 0).ToList();
}
2025-06-11 22:56:25 +02:00
}
private void SetSelectedObjects()
2016-06-27 01:45:38 +02:00
{
Model.SelectedEmployee = Model.SelectedEmployeeOid.HasValue ?
Model.AllEmployees.First(f => f.EmployeeOid.Equals(Model.SelectedEmployeeOid.Value)) :
LoggedInUser.Employee;
2025-06-11 22:56:25 +02:00
var isInList = Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SupportConceptListObjects.Exists(s => s.CostBearer2SupportConceptOid == Model.SelectedCostBearerSupportConceptOid);
if (!Model.SelectedCostBearerSupportConceptOid.HasValue || !isInList)
{
if (Model.SelectedCostBearerSupportConceptOid.HasValue && !isInList)
{
2025-06-11 22:56:25 +02:00
Log.Info($"Model.SelectedCostBearerSupportConceptOid = {Model.SelectedCostBearerSupportConceptOid} is not in list !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2025-06-11 22:56:25 +02:00
var sb = new StringBuilder();
foreach (var o in Model.SupportConceptListObjects)
{
2025-06-11 22:56:25 +02:00
if (sb.Length > 0)
{
sb.Append(", ");
}
sb.Append(o.CostBearer2SupportConceptOid);
}
2025-06-11 22:56:25 +02:00
Log.Info($"Model.SupportConceptListObjects Oids = {sb}");
}
2016-06-27 01:45:38 +02:00
Model.SelectedSupportConceptListObject = Model.SupportConceptListObjects.FirstOrDefault(f => f.CostBearer2SupportConceptOid == -1) ?? Model.SupportConceptListObjects.First();
2025-06-11 22:56:25 +02:00
Model.SelectedCostBearerSupportConceptOid = -1;
}
else
{
Model.SelectedSupportConceptListObject = Model.SupportConceptListObjects.FirstOrDefault(f => f.CostBearer2SupportConceptOid == Model.SelectedCostBearerSupportConceptOid) ?? Model.SupportConceptListObjects.First();
2025-06-11 22:56:25 +02:00
}
Model.HasAnyRatingTypes = Model.HasRightToRateGoals && Model.GoalRatingTypes.Any();
2025-07-18 19:37:01 +02:00
if(Model.GroupBookingSelectedCostBearerSupportConceptOids.Count > 0)
2025-06-11 22:56:25 +02:00
{
Model.GroupBookingSelectedCostBearerSupportConcepts = CustomerService.GetSupportConceptCostBearerRelationsById(Model.GroupBookingSelectedCostBearerSupportConceptOids);
2025-06-11 22:56:25 +02:00
}
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployees = Model.AllEmployees.Where(employee => Model.GroupBookingSelectedEmployeeOids.Contains(employee.EmployeeOid)).ToList();
2025-07-18 19:37:01 +02:00
if(Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SelectedCostBearerSupportConceptOid != -1)
2025-06-11 22:56:25 +02:00
{
LoadSupportConceptThings(Model.SelectedCostBearerSupportConceptOid, true);
if (!SkipServiceRecordInitialization)
{
LoadPaginatedServiceRecordsToModel(Model.CurrentPage);
}
2025-06-11 22:56:25 +02:00
}
2025-07-18 19:37:01 +02:00
else if(Model.IsInGroupBookingMode || Model.IsInMultiBookingMode)
2025-06-17 13:06:29 +02:00
{
LoadSupportConceptThings(null, true);
2025-06-17 13:06:29 +02:00
}
2025-07-18 19:37:01 +02:00
if(Model.AllGoals != null)
2025-06-11 22:56:25 +02:00
{
if (Model.SelectedGoals.Count < Model.SelectedGoalOids.Count) // Diese Abfrage muss bleiben, sonst werden vorher gewählte Bewertungen überschrieben
2025-07-17 16:26:07 +02:00
{
foreach (var oid in Model.SelectedGoalOids)
{
if (Model.SelectedGoals.Count(g => g.ValueListEntryOid == oid) == 0)
{
var dc = Model.AllGoals.FirstOrDefault(g => g.ValueListEntryOid == oid);
if (dc != null)
{
Model.SelectedGoals.Add(DcToMokMapper.CreateZiel(dc));
}
}
}
2025-07-17 16:26:07 +02:00
}
2025-06-11 22:56:25 +02:00
}
2025-07-18 19:37:01 +02:00
if(Model.IsInEditingMode && Model.SelectedServiceRecordOid.HasValue)
{
Model.SelectedServiceRecord = GetServiceRecordDC(Model.SelectedServiceRecordOid.Value, false);
}
2025-06-11 22:56:25 +02:00
}
[HttpGet]
[Authorize]
public ActionResult GetAiPromptbausteinFolder()
{
try
{
var folders = AiService.GetAiPromptbausteinFolder(AiActionType.ServiceRecordDocumentation).ToList();
AddFavoriten(folders);
var projected = ProjectAiFolders(folders);
return new JsonResult
{
Data = projected,
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
MaxJsonLength = int.MaxValue
};
}
catch (Exception ex)
{
Response.StatusCode = 500;
Response.TrySkipIisCustomErrors = true;
return Json(new
{
error = ex.GetType().Name,
message = ex.Message,
inner = ex.InnerException?.Message,
stack = ex.StackTrace
}, JsonRequestBehavior.AllowGet);
}
}
[HttpPost]
[Authorize]
public ActionResult StartPrompt(long promptOid, string docuText)
{
try
{
if (String.IsNullOrWhiteSpace(docuText))
{
return Json(new
{
success = true,
text = string.Empty
});
}
var conv = new AiConversationDC
{
Created = DateTime.Now,
Updated = DateTime.Now,
ActionType = AiActionType.ServiceRecordDocumentation
};
AiViewContextDC viewContext = CreateAiViewContext(docuText);
conv = AiService.CreateAiConversation(conv, viewContext);
var messages = AiService.ExecuteAiConversationWithPrompt(conv.Oid.Value, viewContext, promptOid);
// Die generierte Dokumentation ist die letzte Assistent-Nachricht.
var resultMessage = (messages ?? new AiConversationMessageDC[0])
.LastOrDefault(m => m.Role == AiConversationMessageRole.Assistent)
?? (messages ?? new AiConversationMessageDC[0]).LastOrDefault();
return Json(new
{
success = true,
text = resultMessage?.Message ?? string.Empty
});
}
catch (Exception ex)
{
Log.Error("StartPrompt fehlgeschlagen", ex);
Response.StatusCode = 500;
Response.TrySkipIisCustomErrors = true;
return Json(new
{
success = false,
error = ex.GetType().Name,
message = ex.Message,
inner = ex.InnerException?.Message
});
}
}
/// <summary>
/// Baut den AI-Kontext für die aktuell bearbeitete Einzelbuchung auf:
/// Primary = ausgewähltes Betreuungskonzept, Secondary = aktueller Dokumentationstext.
/// </summary>
private AiViewContextDC CreateAiViewContext(string docuText)
{
2026-06-25 11:50:06 +02:00
long customerOid = -1;
long scOid = -1;
long cbOid = -1;
var oids = new List<long>();
foreach (var record in Model.ServiceRecords)
{
2026-06-25 11:50:06 +02:00
oids.Add(record.ServiceRecordOid ?? -1);
}
if (Model.SelectedCostBearerSupportConceptOid.HasValue)
{
var c2s = DAOFactory.GenericDAO.LoadByID<CostBearer2SupportConcept>(Model.SelectedCostBearerSupportConceptOid.Value);
customerOid = c2s.SupportConcept.Customer.Oid.Value;
scOid = c2s.SupportConcept.Oid.Value;
cbOid = c2s.CostBearer.Oid.Value;
}
var rtn = new Dictionary<TableID, long[]>()
{
{TableID.Customer, new long[]{ customerOid } },
{TableID.SupportConcept, new long[]{ scOid } },
{TableID.CostBearer, new long[]{ cbOid } },
{TableID.ServiceRecord, oids.ToArray() }
};
2026-06-25 11:50:06 +02:00
var dc = new AiViewContextDC()
{
Primary = scOid,
References = rtn,
Secondary = docuText
2026-06-25 11:50:06 +02:00
};
return dc;
}
2026-06-25 11:50:06 +02:00
private void AddFavoriten(List<AiPromptbausteinFolderDC> folders)
{
var favoriten = new AiPromptbausteinFolderDC()
{
Oid = -5,
Title = "Favoriten",
Description = "Eigene Favoriten",
SubPrompts = new List<AiPromptbausteinPromptDC>()
};
AddFavoritenPrompts(folders, favoriten);
folders.Insert(0, favoriten);
}
private void AddFavoritenPrompts(List<AiPromptbausteinFolderDC> folders, AiPromptbausteinFolderDC favoriten)
{
foreach (var folder in folders)
{
if (folder.SubFolders?.Any() ?? false)
AddFavoritenPrompts(folder.SubFolders, favoriten);
foreach (var prompt in folder.SubPrompts)
{
if (prompt.IsFavorite)
favoriten.SubPrompts.Add(prompt);
}
//foreach (var routine in folder.SubRoutines.VMList)
//{
// if (routine.IsFavorite)
// favoriten.SubRoutines.VMList.Add(routine);
//}
}
}
/// <summary>
/// Projiziert die AiPromptbausteinFolderDC-Baumstruktur auf ein schlankes,
/// zirkelbezugsfreies Objekt für die JSON-Serialisierung an das UI.
/// </summary>
private List<object> ProjectAiFolders(List<AiPromptbausteinFolderDC> folders)
{
if (folders == null)
{
return new List<object>();
}
return folders.Select(f => (object)new
{
f.Title,
f.Description,
SubFolders = ProjectAiFolders(f.SubFolders),
SubPrompts = (f.SubPrompts ?? new List<AiPromptbausteinPromptDC>())
.Select(p => new
{
p.Oid,
p.Title,
p.Description,
p.Prompt
}).ToList()
}).ToList();
}
2025-06-11 22:56:25 +02:00
private void InitSettings()
{
2025-06-11 22:56:25 +02:00
//Mandator Settings
Model.ShowBetrag = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowBetrag);
Model.ShowMarker = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowMarker);
Model.EinheitZeiterfassung = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.EinheitZeiterfassung);
2025-06-11 22:56:25 +02:00
/*
* Minuten: 0
* Stunden: 1
* Min & Std: 2
*/
if (Model.EinheitZeiterfassung == 1)
{
Model.IsShowingDurationInHours = true;
}
2025-06-11 22:56:25 +02:00
Model.FilterGroupServiceCategories = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.FilterGroupServiceCategories);
Model.SetStartTimeToEndTimeAfterSave = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.SetStartTimeToEndTimeAfterSave);
2025-10-09 12:56:32 +02:00
Model.MokSettings = new MokSettings
{
SupportConceptExpirationLimitInMonths = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.HilfeplanAuslaufAuswahl, 3),
AnzTageZeiterfassErfolgt = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.AnzTageZeiterfassErfolgt),
AnzTageUnterschriftErfolgt = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.AnzTageUnterschriftErfolgt),
MaxDaysEditServiceRecordsAllowed = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.MaxDaysEditServiceRecordsAllowed),
TimeUntilUILock = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.TimeUntilUILock),
ServiceRecordAllowChangeHours = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.ServiceRecordAllowChangeHours)
};
2025-06-11 22:56:25 +02:00
Model.ShowServiceRecordInsertedOn = !UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.HideServiceRecordInsertedByAndInsertedOn);
2025-06-11 22:56:25 +02:00
Model.ShowSignature = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowSignature) && Model.HasRightToProvideSingleSignature;
2026-05-07 00:47:38 +02:00
2025-06-11 22:56:25 +02:00
Model.ShowDistanceField = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowDistanceFields);
2025-06-11 22:56:25 +02:00
var settingsValue = GetSettingValue(Model.Mandator.Settings, SettingsKeys.IsServiceRecordNoticeMandatory);
2025-06-11 22:56:25 +02:00
Model.IsServiceRecordNoticeMandatory = settingsValue is null || !settingsValue.Equals("0");
Model.IsServiceRecordGoalMandatory = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.IsServiceRecordGoalMandatory);
2025-06-11 22:56:25 +02:00
//User Settings
var user = LoggedInUser;
var userSettings = user?.Settings.FirstOrDefault(f => f.Type.Equals(SettingsType.ApplicationSettings))?.Value;
2025-06-11 22:56:25 +02:00
Model.ShowExpiredSupportConcepts = UserSettingsUtils.GetSettingValueAsBool(userSettings, SettingsKeys.ShowExpiredSupportConcepts);
Model.ShowOnlyOwnSupportConcepts = UserSettingsUtils.GetSettingValueAsBool(userSettings, SettingsKeys.ShowOnlyMySupportConcepts);
Model.IsOnlyYearMonthVisible = UserSettingsUtils.GetSettingValueAsBool(userSettings, SettingsKeys.IsOnlyYearMonthVisible);
2025-06-11 22:56:25 +02:00
Model.LastSelectedServiceRecordMonth = UserSettingsUtils.GetSettingValueAsDateTime(userSettings, SettingsKeys.LastSelectedServiceRecordMonth) ?? DateTime.Today;
2017-02-01 13:53:59 +01:00
2025-06-11 22:56:25 +02:00
//int zeitraum;
var serviceRecordTimeInterval = UserSettingsUtils.GetSettingValueAsEnum(userSettings, SettingsKeys.LastSelectedServiceRecordTimeInterval, ServiceRecordTimeInterval.LastWeek);
2017-02-01 13:53:59 +01:00
2025-06-11 22:56:25 +02:00
Model.ServiceRecordTimeInterval = serviceRecordTimeInterval;
2025-06-11 22:56:25 +02:00
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);
}
2017-02-01 13:53:59 +01:00
2025-06-11 22:56:25 +02:00
Model.LastSelectedServiceRecordTimeIntervalDays = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.LastSelectedServiceRecordTimeIntervalDays);
2016-06-27 01:45:38 +02:00
2025-06-11 22:56:25 +02:00
if (Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.Monatsauswahl)
{
Model.SelectedZeitraum = new NullableDateTimeSpan(Model.LastSelectedServiceRecordMonth.Date.GetFirstOfMonth(), Model.LastSelectedServiceRecordMonth.Date.GetLastOfMonth());
}
Model.AiVoiceMode = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.AiVoiceMode);
2025-06-11 22:56:25 +02:00
CalculateSelectedDayCount(Model.LastSelectedServiceRecordTimeIntervalDays, Model.LastSelectedServiceRecordMonth, Model.SelectedZeitraum?.StartDate, Model.SelectedZeitraum?.EndDate, null);
2016-06-27 01:45:38 +02:00
2025-06-11 22:56:25 +02:00
var customerFilter = MobileUserSettingsUtils.GetSettingValueAsEnum(userSettings, SettingsKeys.CustomerFilterInZeiterfassung, CustomerFilterEnum.MyCustomer);
if (user.CheckForAtLeastOneRight(new List<UserRightType> { UserRightType.ViewAll, UserRightType.SupportConcept_ViewAllSupportConcepts }))
{
//do nothing, darf alles sehen
}
else if (user.HasRight(UserRightType.SupportConcept_ViewMyTeams))
{
if (customerFilter == CustomerFilterEnum.All)
{
customerFilter = CustomerFilterEnum.MyCustomer;
}
}
else
2025-06-11 22:56:25 +02:00
{
customerFilter = CustomerFilterEnum.MyCustomer;
}
//if (Model.SelectedSupportConceptFilter == null)
2025-06-11 22:56:25 +02:00
Model.SelectedSupportConceptFilter = customerFilter;
Model.IsEndDateVisible = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.IsEndDateVisible);
if (Model.IsZeiterfassungInStdMin)
{
var letzteZeiterfassungsdauer = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.LetzteZeiterfassungsDauer);
Model.IsShowingDurationInHours = letzteZeiterfassungsdauer == 1;
}
}
private void LoadSupportConceptThings(long? cb2ScOid, bool loadTextModules)
{
Model.SelectedCostBearerSupportConceptOid = cb2ScOid;
2025-10-09 12:56:32 +02:00
var istEinzelBuchung = !Model.IsInGroupBookingMode && !Model.IsInMultiBookingMode;
2025-10-09 12:56:32 +02:00
if(istEinzelBuchung)
{
Model.SelectedSupportConcept = Model.SupportConcepts.FirstOrDefault(sc => sc.CostBearerRelOids.Any(a => a.Equals(Model.SelectedCostBearerSupportConceptOid)));
}
// Im Einzelbuchungsmodus entweder nichts oder "Hilfeplan auswählen" (-1) ausgewählt.
2025-10-09 12:56:32 +02:00
if(istEinzelBuchung && (!cb2ScOid.HasValue || cb2ScOid.Value == -1))
{
Model.Categories2Descriptions = new Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>>();
Model.SelectedGoalOids = new List<long>();
}
else
{
var allC2SOids = new List<long>();
2025-10-09 12:56:32 +02:00
if(!istEinzelBuchung)
{
allC2SOids = Model.GroupBookingSelectedCostBearerSupportConceptOids;
}
else if(cb2ScOid > 0)
{
allC2SOids.Add(cb2ScOid.Value);
}
var scOids = Model.SupportConceptListObjects.Where(sc => allC2SOids.Contains(sc.CostBearer2SupportConceptOid)).Select(s => s.SupportConceptOid).ToList();
var infos = OperationsService.GetSupportConceptTreeNodeDetailInfos(scOids);
LoadServiceCategoriesToModel(infos);
LoadGoals(infos);
2025-10-09 12:56:32 +02:00
if(istEinzelBuchung && Model.SelectedSupportConcept != null && infos.Count == 1)
{
Model.SelectedSupportConcept.Goals = infos[0].SupportConceptGoals;
}
2025-10-09 12:56:32 +02:00
if(Model.SupportConcepts != null)
{
2025-10-09 12:56:32 +02:00
foreach(var info in infos)
{
var sc = Model.SupportConcepts.FirstOrDefault(s => s.SupportConceptOid == info.SupportConceptOid);
2025-10-09 12:56:32 +02:00
if(sc != null)
{
sc.Goals = info.SupportConceptGoals;
}
}
}
}
var customerOid = Model.SelectedSupportConcept?.Customer?.CustomerOid;
CompactCustomerDC compactCustomer = null;
if(customerOid.HasValue)
{
compactCustomer = CustomerService.GetCompactCustomerDC(customerOid.Value);
}
// Ist der Klient abwesend, wird dies wie im FaC angezeigt
if (compactCustomer?.AbsenceTimes?.Any() ?? false)
{
foreach(var absenceTime in compactCustomer.AbsenceTimes)
{
2025-10-09 12:56:32 +02:00
if(absenceTime.Start.HasValue && DateTime.Now > absenceTime.Start.Value && (absenceTime.End is null || DateTime.Now < absenceTime.End.Value))
{
Model.IsCustomerAbsence = true;
Model.CustomerAbsenceInfo = $"{absenceTime.Reason.Description} von {absenceTime.Start:dd.MM.yyyy} bis {(absenceTime.End.HasValue ? absenceTime.End.Value.ToString("dd.MM.yyyy") : "unbekannt")}";
break;
}
Model.IsCustomerAbsence = false;
Model.CustomerAbsenceInfo = null;
}
}
else
{
Model.IsCustomerAbsence = false;
Model.CustomerAbsenceInfo = null;
}
2025-10-09 12:56:32 +02:00
if(loadTextModules)
{
LoadTextModules();
}
}
2025-06-11 22:56:25 +02:00
public void LoadTextModules()
{
Model.TextModules.Clear();
if (Model.SelectedServiceCategoryOid.HasValue && (Model.LoggedInEmployee?.EmployeeOid.HasValue ?? false))
{
var allTextModules = OperationsService.GetTextModules(Model.HasRightToSeeGlobalTextModules, Model.LoggedInEmployee.EmployeeOid.Value, Model.HasRightToSeeGlobalTextModules, false);
foreach (var tm in allTextModules.Where(textModule => textModule.IsParent == false))
2016-06-27 01:45:38 +02:00
{
2025-06-11 22:56:25 +02:00
if (string.IsNullOrWhiteSpace(tm.Text))
{
tm.Text = tm.Name;
}
2016-06-27 01:45:38 +02:00
}
2025-06-11 22:56:25 +02:00
Model.AllTextModules = allTextModules.Where(tb => tb.TextModuleOid.HasValue).Select(tb => new TextbausteinDisplayItem(tb.Name, tb.Text, tb.Parent?.TextModuleOid, tb.TextModuleOid.Value, tb.IsExpanded)).ToList();
var x = allTextModules.Where(
w => (w.ServiceCategory is null || w.ServiceCategory.ServiceCategoryOid == Model.SelectedServiceCategoryOid.Value)
&& !string.IsNullOrEmpty(w.Text)
&& (w.IsOnlyForEmployee && w.Employee.EmployeeOid.Equals(Model.LoggedInEmployee.EmployeeOid) || !w.IsOnlyForEmployee)).OrderBy(t => t.Text).ToList();
x.AddRangeIfElementsNotIn(BS.Shared.Core.Utils.GetParentTextModules(x));
var textModuleDisplayItems = x.Where(tb => tb.TextModuleOid.HasValue).Select(tb => new TextbausteinDisplayItem(tb.Name, tb.Text, tb.Parent?.TextModuleOid, tb.TextModuleOid.Value, tb.IsExpanded)).ToList();
foreach (var item in textModuleDisplayItems)
{
2025-06-11 22:56:25 +02:00
if (item.ParentOid is null)
{
2025-06-11 22:56:25 +02:00
continue;
}
2025-06-11 22:56:25 +02:00
var parent = textModuleDisplayItems.FirstOrDefault(p => p.Oid == item.ParentOid);
2025-06-11 22:56:25 +02:00
parent?.Children.AddIfNotIn(item);
}
foreach (var item in textModuleDisplayItems)
{
if (item.Children != null)
{
item.Children = item.Children.OrderBy(c => c.Name).ToList();
}
}
2025-06-11 22:56:25 +02:00
Model.TextModules = textModuleDisplayItems.Where(item => item.ParentOid is null).OrderBy(item => item.Name).ToList();
}
}
private IList<CompactSupportConceptDC> GetSelectedGroupBookingSupportConcepts()
{
2025-10-09 12:56:32 +02:00
if(Model.SupportConcepts is null || Model.SupportConcepts.Count == 0)
{
CreateModelSupportConceptListObjects(true);
}
var list = Model.SupportConcepts.Where(sc => sc.CostBearerRelOids.Count > 0 && Model.GroupBookingSelectedCostBearerSupportConceptOids.Contains(sc.CostBearerRelOids[0])).ToList();
return list;
}
2025-07-17 16:26:07 +02:00
public ServiceRecordDC GetServiceRecordDC(long serviceRecordOid, bool getCompact)
{
ServiceRecordDC dc = null;
2026-05-11 12:42:57 +02:00
if(_Model != null)
2025-07-17 16:26:07 +02:00
{
dc = _Model.FindServiceRecord(serviceRecordOid);
}
2026-05-11 12:42:57 +02:00
if(dc is null)
2025-07-17 16:26:07 +02:00
{
var sr = DAOFactory.GenericDAO.LoadByID<ServiceRecord>(serviceRecordOid);
2026-05-11 12:42:57 +02:00
try
{
NHibernateUtil.Initialize(sr);
}
catch(ObjectNotFoundException exception)
{
TempData[TempDataConstants.ErrorAlertPopupMessage] = "Der ausgewählte Eintrag wurde in der Zwischenzeit gelöscht. Bearbeiten nicht möglich.";
return null;
}
if(getCompact)
2025-07-17 16:26:07 +02:00
{
2026-05-11 12:42:57 +02:00
dc = new ServiceRecordDC
2025-07-17 16:26:07 +02:00
{
Betrag = sr.Betrag,
CostBearer2SupportConceptOid = sr.CostBearer2SupportConceptOid,
DistanceInMeter = (int?)sr.DistanceInMeter,
DistanceInMeterDecimal = sr.DistanceInMeter,
DurationInStunden = sr.DurationInStunden,
End = sr.End,
GroupEmployeeCount = sr.GroupEmployeeCount,
GroupOid = sr.GroupOid,
GroupPersonCount = sr.GroupPersonCount,
GroupRoundedDuration = sr.GroupRoundedDuration,
InsertedOn = sr.InsTs,
InsUser = sr.InsUser,
Notice = sr.Notice,
Notice2 = sr.Notice2,
Notice3 = sr.Notice3,
Notice4 = sr.Notice4,
Notice5 = sr.Notice5,
Relevance = sr.Relevance,
RoundedDuration = sr.RoundedDuration,
ServiceRecordFormat = sr.ServiceRecordFormat,
ServiceRecordType = sr.ServiceRecordType ?? ServiceRecordTypeId.DefaultActivity,
ServiceRecordVersion = sr.Version,
SignatureOid = sr.SignatureOid,
WohnheimbuchungsOid = sr.WohnheimbuchungsOid,
ServiceRecordOid = sr.Oid,
Start = sr.Start
};
2026-05-11 12:42:57 +02:00
2025-07-17 16:26:07 +02:00
return dc;
}
2026-05-11 12:42:57 +02:00
2025-07-17 16:26:07 +02:00
dc = MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDC(sr);
}
return dc;
}
2025-06-11 22:56:25 +02:00
[Authorize]
public ActionResult Main()
{
try
{
if(false == MobileSessionFacade.IsUserLoggedIn() || Request.Browser.Browser.Equals("InternetExplorer"))
{
2025-06-11 22:56:25 +02:00
var isNewSession = Session.IsNewSession;
if(isNewSession)
{
TempData[TempDataConstants.AutoEndOfSessionLogoutMessageKey] = "Sie wurden automatisch abgemeldet, da Ihre Session abgelaufen ist.";
}
return Logout();
}
if(false == Model.SessionInitialized)
2025-06-11 22:56:25 +02:00
{
Model.SessionInitialized = true;
var mokSessionTimeout = UserSettingsUtils.GetSettingValueAsInteger(Model.Mandator.Settings, SettingsKeys.MoKSessionTimeout, 20);
2025-06-11 22:56:25 +02:00
Session.Timeout = mokSessionTimeout;
2025-06-11 22:56:25 +02:00
Model.IsPasswordSecurityEnabled = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.IsPasswordSecurityActiv);
2025-06-11 22:56:25 +02:00
if(Model.IsPasswordSecurityEnabled)
2021-04-12 20:32:10 +02:00
{
2025-06-11 22:56:25 +02:00
var tempDataValue = string.Empty;
2021-04-12 20:32:10 +02:00
2025-06-11 22:56:25 +02:00
switch(MobileSessionFacade.PasswordStrength)
2021-04-12 20:32:10 +02:00
{
2025-06-11 22:56:25 +02:00
case 0:
tempDataValue = "Sie benutzen ein sehr schwaches Passwort.<br><br>Bitte &auml;ndern Sie Ihr Passwort, indem Sie im Men&uuml; auf 'Password &auml;ndern' klicken.";
break;
case 1:
tempDataValue = "Sie benutzen ein schwaches Passwort.<br><br>Bitte &auml;ndern Sie Ihr Passwort, indem Sie im Men&uuml; auf 'Password &auml;ndern' klicken.";
break;
2021-04-12 20:32:10 +02:00
}
if(false == string.IsNullOrEmpty(tempDataValue))
2025-06-11 22:56:25 +02:00
{
TempData[TempDataConstants.ShowPwChPopupKey] = tempDataValue;
}
2021-04-12 20:32:10 +02:00
}
}
if(TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] is SchedulerAppointmentDC occurrenceToInsert)
{
TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] = occurrenceToInsert;
}
2016-06-27 01:45:38 +02:00
}
catch(Exception e)
2016-06-27 01:45:38 +02:00
{
Log.Error(e.Message, e);
2016-06-27 01:45:38 +02:00
}
return View(Model);
}
[Authorize]
private void UpdateSettings(string key, string value)
{
if(Model is null)
{
return;
}
2025-06-11 22:56:25 +02:00
var loggedInUser = LoggedInUser;
if(loggedInUser?.UserOid is null)
{
return;
}
var userSettings = loggedInUser.Settings;
UserSettingsUtils.SetSettingValue(SettingsType.ApplicationSettings, key, value, userSettings);
UserService.UpdateUserSettings(loggedInUser.UserOid.Value, userSettings);
}
[HttpPost]
[Authorize]
public ActionResult SetShowExpiredSupportConcepts(FormCollection pCollection)
{
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
SkipModelInitialization = true;
var newValue = "true,false" == pCollection[FormCollectionConstants.ShowExpiredSupportConceptsKey];
UpdateApplicationSettings(SettingsKeys.ShowExpiredSupportConcepts, newValue ? "1" : "0");
Model.ShowExpiredSupportConcepts = newValue;
Model.SupportConceptListObjects.Clear(); // Erzwingt das neu laden
return RedirectToAction("Main");
}
[HttpPost]
public new ActionResult Logout()
{
return base.Logout();
}
private List<ValueListEntryDC> LoadAvailableGoals()
{
var availableGoals = new List<ValueListEntryDC>();
if(Model.IsInGroupBookingMode)
{
var list = GetSelectedGroupBookingSupportConcepts();
LoadSupportConceptThings(null, false);
list.DoForEach(sc => { availableGoals.AddRangeIfElementsNotIn(sc.Goals); });
}
else
{
availableGoals = GetAllGoalsForSelectedSupportConcept();
}
return availableGoals;
}
2016-06-27 01:45:38 +02:00
[Authorize]
2021-06-16 15:11:39 +02:00
public string RateSelectedGoal(long? ratingTypeOid, long? goalOid)
2016-06-27 01:45:38 +02:00
{
2025-06-11 22:56:25 +02:00
if(Model is null || ratingTypeOid is null || goalOid is null || !Model.HasRightToRateGoals)
{
return LeerzeichenFuerGetMethoden;
}
var rating = Model.GoalRatingTypes.FirstOrDefault(ratingType => ratingType.RatingTypeOid == ratingTypeOid);
var allGoals = LoadAvailableGoals();
var goal = allGoals.FirstOrDefault(g => g.ValueListEntryOid?.Equals(goalOid.Value) ?? false);
if(goal != null)
{
if(!Model.SelectedGoals.Any(a => a.ValueListEntryOid.HasValue && a.ValueListEntryOid.Value == goal.ValueListEntryOid))
{
Model.SelectedGoals.AddIfNotIn(DcToMokMapper.CreateZiel(goal));
}
goal.RatingTypeOid = ratingTypeOid;
var selectedGoal = Model.SelectedGoals.FirstOrDefault(a => a.ValueListEntryOid.HasValue && a.ValueListEntryOid.Value == goal.ValueListEntryOid);
if(!(selectedGoal is null))
{
selectedGoal.RatingTypeOid = ratingTypeOid;
}
2021-06-16 15:11:39 +02:00
}
return SerializeObject(new GoalRating(rating?.DisplayName ?? string.Empty, goal?.ValueListEntryOid ?? 0));
2021-06-16 15:11:39 +02:00
}
private List<ValueListEntryDC> _AllGoals;
private List<ValueListEntryDC> GetAllGoalsForSelectedSupportConcept()
{
if(Model?.SelectedSupportConcept?.Goals is null)
{
return new List<ValueListEntryDC>();
}
if(_AllGoals is null)
{
_AllGoals = new List<ValueListEntryDC>(Model.SelectedSupportConcept.Goals);
}
LoadParentGoals(Model.SelectedSupportConcept.Goals);
return _AllGoals;
}
private void LoadParentGoals(IEnumerable<ValueListEntryDC> goals)
{
var parentGoalOids = goals.Where(goal => goal.ParentOid.HasValue).Select(goal => goal.ParentOid.Value).Distinct().ToList();
var parentGoals = CustomerService.GetSupportConceptGoalParents(parentGoalOids);
_AllGoals.AddRangeIfElementsNotIn(parentGoals);
var nextParentGoalOids = parentGoals.Where(goal => goal.ParentOid.HasValue).Select(goal => goal.ParentOid.Value).Distinct().ToList();
if(nextParentGoalOids.Any())
{
LoadParentGoals(parentGoals);
}
}
private void LoadGoals(List<SupportConceptTreeNodeDetailInfoDC> infos)
{
try
2016-06-27 01:45:38 +02:00
{
var selectedGoals = new List<ValueListEntryDC>();
foreach (var item in infos)
{
selectedGoals.AddRange(item.SupportConceptGoals);
}
2016-06-27 01:45:38 +02:00
//if(Model.IsInGroupBookingMode)
//{
// var supportConcepts = GetSelectedGroupBookingSupportConcepts();
2016-06-27 01:45:38 +02:00
// supportConcepts.DoForEach(sc => { selectedGoals.AddRangeIfElementsNotIn(sc.Goals); });
//}
//else
//{
// if(Model.SelectedCostBearerSupportConceptOid is null)
// {
// return;
// }
2021-06-16 15:11:39 +02:00
// var supportConcept = Model.SupportConcepts.FirstOrDefault(sc => sc.CostBearerRelOids.Any(c2sOid => c2sOid.Equals(Model.SelectedCostBearerSupportConceptOid.Value)));
2016-06-27 01:45:38 +02:00
// if(supportConcept is null)
// {
// if (Model.SelectedCostBearerSupportConceptOid.Value > 0)
// {
// Log.Info($"Hilfeplan von Bewilligung mit Oid {Model.SelectedCostBearerSupportConceptOid} nicht gefunden beim Laden der Ziele (LoadGoals).");
// }
// return;
// }
// Model.SelectedSupportConcept = supportConcept;
// selectedGoals = supportConcept.Goals;
//}
var missingParents = selectedGoals.Where(w => w.ParentOid != null && false == selectedGoals.Any(a => a.ValueListEntryOid.Equals(w.ParentOid))).Select(s => s.ParentOid).ToList();
_ParentGoals = new Dictionary<long, ValueListEntryDC>();
foreach(var oid in missingParents)
{
if(oid.HasValue)
{
LoadMissingParents(oid.Value);
}
}
2016-06-27 01:45:38 +02:00
var allGoals = selectedGoals.Union(_ParentGoals.Values).ToList();
2025-06-11 22:56:25 +02:00
Model.AllGoals = allGoals;
Model.GoalTree = BuildGoalTree(Model.AllGoals);
}
catch(Exception exception)
{
Log.Error(exception);
}
2016-06-27 01:45:38 +02:00
}
2021-06-16 15:11:39 +02:00
private List<GoalTreeItem> BuildGoalTree(IReadOnlyCollection<ValueListEntryDC> goals)
2016-06-27 01:45:38 +02:00
{
var ziele = goals.Where(w => _GoalTypes.Contains(w.Type)).OrderBy(s => s.OrderedDisplayName).ToList();
var massnahmen = goals.Where(w => _MeasureTypes.Contains(w.Type)).OrderBy(s => s.OrderedDisplayName).ToList();
2016-06-27 01:45:38 +02:00
var goalTree = new List<GoalTreeItem>();
var goalTreeDic = new Dictionary<long, GoalTreeItem>();
var goalsWithRating = Model.SelectedServiceRecord?.Goals?.Where(goal => goal.RatingTypeOid.HasValue).ToList() ?? new List<ValueListEntryDC>();
2021-06-16 15:11:39 +02:00
var ratingTypes = OperationsService.GetRatingTypesByOids(goalsWithRating.Where(goal => goal.RatingTypeOid.HasValue).Select(goal => goal.RatingTypeOid.Value).Distinct().ToList());
2016-06-27 01:45:38 +02:00
foreach(var ziel in ziele)
2016-06-27 01:45:38 +02:00
{
if(ziel.ValueListEntryOid is null)
{
continue;
}
var treeItem = new GoalTreeItem(true, ziel.Type)
{
Children = new List<GoalTreeItem>(),
Header = ziel.DisplayName ?? string.Empty,
ParentOid = ziel.ParentOid,
ValueListEntryOid = ziel.ValueListEntryOid
};
goalTreeDic.Add(ziel.ValueListEntryOid.Value, treeItem);
2016-06-27 01:45:38 +02:00
if(ziel.ParentOid is null)
2016-06-27 01:45:38 +02:00
{
goalTree.Add(treeItem);
}
}
foreach(var zielMitEltern in goalTreeDic.Values.Where(zielMitEltern => zielMitEltern.ParentOid != null))
2016-06-27 01:45:38 +02:00
{
if(zielMitEltern.ParentOid is null)
{
continue;
}
if (goalTreeDic.ContainsKey(zielMitEltern.ParentOid.Value))
{
goalTreeDic[zielMitEltern.ParentOid.Value].Children.Add(zielMitEltern);
}
2016-06-27 01:45:38 +02:00
}
foreach(var ziel in massnahmen)
2016-06-27 01:45:38 +02:00
{
2021-06-16 15:11:39 +02:00
var ratingName = Model.HasAnyRatingTypes ? "Bewerten" : string.Empty;
var goalWithRating = goalsWithRating.FirstOrDefault(g => g.ValueListEntryOid == ziel.ValueListEntryOid);
if(Model.HasAnyRatingTypes && Model.IsInEditingMode && goalWithRating != null && ratingTypes.Any())
{
var ratingType = ratingTypes.FirstOrDefault(rt => rt.RatingTypeOid == goalWithRating.RatingTypeOid);
if(ratingType != null)
{
ratingName = ratingType.DisplayName;
}
}
var kind = new GoalTreeItem(false, ziel.Type)
{
Children = new List<GoalTreeItem>(),
Header = ziel.DisplayName ?? string.Empty,
IsLeaf = true,
ValueListEntryOid = ziel.ValueListEntryOid,
RatingName = ratingName,
ParentOid = ziel.ParentOid
};
if(ziel.ParentOid is null || !goalTreeDic.ContainsKey(ziel.ParentOid.Value))
2016-06-27 01:45:38 +02:00
{
continue;
2016-06-27 01:45:38 +02:00
}
kind.ParentOid = goalTreeDic[ziel.ParentOid.Value].ParentOid;
goalTreeDic[ziel.ParentOid.Value].Children.Add(kind);
2016-06-27 01:45:38 +02:00
}
foreach(var item in goalTreeDic.Values.Where(item => item.Children.Count == 0))
{
item.IsLeaf = true;
}
2016-06-27 01:45:38 +02:00
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);
}
}
2016-06-27 01:45:38 +02:00
private void LoadMissingParents(long pParentOid)
{
while(true)
2016-06-27 01:45:38 +02:00
{
var parentDC = ValueListService.GetValueListEntryByOid(pParentOid);
if(parentDC?.ValueListEntryOid is null || parentDC?.IsActive == false)
{
break;
}
if(!_ParentGoals.ContainsKey(parentDC.ValueListEntryOid.Value))
2016-06-27 01:45:38 +02:00
{
_ParentGoals.Add(parentDC.ValueListEntryOid.Value, parentDC);
2016-06-27 01:45:38 +02:00
if(parentDC.ParentOid != null)
2016-06-27 01:45:38 +02:00
{
pParentOid = parentDC.ParentOid.Value;
continue;
}
}
break;
}
}
[Authorize]
2016-06-27 01:45:38 +02:00
public string LoadStatistics(long oid)
{
try
{
if (Model is null)
2016-06-27 01:45:38 +02:00
{
Logout();
return LeerzeichenFuerGetMethoden;
2016-06-27 01:45:38 +02:00
}
var isLoaded = false;
foreach(var supportConcept in Model.SupportConcepts)
{
if(supportConcept.CostBearerRelOids.Any(c2sOid => c2sOid == oid))
{
isLoaded = true;
}
if(isLoaded)
{
break;
}
}
if(!isLoaded)
{
return null;
}
2021-04-13 19:45:21 +02:00
var statisticsInfo = OperationsService.GetServiceRecordStatisticInfo(oid, DateTime.Now);
2016-06-27 01:45:38 +02:00
2021-04-13 19:45:21 +02:00
var supportConceptStatisticsData = new SupportConceptStatisticsData();
if(statisticsInfo != null)
2019-09-17 17:44:57 +02:00
{
2021-04-13 19:45:21 +02:00
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}";
2019-09-17 17:44:57 +02:00
2021-04-13 19:45:21 +02:00
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++;
}
2019-09-17 17:44:57 +02:00
}
2021-04-13 19:45:21 +02:00
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);
2021-04-13 19:45:21 +02:00
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}"));
2021-04-13 19:45:21 +02:00
supportConceptStatisticsData.StatisticPeriods.Add(statisticPeriod);
}
2021-04-13 19:45:21 +02:00
foreach(var periodStatistics in supportConceptStatistics.PeriodStatistics)
{
provided = periodStatistics.MinutesProvidedThisWeek / 60;
approved = periodStatistics.MinutesApprovedPerWeek / 60;
freePerWeek = periodStatistics.MinutesFreePerWeek / 60;
2021-04-13 19:45:21 +02:00
providedTotal = periodStatistics.MinutesProvidedTotalRounded / 60;
approvedTotal = periodStatistics.MinutesApprovedTotal / 60;
freePerWeekTotal = (approvedTotal - providedTotal);
2021-04-13 19:45:21 +02:00
var supportConceptApprovalPeriodSpan = periodStatistics.SupportConceptApprovalPeriod.Span;
2021-04-29 15:33:01 +02:00
var minVal = DateTime.Now.AddYears(-50);
var maxVal = DateTime.Now.AddYears(50);
var sd = supportConceptApprovalPeriodSpan.StartDate;
var ed = supportConceptApprovalPeriodSpan.EndDate;
2021-04-29 15:33:01 +02:00
var start = sd > minVal && sd < maxVal ? $"{sd:dd.MM.yy} " : string.Empty;
var end = ed > minVal && ed < maxVal ? $" {ed:dd.MM.yy}" : string.Empty;
2021-04-29 15:33:01 +02:00
var span = $"{start}-{end}";
var serviceCategoryName = periodStatistics.SupportConceptApprovalPeriod.ServiceCategory != null ? periodStatistics.SupportConceptApprovalPeriod.ServiceCategory.Name + ":" : "Bewilligungszeitraum:";
2021-04-13 19:45:21 +02:00
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);
2016-06-27 01:45:38 +02:00
}
catch (Exception e)
{
Log.Error(e.Message, e);
2016-06-27 01:45:38 +02:00
return SerializeObject("Fehler 560");
}
}
[Authorize]
[HttpPost]
public override ActionResult SaveSignature(FormCollection formCollection)
2016-06-27 01:45:38 +02:00
{
try
2016-06-27 01:45:38 +02:00
{
var blob = formCollection[FormCollectionConstants.ServiceRecordSignatureBlobKey];
var date = DateTime.Parse(formCollection[FormCollectionConstants.ServiceRecordSignatureDateKey]);
2025-01-17 16:21:58 +01:00
long.TryParse(formCollection[FormCollectionConstants.ServiceRecordSignatureObjOidKey], out var objectOid);
if(objectOid <= 0)
2025-01-17 16:21:58 +01:00
{
//return RedirectToAction("Main", "Main", Model);
return RedirectToActionPermanent("Main", "Main");
}
2016-06-27 01:45:38 +02:00
var serviceRecord = GetServiceRecordDC(objectOid, false);
if(serviceRecord is null)
{
Log.Error("Einzelunterschrift konnte nicht gespeichert werden, da der Zeiterfassungseintrag im Model nicht gefunden werden konnte.");
TempData[TempDataConstants.ErrorMessageKey] = "Beim Speichern der Unterschrift ist ein Fehler aufgetreten. Bitte wenden Sie sich an Ihren Administrator.";
//return RedirectToAction("Main", "Main", Model);
return RedirectToActionPermanent("Main", "Main");
}
2016-06-27 01:45:38 +02:00
long? oid;
2025-11-24 17:26:11 +01:00
using(var signatureBitmap = SignatureUtils.Base64StringToBitmap(blob.Split(',')[1]))
2025-01-17 16:21:58 +01:00
{
var isValid = SignatureUtils.ValidateSignature(signatureBitmap);
2025-11-24 17:26:11 +01:00
if(!isValid)
{
TempData[TempDataConstants.ErrorMessageKey] = "Das Unterschriftenfeld darf nicht leer sein.";
//return RedirectToAction("Main", "Main", Model);
return RedirectToActionPermanent("Main", "Main");
}
oid = OperationsService.InsertSignature(new SignatureDC
{
DataBild = blob,
Zeitstempel = date,
ServiceRecordOid = objectOid
}).SignatureOid;
Log.Info(String.Format("Unterschrift (Oid {0}) erfolgreich gespeichert für ServiceRecord {1}", oid, objectOid));
}
2025-11-24 17:26:11 +01:00
if(oid is null)
2025-01-17 16:21:58 +01:00
{
TempData[TempDataConstants.ErrorMessageKey] = "Beim Speichern der Unterschrift ist ein Fehler aufgetreten. Bitte wenden Sie sich an Ihren Administrator.";
}
else
{
TempData[TempDataConstants.InfoMessageKey] = $"Die Unterschrift von {serviceRecord.Customer} für den Eintrag vom {MainModel.GetServiceRecordTimeHeader(serviceRecord, false)} wurde erfolgreich gespeichert.";
}
2016-06-27 01:45:38 +02:00
}
2025-11-24 17:26:11 +01:00
catch(Exception ex)
2025-01-17 16:21:58 +01:00
{
Log.Error("Fehler beim Speichern der Einzelunterschrift: " + ex.Message, ex);
2025-01-17 16:21:58 +01:00
}
//return RedirectToAction("Main", "Main", Model);
return RedirectToActionPermanent("Main", "Main");
}
[Authorize]
public static string ApplyWatermark(string blob, string watermarkImagePath)
{
if(string.IsNullOrWhiteSpace(blob))
{
return null;
}
var watermarkImage = Image.FromFile(watermarkImagePath);
var signatureImage = SignatureUtils.Base64StringToBitmap(blob);
var hasTransparentBackground = SignatureUtils.HasTransparentBackground(blob);
if(hasTransparentBackground)
{
signatureImage = SignatureUtils.AddBackgroundToBitmap(signatureImage, Color.White);
}
var watermarker = new Watermarker(signatureImage);
for(var y = 0; y < signatureImage.Height; y++)
2016-06-27 01:45:38 +02:00
{
for(var x = 0; x < signatureImage.Width; x++)
2016-06-27 01:45:38 +02:00
{
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;
2016-06-27 01:45:38 +02:00
}
y += watermarkImage.Height;
2016-06-27 01:45:38 +02:00
}
return "data:image/png;base64," + SignatureUtils.ConvertImageToBase64String(watermarker.Image);
2016-06-27 01:45:38 +02:00
}
[Authorize]
public string LoadCompleteTextbausteinByOid(long pTextbausteinOid)
2017-04-26 14:57:32 +02:00
{
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()
{
2025-10-09 12:56:32 +02:00
if(!IsUserLoggedIn())
2017-04-26 14:57:32 +02:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
return PartialView("TextModulePartial");
}
2025-10-09 12:56:32 +02:00
//Wird alles im InitViewModel gemacht
return PartialView("TextModulePartial", Model);
2017-04-26 14:57:32 +02:00
}
2016-06-27 01:45:38 +02:00
2020-04-08 14:44:20 +02:00
[HttpPost]
[Authorize]
public ActionResult CreateOrUpdateServiceRecord(FormCollection collection)
{
try
{
if(Model is null)
2020-04-08 14:44:20 +02:00
{
2025-06-11 22:56:25 +02:00
Log.Info($"Model ist null bei CreateOrUpdateServiceRecord; User: {LoggedInUser.UserOid} {LoggedInUser.LoginName} ({LoggedInUser.Employee})");
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
2020-04-08 14:44:20 +02:00
}
// Falls ein Termin in die Zeiterfassung übernommen werden soll
2025-06-11 22:56:25 +02:00
SchedulerAppointmentDC appointmentPrototype = null;
if(Model.TransferringAppointmentOid.HasValue && Model.LoggedInEmployee.EmployeeOid.HasValue)
{
var app = DAOFactory.GenericDAO.LoadByID<SchedulerAppointment>(Model.TransferringAppointmentOid.Value);
2025-06-11 22:56:25 +02:00
appointmentPrototype = MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDC(app);
}
else if(TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] is SchedulerAppointmentDC occurrenceToInsert)
{
appointmentPrototype = occurrenceToInsert;
}
var marker = "on" == collection[FormCollectionConstants.MarkerKey];
2020-04-08 14:44:20 +02:00
2025-08-08 13:45:37 +02:00
var doku1 = Model.Dokutypes?.Length > 0 ?
collection[FormCollectionConstants.Dokumentation1Key] :
collection[FormCollectionConstants.Dokumentation6Key];
2020-04-08 14:44:20 +02:00
decimal? betrag = null;
var betragAsString = collection[FormCollectionConstants.BetragKey]?.Replace('.', ',');
if(decimal.TryParse(betragAsString, out var betragAsDecimal))
{
betrag = betragAsDecimal;
}
Log.Info($"CreateOrUpdateServiceRecord: datum:{collection[FormCollectionConstants.DateKey]}; start:{collection[FormCollectionConstants.StartKey]}; ende:{collection[FormCollectionConstants.EndKey]}; dauer:{collection[FormCollectionConstants.DurationKey]}; aktion:{(Model.IsInEditingMode ? "Speichern" : "Anlegen")}");
2020-04-08 14:44:20 +02:00
if(string.IsNullOrEmpty(collection[FormCollectionConstants.DateKey]))
2020-04-08 14:44:20 +02:00
{
Log.Info($"CreateOrUpdateServiceRecord: Das Startdatum ist null. Breche das {(Model.IsInEditingMode ? "Speichern" : "Anlegen")} ab.");
2020-04-08 14:44:20 +02:00
return View("Main", Model);
}
var distanz = collection[FormCollectionConstants.DistanceKey];
2023-05-23 13:56:22 +02:00
decimal? distanceInMeters = null;
2020-04-08 14:44:20 +02:00
if(false == string.IsNullOrEmpty(distanz))
2020-04-08 14:44:20 +02:00
{
2023-05-23 13:56:22 +02:00
if(decimal.TryParse(distanz, out var parsedDistance))
2020-04-08 14:44:20 +02:00
{
distanceInMeters = parsedDistance;
}
}
2025-06-11 22:56:25 +02:00
var selectedCostbearerScRelOid = Model.SelectedCostBearerSupportConceptOid < 1 ? null : Model.SelectedCostBearerSupportConceptOid;
var datum = Convert.ToDateTime(collection[FormCollectionConstants.DateKey]);
2020-04-08 14:44:20 +02:00
var enddatum = datum;
var endDateString = collection[FormCollectionConstants.EndDateKey];
2024-03-19 19:10:13 +01:00
if(endDateString?.Length > 0)
{
enddatum = Convert.ToDateTime(endDateString);
}
var start = collection[FormCollectionConstants.StartKey];
var ende = collection[FormCollectionConstants.EndKey];
var dauer = 0m;
2020-04-08 14:44:20 +02:00
if(datum > enddatum)
{
enddatum = datum;
}
var durationAsString = collection[FormCollectionConstants.DurationKey];
durationAsString = durationAsString?.Replace('.', ',');
if(false == string.IsNullOrEmpty(durationAsString))
2020-04-08 14:44:20 +02:00
{
decimal.TryParse(durationAsString, out dauer);
2020-04-08 14:44:20 +02:00
}
// 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();
2020-04-08 14:44:20 +02:00
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));
2020-04-08 14:44:20 +02:00
}
else
{
zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer));
2020-04-08 14:44:20 +02:00
}
}
else
{
zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, Convert.ToDouble(dauer)) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, Convert.ToDouble(dauer));
2020-04-08 14:44:20 +02:00
}
if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0])
{
dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes;
}
if(Model.IsInEditingMode)
{
var selectedRecordOid = Model.SelectedServiceRecordOid ?? Model.SelectedServiceRecord.ServiceRecordOid;
2025-07-17 16:26:07 +02:00
Model.NewServiceRecord = GetServiceRecordDC(selectedRecordOid.Value, false);
2020-04-08 14:44:20 +02:00
}
if(Model.NewServiceRecord is null)
2020-04-08 14:44:20 +02:00
{
Log.Info("CreateOrUpdateServiceRecord: NewServiceRecord ist null. Breche ab.");
2020-04-08 14:44:20 +02:00
return RedirectToActionPermanent("Main");
}
Model.NewServiceRecord.IP = Request.UserHostAddress;
Model.NewServiceRecord.Goals = CreateValueListEntriesFromMokZiele(Model.SelectedGoals);
2020-04-08 14:44:20 +02:00
Model.NewServiceRecord.Start = zeitenFeld[0];
Model.NewServiceRecord.End = zeitenFeld[1];
Model.NewServiceRecord.Betrag = betrag;
Model.NewServiceRecord.ServiceRecordType = marker ? ServiceRecordTypeId.Content : ServiceRecordTypeId.DefaultActivity;
Model.NewServiceRecord.DistanceInMeter = null;
2023-05-23 13:56:22 +02:00
Model.NewServiceRecord.DistanceInMeterDecimal = distanceInMeters;
2020-04-08 14:44:20 +02:00
2025-06-11 22:56:25 +02:00
if(Model.LoggedInEmployee.EmployeeOid.HasValue)
2020-04-08 14:44:20 +02:00
{
if(false == Model.IsInEditingMode)
2020-04-08 14:44:20 +02:00
{
2025-06-11 22:56:25 +02:00
Model.NewServiceRecord.Employee = Model.SelectedEmployee ?? LoggedInUser.Employee;
2020-04-08 14:44:20 +02:00
}
else
{
if(Model.SelectedEmployee != null)
2020-04-08 14:44:20 +02:00
{
Model.NewServiceRecord.Employee = Model.SelectedEmployee;
}
}
var mokSupportConceptListObject = Model.SupportConceptListObjects.FirstOrDefault(a => a.CostBearer2SupportConceptOid.Equals(selectedCostbearerScRelOid));
2020-04-08 14:44:20 +02:00
if(mokSupportConceptListObject != null)
2020-04-08 14:44:20 +02:00
{
var sc = GetCompactSupportConcept(mokSupportConceptListObject.SupportConceptOid, selectedCostbearerScRelOid);
Model.NewServiceRecord.SupportConcept = sc;
2020-04-08 14:44:20 +02:00
Model.NewServiceRecord.Customer = sc.Customer;
var costBearer = sc.CostBearerList.FirstOrDefault();
Model.NewServiceRecord.CostBearer = costBearer?.Organisation;
2020-04-08 14:44:20 +02:00
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;
2020-04-08 14:44:20 +02:00
}
else
{
Model.NewServiceRecord.RoundedDuration = dauer;
}
}
Model.NewServiceRecord.DurationInStunden = Model.IsShowingDurationInHours ? ZeiterfassungsDauer.Stunden : ZeiterfassungsDauer.Minuten;
2020-04-08 14:44:20 +02:00
Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung;
if(Model.IsEndDateVisible)
{
Model.NewServiceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum;
}
Model.NewServiceRecord.Notice = string.IsNullOrEmpty(doku1) ? null : doku1?.RemoveUppercaseEsszett();
2020-04-08 14:44:20 +02:00
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();
2020-04-08 14:44:20 +02:00
var serviceDescOid = 0L;
if(false == string.IsNullOrEmpty(collection[FormCollectionConstants.ServiceDescriptionKey]))
2020-04-08 14:44:20 +02:00
{
serviceDescOid = Convert.ToInt64(collection[FormCollectionConstants.ServiceDescriptionKey]);
2020-04-08 14:44:20 +02:00
}
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;
2025-06-11 22:56:25 +02:00
Model.NewServiceRecord.InsUser = MobileSessionFacade.EmployeeFullname;
2020-04-08 14:44:20 +02:00
Model.NewServiceRecord.IsCreatedInMobileClient = true;
if(Model.IsInGroupBookingMode && Model.GroupBookingSelectedCostBearerSupportConceptOids.Count > 1)
2020-04-08 14:44:20 +02:00
{
return Model.NewServiceRecord.ServiceRecordOid.HasValue ? SaveGroupBooking() : UpdateGroupBooking();
}
if(false == Model.IsInEditingMode)
2020-04-08 14:44:20 +02:00
{
2026-05-11 12:42:57 +02:00
//if(Model.NewServiceRecord.CostBearer != null && Model.ShowSignature && (Model.NewServiceRecord.ServiceDescription.Category.IsBillable || Model.NewServiceRecord.ServiceDescription.Category.BillableAmount > 0m || Model.NewServiceRecord.ServiceDescription.BillableAmount > 0m))
//{
2026-05-11 12:49:50 +02:00
var dummystats = new SupportConceptStatisticsDC();
dummystats.PeriodStatistics = new List<SupportConceptPeriodStatisticsDC>();
var valRes = OperationsService.ValidateServiceRecord(Model.NewServiceRecord, dummystats, 0, null, null);
2020-04-08 14:44:20 +02:00
2026-05-11 12:49:50 +02:00
2026-05-11 12:42:57 +02:00
var doppelt = valRes.Count > 0 && valRes.FirstOrDefault(v => v.ResultType == DoppelterEintrag) != null;
2026-05-11 12:42:57 +02:00
if(!doppelt)
{
2026-05-11 12:42:57 +02:00
var oidList = OperationsService.InsertNewServiceRecords(new List<ServiceRecordDC> { Model.NewServiceRecord });
2020-04-08 14:44:20 +02:00
2026-05-11 12:42:57 +02:00
Model.LastCreatedServiceRecordOid = oidList[0];
2026-05-11 12:42:57 +02:00
if(Model.IsAllowedToCreateSignature(Model.NewServiceRecord))
{
if(Model.NewServiceRecord.CostBearer != null && Model.ShowSignature && (Model.NewServiceRecord.ServiceDescription.Category.IsBillable || Model.NewServiceRecord.ServiceDescription.Category.BillableAmount > 0m || Model.NewServiceRecord.ServiceDescription.BillableAmount > 0m))
{
2026-05-11 12:42:57 +02:00
TempData[TempDataConstants.ShowSignatureSuggestionPopup] = true;
}
2026-02-27 13:34:33 +01:00
}
}
2026-05-07 00:47:38 +02:00
//}
2026-05-11 12:42:57 +02:00
// Es wird ein Termin aus dem Kalender in die Zeiterfassung übertragen
2026-03-27 15:22:49 +01:00
if(appointmentPrototype is object)
{
var serviceRecord = OperationsService.GetServiceRecordById(Model.LastCreatedServiceRecordOid);
if(appointmentPrototype.ServiceRecordList is null)
{
appointmentPrototype.ServiceRecordList = new List<ServiceRecordDC>();
}
appointmentPrototype.ServiceRecordList.AddIfNotIn(serviceRecord);
if(appointmentPrototype.SchedulerAppointmentOid.HasValue)
{
KalenderService.UpdateSchedulerAppointments(new List<SchedulerAppointmentDC> { appointmentPrototype });
}
else
{
KalenderService.InsertSchedulerAppointments(new List<SchedulerAppointmentDC> { appointmentPrototype });
}
}
2020-04-08 14:44:20 +02:00
}
else
{
OperationsService.UpdateServiceRecords(new List<ServiceRecordDC> { 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.HasValue && previousEndDate.HasValue)
{
var duration = (previousEndDate - previousStartDate).Value.TotalMinutes;
Model.NewStartDate = previousEndDate;
Model.NewEndDate = previousEndDate.Value.AddMinutes(duration);
}
}
2020-04-08 14:44:20 +02:00
Model.NewServiceRecord = new ServiceRecordDC();
}
2026-05-11 12:42:57 +02:00
catch(Exception e)
2020-04-08 14:44:20 +02:00
{
Log.Error(e.Message, e);
}
if (false == Model.IsInGroupBookingMode && !Model.IsInMultiBookingMode)
2025-06-17 13:06:29 +02:00
{
//Setze den zuletzt ausgewählten HP zurück, sonst springt die Anzeige dorthin
Model.PreviouslySelectedCostbearer2SupportConceptOid = null;
}
//Wenn nicht im Editing Mode, dann behalte die zuletzt ausgewählte Leistung bei, die im Reset zurückgesetzt wird
long? oldCatOid = null;
long? oldDescOid = null;
if(false == Model.IsInEditingMode)
2025-06-17 13:06:29 +02:00
{
oldCatOid = Model.SelectedServiceCategoryOid;
oldDescOid = Model.SelectedServiceDescriptionOid;
}
ResetBookingMode(Model.IsInGroupBookingMode ? BookingMode.GroupBookingMode : BookingMode.SingleBookingMode);
2025-06-17 13:06:29 +02:00
var result = ResetEditingMode();
2025-08-15 10:10:25 +02:00
if(oldCatOid.HasValue && oldDescOid.HasValue)
2025-06-17 13:06:29 +02:00
{
Model.SelectedServiceCategoryOid = oldCatOid;
Model.SelectedServiceDescriptionOid = oldDescOid;
}
return result;
2020-04-08 14:44:20 +02:00
}
private List<ValueListEntryDC> CreateValueListEntriesFromMokZiele(IList<MokZiel> ziele)
{
var vleList = new List<ValueListEntryDC>();
foreach (var ziel in ziele)
{
var vleDc = Model.AllGoals.FirstOrDefault(g => g.ValueListEntryOid == ziel.ValueListEntryOid);
if (vleDc != null)
{
vleDc.RatingTypeOid = ziel.RatingTypeOid;
vleList.Add(vleDc);
}
}
return vleList;
}
[Authorize]
private ActionResult SaveGroupBooking()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
var employeeCount = Model.GroupBookingSelectedEmployees.Count;
var personCount = Model.GroupBookingSelectedCostBearerSupportConceptOids.Count;
var cb2ScOids = Model.GroupBookingSelectedCostBearerSupportConceptOids;
var list = CalculateGroupBookingDuration(employeeCount, personCount, cb2ScOids);
var newDCList = new List<ServiceRecordDC>();
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);
if(TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] is SchedulerAppointmentDC occurrenceToInsert)
{
KalenderService.InsertSchedulerAppointment(occurrenceToInsert);
}
TempData[TempDataConstants.AfterInsertKey] = true;
}
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;
TempData[TempDataConstants.AfterInsertKey] = true;
if((Model.TransferringAppointmentOid is null && TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] is null) || Model.LoggedInEmployee?.EmployeeOid is null)
{
return ResetEditingMode();
}
var appointment = Model.TransferringAppointmentOid is null ?
(SchedulerAppointmentDC) TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] :
MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDC(DAOFactory.GenericDAO.LoadByID<SchedulerAppointment>(Model.TransferringAppointmentOid.Value));
if(appointment.ServiceRecordList is null)
{
appointment.ServiceRecordList = new List<ServiceRecordDC>();
}
appointment.ServiceRecordList.AddRange(serviceRecords);
// ToDo: Ist immer noch nicht mit den ServiceRecords verbunden!
if(appointment.SchedulerAppointmentOid is null)
{
KalenderService.InsertSchedulerAppointments(new List<SchedulerAppointmentDC> { appointment });
}
else
{
KalenderService.UpdateSchedulerAppointments(new List<SchedulerAppointmentDC> { appointment });
}
}
}
return ResetEditingMode();
}
[Authorize]
private ActionResult UpdateGroupBooking()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
var dc = Model.SelectedServiceRecord;
var group = OperationsService.GetServiceRecordGroup(dc.GroupOid.Value);
UpdateServiceRecordGroup(group);
var employeeCount = Model.GroupBookingSelectedEmployees.Count;
var customerCount = Model.GroupBookingSelectedCostBearerSupportConceptOids.Count;
group.EmployeeCount = employeeCount;
group.CustomerCount = customerCount;
var roundDuration = true;
var minuteInterval = 0;
CompactOrganisationDC org = null;
var cb2ScOids = new List<long>();
foreach(var scdc in GetSelectedGroupBookingSupportConcepts())
{
if (scdc.CostBearerRelOids.Count > 0)
{
cb2ScOids.Add(scdc.CostBearerRelOids[0]);
if (org is null)
{
org = scdc.CostBearerList[0].Organisation;
if(org != null)
{
minuteInterval = org.ActualMinuteIntervall;
}
}
else
{
if(scdc.CostBearerList[0] is null || !org.Equals(scdc.CostBearerList[0].Organisation))
{
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.GroupBookingSelectedCostBearerSupportConceptOids.Count, 0 , MidpointRounding.AwayFromZero);
}
Model.NewServiceRecord.RoundedDuration = roundedDuration;
Model.NewServiceRecord.GroupRoundedDuration = groupDuration;
group.Notice = Model.NewServiceRecord.Notice?.RemoveUppercaseEsszett();
group.Notice2 = Model.NewServiceRecord.Notice2?.RemoveUppercaseEsszett();
group.Notice3 = Model.NewServiceRecord.Notice3?.RemoveUppercaseEsszett();
group.Notice4 = Model.NewServiceRecord.Notice4?.RemoveUppercaseEsszett();
group.Notice5 = Model.NewServiceRecord.Notice5?.RemoveUppercaseEsszett();
group.RoundedDuration = groupDuration;
group.StartDate = Model.NewServiceRecord.Start;
group.EndDate = Model.NewServiceRecord.End;
foreach(var item in group.ServiceRecordList)
{
item.Goals = Model.NewServiceRecord.Goals;
item.Notice = Model.NewServiceRecord.Notice?.RemoveUppercaseEsszett();
item.Notice2 = Model.NewServiceRecord.Notice2?.RemoveUppercaseEsszett();
item.Notice3 = Model.NewServiceRecord.Notice3?.RemoveUppercaseEsszett();
item.Notice4 = Model.NewServiceRecord.Notice4?.RemoveUppercaseEsszett();
item.Notice5 = Model.NewServiceRecord.Notice5?.RemoveUppercaseEsszett();
item.End = Model.NewServiceRecord.End;
item.Start = Model.NewServiceRecord.Start;
item.RoundedDuration = roundedDuration;
2023-05-23 13:56:22 +02:00
item.DistanceInMeterDecimal = Model.NewServiceRecord.DistanceInMeterDecimal;
item.ServiceDescription = Model.NewServiceRecord.ServiceDescription;
item.ServiceRecordFormat = Model.NewServiceRecord.ServiceRecordFormat;
item.DurationInStunden = Model.NewServiceRecord.DurationInStunden;
item.ServiceDescription = item.ServiceDescription ?? Model.NewServiceRecord.ServiceDescription;
item.GroupEmployeeCount = group.EmployeeCount;
item.GroupPersonCount = group.CustomerCount;
item.GroupOid = Model.NewServiceRecord.GroupOid;
item.GroupRoundedDuration = groupDuration;
item.Betrag = Model.NewServiceRecord.Betrag;
if(item.CostBearer != null && item.CostBearer.CostBearerOid is null && item.SupportConcept != null && item.SupportConcept.CostBearerList.Count > 0)
{
item.CostBearer.CostBearerOid = item.SupportConcept.CostBearerList[0].CostBearerOid;
}
}
if(Model.NewServiceRecord.GroupOid.HasValue)
{
OperationsService.UpdateServiceRecordGroup(group);
}
Model.NewServiceRecord = null;
Model.SelectedServiceRecord = null;
2025-06-11 22:56:25 +02:00
Model.SelectedServiceRecordOid = null;
Model.GroupBookingSelectedEmployees = new List<CompactEmployeeDC>();
ResetBookingMode(BookingMode.SingleBookingMode);
Model.IsInEditingMode = false;
return ResetEditingMode();
}
[Authorize]
private IEnumerable<ServiceRecordDC> CalculateGroupBookingDuration(int pEmployeeCount, int pCustomerCount, ICollection<long> cb2ScOids)
{
var compactSupportConcepts = GetSelectedGroupBookingSupportConcepts();
var nodes = (from supportConcept in compactSupportConcepts let cb = supportConcept.CostBearerList.FirstOrDefault() let sc = compactSupportConcepts.FirstOrDefault(f => f.SupportConceptOid == supportConcept.SupportConceptOid) where cb != null && sc != null select SupportConceptService.CreateFlatSupportConceptItem(sc, CustomerService.LoadOrganisationCompact(cb.Organisation.OrganisationOid))).ToList();
var list = new List<ServiceRecordDC>();
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;
2018-11-26 13:27:16 -04:00
if(Model.SelectedServiceDescriptionOid.HasValue && IsBillable(Model.SelectedServiceDescriptionOid.Value, Model.GetServiceDesctiptions()))
{
roundDuration = true;
foreach(var org in from dc in compactSupportConcepts where dc.CostBearerList.Count > 0 select dc.CostBearerList.First().Organisation)
{
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;
}
2018-11-26 13:27:16 -04:00
private void UpdateServiceRecordGroup(ServiceRecordGroupDC pGroupDC)
{
var newCount = 0;
2018-11-26 13:27:16 -04:00
foreach(var serviceRecord in pGroupDC.ServiceRecordList)
{
if(!serviceRecord.ServiceRecordOid.HasValue)
{
newCount++;
}
}
2018-11-26 13:27:16 -04:00
if(newCount == pGroupDC.ServiceRecordList.Count)
{
return;
}
var dcsToChange = new List<ServiceRecordDC>();
var oldSCs = new Dictionary<long, CompactSupportConceptDC>();
var oldEmps = new Dictionary<long, CompactEmployeeDC>();
var newKeys = new Dictionary<string, string>();
foreach(var sc in GetSelectedGroupBookingSupportConcepts())
{
if(sc?.SupportConceptOid is null)
{
continue;
}
var costBearerRelation = Model.GroupBookingSelectionObject.SelectedRelations.FirstOrDefault(f => f.SupportConceptOid.HasValue && f.SupportConceptOid.Value.Equals(sc.SupportConceptOid));
foreach(var emp in Model.GroupBookingSelectedEmployees)
{
var key = emp.EmployeeOid + "_" + sc.SupportConceptOid;
if (costBearerRelation?.CostBearer2SupportConceptOid != null)
{
var costBearer2SupportConceptOid = sc.CostBearerRelOids[0];
if(costBearer2SupportConceptOid != null)
{
key += "_" + costBearerRelation.CostBearer2SupportConceptOid.Value;
}
newKeys.Add(key, key);
}
}
}
2018-11-26 13:27:16 -04:00
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 GetSelectedGroupBookingSupportConcepts())
{
foreach(var emp in Model.GroupBookingSelectedEmployees)
{
var key = emp.EmployeeOid + "_" + sc.SupportConceptOid;
if(sc.CostBearerRelOids != null && sc.CostBearerRelOids.Count > 0)
{
key += "_" + sc.CostBearerRelOids.ElementAt(0);
}
if(!newKeys.ContainsKey(key))
{
continue;
}
ServiceRecordDC newServiceRecord;
if(dcsToChange.Count > 0)
{
newServiceRecord = dcsToChange[0];
dcsToChange.Remove(newServiceRecord);
}
else
{
newServiceRecord = CloneServiceRecord(Model.NewServiceRecord);
2018-11-26 13:27:16 -04:00
pGroupDC.ServiceRecordList.Add(newServiceRecord);
}
newServiceRecord.Employee = emp;
newServiceRecord.CostBearer = sc.CostBearerList.ElementAt(0).Organisation;
newServiceRecord.Customer = sc.Customer;
newServiceRecord.CostBearer2SupportConceptOid = sc.CostBearerRelOids.ElementAt(0);
newServiceRecord.SupportConcept = GetCompactSupportConcept(sc.SupportConceptOid, newServiceRecord.CostBearer2SupportConceptOid);
}
}
}
foreach(var item in dcsToChange)
{
2018-11-26 13:27:16 -04:00
pGroupDC.ServiceRecordList.Remove(item);
}
}
}
[HttpPost]
[Authorize]
public ActionResult SelectSupportConcept(FormCollection formCollection)
2016-06-27 01:45:38 +02:00
{
2021-03-11 12:09:38 +01:00
try
2016-06-27 01:45:38 +02:00
{
SkipModelInitialization = true; //Verhindere mehrfache Initialisierung, weil später sowieso zur Main Action geleitet wird
2025-10-09 12:56:32 +02:00
if(Model is null)
2021-03-11 12:09:38 +01:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
2021-03-11 12:09:38 +01:00
return Logout();
}
2016-06-27 01:45:38 +02:00
2021-03-11 12:09:38 +01:00
long? cb2ScOid = Convert.ToInt64(formCollection[FormCollectionConstants.CostBearer2SupportConceptOidKey]);
2016-06-27 01:45:38 +02:00
2025-10-09 12:56:32 +02:00
SelectCb2ScRelation(cb2ScOid);
2025-09-09 10:27:54 +02:00
// Sorgt dafür, dass nach dem Neuladen die Abhängigkeiten vom Hilfeplan erhalten bleiben
TempData[TempDataConstants.SupportConceptRelSelectedKey] = true;
return RedirectToActionPermanent("Main");//ResetEditingMode();
2021-03-11 12:09:38 +01:00
}
2025-10-09 12:56:32 +02:00
catch(Exception e)
2021-03-11 12:09:38 +01:00
{
Log.Error($"ERROR SelectSupportConcept: {e.Message}\n{e.StackTrace}");
2021-03-11 12:09:38 +01:00
throw;
}
}
2016-06-27 01:45:38 +02:00
2025-10-09 12:56:32 +02:00
private void SelectCb2ScRelation(long? cb2ScOid)
{
if(Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SelectedCostBearerSupportConceptOid != cb2ScOid)
{
Model.SelectedGoalOids = new List<long>();
Model.SelectedGoals = new List<MokZiel>();
}
Model.SelectedCostBearerSupportConceptOid = cb2ScOid;
Model.CurrentPage = 1;
}
private void LoadServiceCategoriesToModel(List<SupportConceptTreeNodeDetailInfoDC> infos)
{
Model.Categories2Descriptions = new Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>>();
2025-07-18 19:37:01 +02:00
if(infos is null)
{
infos = new List<SupportConceptTreeNodeDetailInfoDC>();
}
if(infos.Count > 0)
{
Model.Categories2Descriptions = CreateServiceCategory2ServiceDescription(infos);
2016-06-27 01:45:38 +02:00
}
else
2016-06-27 01:45:38 +02:00
{
//Sonst ohne Hilfeplan
var allServiceDescriptions = OperationsService.GetAllServiceDescriptions();
allServiceDescriptions.AsParallel().DoForEach(serviceDescription =>
{
if (serviceDescription.Category.ActivationType == ActivationTypeId.Active && (!serviceDescription.Category.OhneHilfeplan.HasValue || serviceDescription.Category.OhneHilfeplan == AccountingvisibilityType.Beides || serviceDescription.Category.OhneHilfeplan == AccountingvisibilityType.NichtKlientenbezogen))
{
Model.Categories2Descriptions.AddOrUpdateValueInDictionary(serviceDescription.Category, serviceDescription);
}
});
2016-06-27 01:45:38 +02:00
}
SelectFirstServiceDescription();
}
private void SelectFirstServiceDescription()
{
2025-07-18 19:37:01 +02:00
if(Model?.Categories2Descriptions is null || Model.Categories2Descriptions.Count == 0)
{
2025-06-11 22:56:25 +02:00
UpdateSelectedServiceCategorieAndDescription(null, null);
return;
}
2025-06-11 22:56:25 +02:00
//Nur, wenn Kategorie und Leistung null sind oder nicht in der Liste alle Kategorien enthalten sind, soll weiter unten die erste Leistung in der Liste gesetzt werden
2025-07-18 19:37:01 +02:00
if(Model.SelectedServiceCategoryOid.HasValue && Model.SelectedServiceDescriptionOid.HasValue)
2025-06-11 22:56:25 +02:00
{
2025-07-18 19:37:01 +02:00
var cat = Model.Categories2Descriptions.Keys.FirstOrDefault(c => c.ServiceCategoryOid == Model.SelectedServiceCategoryOid);
if(cat != null)
2025-06-11 22:56:25 +02:00
{
2025-07-18 19:37:01 +02:00
var desc = Model.Categories2Descriptions[cat].FirstOrDefault(d => d.ServiceDescriptionOid == Model.SelectedServiceDescriptionOid);
2025-06-11 22:56:25 +02:00
2025-07-18 19:37:01 +02:00
if(desc != null)
2025-06-11 22:56:25 +02:00
{
//Setzte Objekte im Model, sonst wird unten die erste Leistung gesetzt
Model.SelectedServiceCategory = cat;
Model.SelectedServiceDescription = desc;
return;
}
}
}
var firstServiceCategory2ServiceDescriptions = Model.Categories2Descriptions.OrderBy(c2d => c2d.Key.Position).ThenBy(c2d => c2d.Key.ServiceCategoryOid).FirstOrDefault(c2d => c2d.Value.Any());
if(firstServiceCategory2ServiceDescriptions.Key is null)
{
2025-06-11 22:56:25 +02:00
UpdateSelectedServiceCategorieAndDescription(null, null);
return;
}
var serviceDescription = firstServiceCategory2ServiceDescriptions.Value.OrderBy(sd => sd.Position).ThenBy(sd => sd.ServiceDescriptionOid).First();
2025-06-11 22:56:25 +02:00
UpdateSelectedServiceCategorieAndDescription(serviceDescription.Category, serviceDescription);
}
2016-06-27 01:45:38 +02:00
2025-06-11 22:56:25 +02:00
private void UpdateSelectedServiceCategorieAndDescription(ServiceCategoryDC cat, ServiceDescriptionDC desc)
{
Model.SelectedServiceCategory = cat;
Model.SelectedServiceDescription = desc;
Model.SelectedServiceCategoryOid = Model.SelectedServiceCategory?.ServiceCategoryOid;
Model.SelectedServiceDescriptionOid = Model.SelectedServiceDescription?.ServiceDescriptionOid;
}
private Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> CreateServiceCategory2ServiceDescription(List<SupportConceptTreeNodeDetailInfoDC> nodes)
{
var result = new Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>>();
var firstNode = nodes.FirstOrDefault();
if(firstNode is null)
{
return result;
}
if (nodes.Count == 1)
{
firstNode.ServiceAccountings.DoForEach(serviceAccounting => result.AddOrUpdateValueInDictionary(serviceAccounting.ServiceDescription.Category, serviceAccounting.ServiceDescription));
}
else if (Model.FilterGroupServiceCategories)
{
var schnittmenge = ErstelleServiceCategorySchnittmenge(nodes);
foreach (var serviceAccounting in schnittmenge)
{
var serviceDescription = serviceAccounting.ServiceDescription;
var serviceCategory = serviceDescription.Category;
result.AddOrUpdateValueInDictionary(serviceCategory, serviceDescription);
}
}
if (result.Count == 0)
{
result = GetAllServiceCategory2ServiceDescriptionDict();
}
return result.OrderBy(kvp => kvp.Key.Position).ToDictionary(category2Descriptions => category2Descriptions.Key, category2Descriptions => category2Descriptions.Value.OrderBy(serviceDescription => serviceDescription.Position).ToList());
}
private Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> GetAllServiceCategory2ServiceDescriptionDict()
{
var result = new Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>>();
var allServiceDescriptions = OperationsService.GetAllServiceDescriptions().Where(sd => sd.Category.ActivationType == ActivationTypeId.Active && sd.ActivationType == ActivationTypeId.Active && sd.Category.OhneHilfeplan != AccountingvisibilityType.NichtKlientenbezogen).ToList();
foreach (var serviceDescription in allServiceDescriptions)
{
result.AddOrUpdateValueInDictionary(serviceDescription.Category, serviceDescription);
}
return result;
}
private List<ServiceAccountingDC> ErstelleServiceCategorySchnittmenge(List<SupportConceptTreeNodeDetailInfoDC> allInfos)
{
if (allInfos.Count == 0)
{
return null;
}
else if (allInfos.Count == 1)
{
return allInfos[0].ServiceAccountings;
}
var schnittmenge = new List<ServiceAccountingDC>();
Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> allDict = null;
foreach (var info in allInfos)
{
if (info.ServiceAccountings != null && info.ServiceAccountings.Count == 0)
{
if (allDict == null)
{
allDict = GetAllServiceCategory2ServiceDescriptionDict();
}
foreach (var cat in allDict.Keys)
{
if (!cat.OhneHilfeplan.HasValue || (cat.OhneHilfeplan.Value != AccountingvisibilityType.NichtKlientenbezogen && cat.OhneHilfeplan.Value != AccountingvisibilityType.Never))
{
var descList = allDict[cat];
foreach (var desc in descList)
{
info.ServiceAccountings.Add(new ServiceAccountingDC { ServiceDescription = desc });
}
}
}
}
}
var erster = allInfos[0];
foreach (var sa in erster.ServiceAccountings)
{
//Prüfe für jeden des ersten ob er auch in allen anderen enthalten ist
bool istDrin = true;
for (int i = 1; i < allInfos.Count; i++)
{
var info2 = allInfos[i];
if (!info2.ServiceAccountings.Exists(sa2 => sa2.ServiceDescription.ServiceDescriptionOid == sa.ServiceDescription.ServiceDescriptionOid))
{
istDrin = false;
}
}
if (istDrin)
{
schnittmenge.Add(sa);
}
}
return schnittmenge;
}
2016-06-27 01:45:38 +02:00
[HttpPost]
[Authorize]
public ActionResult DeleteServiceRecord(FormCollection formCollection)
2016-06-27 01:45:38 +02:00
{
if(Model is null)
2016-06-27 01:45:38 +02:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
2016-06-27 01:45:38 +02:00
}
Model.ServiceRecordOidToDelete = long.Parse(formCollection[FormCollectionConstants.ServiceRecordOidHolderKey]);
2025-06-11 22:56:25 +02:00
if(Model.ServiceRecordOidToDelete != null && Model.ServiceRecordOidToDelete > 0 && LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.Equals(UserRightType.ServiceRecordView_Delete))))
2016-06-27 01:45:38 +02:00
{
var serviceRecordDC = GetServiceRecordDC(Model.ServiceRecordOidToDelete.Value, false);
var version = serviceRecordDC?.ServiceRecordVersion;
if(version != null && Model.IsAllowedToDeleteServiceRecord(serviceRecordDC))
2016-06-27 01:45:38 +02:00
{
OperationsService.DeleteServiceRecord(Model.ServiceRecordOidToDelete.Value, version.Value);
2016-06-27 01:45:38 +02:00
Model.ServiceRecords = Model.ServiceRecords.Where(sr => sr.ServiceRecordOid != null && !sr.ServiceRecordOid.Value.Equals(serviceRecordDC.ServiceRecordOid)).ToList();
2016-06-27 01:45:38 +02:00
}
}
return ResetEditingMode();
2016-06-27 01:45:38 +02:00
}
2025-06-11 22:56:25 +02:00
//[Authorize]
//public ActionResult ReloadGoalRatings()
//{
// if(Model is null)
// {
// TempData[TempDataConstants.DoLogoutKey] = true;
// return PartialView("GoalRatingPopupContentPartial");
// }
2025-06-11 22:56:25 +02:00
// return PartialView("GoalRatingPopupContentPartial", Model);
//}
[Authorize]
public string UpdateGoals(string pGoalOids)
2016-06-27 01:45:38 +02:00
{
if(!IsUserLoggedIn())
2016-06-27 01:45:38 +02:00
{
Logout();
return "0";
2016-06-27 01:45:38 +02:00
}
2019-07-25 14:56:11 +02:00
if(string.IsNullOrEmpty(pGoalOids))
{
Model.SelectedGoalOids.Clear();
Model.SelectedGoals.Clear();
2019-07-25 14:56:11 +02:00
return "0";
2019-07-25 14:56:11 +02:00
}
var splitOids = pGoalOids.Trim(';').Split(';');
var selectedGoalOids = splitOids.Select(long.Parse).ToList();
2016-06-27 01:45:38 +02:00
var removedGoalOids = Model.SelectedGoalOids.Except(selectedGoalOids).ToList();
Model.SelectedGoalOids = selectedGoalOids;
var newGoalOids = selectedGoalOids.Where(goalOid => false == (Model.SelectedGoals?.Any(goal => goal.ValueListEntryOid.HasValue && goal.ValueListEntryOid.Value.Equals(goalOid)) ?? false)).ToList();
var newGoals = DcToMokMapper.CreateZiele(Model.AllGoals.Where(goal => goal.ValueListEntryOid.HasValue && newGoalOids.Contains(goal.ValueListEntryOid.Value))).ToList();
var oldGoals = Model.SelectedGoals.Where(goal => goal.ValueListEntryOid.HasValue && selectedGoalOids.Contains(goal.ValueListEntryOid.Value)).ToList();
oldGoals.AddRange(newGoals);
Model.SelectedGoals = oldGoals;
return string.Join(",", removedGoalOids);
2016-06-27 01:45:38 +02:00
}
[Authorize]
public string SetServiceDescription(long pServiceDescriptionOid)
2016-06-27 01:45:38 +02:00
{
if (Model is null)
2016-06-27 01:45:38 +02:00
{
Logout();
return LeerzeichenFuerGetMethoden;
2016-06-27 01:45:38 +02:00
}
var serviceDescription = OperationsService.GetServiceDescription(pServiceDescriptionOid);
Model.SelectedServiceDescription = serviceDescription;
2025-06-11 22:56:25 +02:00
Model.SelectedServiceDescriptionOid = pServiceDescriptionOid;
return LeerzeichenFuerGetMethoden;
2016-06-27 01:45:38 +02:00
}
[HttpPost]
[Authorize]
public ActionResult LoadServiceRecords(FormCollection formCollection)
{
if(Model is null)
2016-06-27 01:45:38 +02:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
2016-06-27 01:45:38 +02:00
}
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;
2016-06-27 01:45:38 +02:00
CalculateSelectedDayCount(dayCountNumber, lastSelectedServiceRecordMonth, parsedVon, parsedBis, serviceRecordTimeInterval);
2016-06-27 01:45:38 +02:00
return RedirectToActionPermanent("Main");
}
[Authorize]
public ActionResult LoadServiceRecordsNonPost(int dayCountNumber, string start, string end, int month, int year, int recordsKey)
{
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
return PartialView("ServiceRecordListPartial");
}
SkipServiceRecordInitialization = true;
var lastSelectedServiceRecordMonth = new DateTime(year, month, 1);
var isValidStart = DateTime.TryParse(start, out var parsedStart);
var isValidEnd = DateTime.TryParse(end, out var parsedEnd);
if(Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen)
{
if(!isValidStart)
{
parsedStart = DateTime.Today.GetFirstOfMonth();
}
if(!isValidEnd)
{
parsedEnd = DateTime.Today;
}
if(parsedStart > parsedEnd)
{
(parsedStart, parsedEnd) = (parsedEnd, parsedStart);
}
Model.SelectedZeitraum = new NullableDateTimeSpan(parsedStart, parsedEnd);
}
var serviceRecordTimeInterval = (ServiceRecordTimeInterval) recordsKey;
Model.ServiceRecordTimeInterval = serviceRecordTimeInterval;
CalculateSelectedDayCount(dayCountNumber, lastSelectedServiceRecordMonth, parsedStart, parsedEnd, serviceRecordTimeInterval);
2025-06-11 22:56:25 +02:00
if(Model.SelectedCostBearerSupportConceptOid.HasValue && Model.SelectedCostBearerSupportConceptOid != -1)
{
LoadPaginatedServiceRecordsToModel(Model.CurrentPage);
}
return PartialView("ServiceRecordListPartial", Model);
}
private void CalculateSelectedDayCount(int? dayCountNumber, DateTime? lastSelectedServiceRecordMonth, DateTime? von, DateTime? bis, ServiceRecordTimeInterval? serviceRecordTimeInterval)
{
if(dayCountNumber is null)
{
dayCountNumber = 0;
}
if(lastSelectedServiceRecordMonth is null)
{
lastSelectedServiceRecordMonth = DateTime.Today.AddMonths(-1);
}
if(von is null || bis is null)
{
von = DateTime.Today.GetFirstOfMonth();
bis = DateTime.Today;
}
Model.SelectedDayCount = 0;
switch(Model.ServiceRecordTimeInterval)
{
case ServiceRecordTimeInterval.LastWeek:
Model.SelectedDayCount = 7;
break;
case ServiceRecordTimeInterval.LastMonth:
Model.SelectedDayCount = 30;
break;
case ServiceRecordTimeInterval.Last3Month:
Model.SelectedDayCount = 90;
break;
case ServiceRecordTimeInterval.XTage:
Model.SelectedDayCount = dayCountNumber.Value;
Model.LastSelectedServiceRecordTimeIntervalDays = dayCountNumber.Value;
UpdateUserSettingsWithoutReload(SettingsKeys.LastSelectedServiceRecordTimeIntervalDays, dayCountNumber.ToString());
break;
case ServiceRecordTimeInterval.Monatsauswahl:
Model.LastSelectedServiceRecordMonth = lastSelectedServiceRecordMonth.Value;
Model.SelectedDayCount = lastSelectedServiceRecordMonth.Value.Date.GetDaysInMonth();
Model.SelectedZeitraum = new NullableDateTimeSpan(lastSelectedServiceRecordMonth.Value.Date.GetFirstOfMonth(), lastSelectedServiceRecordMonth.Value.Date.GetLastOfMonth());
UpdateUserSettingsWithoutReload(SettingsKeys.LastSelectedServiceRecordMonth, lastSelectedServiceRecordMonth.Value.ToString("dd.MM.yyyy HH:mm:ss"));
break;
case ServiceRecordTimeInterval.ZeitraumWaehlen:
Model.SelectedZeitraum = new NullableDateTimeSpan(von.Value, bis.Value);
break;
}
if(serviceRecordTimeInterval is null)
{
return;
}
UpdateSettings(SettingsKeys.LastSelectedServiceRecordTimeInterval, ((int) serviceRecordTimeInterval.Value).ToString());
}
[HttpPost]
[Authorize]
public ActionResult SelectRecordToEdit(FormCollection formCollection)
2016-06-27 01:45:38 +02:00
{
2026-04-28 12:01:37 +02:00
if(false == IsUserLoggedIn())
2016-06-27 01:45:38 +02:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
2016-06-27 01:45:38 +02:00
}
SkipModelInitialization = true;
var oidString = formCollection[FormCollectionConstants.ServiceRecordOidHolder2Key];
var wasSuccessful = long.TryParse(oidString, out var serviceRecordOid);
2016-06-27 01:45:38 +02:00
if(!wasSuccessful)
{
return RedirectToActionPermanent("Main");
}
Model.SelectedServiceRecordOid = serviceRecordOid;
2025-07-17 16:26:07 +02:00
var selectedServiceRecord = GetServiceRecordDC(serviceRecordOid, false);
if(selectedServiceRecord is null)
{
return RedirectToActionPermanent("Main");
}
2025-09-09 10:27:54 +02:00
#if DEBUG
Model.SelectedServiceRecord = selectedServiceRecord;
#endif
Model.SelectedGoalOids = selectedServiceRecord.Goals.Select(g => g.ValueListEntryOid.Value).ToList();
2025-07-17 16:26:07 +02:00
Model.SelectedGoals = DcToMokMapper.CreateZiele(selectedServiceRecord.Goals);
var selectedServiceDescription = selectedServiceRecord.ServiceDescription;
var selectedServiceCategory = selectedServiceDescription.Category;
2025-06-11 22:56:25 +02:00
Model.SelectedServiceDescriptionOid = selectedServiceDescription?.ServiceDescriptionOid;
Model.SelectedServiceCategoryOid = selectedServiceCategory?.ServiceCategoryOid;
2025-06-11 22:56:25 +02:00
Model.PreviouslySelectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid;
Model.SelectedEmployeeOid = selectedServiceRecord.Employee?.EmployeeOid;
Model.IsInEditingMode = true;
2025-06-17 13:06:29 +02:00
//Model.PreviouslySelectedSupportConceptOid = Model.SelectedSupportConcept?.SupportConceptOid;
2025-06-11 22:56:25 +02:00
Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid;
// Gruppenbuchung
if(selectedServiceRecord.GroupOid.HasValue)
{
Model.IsInGroupBookingMode = true;
2025-06-17 13:06:29 +02:00
//Model.SelectedSupportConceptOid = null;
2025-06-11 22:56:25 +02:00
Model.SelectedEmployeeOid = null;
var group = OperationsService.GetServiceRecordGroup(selectedServiceRecord.GroupOid.Value);
var employees = group.ServiceRecordList.Select(serviceRecord => serviceRecord.Employee).Distinct().ToList();
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployeeOids = employees.Select(e => e.EmployeeOid).ToList();
var cb2ScOids = group.ServiceRecordList.Where(w => w.CostBearer2SupportConceptOid.HasValue).Select(s => s.CostBearer2SupportConceptOid.Value).Distinct().ToList();
2025-06-11 22:56:25 +02:00
//Model.SelectedConceptCostBearerRelations.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptCostBearerRelDCsByOids(cb2ScOids));
Model.GroupBookingSelectedCostBearerSupportConceptOids = cb2ScOids;
2025-06-11 22:56:25 +02:00
//var selectedSupportConcepts = new List<SupportConceptDC>();
//selectedSupportConcepts.AddRangeIfElementsNotIn(OperationsService.GetSupportConceptsById(group.ServiceRecordList.Select(s => s.SupportConcept.SupportConceptOid)));
//Model.GroupBookingSelectedSupportConcepts = selectedSupportConcepts;
//Model.GroupBookingSelectedSupportConceptOids = group.ServiceRecordList.Select(s => s.SupportConcept.SupportConceptOid).ToList();
}
2025-06-11 22:56:25 +02:00
return RedirectToActionPermanent("Main");
}
[Authorize]
2017-04-26 14:57:32 +02:00
public string GetSelectedRecordInformation()
2016-06-27 01:45:38 +02:00
{
if(Model is null)
{
Logout();
return LeerzeichenFuerGetMethoden;
}
var result = LeerzeichenFuerGetMethoden;
2016-06-27 01:45:38 +02:00
if(Model.SelectedServiceRecordOid.HasValue)
2016-06-27 01:45:38 +02:00
{
result = SerializeObject(GetServiceRecordDC(Model.SelectedServiceRecordOid.Value, false));
2016-06-27 01:45:38 +02:00
}
return result;
}
[Authorize]
2017-04-26 14:57:32 +02:00
public string GetSelectedRecordInformationWithOid(long oid)
2016-06-27 01:45:38 +02:00
{
if(Model is null)
{
Logout();
return LeerzeichenFuerGetMethoden;
}
var serviceRecord = GetServiceRecordDC(oid, false);
2016-06-27 01:45:38 +02:00
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);
2016-06-27 01:45:38 +02:00
}
[Authorize]
public ActionResult GetSingleSignatureInfo(long serviceRecordOid)
{
if(Model is null)
{
return Logout();
}
var serviceRecord = GetServiceRecordDC(serviceRecordOid, false);
if(serviceRecord?.ServiceRecordOid is null)
{
return PartialView("SingleSignaturePopupPartial", Model);
}
var hasMonatsunterschrift = OperationsService.CheckForConfirmationReceiptSignatureForServiceRecord(serviceRecord.ServiceRecordOid.Value, SignatureType.Customer);
Model.ServiceRecord2Monatsunterschrift = new ServiceRecord2Monatsunterschrift(serviceRecord, hasMonatsunterschrift);
return PartialView("SingleSignaturePopupPartial", Model);
}
[Authorize]
[HttpPost]
public ActionResult ValidateServiceRecord(FormCollection formCollection)
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
if(TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] is SchedulerAppointmentDC occurrenceToInsert)
{
TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] = occurrenceToInsert;
}
var inEditMode = Model.IsInEditingMode;
var von = formCollection[FormCollectionConstants.DateKey];
var bis = formCollection[FormCollectionConstants.EndDateKey];
var start = formCollection[FormCollectionConstants.StartKey];
var end = formCollection[FormCollectionConstants.EndKey];
var durationRaw = formCollection[FormCollectionConstants.DurationKey];
var betragRaw = formCollection[FormCollectionConstants.BetragKey];
var distanceRaw = formCollection[FormCollectionConstants.DistanceKey];
var doku1 = formCollection[FormCollectionConstants.Dokumentation1Key]?.RemoveUppercaseEsszett();
var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key]?.RemoveUppercaseEsszett();
var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key]?.RemoveUppercaseEsszett();
var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key]?.RemoveUppercaseEsszett();
var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key]?.RemoveUppercaseEsszett();
var formId = formCollection[FormCollectionConstants.FormIdKey];
2016-06-27 01:45:38 +02:00
2025-01-22 16:42:02 +01:00
var markerRaw = formCollection[FormCollectionConstants.MarkerKey];
var marker = "on" == markerRaw;
var serviceDescription = formCollection[FormCollectionConstants.ServiceDescriptionKey];
2016-06-27 01:45:38 +02:00
var startHoursDt = ConvertTimeStringToDateTime(start);
var endHoursDt = ConvertTimeStringToDateTime(end);
2016-06-27 01:45:38 +02:00
if(false == DateTime.TryParse(von, out var startDate))
2016-06-27 01:45:38 +02:00
{
startDate = DateTime.Now.Date;
2016-06-27 01:45:38 +02:00
}
if(false == 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);
2016-06-27 01:45:38 +02:00
var dauer = (int) (endDt - startDt).TotalMinutes;
2024-03-19 19:10:13 +01:00
if(dauer == 0 || start == string.Empty && end == string.Empty)
2016-06-27 01:45:38 +02:00
{
startDt = startDt.AddSeconds(1);
endDt = endDt.AddSeconds(1);
}
var checkServiceRecord = new ServiceRecordDC();
if(inEditMode && Model.SelectedServiceRecordOid.HasValue)
2016-06-27 01:45:38 +02:00
{
checkServiceRecord = GetServiceRecordDC(Model.SelectedServiceRecordOid.Value, false);
2016-06-27 01:45:38 +02:00
}
if(checkServiceRecord is null)
2016-06-27 01:45:38 +02:00
{
checkServiceRecord = new ServiceRecordDC();
2016-06-27 01:45:38 +02:00
}
2025-01-22 16:42:02 +01:00
checkServiceRecord.ServiceRecordType = marker ? ServiceRecordTypeId.Content : ServiceRecordTypeId.DefaultActivity;
checkServiceRecord.Notice = doku1;
checkServiceRecord.Notice2 = doku2;
checkServiceRecord.Notice3 = doku3;
checkServiceRecord.Notice4 = doku4;
checkServiceRecord.Notice5 = doku5;
if(betragRaw is object && decimal.TryParse(betragRaw, out var betrag))
{
checkServiceRecord.Betrag = betrag;
}
checkServiceRecord.Goals = CreateValueListEntriesFromMokZiele(Model.SelectedGoals);
2016-06-27 01:45:38 +02:00
checkServiceRecord.Start = startDt;
checkServiceRecord.End = endDt;
2016-06-27 01:45:38 +02:00
checkServiceRecord.IP = Request.UserHostAddress;
checkServiceRecord.ServiceDescription = OperationsService.GetServiceDescription(Model.SelectedServiceDescriptionOid.Value);
2025-06-11 22:56:25 +02:00
checkServiceRecord.Employee = Model.SelectedEmployee ?? LoggedInUser.Employee;
// Mitarbeiter ausgewählt und Einzelbuchung
if(Model.SelectedEmployee != null && !Model.IsInGroupBookingMode && !Model.IsInMultiBookingMode)
2016-06-27 01:45:38 +02:00
{
var supportConcept = Model.SupportConcepts.FirstOrDefault(fod => fod.CostBearerRelOids.Any(a => a.Equals(Model.SelectedCostBearerSupportConceptOid)));
2016-06-27 01:45:38 +02:00
if(supportConcept != null)
2016-06-27 01:45:38 +02:00
{
checkServiceRecord.SupportConcept = GetCompactSupportConcept(supportConcept.SupportConceptOid, Model.SelectedCostBearerSupportConceptOid);
2016-06-27 01:45:38 +02:00
checkServiceRecord.Customer = supportConcept.Customer;
var costbearer = supportConcept.CostBearerList.FirstOrDefault();
checkServiceRecord.CostBearer = costbearer.Organisation;
var intervall = checkServiceRecord.CostBearer.ActualMinuteIntervall;
2016-06-27 01:45:38 +02:00
if(intervall > 0)
2016-06-27 01:45:38 +02:00
{
checkServiceRecord.RoundedDuration = dauer % intervall != 0 ? dauer + (intervall - dauer % intervall) : dauer;
2016-06-27 01:45:38 +02:00
}
2025-06-11 22:56:25 +02:00
checkServiceRecord.CostBearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid;
2016-06-27 01:45:38 +02:00
}
}
var mandator = MobileSessionFacade.Mandator;
2020-04-08 14:44:20 +02:00
var maxDaysEditSRsAllowedString = GetSettingValue(mandator.Settings, SettingsKeys.MaxDaysEditServiceRecordsAllowed);
var limitFuerZeiterfassungString = GetSettingValue(mandator.Settings, SettingsKeys.AnzTageZeiterfassErfolgt);
2020-04-08 14:44:20 +02:00
if(!int.TryParse(maxDaysEditSRsAllowedString, out var maxDaysEditSRsAllowed))
2020-04-08 14:44:20 +02:00
{
maxDaysEditSRsAllowed = 0;
}
if(!int.TryParse(limitFuerZeiterfassungString, out var limitFuerZeiterfassung))
2020-04-08 14:44:20 +02:00
{
limitFuerZeiterfassung = 0;
}
2025-06-11 22:56:25 +02:00
if(LoggedInUser.HasRight(UserRightType.ServiceRecord_AllowEditAfterMaxDaysInNextMonth))
{
maxDaysEditSRsAllowed = -1;
}
2016-06-27 01:45:38 +02:00
SupportConceptStatisticsDC stats = null;
2025-06-11 22:56:25 +02:00
if(Model.SelectedCostBearerSupportConceptOid != null && Model.SelectedCostBearerSupportConceptOid > 0)
2016-06-27 01:45:38 +02:00
{
2025-06-11 22:56:25 +02:00
stats = OperationsService.CreateSupportConceptStatistics(Model.SelectedCostBearerSupportConceptOid.Value, DateTime.Now);
2016-06-27 01:45:38 +02:00
}
var employeeOids = new List<long> { checkServiceRecord.Employee.EmployeeOid };
var validationResults = new List<ServiceRecord2Validation>();
checkServiceRecord.ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung;
if(Model.IsEndDateVisible)
{
checkServiceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum;
}
checkServiceRecord.DurationInStunden = Model.IsShowingDurationInHours ? ZeiterfassungsDauer.Stunden : ZeiterfassungsDauer.Minuten;
string dateRangeString = null;
// Gruppenbuchung
if(Model.IsInGroupBookingMode)
2016-06-27 01:45:38 +02:00
{
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));
}
2016-06-27 01:45:38 +02:00
var costBearer2SupportConceptOids = Model.GroupBookingSelectedCostBearerSupportConceptOids;
var relations = CustomerService.GetSupportConceptCostBearerRelationsById(costBearer2SupportConceptOids);
var isNew = checkServiceRecord.ServiceRecordOid is null;
if(isNew)
{
foreach(var rel in relations)
{
var sr = CloneServiceRecord(checkServiceRecord);
sr.SupportConcept = rel.SupportConcept;
sr.CostBearer = rel.CostBearer;
sr.CostBearer2SupportConceptOid = rel.CostBearer2SupportConceptOid;
sr.Customer = rel.SupportConcept?.Customer;
var result = OperationsService.ValidateServiceRecord(sr, null, maxDaysEditSRsAllowed, employeeOids, costBearer2SupportConceptOids);
dateRangeString = rel.DateRangeString;
validationResults.AddIfNotIn(new ServiceRecord2Validation(sr, result, dateRangeString));
}
}
else if(serviceRecordGroup != null)
{
foreach(var serviceRecord in serviceRecordGroup.ServiceRecordList)
{
var sr = CloneServiceRecord(checkServiceRecord);
sr.ServiceRecordOid = serviceRecord.ServiceRecordOid;
sr.SupportConcept = serviceRecord.SupportConcept;
sr.CostBearer = serviceRecord.CostBearer;
sr.CostBearer2SupportConceptOid = serviceRecord.CostBearer2SupportConceptOid;
sr.Customer = serviceRecord.SupportConcept?.Customer;
var result = OperationsService.ValidateServiceRecord(sr, null, maxDaysEditSRsAllowed, employeeOids, costBearer2SupportConceptOids);
var node = CreateFlatSupportConceptItem(GetCompactSupportConcept(sr.SupportConcept.SupportConceptOid, sr.CostBearer2SupportConceptOid), null);
dateRangeString = node?.SupportConceptTreeNodeDC != null ? node.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.DateRangeString : string.Empty;
validationResults.AddIfNotIn(new ServiceRecord2Validation(sr, result, dateRangeString));
}
}
} // Einzelbuchung
else if(!Model.IsInMultiBookingMode)
{
if(Model.SelectedSupportConcept != null)
{
var node = CreateFlatSupportConceptItem(GetCompactSupportConcept(Model.SelectedSupportConcept.SupportConceptOid, Model.SelectedCostBearerSupportConceptOid), null);
dateRangeString = node?.SupportConceptTreeNodeDC != null ? node.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.DateRangeString : "";
}
var result = OperationsService.ValidateServiceRecord(checkServiceRecord, stats, maxDaysEditSRsAllowed, null, null);
validationResults.AddIfNotIn(new ServiceRecord2Validation(checkServiceRecord, result, dateRangeString ?? ""));
} // Mehrfachbuchung
else if(Model.IsInMultiBookingMode && !Model.IsInGroupBookingMode)
{
employeeOids.AddRangeIfElementsNotIn(Model.GroupBookingSelectedEmployees.Select(e => e.EmployeeOid));
var cb2ScOids = Model.GroupBookingSelectedCostBearerSupportConceptOids;
var relations = CustomerService.GetSupportConceptCostBearerRelationsById(cb2ScOids);
foreach(var costBearer2SupportConceptRel in relations)
{
dateRangeString = costBearer2SupportConceptRel.DateRangeString ?? string.Empty;
var prototype = CloneServiceRecord(checkServiceRecord);
prototype.Customer = costBearer2SupportConceptRel.SupportConcept.Customer;
prototype.SupportConcept = costBearer2SupportConceptRel.SupportConcept;
prototype.CostBearer = costBearer2SupportConceptRel.CostBearer;
prototype.CostBearer2SupportConceptOid = costBearer2SupportConceptRel.CostBearer2SupportConceptOid;
var organisation = CustomerService.LoadOrganisationCompact(costBearer2SupportConceptRel.CostBearer.OrganisationOid);
if(!(organisation is null))
{
var calculations = Calculations.GetInstance(organisation.CostBearerID);
prototype.RoundedDuration = calculations.GetRoundedDuration(organisation, dauer);
}
var multiBookingValidationResults = OperationsService.ValidateServiceRecord(prototype, null, maxDaysEditSRsAllowed, employeeOids, cb2ScOids);
validationResults.AddIfNotIn(new ServiceRecord2Validation(prototype, multiBookingValidationResults, dateRangeString));
}
}
2025-06-11 22:56:25 +02:00
var user = LoggedInUser;
var allowOverlappingFls = user.HasRight(UserRightType.ServiceRecord_AllowCreateOverlappingFLS);
var allowOverlappingFlsForEmployee = user.HasRight(UserRightType.ServiceRecord_AllowCreateOverlappingFLSForEmployee);
var allowMoreFlsThanApproved = user.HasRight(UserRightType.ServiceRecord_AllowCreateMoreFLSThanApproved);
var bookAfterSettlementInvoice = user.HasRight(UserRightType.BookServiceRecordAfterSettlementInvoice);
var bookServiceRecordOutOfSupportConcept = user.HasRight(UserRightType.BookServiceRecordOutOfSupportConcept);
var allowCreateAfterEmployeeSignature = user.HasRight(UserRightType.ServiceRecord_AllowCreateAfterEmployeeSignature);
var allowEditAfterEmployeeSignature = user.HasRight(UserRightType.ServiceRecord_AllowEditAfterEmployeeSignature);
2025-06-11 22:56:25 +02:00
var allowCreateAll = user.HasRight(UserRightType.CreateAll);
var allowEditAll = user.HasRight(UserRightType.CreateAll);
2020-10-01 11:45:48 +02:00
var newResult = new ValidationResult();
var exitLoop = false;
if(Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any() && Model.SelectedGoals.Count == 0)
{
2020-11-09 17:55:01 +01:00
newResult.Message += "Es wurden keine Ziele zugeordnet.<br/><br/>";
newResult.KannTrotzdemGespeichertWerden = true;
exitLoop = false;
}
foreach(var sr2V in validationResults)
{
if(exitLoop)
{
break;
}
foreach(var vr in sr2V.ValidationResults)
{
if(exitLoop)
{
break;
}
Debug.WriteLine($"---->ValidationResult: {vr.ResultType}");
switch(vr.ResultType)
{
case ServiceRecordOverlapping:
2025-10-31 11:56:14 +01:00
newResult.Message = $"An dem gew&auml;hlten Datum {startDt:dd.MM.yyyy HH:mm} existiert bereits ein Eintrag ({vr.Message} bei Klient/in {vr.CustomerName}).<br /><br />";
newResult.KannTrotzdemGespeichertWerden = allowOverlappingFls;
exitLoop = !allowOverlappingFls;
break;
case EmployeeOverlapping:
2025-10-31 11:56:14 +01:00
newResult.Message += $"An dem gew&auml;hlten Datum {startDt:dd.MM.yyyy HH:mm} existiert bereits ein Eintrag von {vr.EmployeeName} ({vr.Message}).<br /><br />";
newResult.KannTrotzdemGespeichertWerden = allowOverlappingFlsForEmployee;
exitLoop = !allowOverlappingFlsForEmployee;
break;
case OutsideOfSupportConcept:
2025-10-31 11:56:14 +01:00
newResult.Message += $"Das gew&auml;hlte Datum {startDt:dd.MM.yyyy HH:mm} liegt au&szlig;erhalb des Zeitraumes des gew&auml;hlten Hilfeplans ({sr2V.HilfePlanZeitraum}).<br /><br />";
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&uuml;r " + klient + " genehmigten FLS (" + vr.ApprovedHours + ") werden mit diesem Eintrag &uuml;berschritten. (" + vr.HoursNew + ").";
newResult.Message += msg + "<br /><br />";
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.<br /><br />";
exitLoop = true;
newResult.KannTrotzdemGespeichertWerden = false;
break;
case ServiceRecordValidationResult.Error:
newResult.Message += "Beim Speichern ist ein Fehler aufgetreten.<br /><br />";
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&uuml;cksichtigen, muss eventuell eine neue Spitzabrechnung erstellt werden.<br /><br />";
}
else
{
newResult.Message += "Sie k&ouml;nnen den Eintrag nicht bearbeiten, da bereits eine Spitzabrechnung f&uuml;r " + klient2 + "<br /><br />";
}
break;
case FristAbgelaufen:
var intervall = "einem Tag";
if(limitFuerZeiterfassung != 1)
{
intervall = "" + limitFuerZeiterfassung + " Tagen";
}
2025-06-11 22:56:25 +02:00
if(!LoggedInUser.HasRight(UserRightType.ServiceRecordAllowEditAfterMindays))
{
if(limitFuerZeiterfassung == 1)
{
2025-10-31 11:56:14 +01:00
newResult.Message += $"Sie k&ouml;nnen keine neuen Leistungen f&uuml;r den {startDt:dd.MM.yyyy} dokumentieren, da die Zeiterfassung innerhalb von einem Tag erfolgen muss.<br /><br />";
}
else
{
2025-10-31 11:56:14 +01:00
newResult.Message += $"Sie k&ouml;nnen keine neuen Leistungen f&uuml;r den {startDt:dd.MM.yyyy} dokumentieren, da die Zeiterfassung innerhalb von {intervall} erfolgen muss.<br /><br />";
}
newResult.KannTrotzdemGespeichertWerden = false;
exitLoop = true;
}
break;
case Custom:
newResult.Message += vr.Message + "<br /><br />";
exitLoop = true;
newResult.KannTrotzdemGespeichertWerden = vr.Allow;
break;
case SignatureExists:
var klient3 = "diesem Hilfeplan";
if(!string.IsNullOrEmpty(vr.CustomerName))
{
klient3 = "Klient " + vr.CustomerName;
}
newResult.Message += $"Für den ausgewählten Zeitraum existiert bereits eine Monatsunterschrift bei {klient3}, die mit dem Anlegen dieses Eintrags verfällt und neu geleistet werden muss.<br /><br />";
exitLoop = false;
newResult.KannTrotzdemGespeichertWerden = true;
break;
default:
Debug.WriteLine($"---->ValidationResult: {vr.ResultType}");
break;
}
}
}
2016-06-27 01:45:38 +02:00
var signatureValidationResult = OperationsService.CheckForExistingSignature(checkServiceRecord);
if(signatureValidationResult != null && newResult.KannTrotzdemGespeichertWerden)
{
newResult.Message += $"<br />{signatureValidationResult.Message}<br /><br />";
}
if(!string.IsNullOrEmpty(newResult.Message))
{
newResult.Message += newResult.KannTrotzdemGespeichertWerden ? newResult.Message.Contains("Möchten Sie trotzdem speichern?") ? string.Empty : "<br />Möchten Sie trotzdem speichern?<br /><br />" : "<br />Speichern nicht möglich.<br /><br />";
Model.SelectedServiceRecord = checkServiceRecord;
}
2016-06-27 01:45:38 +02:00
Model.NewServiceRecord = new ServiceRecordDC();
if(newResult?.Message != null)
{
TempData[TempDataServiceRecordValidationKey] = newResult;
TempData[TempDataFormIdKey] = formId;
}
else
{
var formCollection2 = new FormCollection
{
[FormCollectionConstants.DateKey] = von,
[FormCollectionConstants.EndDateKey] = bis,
[FormCollectionConstants.StartKey] = start,
[FormCollectionConstants.EndKey] = end,
[FormCollectionConstants.DurationKey] = durationRaw,
[FormCollectionConstants.DistanceKey] = distanceRaw,
[FormCollectionConstants.BetragKey] = betragRaw,
2025-01-22 16:42:02 +01:00
[FormCollectionConstants.MarkerKey] = markerRaw,
[FormCollectionConstants.ServiceDescriptionKey] = serviceDescription,
[FormCollectionConstants.Dokumentation1Key] = doku1,
[FormCollectionConstants.Dokumentation2Key] = doku2,
[FormCollectionConstants.Dokumentation3Key] = doku3,
[FormCollectionConstants.Dokumentation4Key] = doku4,
[FormCollectionConstants.Dokumentation5Key] = doku5,
[FormCollectionConstants.Dokumentation6Key] = Model.Dokutypes != null && Model.Dokutypes.Length == 0 ? doku1 : null
};
TempData[TempDataConstants.AfterValidationStateKey] = null;
if(Model.IsInGroupBookingMode)
{
return CreateOrUpdateGroupBooking(formCollection2);
}
return Model.IsInMultiBookingMode ? CreateMultiBooking(formCollection2) : CreateOrUpdateServiceRecord(formCollection2);
}
if(decimal.TryParse(distanceRaw, out var distanceInMeters) && Model.SelectedServiceRecord != null)
{
Model.SelectedServiceRecord.DistanceInMeterDecimal = distanceInMeters;
}
if(decimal.TryParse(durationRaw, out var duration) &&
Model.SelectedServiceRecord != null &&
Model.SelectedServiceRecord.RoundedDuration == 0)
{
Model.SelectedServiceRecord.RoundedDuration = Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1 ? duration * 60 : duration;
}
2025-06-11 22:56:25 +02:00
Model.SelectedServiceRecordOid = Model.SelectedServiceRecord?.ServiceRecordOid;
2025-10-31 11:56:14 +01:00
Model.SelectedServiceRecord.Start = startDt;
Model.SelectedServiceRecord.End = endDt;
2025-06-11 22:56:25 +02:00
TempData[TempDataConstants.AfterValidationStateKey] = true;
return View("Main", Model);
2016-06-27 01:45:38 +02:00
}
[Authorize]
public string ValidateServiceRecordDeletion(string serviceRecordOidString)
{
2025-07-17 16:26:07 +02:00
SkipModelInitialization = true;
if(!IsUserLoggedIn())
{
Logout();
return LeerzeichenFuerGetMethoden;
}
var isSuccessful = long.TryParse(serviceRecordOidString, out var serviceRecordOid);
if(!isSuccessful)
{
return "Error";
}
var newResult = new ValidationResult();
2025-07-17 16:26:07 +02:00
var serviceRecord = GetServiceRecordDC(serviceRecordOid, true);
if(serviceRecord is null)
{
return LeerzeichenFuerGetMethoden;
}
2025-06-11 22:56:25 +02:00
var validationResultList = OperationsService.ValidateServiceRecordDeletion(serviceRecord, Model.LoggedInEmployee.EmployeeOid.Value);
if(validationResultList.Count > 0)
{
foreach(var result in validationResultList)
{
switch(result.ResultType)
{
case Custom:
newResult.KannTrotzdemGespeichertWerden = true;
2025-05-23 15:57:18 +02:00
newResult.Message += RemoveConfirmationFromValidationResultMessage(result.Message) + "<br><br>";
break;
}
}
if(newResult.Message?.Length > 0)
{
newResult.Message += "Möchten Sie ihn trotzdem löschen?<br/><br/>";
}
return SerializeObject(newResult);
}
2020-11-09 17:55:01 +01:00
return serviceRecord.GroupOid != null
2025-05-23 15:57:18 +02:00
? SerializeObject(new ValidationResult{KannTrotzdemGespeichertWerden = true, Message = "ACHTUNG, wenn Sie fortfahren, löschen Sie die gesamte Gruppenbuchung.<br>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.<br/>Sind Sie sicher, dass Sie den gesamten Gruppeneintrag löschen möchten?<br><br>" })
2020-11-09 17:55:01 +01:00
: 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)
2016-06-27 01:45:38 +02:00
{
try
2016-06-27 01:45:38 +02:00
{
if(Model is null)
{
Logout();
return LeerzeichenFuerGetMethoden;
}
2016-06-27 01:45:38 +02:00
Model.SelectedEmployee = Model.AllEmployees.First(f => f.EmployeeOid.Equals(employeeOid));
2025-06-11 22:56:25 +02:00
Model.SelectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid;
return Model.SelectedEmployee?.DetailDescription ?? LeerzeichenFuerGetMethoden;
}
catch(Exception e)
{
Log.Info("Error in SetServiceRecordEmployee:");
Log.Error(e.Message, e);
if(Model?.AllEmployees is null)
{
Log.Info("Weitere Infos: Model oder AllEmployees = null!");
}
else
{
Log.Info($"Weitere Infos: AllEmployees enthält {Model.AllEmployees.Count} Elemente: ");
var stringBuilder = new StringBuilder();
foreach (var ce in Model.AllEmployees)
{
if (stringBuilder.Length > 0)
{
stringBuilder.Append(",");
}
2016-06-27 01:45:38 +02:00
stringBuilder.Append(ce.EmployeeOid);
2016-06-27 01:45:38 +02:00
}
Log.Info(stringBuilder.ToString());
}
throw e;
}
}
2016-06-27 01:45:38 +02:00
[Authorize]
public string CheckToken(string token)
{
if(token != null && token.Equals("abcd"))
{
return SerializeObject("localhost;demo");
}
2016-06-27 01:45:38 +02:00
return LeerzeichenFuerGetMethoden;
}
2016-06-27 01:45:38 +02:00
#region Menü
2020-04-08 14:44:20 +02:00
// Menünavigation
[Authorize]
public ActionResult RedirectToScheduler()
{
return RedirectToActionPermanent("Scheduler", "Scheduler");
}
2016-06-27 01:45:38 +02:00
[Authorize]
public ActionResult RedirectToCustomer()
{
if(Model?.SelectedSupportConcept?.Customer?.Oid.HasValue ?? false)
{
return RedirectToActionPermanent("Customer", "Customer", new { id = Model.SelectedSupportConcept.Customer.Oid });
}
2016-06-27 01:45:38 +02:00
return RedirectToActionPermanent("Customer", "Customer");
}
2016-06-27 01:45:38 +02:00
[Authorize]
public ActionResult RedirectToReportView()
{
2025-06-11 22:56:25 +02:00
return Model.HasRightToViewQuittierungsbelege ? RedirectToAction("InitReports", "Report") : RedirectToMain();
}
[Authorize]
public ActionResult RedirectToReportViewer()
{
return RedirectToActionPermanent("ReportViewer", "ReportViewer");
}
public ActionResult RedirectToMain()
{
return RedirectToActionPermanent("Main", "Main");
}
2019-07-29 19:40:14 +02:00
[Authorize]
public ActionResult RedirectToDevExpressScheduler()
{
2026-07-20 14:20:02 +02:00
//#if DEBUG
return RedirectToActionPermanent("DevExpressScheduler", "DevExpressScheduler");
2026-07-20 14:20:02 +02:00
//#endif
2026-07-20 14:20:02 +02:00
//return RedirectToMain();
}
/// <summary>
/// Leitet zur Mitarbeiter-Seite weiter, die bis jetzt aber nur die Abwesenheiten des angemeldeten Mitarbeiters anzeigt
/// </summary>
/// <returns>Aufruf zur Mitarbeiter-Seite</returns>
[Authorize]
public ActionResult RedirectToPersons()
{
return RedirectToActionPermanent("Person", "Person");
}
[Authorize]
public ActionResult RedirectToEmployees()
{
return RedirectToActionPermanent("Employee", "Employee", new { id = Model.LoggedInEmployee?.EmployeeOid });
}
[Authorize]
2025-07-18 19:37:01 +02:00
public ActionResult RedirectToDevTools()
{
#if DEBUG
2025-07-18 19:37:01 +02:00
return RedirectToActionPermanent("DevTools", "DevTools");
#endif
return RedirectToMain();
}
#endregion
// Gruppenbuchungen
[HttpPost]
[Authorize]
public ActionResult SetGroupBookingMode(FormCollection pFormCollection)
{
SkipModelInitialization = true;
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
Model.TransferringAppointmentOid = null;
Model.IsInTransferMode = false;
var bookingMode = "true,false" == pFormCollection[FormCollectionConstants.IsInGroupBookingModeKey] ? BookingMode.GroupBookingMode : BookingMode.SingleBookingMode;
ResetBookingMode(bookingMode);
return RedirectToAction("Main");
}
2020-08-04 12:45:46 +02:00
/// <summary>
/// Setzt die getroffenen Auswahlen zurück
/// </summary>
/// <param name="bookingMode">
/// Einzelbuchung, Gruppenbuchung oder Mehrfachbuchung wie im FaC
/// </param>
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();
2025-06-11 22:56:25 +02:00
Model.PreviouslySelectedEmployeeOid = Model.SelectedEmployeeOid;
2025-06-17 13:06:29 +02:00
//Model.PreviouslySelectedSupportConceptOid = Model.SelectedSupportConceptOid;
2025-06-11 22:56:25 +02:00
Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid;
2025-06-17 13:06:29 +02:00
//Model.SelectedSupportConceptOid = null;
2025-06-11 22:56:25 +02:00
Model.SelectedCostBearerSupportConceptOid = null;
Model.SelectedEmployeeOid = null;
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployeeOids.AddIfNotIn(LoggedInUser.Employee.EmployeeOid);
Model.IsInEditingMode = false;
2025-06-11 22:56:25 +02:00
Model.SelectedServiceRecordOid = null;
}
if(bookingMode == BookingMode.MultiBookingMode)
{
ResetGroupBookingMode();
2025-06-11 22:56:25 +02:00
Model.PreviouslySelectedEmployeeOid = Model.SelectedEmployeeOid;
2025-06-17 13:06:29 +02:00
//Model.PreviouslySelectedSupportConceptOid = Model.SelectedSupportConceptOid;
2025-06-11 22:56:25 +02:00
Model.PreviouslySelectedCostbearer2SupportConceptOid = Model.SelectedCostBearerSupportConceptOid;
2025-06-17 13:06:29 +02:00
//Model.SelectedSupportConceptOid = null;
2025-06-11 22:56:25 +02:00
Model.SelectedCostBearerSupportConceptOid = null;
Model.SelectedEmployeeOid = null;
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployeeOids.AddIfNotIn(LoggedInUser.Employee.EmployeeOid);
Model.IsInEditingMode = false;
2025-06-11 22:56:25 +02:00
Model.SelectedServiceRecordOid = null;
}
if(bookingMode == BookingMode.SingleBookingMode)
{
ResetMultiBookingMode();
2025-06-11 22:56:25 +02:00
Model.SelectedEmployeeOid = Model.PreviouslySelectedEmployeeOid ?? LoggedInUser.Employee.EmployeeOid;
2025-06-17 13:06:29 +02:00
//if (Model.PreviouslySelectedSupportConceptOid.HasValue)
//{
// Model.SelectedSupportConceptOid = Model.PreviouslySelectedSupportConceptOid;
//}
2025-06-11 22:56:25 +02:00
if (Model.PreviouslySelectedCostbearer2SupportConceptOid.HasValue)
{
Model.SelectedCostBearerSupportConceptOid = Model.PreviouslySelectedCostbearer2SupportConceptOid;
}
ResetGroupBookingMode();
2025-06-17 13:06:29 +02:00
ResetMultiBookingMode();
}
2025-06-17 13:06:29 +02:00
//Model.SelectedSupportConceptOid = Model.SelectedSupportConcept?.SupportConceptOid;
2025-06-11 22:56:25 +02:00
Model.SelectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid;
Model.SelectedServiceRecordOid = Model.SelectedServiceRecord?.ServiceRecordOid;
}
private void ResetMultiBookingMode()
{
Model.Categories2Descriptions.Clear();
2025-06-11 22:56:25 +02:00
//Model.MultiBookingSelectedConceptCostBearerRelations.Clear();
Model.GroupBookingSelectedCostBearerSupportConceptOids.Clear();
Model.GroupBookingSelectedCostBearerSupportConcepts.Clear();
Model.GroupBookingSelectedEmployeeOids.Clear();
Model.GroupBookingSelectedEmployees.Clear();
Model.GroupBookingSelectedGroupOfPeopleOids.Clear();
}
private void ResetGroupBookingMode()
{
Model.Categories2Descriptions.Clear();
Model.GroupBookingSelectedCostBearerSupportConceptOids.Clear();
Model.GroupBookingSelectedCostBearerSupportConcepts.Clear();
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployeeOids.Clear();
Model.GroupBookingSelectedEmployees.Clear();
Model.GroupBookingSelectedGroupOfPeopleOids.Clear();
}
[HttpPost]
[Authorize]
public ActionResult ResetSingleBookingForm()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
ResetBookingMode(BookingMode.SingleBookingMode);
LoadSupportConceptThings(Model.SelectedCostBearerSupportConceptOid, false);
return View("Main", Model);
}
[HttpPost]
[Authorize]
public ActionResult SetAiVoiceMode(string mode)
{
SkipModelInitialization = true;
Model.AiVoiceMode = mode == "1" ? 1 : 0;
UpdateUserSettingsWithoutReload(SettingsKeys.AiVoiceMode, Model.AiVoiceMode.ToString());
return new HttpStatusCodeResult(200);
}
2026-03-30 00:07:52 +02:00
/// <summary>
/// Ermittelt die externe URL, die beim Klick auf den AI-Voice-Button aufgerufen werden soll.
/// Die callId wird server-seitig als GUID erzeugt (kryptographisch sicher) und zusammen
/// mit der URL an den Client zurückgegeben.
2026-03-30 00:07:52 +02:00
/// </summary>
[HttpGet]
[Authorize]
public JsonResult GetExternalCallUrl()
2026-03-30 00:07:52 +02:00
{
2026-03-30 00:07:52 +02:00
try
{
SkipModelInitialization = true;
// CallId server-seitig erzeugen Guid.NewGuid() ist kryptographisch sicher (128-Bit)
// In der Session speichern der Browser bekommt sie nie zu sehen
var callId = Guid.NewGuid().ToString("N");
Session["ExternalCallId"] = callId;
// CallbackUrl server-seitig zusammenbauen
var callbackUrl = Url.Action("ExternalCallCallback", "Main", new { callId }, Request.Url.Scheme);
2026-03-30 00:07:52 +02:00
var externalUrl = "";
if (Mandator?.OwnChatCode != null)
{
var ts = new TranscriptionService();
var sendOwnChatMessage = Model.AiVoiceMode == 0 ? false : true;
2026-03-30 00:07:52 +02:00
var avd = ts.InitTranskription(MobileSessionFacade.Tenant, sendOwnChatMessage);
if (!sendOwnChatMessage)
{
externalUrl = avd.OwnChatUrl;
}
else
{
avd.OwnChatUrl = null;
}
2026-03-30 00:07:52 +02:00
if (!string.IsNullOrEmpty(avd.Token))
2026-03-30 00:07:52 +02:00
{
_externalCallTokens[callId] = ts.MapAiVoiceDataDC(avd);
}
2026-04-01 19:17:39 +02:00
Log.Info($"GetExternalCallUrl: {callId}. Url = {externalUrl}, Transkription startet!");
2026-03-30 00:07:52 +02:00
}
2026-04-01 19:17:39 +02:00
else
{
Log.Info($"GetExternalCallUrl: {callId}. Url = {callbackUrl}, Transkription starten hat nicht geklappt. Kein OwnChatCode vorhanden!");
}
2026-03-30 00:07:52 +02:00
return Json(new { success = true, url = externalUrl }, JsonRequestBehavior.AllowGet);
}
catch(Exception ex)
{
return Json(new { success = false, message = "Fehler beim Ermitteln der externen URL: " + ex.Message }, JsonRequestBehavior.AllowGet);
}
}
/// <summary>
/// Callback-Endpunkt, der vom externen System aufgerufen wird.
/// Markiert den externen Aufruf als abgeschlossen.
/// </summary>
[HttpGet]
[AllowAnonymous]
public ActionResult ExternalCallCallback(string callId, string data = null)
{
if(!string.IsNullOrEmpty(callId))
{
_externalCallResults[callId] = data ?? string.Empty;
_externalCallStatusMessages.TryRemove(callId, out _);
_externalCallTokens.TryRemove(callId, out _);
}
return Content("OK");
}
/// <summary>
/// Kann vom externen System aufgerufen werden, um eine Statusmeldung zu setzen,
/// die dem Benutzer im Wartedialog angezeigt wird (ohne den Vorgang abzuschließen).
/// </summary>
[HttpGet]
[AllowAnonymous]
public ActionResult ExternalCallUpdateStatus(string callId, string message)
{
if(!string.IsNullOrEmpty(callId) && message != null)
{
_externalCallStatusMessages[callId] = message;
}
return Content("OK");
}
/// <summary>
/// Wird vom Browser per Polling aufgerufen, um zu prüfen ob der Callback bereits eingegangen ist.
/// Gibt bei completed=false optional eine Statusmeldung zurück.
/// </summary>
[HttpGet]
[Authorize]
public JsonResult CheckExternalCallStatus()
2026-03-30 00:07:52 +02:00
{
var callId = Session["ExternalCallId"] as string;
2026-03-30 00:07:52 +02:00
if(!string.IsNullOrEmpty(callId) && _externalCallResults.TryRemove(callId, out var data))
{
_externalCallStatusMessages.TryRemove(callId, out _);
_externalCallTokens.TryRemove(callId, out _);
Session.Remove("ExternalCallId");
2026-03-30 00:07:52 +02:00
return Json(new { completed = true, data }, JsonRequestBehavior.AllowGet);
}
string statusMessage = null;
2026-04-01 19:17:39 +02:00
//Log.Info($"CheckExternalCallStatus: Start {callId}.");
if (!string.IsNullOrEmpty(callId) && _externalCallTokens.TryRemove(callId, out var avddc))
2026-03-30 00:07:52 +02:00
{
var ts = new TranscriptionService();
var avd = ts.MapAiVoiceData(avddc);
avd = ts.GetTranskription(avd);
2026-04-01 19:17:39 +02:00
2026-03-30 00:07:52 +02:00
statusMessage = avd.StatusMessage;
2026-04-01 19:17:39 +02:00
if (!String.IsNullOrEmpty(avd.OwnChatUrl)) // Wenn nicht null, dann wurde die Spracheingabe über direkt Link gestartet
{
if (!String.IsNullOrEmpty(statusMessage) && statusMessage.Contains("klicken Sie auf den Link"))
{
statusMessage = "Warte auf Beendigung der Aufzeichnung in ownChat...\r\nHINWEIS: Wenn ownChat auf diesem Gerät nicht installiert ist, ist die Spracheingabe nicht möglich. In diesem Fall brechen Sie den Vorgang bitte ab. Wenn Sie ownChat auf einem anderen Gerät nutzen, können Sie in den Einstellungen auch in den Push-Modus wechseln.";
}
}
2026-04-01 19:17:39 +02:00
if (!String.IsNullOrEmpty(avd.TranskriptionText))
{
statusMessage = "Transkription erfolgreich durchgeführt";
Log.Info($"CheckExternalCallStatus: {callId}. Transkription erfolgreich durchgeführt!");
ExternalCallCallback(callId, avd.TranskriptionText);
}
else if (!String.IsNullOrEmpty(avd.Error))
{
statusMessage = avd.Error;
Log.Info($"CheckExternalCallStatus: {callId}. Transkription mit Fehler beendet: {avd.Error}");
ExternalCallCallback(callId, "");
}
else
{
//Log.Info($"CheckExternalCallStatus: {callId}. Status: {statusMessage}");
}
2026-03-30 00:07:52 +02:00
avddc = ts.MapAiVoiceDataDC(avd);
_externalCallTokens[callId] = avddc;
2026-04-01 19:17:39 +02:00
}
else
{
Log.Info($"CheckExternalCallStatus: {callId}. Kein Token gefunden.");
2026-03-30 00:07:52 +02:00
}
return Json(new { completed = false, statusMessage }, JsonRequestBehavior.AllowGet);
}
2026-04-01 19:17:39 +02:00
2026-03-30 00:07:52 +02:00
/// <summary>
/// Wird aufgerufen, wenn der Benutzer den externen Aufruf abbricht.
/// Räumt den Eintrag auf, falls vorhanden.
/// </summary>
[HttpPost]
[Authorize]
public ActionResult CancelExternalCall()
2026-03-30 00:07:52 +02:00
{
var callId = Session["ExternalCallId"] as string;
2026-03-30 00:07:52 +02:00
if(!string.IsNullOrEmpty(callId))
{
_externalCallResults.TryRemove(callId, out _);
_externalCallStatusMessages.TryRemove(callId, out _);
_externalCallTokens.TryRemove(callId, out _);
Session.Remove("ExternalCallId");
2026-03-30 00:07:52 +02:00
}
return new HttpStatusCodeResult(200);
}
[HttpPost]
[Authorize]
public ActionResult ResetGroupBookingForm()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
}
ResetBookingMode(BookingMode.GroupBookingMode);
return View("Main", Model);
}
[HttpPost]
[Authorize]
public ActionResult ResetMultiBookingForm()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
2025-06-17 13:06:29 +02:00
//if(Model.PreviouslySelectedSupportConceptOid != null && Model.SelectedSupportConceptOid is null)
if (Model.PreviouslySelectedCostbearer2SupportConceptOid != null && Model.SelectedCostBearerSupportConceptOid is null)
{
2025-06-17 13:06:29 +02:00
//Model.SelectedSupportConceptOid = Model.PreviouslySelectedSupportConceptOid;
2025-06-11 22:56:25 +02:00
Model.SelectedCostBearerSupportConceptOid = Model.PreviouslySelectedCostbearer2SupportConceptOid;
}
ResetModel();
return View("Main", Model);
}
[HttpPost]
[Authorize]
public ActionResult ResetEditingMode()
{
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
SkipModelInitialization = true;
ResetModel();
Model.TransferringAppointmentOid = null;
Model.IsInTransferMode = false;
return RedirectToActionPermanent("Main");
}
[Authorize]
[HttpPost]
public ActionResult ResetTransferMode()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
Model.TransferringAppointmentOid = null;
Model.IsInTransferMode = false;
ResetModel();
return RedirectToScheduler();
}
[Authorize]
private void ResetModel()
{
if(Model is null)
{
return;
}
TempData[TempDataConstants.AfterValidationStateKey] = null;
2025-06-11 22:56:25 +02:00
Model.NewServiceRecord = new ServiceRecordDC();
Model.SelectedServiceRecordOid = null;
Model.IsInEditingMode = false;
2025-06-11 22:56:25 +02:00
Model.SelectedEmployeeOid = LoggedInUser.Employee.EmployeeOid;
Model.GroupBookingSelectedCostBearerSupportConceptOids.Clear();
Model.GroupBookingSelectedCostBearerSupportConcepts.Clear();
Model.GroupBookingSelectedGroupOfPeopleOids.Clear();
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployeeOids = new List<long> { LoggedInUser.Employee.EmployeeOid };
Model.IsInMultiBookingMode = false;
2025-06-11 22:56:25 +02:00
Model.SelectedGoalOids.Clear();
2025-07-17 16:26:07 +02:00
Model.SelectedGoals.Clear();
2025-06-11 22:56:25 +02:00
Model.SelectedServiceCategoryOid = null;
Model.SelectedServiceDescriptionOid = null;
2020-08-04 12:45:46 +02:00
2025-06-11 22:56:25 +02:00
//LoadServiceCategoriesToModel(Model.SelectedCostBearerSupportConceptOid);
2025-06-11 22:56:25 +02:00
//Model.MainSessionModel.ResetValues();
2016-06-27 01:45:38 +02:00
}
[Authorize]
2025-10-09 12:56:32 +02:00
public ActionResult AddScCbRelsToGroupBooking(string[] relOids, string[] groupOids, bool isGroupTabActive)
2017-04-26 14:57:32 +02:00
{
if(!IsUserLoggedIn())
2025-10-09 12:56:32 +02:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
return PartialView("GroupBookingScCbRelList");
}
AddScCbRelsToGroupOrMultiBooking(relOids, groupOids);
2025-10-09 12:56:32 +02:00
TempData[TempDataConstants.IsGroupTabActiveKey] = isGroupTabActive;
return PartialView("GroupBookingScCbRelList", Model);
}
[Authorize]
2025-10-09 12:56:32 +02:00
public ActionResult AddScCbRelsToMultiBooking(string[] relOids, string[] groupOids, bool isGroupTabActive)
{
2025-10-09 12:56:32 +02:00
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
return PartialView("MultiBookingScCbRelList");
}
2025-10-09 12:56:32 +02:00
AddScCbRelsToGroupOrMultiBooking(relOids, groupOids);
2025-10-09 12:56:32 +02:00
TempData[TempDataConstants.IsGroupTabActiveKey] = isGroupTabActive;
return PartialView("MultiBookingScCbRelList", Model);
}
private void AddScCbRelsToGroupOrMultiBooking(string[] relOids, string[] groupOids)
{
SkipModelInitialization = true;
var singleRels = new List<long>();
var groupRels = new List<long>();
if(groupOids is null)
{
groupOids = Array.Empty<string>();
}
if(relOids is null)
{
relOids = Array.Empty<string>();
}
relOids.DoForEach(relOid =>
{
if(long.TryParse(relOid, out var singleRelOid))
{
singleRels.AddIfNotIn(singleRelOid);
}
});
groupOids.DoForEach(groupOid =>
{
if(long.TryParse(groupOid, out var g))
{
groupRels.AddIfNotIn(g);
}
});
2025-10-09 12:56:32 +02:00
AddScCbRelsToBooking(singleRels, groupRels);
// Sorgt dafür, dass nach dem Neuladen die Abhängigkeiten vom Hilfeplan erhalten bleiben
TempData[TempDataConstants.SupportConceptRelSelectedKey] = true;
}
[Authorize]
public void AddScCbRelsToBooking(List<long> singleRels, List<long> groupRels, bool forceReload = false)
{
var groups = new List<GroupOfPeopleDC>();
if(singleRels is null)
{
singleRels = new List<long>();
}
if(groupRels is null)
{
groupRels = new List<long>();
}
Model.GroupsOfPeople = EmployeeService.GetAllGroups(LoggedInEmployee.EmployeeOid).OrderBy(gop => gop.Name).ToList();
Model.GroupBookingSelectedGroupOfPeopleOids.Clear();
groupRels.DoForEach(groupOid =>
{
var group = Model.GroupsOfPeople.FirstOrDefault(f => f.GroupOfPeopleOid.HasValue && f.GroupOfPeopleOid.Value.Equals(groupOid));
2025-10-09 12:56:32 +02:00
if(group is null)
{
return;
}
groups.AddIfNotIn(group);
});
Model.GroupBookingSelectedCostBearerSupportConcepts.Clear();
Model.GroupBookingSelectedCostBearerSupportConceptOids.Clear();
Model.GroupBookingSelectedCostBearerSupportConceptOids.AddRangeIfElementsNotIn(singleRels);
foreach(var group in Model.GroupsOfPeople)
{
var groupRelOids = new List<long>();
group.SupportConceptList
.Where(sc => false == sc.IsArchived && false == sc.IsDeleted)
.ToList()
.ForEach(f => groupRelOids.AddRange(f.CostBearerRelOids));
if(!group.GroupOfPeopleOid.HasValue)
{
continue;
}
var groupOid = group.GroupOfPeopleOid.Value;
var allMembersSelected = groupRelOids.Any() && groupRelOids.All(x => singleRels.Contains(x));
if(allMembersSelected)
{
Model.GroupBookingSelectedGroupOfPeopleOids.AddIfNotIn(groupOid);
}
else if(Model.GroupBookingSelectedGroupOfPeopleOids.Contains(groupOid))
{
Model.GroupBookingSelectedGroupOfPeopleOids.Remove(groupOid);
}
}
2025-10-09 12:56:32 +02:00
foreach(var gruppe in groups.Where(g => g.GroupOfPeopleOid.HasValue))
{
var groupRelOids = new List<long>();
gruppe.SupportConceptList
.Where(sc => false == sc.IsArchived && false == sc.IsDeleted)
.ToList()
.ForEach(f => groupRelOids.AddRange(f.CostBearerRelOids));
2025-10-09 12:56:32 +02:00
if(!gruppe.GroupOfPeopleOid.HasValue)
{
continue;
}
var groupOid = gruppe.GroupOfPeopleOid.Value;
var allMembersSelected = groupRelOids.All(x => singleRels.Contains(x));
if(allMembersSelected)
{
Model.GroupBookingSelectedGroupOfPeopleOids.AddIfNotIn(groupOid);
}
2025-10-09 12:56:32 +02:00
else if(Model.GroupBookingSelectedGroupOfPeopleOids.Contains(groupOid))
{
Model.GroupBookingSelectedGroupOfPeopleOids.Remove(groupOid);
}
}
2025-10-09 12:56:32 +02:00
CreateModelSupportConceptListObjects(forceReload);
2025-07-17 16:26:07 +02:00
LoadSupportConceptThings(null, true);
}
[Authorize]
public ActionResult RemoveSupportConceptCostbearerRel(string relOid)
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return PartialView("GroupBookingSelectionPartial");
}
if(!long.TryParse(relOid, out var c2sOid))
{
return PartialView("GroupBookingSelectionPartial", Model);
}
RemoveRelOidFromGroupBooking(c2sOid);
2025-06-11 22:56:25 +02:00
return PartialView("GroupBookingSelectionPartial", Model);
}
[Authorize]
public ActionResult ReloadGroupBookingForm()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
}
else
{
//LoadServiceCategoriesToModel(null);
}
return PartialView("GroupBookingSelectionPartial", Model);
}
[Authorize]
public string AddEmployeesToGroupBooking(string pEmployeeOids)
{
if(Model is null)
{
Logout();
return LeerzeichenFuerGetMethoden;
}
if(string.IsNullOrEmpty(pEmployeeOids))
{
Model.GroupBookingSelectedEmployees.Clear();
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployeeOids.Clear();
return JsonConvert.SerializeObject(Model.GroupBookingSelectedEmployees.Count);
}
var rawEmployeeOids = pEmployeeOids.Split(',');
var oids = new List<long>();
rawEmployeeOids.DoForEach(s => oids.AddIfNotIn(long.Parse(s)));
2025-10-09 12:56:32 +02:00
AddEmployeesToGroupBookingInternally(oids);
return JsonConvert.SerializeObject(Model.GroupBookingSelectedEmployees.Count);
}
[Authorize]
public void AddEmployeesToGroupBookingInternally(List<long> employeeOids)
{
if(employeeOids == null || employeeOids.Count == 0)
{
Model.GroupBookingSelectedEmployees.Clear();
Model.GroupBookingSelectedEmployeeOids.Clear();
return;
}
var employees = Model.EmployeesForGroupAndMultiBooking.Where(w => employeeOids.Contains(w.EmployeeOid));
Model.GroupBookingSelectedEmployees.Clear();
Model.GroupBookingSelectedEmployees.AddRangeIfElementsNotIn(employees);
2025-06-11 22:56:25 +02:00
Model.GroupBookingSelectedEmployeeOids = Model.GroupBookingSelectedEmployees.Select(e => e.EmployeeOid).ToList();
}
[Authorize]
2021-04-13 19:45:21 +02:00
public string GetSignatureImage(long serviceRecordOid, long signatureOid)
{
2025-07-17 16:26:07 +02:00
SkipModelInitialization = true;
if(!IsUserLoggedIn())
{
2021-04-13 19:45:21 +02:00
Logout();
return LeerzeichenFuerGetMethoden;
}
2025-07-17 16:26:07 +02:00
var signatureServiceRecord = GetServiceRecordDC(serviceRecordOid, true);
2021-04-13 19:45:21 +02:00
var signatureServiceRecordHeader = MainModel.GetServiceRecordTimeHeader(signatureServiceRecord, false);
2021-04-13 19:45:21 +02:00
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});
}
2019-07-25 14:56:11 +02:00
[HttpPost]
[Authorize]
public ActionResult SetSupportConceptFilter(FormCollection formCollection)
2019-07-25 14:56:11 +02:00
{
if(!IsUserLoggedIn())
2019-07-25 14:56:11 +02:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
SkipModelInitialization = true;
var selectedSupportConceptFilter = formCollection[nameof(Model.SelectedSupportConceptFilter)];
if(!Enum.TryParse(selectedSupportConceptFilter, out CustomerFilterEnum customerFilter))
{
customerFilter = CustomerFilterEnum.MyCustomer;
}
UpdateApplicationSettings(SettingsKeys.CustomerFilterInZeiterfassung, customerFilter.ToString());
Model.SupportConceptListObjects.Clear(); // Erzwingt das neu laden
return RedirectToActionPermanent("Main");
}
[Authorize]
[HttpPost]
public ActionResult CreateOrUpdateGroupBooking(FormCollection formCollection)
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
try
{
if(false == Model.IsInEditingMode)
{
if(Model.GroupBookingSelectedCostBearerSupportConceptOids.Count == 1)
{
Model.SelectedCostBearerSupportConceptOid = Model.GroupBookingSelectedCostBearerSupportConceptOids.FirstOrDefault();
}
}
else
{
var selectedRecordOid = Model.SelectedServiceRecordOid ?? Model.SelectedServiceRecord.ServiceRecordOid;
Model.NewServiceRecord = OperationsService.GetServiceRecordById(selectedRecordOid.Value);
}
string doku1;
2019-07-25 14:56:11 +02:00
if(Model.Dokutypes != null && Model.Dokutypes.Length > 0)
{
doku1 = formCollection[FormCollectionConstants.Dokumentation1Key];
}
else
{
doku1 = formCollection[FormCollectionConstants.Dokumentation6Key];
}
2019-07-25 14:56:11 +02:00
// Wenn kein Datum angegeben wurde, wird die Main-Seite geladen und abgebrochen
if(string.IsNullOrEmpty(formCollection[FormCollectionConstants.DateKey]))
{
return View("Main", Model);
}
// Marker
var marker = "on" == formCollection[FormCollectionConstants.MarkerKey];
decimal? betrag = null;
var betragAsString = formCollection[FormCollectionConstants.BetragKey]?.Replace('.', ',');
if(decimal.TryParse(betragAsString, out var betragAsDecimal))
{
betrag = betragAsDecimal;
}
// Distanz
var distanz = formCollection[FormCollectionConstants.DistanceKey];
2023-05-23 13:56:22 +02:00
decimal? distanceInMeters = null;
if(!string.IsNullOrEmpty(distanz))
{
2023-05-23 13:56:22 +02:00
if(decimal.TryParse(distanz, out var parsedDistance))
{
distanceInMeters = parsedDistance;
}
}
// Kostenträger-Hilfeplan-Relation
2025-06-11 22:56:25 +02:00
var selectedCostbearer2SupportConceptRelOid = Model.SelectedCostBearerSupportConceptOid < 1 ? null : Model.SelectedCostBearerSupportConceptOid;
// Datumsteil des Startdatums
var datum = Convert.ToDateTime(formCollection[FormCollectionConstants.DateKey]);
// Enddatum wird der gleiche Tag wie vom Start
var enddatum = datum;
// Es wird geprüft, ob es das Enddatumsfeld gibt (das haben nicht alle Kunden)
var endDateString = formCollection[FormCollectionConstants.EndDateKey];
2024-03-19 19:10:13 +01:00
if(endDateString?.Length > 0)
{
enddatum = Convert.ToDateTime(endDateString);
}
// Start- und Endzeit zur Dauerberechnung
var start = formCollection[FormCollectionConstants.StartKey];
var ende = formCollection[FormCollectionConstants.EndKey];
var dauer = 0m;
if(datum > enddatum)
{
enddatum = datum;
}
var durationAsString = formCollection[FormCollectionConstants.DurationKey];
durationAsString = durationAsString.Replace('.', ',');
if(!string.IsNullOrEmpty(durationAsString))
{
decimal.TryParse(durationAsString, out dauer);
}
// Wenn die Dauer in Stunden ist
if(Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1)
{
dauer *= 60m;
}
// Dokumentation
var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key];
var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key];
var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key];
var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key];
// Ziele und Maßnahmen
// Start- und Endstrings werden in DateTime-Objekte konvertiert
var zeitenFeld = new DateTime[2];
if(start == string.Empty && ende == string.Empty)
{
zeitenFeld[0] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1);
if(enddatum == datum)
{
zeitenFeld[1] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer));
}
else
{
zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer));
}
}
else
{
zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, Convert.ToDouble(dauer)) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, Convert.ToDouble(dauer));
}
if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0])
{
dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes;
}
if(Model.NewServiceRecord is null)
{
return RedirectToActionPermanent("Main");
}
Model.NewServiceRecord.IP = Request.UserHostAddress;
Model.NewServiceRecord.Goals = CreateValueListEntriesFromMokZiele(Model.SelectedGoals);
Model.NewServiceRecord.Start = zeitenFeld[0];
Model.NewServiceRecord.End = zeitenFeld[1];
Model.NewServiceRecord.Betrag = betrag;
if(marker)
{
Model.NewServiceRecord.ServiceRecordType = ServiceRecordTypeId.Content;
}
2023-05-23 13:56:22 +02:00
Model.NewServiceRecord.DistanceInMeterDecimal = distanceInMeters;
2025-06-11 22:56:25 +02:00
if(Model.LoggedInEmployee.EmployeeOid.HasValue)
{
if(Model.SelectedEmployee != null)
{
Model.NewServiceRecord.Employee = Model.SelectedEmployee;
}
2025-07-17 16:26:07 +02:00
var sclo = Model.SupportConceptListObjects.FirstOrDefault(a => a.CostBearer2SupportConceptOid.Equals(selectedCostbearer2SupportConceptRelOid));
if (sclo != null)
{
var sc = GetCompactSupportConcept(sclo.SupportConceptOid, selectedCostbearer2SupportConceptRelOid);
Model.NewServiceRecord.SupportConcept = sc;
Model.NewServiceRecord.Customer = sc.Customer;
var cb2ScRel = sc.CostBearerList.FirstOrDefault();
Model.NewServiceRecord.CostBearer = cb2ScRel.Organisation;
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;
2025-06-11 22:56:25 +02:00
Model.NewServiceRecord.InsUser = MobileSessionFacade.EmployeeFullname;
Model.NewServiceRecord.IsCreatedInMobileClient = true;
if(Model.SetStartTimeToEndTimeAfterSave)
{
var previousStartDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.Start : Model.NewServiceRecord?.Start;
var previousEndDate = Model.IsInEditingMode ? Model.SelectedServiceRecord?.End : Model.NewServiceRecord?.End;
if(previousStartDate.HasValue && previousEndDate.HasValue)
{
var duration = (previousEndDate - previousStartDate).Value.TotalMinutes;
Model.NewStartDate = previousEndDate;
Model.NewEndDate = previousEndDate.Value.AddMinutes(duration);
}
}
return Model.IsInEditingMode ? UpdateGroupBooking() : SaveGroupBooking();
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
}
return ResetEditingMode();
2019-07-25 14:56:11 +02:00
}
private CompactSupportConceptDC GetCompactSupportConcept(long supportConceptOid, long? c2sOid)
2025-07-17 16:26:07 +02:00
{
CompactSupportConceptDC sc = null;
if (Model.SupportConcepts != null)
{
sc = Model.SupportConcepts.FirstOrDefault(s => s.SupportConceptOid == supportConceptOid && s.CostBearerRelOids.Any(a => a == c2sOid));
2025-07-17 16:26:07 +02:00
}
if (sc == null)
{
sc = CustomerService.LoadCompactSupportConceptDC(supportConceptOid, Model.LoggedInEmployee.EmployeeOid);
if (c2sOid.HasValue && sc.CostBearerRelOids.Count > 1)
{
var oids2Remove = sc.CostBearerRelOids.Where(o => o != c2sOid.Value).ToList();
var cb2Remove = sc.CostBearerList.Where(c => c.CostBearer2SupportConceptOid != c2sOid.Value).ToList();
sc.CostBearerRelOids.RemoveRange(oids2Remove);
sc.CostBearerList.RemoveRange(cb2Remove);
}
2025-07-17 16:26:07 +02:00
}
return sc;
}
[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;
}
2023-02-23 11:48:41 +01:00
/// <summary>
/// Bereitet die Übernahme eines Termins in die Zeiterfassung vor. Wird im SchedulerController aufgerufen.
/// </summary>
/// <returns>Main.cshtml</returns>
2023-02-23 11:48:41 +01:00
[Authorize]
public ActionResult PrepareServiceRecordInsert()
{
if(false == IsUserLoggedIn())
2023-02-23 11:48:41 +01:00
{
TempData[TempDataConstants.DoLogoutKey] = true;
2023-02-23 11:48:41 +01:00
return Logout();
}
Model.TransferringAppointmentOid = TempData[TempDataConstants.AppointmentOidKey] as long?;
var recurrenceIndex = (int?) TempData[TempDataConstants.AppointmentRecurrenceIndexKey];
var isSerientermin = recurrenceIndex.HasValue;
//TempData[TempDataConstants.AppointmentIsSerienterminKey] is true;
if((false == Model.TransferringAppointmentOid.HasValue && false == isSerientermin) || false == Model.LoggedInEmployee.EmployeeOid.HasValue)
{
return View("Main", Model);
}
2023-02-23 11:48:41 +01:00
var app = Model.TransferringAppointmentOid.HasValue ? DAOFactory.GenericDAO.LoadByID<SchedulerAppointment>(Model.TransferringAppointmentOid.Value) : null;
var appointment = app is null ? null : MapperFactory.SchedulerAppointmentDCSchedulerAppointment.MapToNewDC(app);
2023-02-23 11:48:41 +01:00
var startRaw = TempData[TempDataConstants.AppointmentStartKey]?.ToString();
var endRaw = TempData[TempDataConstants.AppointmentEndKey]?.ToString();
var subject = TempData[TempDataConstants.AppointmentSubjectKey]?.ToString();
var isAllDay = TempData[TempDataConstants.AppointmentIsAllDayKey] is true;
2023-02-23 11:48:41 +01:00
var customerOids = new List<long>();
var employeeOids = new List<long>();
var resourceOids = new List<long>();
if(TempData[TempDataConstants.AppointmentEmployeeOidsKey] is string employeeOidsRaw && employeeOidsRaw.Length > 0)
{
employeeOids = Utils.ConvertCharSeparatedValuesToLongList(employeeOidsRaw, ',');
}
if(TempData[TempDataConstants.AppointmentCustomerOidsKey] is string customerOidsRaw && customerOidsRaw.Length > 0)
{
customerOids = Utils.ConvertCharSeparatedValuesToLongList(customerOidsRaw, ',');
}
if(TempData[TempDataConstants.AppointmentResourceOidsKey] is string resourceOidsRaw && resourceOidsRaw.Length > 0)
{
resourceOids = Utils.ConvertCharSeparatedValuesToLongList(resourceOidsRaw, ',');
}
2023-02-23 11:48:41 +01:00
DateTime.TryParse(startRaw, out var start);
DateTime.TryParse(endRaw, out var end);
2023-02-23 11:48:41 +01:00
if(appointment is object)
{
customerOids = appointment.CustomerList.Select(customer => customer.CustomerOid).ToList();
employeeOids = appointment.EmployeeList.Select(e2a => e2a.Employee.EmployeeOid).ToList();
}
if(isAllDay)
{
start = start.MergeDateWithHoursMinutesSeconds(0, 0, 1);
end = end.MergeDateWithHoursMinutesSeconds(0, 0, 1);
}
if(employeeOids.Count == 0)
{
employeeOids.Add(Model.LoggedInEmployee.EmployeeOid.Value);
}
var notice = appointment?.Description ?? TempData[TempDataConstants.AppointmentSubjectKey]?.ToString();
if(appointment is null)
{
notice = TempData[TempDataConstants.AppointmentDescriptionKey]?.ToString() ??
TempData[TempDataConstants.AppointmentSubjectKey]?.ToString();
}
Model.SupportConceptListObjects.Clear(); //Macht, dass beim Init die SupportConcepts neu geladen werden
InitViewModel(true);
var supportConcepts = Model.SupportConcepts.Where(sc => customerOids.Contains(sc.Customer.CustomerOid)).ToList();
var supportConceptList = new List<CompactSupportConceptDC>();
foreach(var customerOid in customerOids)
{
var supportConcept = supportConcepts.FirstOrDefault(sc => sc.Customer.CustomerOid.Equals(customerOid));
if(supportConcept is null)
2023-02-23 11:48:41 +01:00
{
continue;
}
2023-02-23 11:48:41 +01:00
supportConceptList.AddIfNotIn(supportConcept);
}
// Falls es sich um einen Serientermin handelt, Ausnahme erstellen und speichern, nachdem der Eintrag in der Datenbank gespeichert wurde.
if(isSerientermin && appointment is null)
{
var customers = CustomerService.GetCompactCustomersById(customerOids);
var employees = EmployeeService.GetActiveCompactEmployeesByOids(employeeOids);
var resources = OperationsService.GetResourcesByOids(resourceOids);
appointment = new SchedulerAppointmentDC
{
StartDate = start,
EndDate = end,
ActivationType = ActivationTypeId.Active,
AllDay = isAllDay,
CustomerList = customers,
ResourceList = resources,
EmployeeList = new List<Employee2SchedulerAppointmentDC>(),
Location = TempData[TempDataConstants.AppointmentLocationKey]?.ToString(),
IsPrivate = TempData[TempDataConstants.AppointmentIsPrivateKey] is true,
Subject = subject,
SupportConceptList = supportConceptList,
Type = (int) AppointmentType.ChangedOccurrence,
Originator = Model.LoggedInUser.Employee
};
foreach(var employee in employees)
{
appointment.EmployeeList.Add(new Employee2SchedulerAppointmentDC { Employee = employee });
}
var recurrenceInfo = TempData[TempDataConstants.AppointmentRecurrenceInfoKey].ToString();
var pattern = StaticAppointmentFactory.CreateAppointment(AppointmentType.Pattern);
pattern.RecurrenceInfo.FromXml(recurrenceInfo);
pattern.Start = pattern.RecurrenceInfo.Start;
pattern.End = pattern.RecurrenceInfo.End;
var apt = pattern.CreateException(AppointmentType.ChangedOccurrence, recurrenceIndex.Value);
appointment = SchedulerAppointmentDC.RecurringExceptionFromDevExpressAppointment(apt, appointment, recurrenceIndex.Value, pattern.RecurrenceInfo.Id.ToString());
TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] = appointment;
}
// Ohne Hilfeplan
if(supportConceptList.Count == 0)
{
ResetBookingMode(BookingMode.SingleBookingMode);
Model.SelectedEmployee = Model.AllEmployees.FirstOrDefault(e => e.EmployeeOid.Equals(Model.LoggedInEmployee.EmployeeOid.Value));
2023-02-23 11:48:41 +01:00
LoadSupportConceptThings(-2, false);
if(Model.SelectedServiceDescription != null)
{
Model.SelectedServiceCategory = Model.SelectedServiceDescription.Category;
var serviceRecord = CreateServiceRecordFromScratch(start, end, null, Model.SelectedEmployee, notice);
serviceRecord.ServiceDescription = Model.SelectedServiceDescription;
Model.SelectedServiceRecord = serviceRecord;
2023-02-23 11:48:41 +01:00
}
}
// Einzelbuchung
else
{
var availableRelOids = new List<long>();
Model.SupportConceptListObjects.DoForEach(sclo =>
{
availableRelOids.AddIfNotIn(sclo.CostBearer2SupportConceptOid);
});
2023-02-23 11:48:41 +01:00
if(supportConceptList.Count == 1 && employeeOids.Count == 1)
2023-02-23 11:48:41 +01:00
{
ResetBookingMode(BookingMode.SingleBookingMode);
Model.SelectedEmployee = Model.AllEmployees.FirstOrDefault(e => e.EmployeeOid.Equals(employeeOids.FirstOrDefault()));
2023-02-23 11:48:41 +01:00
var compactSupportConcept = supportConceptList.First();
var scListObject = Model.SupportConceptListObjects.FirstOrDefault(f => f.SupportConceptOid.Equals(compactSupportConcept.SupportConceptOid));
2023-02-23 11:48:41 +01:00
if(scListObject is object)
2023-02-23 11:48:41 +01:00
{
LoadSupportConceptThings(scListObject.CostBearer2SupportConceptOid, true);
2023-02-23 11:48:41 +01:00
}
var serviceRecord = CreateServiceRecordFromScratch(start, end, compactSupportConcept?.Customer, Model.SelectedEmployee, notice);
2023-02-23 11:48:41 +01:00
var costBearer = compactSupportConcept?.CostBearerList.FirstOrDefault();
2023-02-23 11:48:41 +01:00
var cb2ScOid = compactSupportConcept?.CostBearerRelOids.FirstOrDefault(cbOid => availableRelOids.Contains(cbOid));
2023-02-23 11:48:41 +01:00
serviceRecord.CostBearer = costBearer?.Organisation;
serviceRecord.CostBearer2SupportConceptOid = cb2ScOid;
serviceRecord.ServiceDescription = Model.SelectedServiceDescription;
if(Model.SelectedServiceDescription != null)
{
Model.SelectedServiceRecord = serviceRecord;
}
Model.SelectedCostBearerSupportConceptOid = cb2ScOid;
}
else // Gruppenbuchung
{
ResetBookingMode(BookingMode.GroupBookingMode);
Model.GroupBookingSelectedEmployees = Model.AllEmployees.Where(w => employeeOids.Contains(w.EmployeeOid)).ToList();
var roundedDuration = (int) (end - start).TotalMinutes;
Model.SelectedServiceRecord = new ServiceRecordDC
{
Start = start,
End = end,
RoundedDuration = roundedDuration,
Notice = notice,
ServiceDescription = Model.GetSelectedOrFirstServiceDescription()
};
var costBearer2SupportConceptOids = new List<long>();
foreach(var supportConcept in supportConceptList)
{
var cb2ScOid = supportConcept?.CostBearerRelOids.FirstOrDefault(cbOid => availableRelOids.Contains(cbOid));
if(cb2ScOid is null)
{
continue;
}
costBearer2SupportConceptOids.AddIfNotIn(cb2ScOid.Value);
}
if(costBearer2SupportConceptOids.Any())
{
Model.GroupBookingSelectedCostBearerSupportConceptOids = costBearer2SupportConceptOids;
}
Model.GroupBookingSelectedEmployeeOids = employeeOids;
2023-02-23 11:48:41 +01:00
}
}
Model.SelectedServiceRecordOid = Model.SelectedServiceRecord?.ServiceRecordOid;
2025-06-11 22:56:25 +02:00
SetSelectedObjects();
Model.TransferringAppointmentOid = appointment?.SchedulerAppointmentOid;
Model.IsInTransferMode = true;
2023-02-23 11:48:41 +01:00
return View("Main", Model);
}
2025-08-15 10:10:25 +02:00
private ServiceRecordDC CreateServiceRecordFromScratch(DateTime start, DateTime end, CompactCustomerDC customer, CompactEmployeeDC employee, string notice)
2023-02-23 11:48:41 +01:00
{
var serviceRecord = new ServiceRecordDC
{
Employee = employee,
Customer = customer,
Notice = notice?.RemoveUppercaseEsszett(),
2023-02-23 11:48:41 +01:00
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)
{
2025-07-17 16:26:07 +02:00
SkipModelInitialization = true;
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
try
{
if(long.TryParse(formCollection["sr-signature-to-del-oid"], out var signatureOid) && long.TryParse(formCollection["sr-sig-to-del-record-oid"], out var serviceRecordOid))
{
OperationsService.DeleteSignature(signatureOid, serviceRecordOid);
}
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
}
return RedirectToActionPermanent("Main");
}
#region Mehrfachbuchung
[Authorize]
public ActionResult ReloadMultiBookingForm()
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
}
else
{
//LoadServiceCategoriesToModel(null);
}
return PartialView("MultiBookingSelectionPartial", Model);
}
[Authorize]
public ActionResult RemoveSupportConceptCostbearerRelFromMultiBooking(string relOid)
{
//das funktioniert hier noch nicht mit dem letzten Eintrag
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return PartialView("MultiBookingSelectionPartial");
}
if(!long.TryParse(relOid, out var c2sOid))
{
return PartialView("MultiBookingSelectionPartial", Model);
}
RemoveRelOidFromGroupBooking(c2sOid);
return PartialView("MultiBookingSelectionPartial", Model);
}
private void RemoveRelOidFromGroupBooking(long c2sOid)
{
var list = GetSelectedGroupBookingSupportConcepts();
LoadSupportConceptThings(null, false);
var supportConcept2Remove = list.FirstOrDefault(f => f.CostBearerRelOids.Any(a => a == c2sOid));
if (supportConcept2Remove != null)
{
var supportConcepts = list.Where(supportConcept => supportConcept.SupportConceptOid.Equals(supportConcept2Remove.SupportConceptOid) == false).ToList();
// Ziele, die bei den verbleibenden Hilfeplänen nicht vorhanden sind, werden aus der Auswahl entfernt.
var remainingGoals = new List<long>();
foreach (var supportConcept in supportConcepts)
{
foreach (var goal in supportConcept.Goals)
{
remainingGoals.AddIfNotIn(goal.ValueListEntryOid.Value);
}
}
Model.SelectedGoals = Model.SelectedGoals.Where(goal => remainingGoals.Contains(goal.ValueListEntryOid.Value)).ToList();
}
Model.GroupBookingSelectedCostBearerSupportConceptOids.Remove(c2sOid);
var c2s2Remove = Model.GroupBookingSelectedCostBearerSupportConcepts.FirstOrDefault(c => c.CostBearer2SupportConceptOid == c2sOid);
if (c2s2Remove != null)
{
Model.GroupBookingSelectedCostBearerSupportConcepts.Remove(c2s2Remove);
}
//Model.GroupBookingSelectedSupportConcepts.Remove(supportConcept2Remove);
//Model.SelectedConceptCostBearerRelations.Remove(relation2Remove);
var selectedGroups = Model.GroupsOfPeople.Where(group => group.GroupOfPeopleOid.HasValue && Model.GroupBookingSelectedGroupOfPeopleOids.Contains(group.GroupOfPeopleOid.Value)).ToList();
var groups = selectedGroups.Where(group => group.SupportConceptList.All(a => Model.GroupBookingSelectedCostBearerSupportConceptOids.Contains(a.CostBearerRelOids[0])));
Model.GroupBookingSelectedGroupOfPeopleOids = groups.Where(group => group.GroupOfPeopleOid.HasValue).Select(group => group.GroupOfPeopleOid.Value).ToList();
LoadSupportConceptThings(null, true);
if (Model.SelectedServiceCategory != null && !Model.Categories2Descriptions.Keys.Contains(Model.SelectedServiceCategory))
{
var firstCategory2ServiceDescriptions = Model.Categories2Descriptions.FirstOrDefault();
var firstServiceCategory = firstCategory2ServiceDescriptions.Key;
var firstServiceDescription = firstCategory2ServiceDescriptions.Value?.FirstOrDefault();
Model.SelectedServiceCategory = firstServiceCategory;
Model.SelectedServiceDescription = firstServiceDescription;
}
Model.SelectedGoalOids = Model.SelectedGoals.Select(g => g.ValueListEntryOid.Value).ToList();
//Model.GroupBookingSelectedSupportConceptOids = Model.GroupBookingSelectedSupportConcepts.Select(g => g.SupportConceptOid.Value).ToList();
//Model.SelectedConceptCostBearerRelationOids = Model.SelectedConceptCostBearerRelations.Select(g => g.CostBearer2SupportConceptOid.Value).ToList();
Model.SelectedServiceCategoryOid = Model.SelectedServiceCategory?.ServiceCategoryOid;
Model.SelectedServiceDescriptionOid = Model.SelectedServiceDescription?.ServiceDescriptionOid;
}
[Authorize]
[HttpPost]
public ActionResult SetMultiBookingMode(FormCollection formCollection)
{
SkipModelInitialization = true;
if(!IsUserLoggedIn())
{
return Logout();
}
Model.IsInTransferMode = false;
Model.TransferringAppointmentOid = null;
try
{
var isInMultiBookingMode = "true,false" == formCollection[FormCollectionConstants.IsInMultiBookingModeKey];
Model.IsInMultiBookingMode = isInMultiBookingMode;
ResetBookingMode(isInMultiBookingMode ? BookingMode.MultiBookingMode : BookingMode.SingleBookingMode);
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
}
return RedirectToAction("Main");
}
[Authorize]
[HttpPost]
public ActionResult CreateMultiBooking(FormCollection formCollection)
{
if(Model is null)
{
return Logout();
}
try
{
string doku1;
if(Model.Dokutypes != null && Model.Dokutypes.Length > 0)
{
doku1 = formCollection[FormCollectionConstants.Dokumentation1Key]?.RemoveUppercaseEsszett();
}
else
{
doku1 = formCollection[FormCollectionConstants.Dokumentation6Key]?.RemoveUppercaseEsszett();
}
// Wenn kein Datum angegeben wurde, wird die Main-Seite geladen und abgebrochen
if(string.IsNullOrEmpty(formCollection[FormCollectionConstants.DateKey]))
{
return View("Main", Model);
}
var marker = "on" == formCollection[FormCollectionConstants.MarkerKey];
decimal? betrag = null;
var betragAsString = formCollection[FormCollectionConstants.BetragKey]?.Replace('.', ',');
if(decimal.TryParse(betragAsString, out var betragAsDecimal))
{
betrag = betragAsDecimal;
}
var distanz = formCollection[FormCollectionConstants.DistanceKey];
2023-05-23 13:56:22 +02:00
decimal? distanceInMeters = null;
if(!string.IsNullOrEmpty(distanz))
{
2023-05-23 13:56:22 +02:00
if(decimal.TryParse(distanz, out var parsedDistance))
{
distanceInMeters = parsedDistance;
}
}
2025-06-11 22:56:25 +02:00
var selectedCostbearer2SupportConceptRelOid = Model.SelectedCostBearerSupportConceptOid < 1 ? null : Model.SelectedCostBearerSupportConceptOid;
var datum = Convert.ToDateTime(formCollection[FormCollectionConstants.DateKey]);
var enddatum = datum;
var endDateString = formCollection[FormCollectionConstants.EndDateKey];
2024-03-19 19:10:13 +01:00
if(endDateString?.Length > 0)
{
enddatum = Convert.ToDateTime(endDateString);
}
var start = formCollection[FormCollectionConstants.StartKey];
var ende = formCollection[FormCollectionConstants.EndKey];
var dauer = 0m;
if(datum > enddatum)
{
enddatum = datum;
}
var durationAsString = formCollection[FormCollectionConstants.DurationKey];
durationAsString = durationAsString.Replace('.', ',');
if(!string.IsNullOrEmpty(durationAsString))
{
decimal.TryParse(durationAsString, out dauer);
}
if(Model.SelectedDurationUnit == "Stunden" || Model.EinheitZeiterfassung == 1)
{
dauer *= 60m;
}
var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key]?.RemoveUppercaseEsszett();
var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key]?.RemoveUppercaseEsszett();
var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key]?.RemoveUppercaseEsszett();
var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key]?.RemoveUppercaseEsszett();
var zeitenFeld = new DateTime[2];
if(start == string.Empty && ende == string.Empty)
{
zeitenFeld[0] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1);
if(enddatum == datum)
{
zeitenFeld[1] = new DateTime(datum.Year, datum.Month, datum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer));
}
else
{
zeitenFeld[1] = new DateTime(enddatum.Year, enddatum.Month, enddatum.Day, 0, 0, 1).AddMinutes(Convert.ToDouble(dauer));
}
}
else
{
zeitenFeld = enddatum == datum ? ConvertRecordTimes(start, ende, datum, Convert.ToDouble(dauer)) : ConvertRecordTimesWithEndDate(start, ende, datum, enddatum, Convert.ToDouble(dauer));
}
if(dauer == 0 || zeitenFeld[1] != zeitenFeld[0])
{
dauer = (int)(zeitenFeld[1] - zeitenFeld[0]).TotalMinutes;
}
var serviceRecordsToInsert = new List<ServiceRecordDC>();
if(Model.GroupBookingSelectedCostBearerSupportConceptOids.Any() && Model.GroupBookingSelectedEmployees.Any())
{
foreach(var sc2cbRel in Model.GroupBookingSelectedCostBearerSupportConcepts)
{
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.GroupBookingSelectedEmployees)
{
var newServiceRecord = new ServiceRecordDC
{
IP = Request.UserHostAddress,
Start = zeitenFeld[0],
End = zeitenFeld[1],
2023-05-23 13:56:22 +02:00
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,
2025-06-11 22:56:25 +02:00
InsUser = MobileSessionFacade.EmployeeFullname,
IsCreatedInMobileClient = true,
Employee = employee,
ServiceRecordFormat = ServiceRecordFormate.OriginaleZeiterfassung,
ServiceDescription = OperationsService.GetServiceDescription(Model.SelectedServiceDescriptionOid.Value),
Betrag = betrag
};
if(marker)
{
newServiceRecord.ServiceRecordType = ServiceRecordTypeId.Content;
}
if(Model.IsEndDateVisible)
{
newServiceRecord.ServiceRecordFormat = ServiceRecordFormate.ZeiterfassungMitEndDatum;
}
serviceRecordsToInsert.Add(newServiceRecord);
}
}
OperationsService.InsertNewServiceRecords(serviceRecordsToInsert);
if(TempData[TempDataConstants.AppointmentOccurrenceToInsertKey] is SchedulerAppointmentDC occurrenceToInsert)
{
KalenderService.InsertSchedulerAppointment(occurrenceToInsert);
}
TempData[TempDataConstants.AfterInsertKey] = true;
}
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
}
return ResetEditingMode();
}
[Authorize]
public string AddEmployeesToMultiBooking(string pEmployeeOids)
{
if(Model is null)
{
Logout();
return LeerzeichenFuerGetMethoden;
}
if(string.IsNullOrEmpty(pEmployeeOids))
{
Model.GroupBookingSelectedEmployees.Clear();
return JsonConvert.SerializeObject(Model.GroupBookingSelectedEmployees.Count);
}
2025-10-09 12:56:32 +02:00
var oids = string.IsNullOrWhiteSpace(pEmployeeOids) ? new List<long>() : pEmployeeOids.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToList();
2025-10-09 12:56:32 +02:00
AddEmployeesToMultiBookingInternally(oids);
2025-10-09 12:56:32 +02:00
return JsonConvert.SerializeObject(Model.GroupBookingSelectedEmployees.Count);
}
[Authorize]
public void AddEmployeesToMultiBookingInternally(List<long> employeeOids)
{
if(employeeOids is null || employeeOids.Count == 0)
{
Model.GroupBookingSelectedEmployees.Clear();
return;
}
var employees = Model.EmployeesForGroupAndMultiBooking.Where(w => employeeOids.Contains(w.EmployeeOid)).ToList();
Model.GroupBookingSelectedEmployees.Clear();
Model.MainSessionModel.GroupBookingSelectedEmployeeOids.Clear();
Model.GroupBookingSelectedEmployees.AddRangeIfElementsNotIn(employees);
Model.MainSessionModel.GroupBookingSelectedEmployeeOids = employeeOids;
}
// Veraltet
[Authorize]
public string MultiBookingHasSelectedSupportConcepts()
{
try
{
return JsonConvert.SerializeObject(Model.GroupBookingSelectedCostBearerSupportConceptOids.Any());
}
catch(Exception exception)
{
Log.Error(exception.Message, exception);
}
return JsonConvert.SerializeObject(false);
}
[Authorize]
public string MultiBookingHasSelectedEmployees()
{
try
{
return JsonConvert.SerializeObject(Model.GroupBookingSelectedEmployees.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 || false == MobileSessionFacade.IsUserLoggedIn() || LoggedInUser.UserVersion is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return Logout();
}
var oldPassword = formCollection["old-password"];
var newPassword = formCollection["new-password"];
var passwordConfirmation = formCollection["confirm-new-password"];
if(false == newPassword.Equals(passwordConfirmation))
{
TempData[TempDataConstants.PwChErrKey] = "Die Passwörter stimmen nicht überein!";
return RedirectToActionPermanent("Main");
}
var passwordUtils = new PasswordUtils();
if(passwordUtils.EvaluatePasswordStrength(newPassword) < 2)
{
2025-06-11 22:56:25 +02:00
var checkResult = UserService.CheckPassword(LoggedInUser.UserOid.Value, oldPassword, newPassword);
if(false == checkResult is null)
{
TempData[TempDataConstants.PwChErrKey] = checkResult;
return RedirectToActionPermanent("Main");
}
}
2025-06-11 22:56:25 +02:00
var userName = LoggedInUser.LoginName;
var userVersion = LoggedInUser.UserVersion.Value;
UserService.ChangePassword(userName, userVersion, oldPassword, newPassword);
return RedirectToActionPermanent("Main");
}
#region ServiceRecord-Pagination
[Authorize]
public ActionResult LoadServiceRecordPage(int selectedPage)
{
SkipServiceRecordInitialization = true;
if(Model.SelectedZeitraum?.StartDate is null || Model.SelectedZeitraum.EndDate is null)
{
Model.SelectedZeitraum = new NullableDateTimeSpan(DateTime.Today.GetFirstOfMonth(), DateTime.Today);
}
LoadPaginatedServiceRecordsToModel(selectedPage);
return PartialView("ServiceRecordListPartial", Model);
}
private void LoadPaginatedServiceRecordsToModel(int selectedPage)
{
2025-08-15 10:10:25 +02:00
if(Model.IsInGroupBookingMode || Model.IsInMultiBookingMode)
{
return;
}
var records = new List<ServiceRecordDC>();
if(selectedPage < 1)
{
selectedPage = 1;
}
var selectedDayCount = (long?) (Model.SelectedDayCount == 0 ? null : (int?) Model.SelectedDayCount);
Model.CurrentPage = selectedPage;
int totalServiceRecords;
var firstResult = (selectedPage - 1) * Model.MaxResults;
2025-06-11 22:56:25 +02:00
var selectedEmployeeOid = Model.SelectedEmployee?.EmployeeOid ?? Model.LoggedInEmployee.EmployeeOid.Value;
// Ohne Hilfeplan
2025-06-11 22:56:25 +02:00
if(Model.SelectedCostBearerSupportConceptOid is null || Model.SelectedCostBearerSupportConceptOid < 1)
{
records = Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen || Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.Monatsauswahl ?
//Zeitraum oder Monat gewählt
OperationsService.GetEmployeesServiceRecordsWithStartEndDatePaginated(selectedEmployeeOid, Model.SelectedZeitraum.StartDate.Value, Model.SelectedZeitraum.EndDate.Value, firstResult, Model.MaxResults, out totalServiceRecords).ToList() :
OperationsService.GetEmployeesServiceRecords2Paginated(selectedEmployeeOid, selectedDayCount, firstResult, Model.MaxResults, out totalServiceRecords).ToList();
}
else
{
records = Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.ZeitraumWaehlen || Model.ServiceRecordTimeInterval == ServiceRecordTimeInterval.Monatsauswahl ?
//Zeitraum oder Monat gewählt
OperationsService
.GetCustomerServiceRecordsWithStartEndDatePaginated(
Model.SelectedSupportConcept.Customer.CustomerOid,
2025-06-11 22:56:25 +02:00
Model.SelectedCostBearerSupportConceptOid.Value,
Model.SelectedZeitraum.StartDate.Value,
Model.SelectedZeitraum.EndDate.Value,
firstResult, Model.MaxResults,
out totalServiceRecords) :
2025-06-11 22:56:25 +02:00
OperationsService.FindServiceRecordsForLastDaysPaginated(Model.SelectedCostBearerSupportConceptOid, Model.SelectedDayCount, Model.LoggedInEmployee?.EmployeeOid, firstResult, Model.MaxResults, out totalServiceRecords).ToList();
}
var pages = Math.DivRem(totalServiceRecords, Model.MaxResults, out var remainder);
if(remainder > 0)
{
pages++;
}
Model.ServiceRecordCount = totalServiceRecords;
Model.ServiceRecordPageCount = pages;
var recordsOhneDuplikate = new List<ServiceRecordDC>();
foreach(var r in records.Where(r => !recordsOhneDuplikate.Any(a => a.GroupOid.HasValue && a.GroupOid.Value.Equals(r.GroupOid))))
{
recordsOhneDuplikate.Add(r);
}
var serviceRecords = recordsOhneDuplikate.Where(serviceRecord => serviceRecord.Start.HasValue && serviceRecord.End.HasValue)
.OrderBy(serviceRecord => serviceRecord.Start.Value.Date)
.ThenBy(serviceRecord => serviceRecord.Start.Value.Hour)
.ThenBy(serviceRecord => serviceRecord.Start.Value.Minute)
.ThenBy(serviceRecord => serviceRecord.End.Value.Date)
.ThenBy(serviceRecord => serviceRecord.End.Value.Hour)
.ThenBy(serviceRecord => serviceRecord.End.Value.Minute)
.ThenByDescending(serviceRecord => serviceRecord.InsertedOn.Value).ToList();
var goalOids = new List<long>();
serviceRecords.DoForEach(serviceRecord =>
{
goalOids.AddRangeIfElementsNotIn(serviceRecord.Goals.Where(goal => goal.ParentOid.HasValue).Select(goal => goal.ParentOid.Value));
});
var goalCategories = ValueListService.GetGoalCategoriesByOids(goalOids);
Model.ServiceRecordOids2GoalHeader = GetServiceRecordOids2GoalHeaders(serviceRecords, goalCategories);
Model.ServiceRecords = serviceRecords;
2025-09-09 10:27:54 +02:00
if(selectedPage > 1 && Model.ServiceRecordPageCount < selectedPage)
{
LoadPaginatedServiceRecordsToModel(1);
}
}
[Authorize]
public static Dictionary<long, List<string>> GetServiceRecordOids2GoalHeaders(List<ServiceRecordDC> serviceRecords, List<ValueListEntryDC> goalCategories)
{
var serviceRecordOids2GoalHeaders = new Dictionary<long, List<string>>();
serviceRecords.DoForEach(serviceRecord =>
{
if(serviceRecord.ServiceRecordOid is null)
{
return;
}
serviceRecord.Goals.OrderBy(vle => $"{vle.Abbreviation}-{vle.TypeDescription}").DoForEach(goal =>
{
var goalCategory = goalCategories.FirstOrDefault(g => g.ValueListEntryOid.HasValue && goal.ValueListEntryOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ValueListEntryOid.Value) || (g.ValueListEntryOid.HasValue && goal.ParentOid.HasValue && g.ValueListEntryOid.Value.Equals(goal.ParentOid.Value)));
if(goalCategory != null)
{
serviceRecordOids2GoalHeaders.AddOrUpdateValueInDictionary(serviceRecord.ServiceRecordOid.Value, new List<string> { goalCategory.DisplayName });
}
});
});
return serviceRecordOids2GoalHeaders;
}
[Authorize]
public ActionResult GoToFirstPage()
{
return LoadServiceRecordPage(1);
}
[Authorize]
public ActionResult GoToLastPage()
{
return LoadServiceRecordPage(Model.ServiceRecordPageCount);
}
#endregion
#region Einmal-Link für die Unterschrift
[Authorize]
public ActionResult GenerateOneTimeLinkForSignature(long serviceRecordOid)
{
var token = BeWo.Service.Security.SecurityUtils.CreateExternalSignatureToken(serviceRecordOid);
var server = "https://" + LoginController.GetServerFromTenant(MobileSessionFacade.Tenant);
#if DEBUG
server = "http://" + GetLocalIPAddress() + "/BeWoPlanerMobil";
#endif
var link = $"{server}/ExternalSignature/ExternalSignature/{token}";
Model.OneTimeLink = link;
2025-07-17 16:26:07 +02:00
var serviceRecord = GetServiceRecordDC(serviceRecordOid, false);
var hilfeplan = Model.SelectedSupportConceptListObject.NameAndDateOfBirth + " | " + Model.SelectedSupportConceptListObject.SupportConceptTimeSpan;
var leistung = serviceRecord.ServiceDescription.Name;
var kategorie = serviceRecord.ServiceDescription.Category;
var employee = $"{serviceRecord.Employee.FirstName} {serviceRecord.Employee.LastName}";
var datumUhrzeit = MainModel.GetServiceRecordTimeString(serviceRecord);
Model.OneTimeLinkText = $"Hilfeplan: {hilfeplan}<br />Kategorie: {kategorie}<br />Leistung: {leistung}<br />Mitarbeiter: {employee}<br />Datum / Uhrzeit: {datumUhrzeit}<br /><br />";
Model.ShareDetails = $"Unterschrift für erbrachte Leistung am {datumUhrzeit}";
return PartialView("OneTimeLinkCreationPartial", Model);
}
[Authorize]
public ActionResult CancelLinkCreation()
{
Model.OneTimeLink = null;
Model.OneTimeLinkText = null;
Model.ShareDetails = null;
return PartialView("OneTimeLinkCreationPartial", Model);
}
#endregion
private static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach(var ip in host.AddressList)
{
if(ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("No network adapters with an IPv4 address in the system!");
}
[Authorize]
public ActionResult ReloadGoals()
{
SkipModelInitialization = true;
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
}
CreateModelSupportConceptListObjects(false);
2025-07-17 16:26:07 +02:00
LoadSupportConceptThings(null, true);
Model.GoalRatingTypes = OperationsService.GetAllRatingTypes().OrderBy(o => o.Position).ToList();
Model.HasAnyRatingTypes = Model.HasRightToRateGoals && Model.GoalRatingTypes.Any();
2025-07-17 16:26:07 +02:00
return PartialView("GoalTreePartial", Model);
}
[Authorize]
public ActionResult SetSelectedServiceCategory(string categoryOidStr)
{
if(Model is null)
{
TempData[TempDataConstants.DoLogoutKey] = true;
return PartialView("Category2ServiceDescriptionPartial");
}
if(long.TryParse(categoryOidStr, out var categoryOid))
{
2025-10-09 12:56:32 +02:00
SelectServiceCategory(categoryOid);
}
2025-10-09 12:56:32 +02:00
return PartialView("Category2ServiceDescriptionPartial", Model);
}
2025-10-09 12:56:32 +02:00
private void SelectServiceCategory(long categoryOid)
{
Model.SelectedServiceCategory = Model.Categories2Descriptions.FirstOrDefault(f => f.Key?.ServiceCategoryOid != null && f.Key.ServiceCategoryOid.Value.Equals(categoryOid)).Key;
Model.SelectedServiceDescription = null;
2025-10-09 12:56:32 +02:00
if(Model.SelectedServiceCategory != null)
{
var selectedServiceDescription = Model.Categories2Descriptions[Model.SelectedServiceCategory].OrderBy(sd => sd.Position).ThenBy(sd => sd.ServiceDescriptionOid).FirstOrDefault();
Model.SelectedServiceDescription = selectedServiceDescription;
2025-06-11 22:56:25 +02:00
Model.SelectedServiceCategoryOid = Model.SelectedServiceCategory?.ServiceCategoryOid;
Model.SelectedServiceDescriptionOid = Model.SelectedServiceDescription?.ServiceDescriptionOid;
}
}
[Authorize]
public string CheckSession()
{
return (Model is null).ToString();
}
[HttpPost]
public ActionResult ZombieLogout()
{
#if DEBUG
TempData[TempDataConstants.ErrorMessageKey] = "Der Browser wurde aus der Versenkung zurückgeholt und das Model ist jetzt null!";
#endif
return base.Logout();
}
[Authorize]
public override string SaveCollapsibleStatus(bool isOpen, string identifier)
{
SkipModelInitialization = true;
if(!IsUserLoggedIn())
{
TempData[TempDataConstants.DoLogoutKey] = true;
return LeerzeichenFuerGetMethoden;
}
return SaveCollapsibleStatusToModel(Model, isOpen, identifier);
}
2025-08-08 13:45:37 +02:00
[Authorize]
[HttpPost]
public ActionResult RestoreServiceRecordForm(FormCollection formCollection)
{
2025-10-09 12:56:32 +02:00
if(Model is null)
{
return Logout();
}
var bookingModeValue = formCollection[FormCollectionConstants.BookingModeKey];
var bookingModeInt = int.Parse(bookingModeValue);
var bookingMode = (BookingMode) bookingModeInt;
2025-08-08 13:45:37 +02:00
var dateInputValue = formCollection[FormCollectionConstants.DateKey];
var startTimeInputValue = formCollection[FormCollectionConstants.StartKey];
2025-09-09 10:27:54 +02:00
2025-08-08 13:45:37 +02:00
var endDateInputValue = formCollection[FormCollectionConstants.EndDateKey];
2025-09-09 10:27:54 +02:00
var endTimeInputValue = formCollection[FormCollectionConstants.EndKey];
2025-10-09 12:56:32 +02:00
var currentPageValue = formCollection[FormCollectionConstants.CurrentPageKey];
2025-08-08 13:45:37 +02:00
var doku1 = formCollection[FormCollectionConstants.Dokumentation1Key];
var doku2 = formCollection[FormCollectionConstants.Dokumentation2Key];
var doku3 = formCollection[FormCollectionConstants.Dokumentation3Key];
var doku4 = formCollection[FormCollectionConstants.Dokumentation4Key];
var doku5 = formCollection[FormCollectionConstants.Dokumentation5Key];
var doku6 = formCollection[FormCollectionConstants.Dokumentation6Key];
var distanceInputValue = formCollection[FormCollectionConstants.DistanceKey];
2025-10-09 12:56:32 +02:00
distanceInputValue = distanceInputValue.Replace(".", ",");
var markerRaw = formCollection[FormCollectionConstants.MarkerKey];
var marker = markerRaw == "true" || markerRaw == "on";
2025-08-08 13:45:37 +02:00
var serviceDescriptionOidInputValue = formCollection[FormCollectionConstants.ServiceDescriptionKey];
var durationInputValue = formCollection[FormCollectionConstants.DurationKey];
2025-10-09 12:56:32 +02:00
var durationUnit = formCollection[FormCollectionConstants.DurationUnitKey];
2025-08-08 13:45:37 +02:00
var betragInputValue = formCollection[FormCollectionConstants.BetragKey];
2025-10-09 12:56:32 +02:00
var selectedSingleBookingCb2ScOidInputValue = formCollection[FormCollectionConstants.CostBearer2SupportConceptOidKey];
2025-08-08 13:45:37 +02:00
var selectedGroupBookingCb2ScOidsInputValue = formCollection[FormCollectionConstants.GroupBookingSelectedCb2ScOidsKey];
var selectedMultiBookingCb2ScOidsInputValue = formCollection[FormCollectionConstants.MultiBookingSelectedCb2ScOidsKey];
2025-10-09 12:56:32 +02:00
2025-08-08 13:45:37 +02:00
var selectedSingleBookingEmployeeOidInputValue = formCollection[FormCollectionConstants.SingleBookingEmployeeOidKey];
if(false == long.TryParse(selectedSingleBookingEmployeeOidInputValue, out var sbEmployeeOid) && Model.LoggedInEmployee?.EmployeeOid != null)
2025-10-09 12:56:32 +02:00
{
sbEmployeeOid = Model.LoggedInEmployee.EmployeeOid.Value;
}
2025-08-08 13:45:37 +02:00
var selectedGroupBookingEmployeeOidsInputValue = formCollection[FormCollectionConstants.GroupBookingSelectedEmployeeOidsKey];
var selectedMultiBookingEmployeeOidsInputValue = formCollection[FormCollectionConstants.MultiBookingSelectedEmployeeOidsKey];
2025-10-09 12:56:32 +02:00
2025-08-08 13:45:37 +02:00
var selectedGoalOidsInputValue = formCollection[FormCollectionConstants.SelectedGoalOids];
var goals2Ratings = string.IsNullOrWhiteSpace(selectedGoalOidsInputValue) ? new Dictionary<long, long?>() : Utils.JsonMap2Dictionary(selectedGoalOidsInputValue);
var goalOids = new List<long>();
foreach(var goal2Rating in goals2Ratings)
{
goalOids.AddIfNotIn(goal2Rating.Key);
}
2025-10-09 12:56:32 +02:00
2025-09-09 10:27:54 +02:00
var isStartDateValid = DateTime.TryParse(dateInputValue, out var startDate);
if(isStartDateValid is false)
2025-10-09 12:56:32 +02:00
{
startDate = DateTime.Today;
}
2025-09-09 10:27:54 +02:00
var isEndDateValid = DateTime.TryParse(endDateInputValue, out var endDate);
2025-10-09 12:56:32 +02:00
2025-08-08 13:45:37 +02:00
decimal.TryParse(distanceInputValue, out var distance);
2025-09-09 10:27:54 +02:00
decimal.TryParse(betragInputValue, out var betrag);
2025-10-09 12:56:32 +02:00
var isServiceDescriptionOidValid = long.TryParse(serviceDescriptionOidInputValue, out var serviceDescriptionOid);
var isSbCb2ScOidValid = long.TryParse(selectedSingleBookingCb2ScOidInputValue, out var sbCb2ScOid);
var isCurrentPageValid = int.TryParse(currentPageValue, out var currentPage);
decimal.TryParse(durationInputValue, out var duration);
if(durationUnit == "h")
{
duration *= 60;
}
if(currentPage == 0 || false == isCurrentPageValid)
{
currentPage = 1;
}
2025-09-09 10:27:54 +02:00
2025-10-09 12:56:32 +02:00
if(isSbCb2ScOidValid)
{
Model.SelectedCostBearerSupportConceptOid = sbCb2ScOid;
SelectCb2ScRelation(sbCb2ScOid);
InitViewModel(true);
LoadSupportConceptThings(sbCb2ScOid, true);
Model.CurrentPage = currentPage;
}
2025-08-08 13:45:37 +02:00
2025-09-09 10:27:54 +02:00
var serviceRecord = new ServiceRecordDC();
2025-10-09 12:56:32 +02:00
// Gruppen- oder Mehrfachbuchung
if(bookingMode is BookingMode.GroupBookingMode || bookingMode is BookingMode.MultiBookingMode)
2025-09-09 10:27:54 +02:00
{
2025-10-09 12:56:32 +02:00
var relStr = bookingMode == BookingMode.GroupBookingMode ? selectedGroupBookingCb2ScOidsInputValue : selectedMultiBookingCb2ScOidsInputValue;
var empStr = bookingMode == BookingMode.GroupBookingMode ? selectedGroupBookingEmployeeOidsInputValue : selectedMultiBookingEmployeeOidsInputValue;
var cb2ScOids = string.IsNullOrWhiteSpace(relStr) ? new List<long>() : relStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToList();
var empOids = string.IsNullOrWhiteSpace(empStr) ? new List<long>() : empStr.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToList();
AddScCbRelsToBooking(cb2ScOids, new List<long>(), true);
AddEmployeesToGroupBookingInternally(empOids);
InitViewModel(true);
LoadSupportConceptThings(null, true);
2025-09-09 10:27:54 +02:00
}
2025-10-09 12:56:32 +02:00
if(isServiceDescriptionOidValid)
{
var selectedServiceDescription = Model.Categories2Descriptions.FirstOrDefault(f => f.Value.Any(a => a.ServiceDescriptionOid.HasValue && a.ServiceDescriptionOid.Value.Equals(serviceDescriptionOid)));
if(selectedServiceDescription is KeyValuePair<ServiceCategoryDC, List<ServiceDescriptionDC>> category2Description && (category2Description.Key?.ServiceCategoryOid.HasValue ?? false))
{
SelectServiceCategory(category2Description.Key.ServiceCategoryOid.Value);
Model.SelectedServiceDescription = category2Description.Value.First(f => f.ServiceDescriptionOid.HasValue && f.ServiceDescriptionOid.Value.Equals(serviceDescriptionOid));
}
}
if(isEndDateValid is false)
2025-09-09 10:27:54 +02:00
{
endDate = startDate;
}
serviceRecord.ServiceRecordType = marker ? ServiceRecordTypeId.Content : ServiceRecordTypeId.DefaultActivity;
serviceRecord.Start = startDate.MergeDateAndTimeString(startTimeInputValue);
serviceRecord.End = endDate.MergeDateAndTimeString(endTimeInputValue);
2025-10-09 12:56:32 +02:00
serviceRecord.ServiceDescription = Model.SelectedServiceDescription;
serviceRecord.Betrag = betrag;
2025-10-09 12:56:32 +02:00
serviceRecord.RoundedDuration = duration;
if(bookingMode is BookingMode.SingleBookingMode)
2025-10-09 12:56:32 +02:00
{
serviceRecord.Employee = Model.AllEmployees.FirstOrDefault(f => f.EmployeeOid == sbEmployeeOid) ?? Model.LoggedInUser.Employee;
}
2025-09-09 10:27:54 +02:00
var scOids = new List<long>();
if(bookingMode is BookingMode.GroupBookingMode || bookingMode is BookingMode.MultiBookingMode)
{
scOids = Model.GroupBookingSelectedCostBearerSupportConcepts.Select(sc2Cb => sc2Cb.SupportConcept.SupportConceptOid).ToList();
}
else if(Model.SelectedSupportConcept is object)
{
scOids.Add(Model.SelectedSupportConcept.SupportConceptOid);
}
var infos = OperationsService.GetSupportConceptTreeNodeDetailInfos(scOids);
LoadGoals(infos);
Model.SelectedGoalOids = new List<long>();
var allGoalOids = Model.AllGoals.Where(w => w.ValueListEntryOid.HasValue).Select(s => s.ValueListEntryOid.Value);
var selectedGoalOids = allGoalOids.Intersect(goalOids).ToList();
Model.SelectedGoalOids = selectedGoalOids;
foreach(var goalOid in Model.SelectedGoalOids)
{
var goal = Model.AllGoals.FirstOrDefault(f => f.ValueListEntryOid.HasValue && f.ValueListEntryOid.Equals(goalOid));
if(goal is null)
{
continue;
}
Model.SelectedGoals.Add(DcToMokMapper.CreateZiel(goal));
}
foreach(var goalOid2RatingOid in goals2Ratings)
{
var goalOid = goalOid2RatingOid.Key;
var ratingTypeOid = goalOid2RatingOid.Value;
if(false == Model.SelectedGoalOids.Contains(goalOid))
{
continue;
}
var goal = Model.SelectedGoals.FirstOrDefault(f => f.ValueListEntryOid.HasValue && f.ValueListEntryOid.Equals(goalOid));
if(goal is null)
{
continue;
}
goal.RatingTypeOid = ratingTypeOid;
}
2025-10-09 12:56:32 +02:00
if(Model.NumberOfDokuTypes == 0)
{
serviceRecord.Notice = doku6;
}
else
{
serviceRecord.Notice = doku1;
serviceRecord.Notice2 = doku2;
serviceRecord.Notice3 = doku3;
serviceRecord.Notice4 = doku4;
serviceRecord.Notice5 = doku5;
}
serviceRecord.DistanceInMeter = null;
serviceRecord.DistanceInMeterDecimal = distance;
2025-10-09 12:56:32 +02:00
Model.SelectedServiceRecord = serviceRecord;
2025-08-08 13:45:37 +02:00
TempData[TempDataConstants.AfterRestoreKey] = true;
return View("Main", Model);
}
}
public class ServiceRecord2Monatsunterschrift
{
public ServiceRecordDC ServiceRecord { get; }
public bool HasMonatsunterschrift { get; }
public string ServiceRecordTimeInfo { get; }
public string Kategorie { get; }
public string Leistung { get; }
public string Mitarbeiter { get; }
public string DatumSchraegstrichUhrzeit { get; }
public ServiceRecord2Monatsunterschrift(ServiceRecordDC serviceRecord, bool hasMonatsunterschrift)
{
ServiceRecord = serviceRecord;
HasMonatsunterschrift = hasMonatsunterschrift;
ServiceRecordTimeInfo = MainModel.GetServiceRecordTimeString(serviceRecord);
Kategorie = serviceRecord.ServiceDescription.CategoryName;
Leistung = serviceRecord.ServiceDescription.Name;
Mitarbeiter = serviceRecord.Employee.ToString();
DatumSchraegstrichUhrzeit = MainModel.GetServiceRecordTimeHeader(serviceRecord, true);
}
}
2016-06-27 01:45:38 +02:00
}