Ressourcen im Kalender des Mobilklienten verfügbar gemacht.
Verbesserungen im Mobilklienten.
This commit is contained in:
@@ -180,7 +180,8 @@
|
||||
<Compile Include="Models\SchedulerModel.cs" />
|
||||
<Compile Include="Util\AppointmentListItem.cs" />
|
||||
<Compile Include="Util\BeWoLoginState.cs" />
|
||||
<Compile Include="Util\GoalDisplayItem.cs" />
|
||||
<Compile Include="Util\BootstrapTreeViewItem.cs" />
|
||||
<Compile Include="Util\ConvertedDateTimes.cs" />
|
||||
<Compile Include="Util\GoalTreeItem.cs" />
|
||||
<Compile Include="Controllers\LoginController.cs" />
|
||||
<Compile Include="Controllers\MainController.cs" />
|
||||
|
||||
@@ -290,12 +290,12 @@ namespace BeWoPlanerMobil.Controllers
|
||||
|
||||
var parentItems = goals.Where(w => w.ValueListEntryOid.HasValue && goals.Any(a => a.ParentOid.HasValue && a.ParentOid.Equals(w.ValueListEntryOid))).ToList();
|
||||
|
||||
var goalTree = new List<GoalDisplayItem>();
|
||||
var goalTreeDic = new Dictionary<long, GoalDisplayItem>();
|
||||
var goalTree = new List<BootstrapTreeViewItem>();
|
||||
var goalTreeDic = new Dictionary<long, BootstrapTreeViewItem>();
|
||||
|
||||
foreach (var ziel in ziele.Where(ziel => ziel.ValueListEntryOid.HasValue))
|
||||
{
|
||||
var treeItem = new GoalDisplayItem(ziel.TypeDescription, ziel.ParentOid, ziel.ValueListEntryOid.Value, parentItems.Contains(ziel));
|
||||
var treeItem = new BootstrapTreeViewItem(ziel.TypeDescription, ziel.ParentOid, ziel.ValueListEntryOid.Value, parentItems.Contains(ziel));
|
||||
|
||||
goalTreeDic.Add(ziel.ValueListEntryOid.Value, treeItem);
|
||||
|
||||
@@ -307,17 +307,17 @@ namespace BeWoPlanerMobil.Controllers
|
||||
|
||||
foreach (var zielMitEltern in goalTreeDic.Values.Where(w => w.ParentOid != null))
|
||||
{
|
||||
goalTreeDic[zielMitEltern.ParentOid.Value].nodes.Add(zielMitEltern);
|
||||
goalTreeDic[zielMitEltern.ParentOid.Value].Nodes.Add(zielMitEltern);
|
||||
}
|
||||
|
||||
foreach (var ziel in massnahmen)
|
||||
{
|
||||
var node = new GoalDisplayItem(ziel.TypeDescription, ziel.ParentOid, ziel.ValueListEntryOid.Value, parentItems.Contains(ziel));
|
||||
var node = new BootstrapTreeViewItem(ziel.TypeDescription, ziel.ParentOid, ziel.ValueListEntryOid.Value, parentItems.Contains(ziel));
|
||||
|
||||
if (ziel.ParentOid != null && goalTreeDic.ContainsKey(ziel.ParentOid.Value))
|
||||
{
|
||||
node.ParentOid = goalTreeDic[ziel.ParentOid.Value].ParentOid;
|
||||
goalTreeDic[ziel.ParentOid.Value].nodes.Add(node);
|
||||
goalTreeDic[ziel.ParentOid.Value].Nodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Web.Helpers;
|
||||
using System.Web.Mvc;
|
||||
|
||||
using BeWoPlanerMobil.Models;
|
||||
using BeWoPlanerMobil.Service;
|
||||
using BeWoPlanerMobil.Util;
|
||||
using BS.Shared;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.DataContracts.Compact;
|
||||
using BS.Shared.Extensions;
|
||||
|
||||
using DevExpress.XtraScheduler;
|
||||
using DevExpress.XtraScheduler.Compatibility;
|
||||
using Newtonsoft.Json;
|
||||
using static BeWoPlanerMobil.Util.MobileUtils;
|
||||
|
||||
namespace BeWoPlanerMobil.Controllers
|
||||
@@ -54,6 +58,20 @@ namespace BeWoPlanerMobil.Controllers
|
||||
return RedirectToActionPermanent("Index", "Login");
|
||||
}
|
||||
|
||||
if(AbstractModel.HasRightToInsertRessourceAppointments)
|
||||
{
|
||||
var allResources = KalenderService.GetAllResources().ToList();
|
||||
|
||||
var categories2Resources = new Dictionary<ValueListEntryDC, List<ResourceDC>>();
|
||||
|
||||
foreach(var category in allResources.Select(resource => resource.ResourceCategory))
|
||||
{
|
||||
categories2Resources.AddOrUpdateValueInDictionary(category, allResources.Where(resource => resource.ResourceCategory.Equals(category)).ToList());
|
||||
}
|
||||
|
||||
Model.ResourceCategories2Resources = categories2Resources;
|
||||
}
|
||||
|
||||
LoadAppointmentsForDate();
|
||||
|
||||
return View(Model);
|
||||
@@ -102,7 +120,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
var changedOccurrences = holySweetFlyingFuck.Where(w => w.Type == 3).Select(s => GetOccurrenceId(s.RecurrenceInfo)).ToList();
|
||||
|
||||
holySweetFlyingFuck = holySweetFlyingFuck.Where(w => w.Type != 4).ToList();
|
||||
|
||||
var numberOfPatterns = appointments.Count(appointment => appointment.RecurrenceInfo != null && appointment.Type == 1);
|
||||
foreach(var appointment in appointments)
|
||||
{
|
||||
if(appointment.RecurrenceInfo != null && appointment.Type == 1)
|
||||
@@ -137,7 +155,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
continue;
|
||||
}
|
||||
|
||||
holySweetFlyingFuck.AddIfNotIn(new SchedulerAppointmentDC
|
||||
var recurringAppointment = new SchedulerAppointmentDC
|
||||
{
|
||||
AllDay = appointment.AllDay,
|
||||
CustomerList = appointment.CustomerList,
|
||||
@@ -155,7 +173,11 @@ namespace BeWoPlanerMobil.Controllers
|
||||
StartDate = termin.Start,
|
||||
Subject = appointment.Subject ?? "",
|
||||
Type = appointment.Type
|
||||
});
|
||||
};
|
||||
|
||||
Model.RecurringAppointments.AddIfNotIn(recurringAppointment);
|
||||
|
||||
holySweetFlyingFuck.AddIfNotIn(recurringAppointment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,7 +185,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
|
||||
holySweetFlyingFuck.AddRange(zuErledigen);
|
||||
|
||||
Model.Appointments = holySweetFlyingFuck;
|
||||
Model.Appointments = holySweetFlyingFuck.OrderBy(appointment => appointment.StartDate).ToList();
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
@@ -185,22 +207,27 @@ namespace BeWoPlanerMobil.Controllers
|
||||
var location = formCollection["Location"];
|
||||
var notice = formCollection["Notice"];
|
||||
|
||||
var isSuccessfulStartDate = DateTime.TryParseExact(rawStartDate, "dd.MM.yyyy", null, DateTimeStyles.None, out var startDate);
|
||||
var isSuccessfulStartTime = DateTime.TryParseExact(rawStartTime, "HH:mm", null, DateTimeStyles.None, out var startTime);
|
||||
var isSuccessfulEndDate = DateTime.TryParseExact(rawEndDate, "dd.MM.yyyy", null, DateTimeStyles.None, out var endDate);
|
||||
var isSuccessfulEndTime = DateTime.TryParseExact(rawEndTime, "HH:mm", null, DateTimeStyles.None, out var endTime);
|
||||
|
||||
if (isSuccessfulStartDate && isSuccessfulStartTime && isSuccessfulEndDate && isSuccessfulEndTime)
|
||||
var startAndEnd = ConvertStringDatesToDateTimes($"{rawStartDate} {rawStartTime}", $"{rawEndDate} {rawEndTime}");
|
||||
|
||||
var startDate = startAndEnd.StartDate;
|
||||
var endDate = startAndEnd.EndDate;
|
||||
|
||||
if (isSuccessfulStartTime && isSuccessfulEndTime)
|
||||
{
|
||||
startDate = startDate.MergeDatesByDate(startTime);
|
||||
endDate = endDate.MergeDatesByDate(endTime);
|
||||
|
||||
var appointmentToInsert = Model.SelectedAppointment ?? new SchedulerAppointmentDC();
|
||||
|
||||
appointmentToInsert.EmployeeList = new List<Employee2SchedulerAppointmentDC>();
|
||||
appointmentToInsert.CustomerList = new List<CompactCustomerDC>();
|
||||
appointmentToInsert.ResourceList = new List<ResourceDC>();
|
||||
appointmentToInsert.SupportConceptList = new List<CompactSupportConceptDC>();
|
||||
var isNew = !appointmentToInsert.SchedulerAppointmentOid.HasValue;
|
||||
|
||||
appointmentToInsert.EmployeeList = isNew ? new List<Employee2SchedulerAppointmentDC>() : appointmentToInsert.EmployeeList;
|
||||
appointmentToInsert.CustomerList = isNew ? new List<CompactCustomerDC>() : appointmentToInsert.CustomerList;
|
||||
appointmentToInsert.ResourceList = Model.SelectedResources ?? new List<ResourceDC>();
|
||||
appointmentToInsert.SupportConceptList = isNew ? new List<CompactSupportConceptDC>() : appointmentToInsert.SupportConceptList;
|
||||
appointmentToInsert.EndDate = endDate;
|
||||
appointmentToInsert.StartDate = startDate;
|
||||
appointmentToInsert.Subject = subject;
|
||||
@@ -208,7 +235,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
appointmentToInsert.Originator = MobileSessionFacade.LoggedInCompactEmployee;
|
||||
appointmentToInsert.Location = location;
|
||||
|
||||
if (appointmentToInsert.SchedulerAppointmentOid.HasValue)
|
||||
if (!isNew)
|
||||
{
|
||||
KalenderService.UpdateSchedulerAppointments(new List<SchedulerAppointmentDC> {appointmentToInsert});
|
||||
}
|
||||
@@ -227,6 +254,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
if (Model != null)
|
||||
{
|
||||
Model.SelectedAppointment = null;
|
||||
Model.SelectedResources?.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +275,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
if(Model != null)
|
||||
{
|
||||
Model.SelectedAppointment = null;
|
||||
Model.SelectedResources.Clear();
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
@@ -266,6 +295,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
if(Model != null)
|
||||
{
|
||||
Model.SelectedAppointment = null;
|
||||
Model.SelectedResources.Clear();
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
@@ -288,6 +318,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
if(Model != null)
|
||||
{
|
||||
Model.SelectedAppointment = null;
|
||||
Model.SelectedResources.Clear();
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
@@ -304,6 +335,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
if (isSuccessful)
|
||||
{
|
||||
Model.SelectedAppointment = Model.Appointments.FirstOrDefault(app => app.SchedulerAppointmentOid.HasValue && app.SchedulerAppointmentOid.Value == appointmentOid);
|
||||
Model.SelectedResources = Model.SelectedAppointment?.ResourceList ?? new List<ResourceDC>();
|
||||
}
|
||||
|
||||
return RedirectToActionPermanent("Scheduler");
|
||||
@@ -315,11 +347,13 @@ namespace BeWoPlanerMobil.Controllers
|
||||
if (Model != null)
|
||||
{
|
||||
Model.SelectedAppointment = null;
|
||||
Model.SelectedResources.Clear();
|
||||
}
|
||||
|
||||
return Json(null, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
|
||||
// TODO: Serientermine und Ressourcen berücksichtigen!
|
||||
[Authorize]
|
||||
public JsonResult CheckForOverlappingAppointments(string startDateRaw, string endDateRaw, string startTimeRaw, string endTimeRaw)
|
||||
{
|
||||
@@ -341,19 +375,58 @@ namespace BeWoPlanerMobil.Controllers
|
||||
startDate = startDate.MergeDatesByDate(startTime);
|
||||
endDate = endDate.MergeDatesByDate(endTime);
|
||||
|
||||
var customerList = Model.SelectedAppointment?.CustomerList?.Select(customer => customer.CustomerOid).ToList() ?? new List<long>();
|
||||
var employeeList = Model.SelectedAppointment?.EmployeeList?.Select(employee2Appointment => employee2Appointment.Employee.EmployeeOid).ToList() ?? new List<long>();
|
||||
var resourceList = Model.SelectedAppointment?.ResourceList?.Select(resource => resource.ResourceOid.Value).ToList() ?? new List<long>();
|
||||
var customerOidList = Model.SelectedAppointment?.CustomerList?.Select(customer => customer.CustomerOid).ToList() ?? new List<long>();
|
||||
var employeeOidList = Model.SelectedAppointment?.EmployeeList?.Select(employee2Appointment => employee2Appointment.Employee.EmployeeOid).ToList() ?? new List<long>();
|
||||
var resourceOidList = Model.SelectedResources.Where(resource => resource.ResourceOid.HasValue).Select(resource => resource.ResourceOid.Value).ToList() ?? new List<long>();
|
||||
|
||||
var originator = Model.SelectedAppointment?.Originator ?? MobileSessionFacade.LoggedInCompactEmployee;
|
||||
|
||||
var recurrenceId = Model.SelectedAppointment?.RecurrenceId ?? string.Empty;
|
||||
var recurrenceIndex = Model.SelectedAppointment?.RecurrenceIndex ?? 0;
|
||||
|
||||
isOverlapping = KalenderService.OverlappingAppointmentsExist(startDate, endDate, employeeList, customerList, resourceList, originator.EmployeeOid, oid, recurrenceId, recurrenceIndex);
|
||||
isOverlapping = KalenderService.OverlappingAppointmentsExist(startDate, endDate, employeeOidList, customerOidList, resourceOidList, originator.EmployeeOid, oid, recurrenceId, recurrenceIndex);
|
||||
}
|
||||
|
||||
return Json(isOverlapping, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
|
||||
public string SelectResourcesForAppointment(string resourceOids)
|
||||
{
|
||||
if(Model == null)
|
||||
{
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
var oidList = ConvertOidStringToList(resourceOids);
|
||||
|
||||
var list = new List<ResourceDC>();
|
||||
|
||||
Model.ResourceCategories2Resources.Values.DoForEach(l => l.DoForEach(s => list.AddIfNotIn(s)));
|
||||
|
||||
Model.SelectedResources = list.Where(resource => resource.ResourceOid.HasValue && oidList.Contains(resource.ResourceOid.Value)).ToList();
|
||||
|
||||
return JsonConvert.SerializeObject(Model.SelectedResources);
|
||||
}
|
||||
|
||||
public string CheckResourcesAvailability(string start, string end, string resourceOids)
|
||||
{
|
||||
if(!AbstractModel.HasRightToInsertRessourceAppointments)
|
||||
{
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(start) && !string.IsNullOrWhiteSpace(end) && !string.IsNullOrWhiteSpace(resourceOids) && Model != null)
|
||||
{
|
||||
var oidList = ConvertOidStringToList(resourceOids);
|
||||
|
||||
var dateTimes = ConvertStringDatesToDateTimes(start, end);
|
||||
|
||||
var unavailableResources = KalenderService.CheckResourceAvailability(dateTimes.StartDate, dateTimes.EndDate, oidList, Model.SelectedAppointment?.SchedulerAppointmentOid);
|
||||
|
||||
return JsonConvert.SerializeObject(unavailableResources);
|
||||
}
|
||||
|
||||
return _LeerzeichenFuerGetMethoden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Linq;
|
||||
|
||||
using BeWoPlanerMobil.Service;
|
||||
using BeWoPlanerMobil.Service;
|
||||
|
||||
using BS.Shared;
|
||||
using BS.Shared.DataContracts;
|
||||
@@ -9,17 +7,11 @@ namespace BeWoPlanerMobil.Models
|
||||
{
|
||||
public class AbstractModel
|
||||
{
|
||||
public static bool IsDeleteBtnVisible
|
||||
{
|
||||
get { return MobileSessionFacade.LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.RightType.Equals(UserRightType.ServiceRecordView_Delete))); }
|
||||
}
|
||||
public static bool IsDeleteBtnVisible => MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecordView_Delete);
|
||||
|
||||
public static bool IsAllowedToSeeScheduler
|
||||
{
|
||||
get { return MobileSessionFacade.LoggedInUser != null && MobileSessionFacade.LoggedInUser.UserGroups.Any(a => a.Rights.Any(right => right.RightType.Equals(UserRightType.KalenderAnsehen))); }
|
||||
}
|
||||
public static bool IsAllowedToSeeScheduler => MobileSessionFacade.LoggedInUser != null && MobileSessionFacade.CheckForUserRight(UserRightType.KalenderAnsehen) || MobileSessionFacade.CheckForUserRight(UserRightType.ViewAll);
|
||||
|
||||
public static bool IsAllowedToSeeCustomers => MobileSessionFacade.CheckForUserRight(UserRightType.ViewAll) || (MobileSessionFacade.CheckForUserRight(UserRightType.CustomerView_View) || MobileSessionFacade.CheckForUserRight(UserRightType.Customer_ViewMyCustomers));
|
||||
public static bool IsAllowedToSeeCustomers => MobileSessionFacade.CheckForUserRight(UserRightType.ViewAll) || MobileSessionFacade.CheckForUserRight(UserRightType.CustomerView_View) || MobileSessionFacade.CheckForUserRight(UserRightType.Customer_ViewMyCustomers);
|
||||
|
||||
public static bool IsEmployeeSelectionVisible => MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreationForOtherEmployees) || MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecord_AllowCreationForOtherTeamMember);
|
||||
|
||||
@@ -40,5 +32,7 @@ namespace BeWoPlanerMobil.Models
|
||||
public static bool HasRightToSeeServiceRecords => MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecordView_View) && MobileSessionFacade.CheckForUserRight(UserRightType.ServiceRecordView_Create);
|
||||
|
||||
public static string TimeOfLastAction { get; set; }
|
||||
|
||||
public static bool HasRightToInsertRessourceAppointments => MobileSessionFacade.CheckForUserRight(UserRightType.KalenderRessourcentermineAnlegen) || MobileSessionFacade.CheckForUserRight(UserRightType.CreateAll);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using BeWoPlanerMobil.Util;
|
||||
using BS.Shared;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BeWoPlanerMobil.Models
|
||||
{
|
||||
@@ -92,5 +93,13 @@ namespace BeWoPlanerMobil.Models
|
||||
public string EndTimeToEdit => SelectedAppointment?.EndDate?.ToShortTimeString() ?? string.Empty;
|
||||
|
||||
public string LocationToEdit => SelectedAppointment?.Location ?? string.Empty;
|
||||
|
||||
public List<ResourceDC> AllResources { get; set; } = new List<ResourceDC>();
|
||||
|
||||
public List<ResourceDC> SelectedResources { get; set; } = new List<ResourceDC>();
|
||||
|
||||
public Dictionary<ValueListEntryDC, List<ResourceDC>> ResourceCategories2Resources { get; set; } = new Dictionary<ValueListEntryDC, List<ResourceDC>>();
|
||||
|
||||
public List<SchedulerAppointmentDC> RecurringAppointments { get; set; } = new List<SchedulerAppointmentDC>();
|
||||
}
|
||||
}
|
||||
@@ -103,8 +103,6 @@ function updateGroupBookingGroupList(groupBookingSelectionObject) {
|
||||
} else {
|
||||
activateGroupBookingForm();
|
||||
}
|
||||
|
||||
console.log("updateGroupBookingGroupList called");
|
||||
}
|
||||
|
||||
function addEmployeeToGroupBooking() {
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
$("#scheduler-start-time, #scheduler-end-time, #subject, #location, #notice").val("");
|
||||
|
||||
$("#scheduler-start-date, #scheduler-end-date").val(moment().format("DD.MM.YYYY"));
|
||||
|
||||
$("#resources-popup input:checked").each(function() {
|
||||
$(this).prop("checked", false);
|
||||
});
|
||||
|
||||
$("#selected-resources-list").empty();
|
||||
}
|
||||
|
||||
function submitInsertAppointmentForm() {
|
||||
@@ -75,13 +81,80 @@ function validateAppointmentForm() {
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedOids = [];
|
||||
var oidString = "";
|
||||
|
||||
$("#resources-popup input:checked").each(function() {
|
||||
var id = $(this).attr("id");
|
||||
selectedOids.push(id.split("-")[0]);
|
||||
});
|
||||
|
||||
for(var i = 0; i < selectedOids.length; i++) {
|
||||
oidString += selectedOids[i] + ",";
|
||||
}
|
||||
|
||||
$.get(getCheckResourcesAvailabilityUrl(), { start: startDate.format("DD.MM.YYYY HH:mm"), end: endDate.format("DD.MM.YYYY HH:mm"), resourceOids: oidString }).done(function(result) {
|
||||
if(result === undefined || result === null || result.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.length > 1) {
|
||||
try {
|
||||
var unavailableResources = $.parseJSON(result);
|
||||
var resourceCount = 0;
|
||||
var names = "";
|
||||
|
||||
$.each(unavailableResources, function(index, resource) {
|
||||
if (names.length > 1) {
|
||||
names += ", ";
|
||||
}
|
||||
|
||||
resourceCount++;
|
||||
|
||||
names += resource.Name;
|
||||
});
|
||||
|
||||
var unavailableResourcesMessage;
|
||||
|
||||
if(resourceCount > 0) {
|
||||
if(resourceCount > 1) {
|
||||
unavailableResourcesMessage = "Einige der ausgewählten Ressourcen (" + names + ") sind zum gewählten Zeitpunkt nicht verfügbar.";
|
||||
} else {
|
||||
unavailableResourcesMessage = "Eine der ausgewählten Ressourcen (" + names + ") ist zum gewählten Zeitpunkt nicht verfügbar.";
|
||||
}
|
||||
|
||||
hideSpinner();
|
||||
$("#messagePopup .modal-body").html('<div class="alert alert-warning" role="alert">' + unavailableResourcesMessage + "<br/><br/>Möchten Sie trotzdem speichern?</div>");
|
||||
showMessagePopup("Fehler");
|
||||
showMessagePopupWithCallback("Überschneidung",
|
||||
null,
|
||||
function() {
|
||||
$("#messagePopup .modal-body").html();
|
||||
showSpinner();
|
||||
insertOrUpdateAppointment(startDate.format("DD.MM.YYYY"), endDate.format("DD.MM.YYYY"), startDate.format("HH:mm"), endDate.format("HH:mm"));
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
} catch(error) {
|
||||
console.log("%c" + error.message, "color:red;");
|
||||
hideSpinner();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
insertOrUpdateAppointment(startDate.format("DD.MM.YYYY"), endDate.format("DD.MM.YYYY"), startDate.format("HH:mm"), endDate.format("HH:mm"));
|
||||
});
|
||||
}
|
||||
|
||||
function insertOrUpdateAppointment(formattedStartDate, formattedEndDate, formattedStartTime, formattedEndTime) {
|
||||
$.get(
|
||||
getCheckForOverlappingAppointmentsUrl(),
|
||||
{
|
||||
startDateRaw: startDate.format("DD.MM.YYYY"),
|
||||
endDateRaw: endDate.format("DD.MM.YYYY"),
|
||||
startTimeRaw: startDate.format("HH:mm"),
|
||||
endTimeRaw: endDate.format("HH:mm")
|
||||
startDateRaw: formattedStartDate,
|
||||
endDateRaw: formattedEndDate,
|
||||
startTimeRaw: formattedStartTime,
|
||||
endTimeRaw: formattedEndTime
|
||||
}
|
||||
).done(function(result) {
|
||||
var isOverlapping = $.parseJSON(result);
|
||||
@@ -126,4 +199,63 @@ function toggleAppointmentForm() {
|
||||
} else {
|
||||
showAppointmentForm();
|
||||
}
|
||||
}
|
||||
|
||||
function changeResourceSelection() {
|
||||
var selectedOids = [];
|
||||
var oidString = "";
|
||||
|
||||
$("#resources-popup input:checked").each(function() {
|
||||
var id = $(this).attr("id");
|
||||
|
||||
selectedOids.push(id.split("-")[0]);
|
||||
});
|
||||
|
||||
for (var i = 0; i < selectedOids.length; i++) {
|
||||
oidString += selectedOids[i] + ",";
|
||||
}
|
||||
|
||||
$.get(getSelectResourcesForAppointmentUrl(), { resourceOids: oidString }).done(test);
|
||||
}
|
||||
|
||||
function test(jsonResult) {
|
||||
var list = $("#selected-resources-list");
|
||||
|
||||
list.empty();
|
||||
|
||||
if (isEmptyOrSpaces(jsonResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var resourceList = $.parseJSON(jsonResult);
|
||||
|
||||
$.each(resourceList, function(index, customListItem) {
|
||||
var html =
|
||||
"<div class='list-group-item' id='relation-item-" + customListItem.ResourceOid + "'>" +
|
||||
"<div class='row'>" +
|
||||
"<div class='col my-auto'>" +
|
||||
"<i class='fas fa-cubes text-bewo-resource mr-2'></i>" + customListItem.Name +
|
||||
"</div>" +
|
||||
"<div class='col-auto my-auto'>" +
|
||||
"<button type='button' class='btn btn-primary' onclick='removeSelectedResource(" + customListItem.ResourceOid + ")'>" +
|
||||
"<span class='fas fa-times-circle'></span>" +
|
||||
"</button>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
|
||||
list.append(html);
|
||||
});
|
||||
}
|
||||
|
||||
function removeSelectedResource(resourceOid) {
|
||||
$("#relation-item-" + resourceOid).remove();
|
||||
|
||||
var checkbox = $("#" + resourceOid + "-checkbox");
|
||||
|
||||
if (checkbox.length) {
|
||||
checkbox.prop("checked", false);
|
||||
}
|
||||
|
||||
changeResourceSelection();
|
||||
}
|
||||
35
BeWoPlanerMobil/Util/BootstrapTreeViewItem.cs
Normal file
35
BeWoPlanerMobil/Util/BootstrapTreeViewItem.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BeWoPlanerMobil.Util
|
||||
{
|
||||
public class BootstrapTreeViewItem
|
||||
{
|
||||
[JsonProperty("selectable")]
|
||||
public bool Selectable { get; set; }
|
||||
|
||||
[JsonProperty("text")]
|
||||
public string Text { get; set; }
|
||||
|
||||
[JsonProperty("tags")]
|
||||
public List<string> Tags { get; set; }
|
||||
|
||||
[JsonProperty("nodes")]
|
||||
public List<BootstrapTreeViewItem> Nodes { get; set; } = new List<BootstrapTreeViewItem>();
|
||||
|
||||
[JsonIgnore]
|
||||
public long Oid { get; }
|
||||
|
||||
[JsonIgnore]
|
||||
public long? ParentOid { get; set; }
|
||||
|
||||
public BootstrapTreeViewItem(string text, long? parentOid, long oid, bool isParent)
|
||||
{
|
||||
Text = text;
|
||||
Tags = new List<string> { oid.ToString() };
|
||||
ParentOid = parentOid;
|
||||
Oid = oid;
|
||||
Selectable = !isParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
BeWoPlanerMobil/Util/ConvertedDateTimes.cs
Normal file
17
BeWoPlanerMobil/Util/ConvertedDateTimes.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace BeWoPlanerMobil.Util
|
||||
{
|
||||
public class ConvertedDateTimes
|
||||
{
|
||||
public DateTime StartDate { get; set; }
|
||||
|
||||
public DateTime EndDate { get; set; }
|
||||
|
||||
public ConvertedDateTimes(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
StartDate = startDate;
|
||||
EndDate = endDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BeWoPlanerMobil.Util
|
||||
{
|
||||
public class GoalDisplayItem
|
||||
{
|
||||
public bool selectable { get; set; }
|
||||
public string text { get; set; }
|
||||
public List<string> tags { get; set; }
|
||||
public List<GoalDisplayItem> nodes { get; set; } = new List<GoalDisplayItem>();
|
||||
|
||||
[JsonIgnore]
|
||||
public long Oid { get; }
|
||||
|
||||
[JsonIgnore]
|
||||
public long? ParentOid { get; set; }
|
||||
|
||||
public GoalDisplayItem(string text, long? parentOid, long oid, bool isParent)
|
||||
{
|
||||
this.text = text;
|
||||
tags = new List<string> {oid.ToString()};
|
||||
ParentOid = parentOid;
|
||||
Oid = oid;
|
||||
selectable = !isParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -411,5 +412,49 @@ namespace BeWoPlanerMobil.Util
|
||||
|
||||
return new BeWoLoginState(responseState, message.Replace("\\", "\\\\"));
|
||||
}
|
||||
|
||||
public static List<long> ConvertOidStringToList(string oids, char token = ',')
|
||||
{
|
||||
var result = new List<long>();
|
||||
|
||||
if(IsNullOrWhiteSpace(oids))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var oidArray = oids.Trim(token).Split(token);
|
||||
|
||||
oidArray.DoForEach(oidString =>
|
||||
{
|
||||
var isSuccessful = long.TryParse(oidString, out var oid);
|
||||
|
||||
if(isSuccessful)
|
||||
{
|
||||
result.AddIfNotIn(oid);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ConvertedDateTimes ConvertStringDatesToDateTimes(string start, string end)
|
||||
{
|
||||
try
|
||||
{
|
||||
var isSuccessfulStartDate = DateTime.TryParseExact(start, "dd.MM.yyyy HH:mm", null, DateTimeStyles.None, out var startDate);
|
||||
var isSuccessfulEndDate = DateTime.TryParseExact(end, "dd.MM.yyyy HH:mm", null, DateTimeStyles.None, out var endDate);
|
||||
|
||||
if(isSuccessfulStartDate && isSuccessfulEndDate)
|
||||
{
|
||||
return new ConvertedDateTimes(startDate, endDate);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Die Datumsstring dürfen nicht null sein und müssen das Format 'dd.MM.yyyy HH:mm' haben.");
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,11 +52,6 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var test = "@HttpContext.Current.Request.RequestContext.RouteData.Values["blubb"]";
|
||||
console.log("blubb:" + test);
|
||||
});
|
||||
|
||||
$("body").keyup(
|
||||
function(event) {
|
||||
if (event.which === 13) {
|
||||
|
||||
@@ -45,6 +45,14 @@
|
||||
return "@Url.Action("CheckForOverlappingAppointments", "Scheduler")";
|
||||
}
|
||||
|
||||
function getSelectResourcesForAppointmentUrl() {
|
||||
return "@Url.Action("SelectResourcesForAppointment", "Scheduler")";
|
||||
}
|
||||
|
||||
function getCheckResourcesAvailabilityUrl() {
|
||||
return "@Url.Action("CheckResourcesAvailability", "Scheduler")";
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
toggleFormVisibility();
|
||||
|
||||
@@ -59,7 +67,6 @@
|
||||
$(window).resize(function() {
|
||||
toggleFormVisibility();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="container mt-3">
|
||||
@@ -151,6 +158,41 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if(AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#resources-popup">Ressourcen hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group my-1">
|
||||
<div class="list-group" id="selected-resources-list">
|
||||
@foreach(var selectedResource in Model.SelectedResources)
|
||||
{
|
||||
<div class="list-group-item my-auto" id="relation-item-@selectedResource.ResourceOid">
|
||||
<div class="row">
|
||||
<div class="col my-auto">
|
||||
<i class="fas fa-cubes text-bewo-resource mr-2"></i>
|
||||
@selectedResource.Name
|
||||
</div>
|
||||
<div class="col-auto my-auto">
|
||||
<button type="button" class="btn btn-primary" onclick="removeSelectedResource(@selectedResource.ResourceOid)">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-md">
|
||||
<div class="form-group mb-1">
|
||||
@@ -273,4 +315,46 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(AbstractModel.HasRightToInsertRessourceAppointments && Model.ResourceCategories2Resources.Any())
|
||||
{
|
||||
<div class="modal" tabindex="-1" role="dialog" id="resources-popup">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title">Ressourcen</h6>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container-fluid">
|
||||
@foreach(var category2Resources in Model.ResourceCategories2Resources)
|
||||
{
|
||||
<div class="card w-100 mb-3" id="resource-category-@category2Resources.Key.ValueListEntryOid">
|
||||
<div class="card-header">
|
||||
<h5>@category2Resources.Key.DisplayName</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@foreach(var resource in category2Resources.Value)
|
||||
{
|
||||
var checkedValue = Model.SelectedResources.Contains(resource) ? "checked" : string.Empty;
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="@resource.ResourceOid-checkbox" @checkedValue onchange="changeResourceSelection()" />
|
||||
<label class="custom-control-label" for="@resource.ResourceOid-checkbox">@resource.Name</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Übernehmen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -1594,8 +1594,7 @@ namespace BeWo.Data.Access
|
||||
CreateCriteria(Task.PropertyName_EmployeeList, JoinType.InnerJoin)
|
||||
.Add(Restrictions.Eq(BeWoEntityBase.PropertyName_Oid, employeeOid)).List<Task>();
|
||||
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
public Wohnheimbuchung GetWohnheimbuchungByWohnheimAndBuchungsdatum(long pWohnheimOid, DateTime pBuchungsdatum)
|
||||
@@ -3142,5 +3141,61 @@ namespace BeWo.Data.Access
|
||||
|
||||
return c.List<CostBearer2SupportConcept>().ToList();
|
||||
}
|
||||
|
||||
public bool IsResourceAvailable(DateTime start, DateTime end, long resourceOid)
|
||||
{
|
||||
var c = CreateCriteriaIsActive<Resource>();
|
||||
|
||||
var sql = $"SELECT COUNT(*) FROM resource WHERE oid = {resourceOid} AND isactive = 1 AND oid NOT IN (SELECT resourceoid FROM resource2newschapp r WHERE r.newschappoid NOT IN (SELECT oid FROM newschedulerappointment WHERE startdate > '{start:yyyy-MM-dd HH:mm:ss}' OR enddate < '{end:yyyy-MM-dd HH:mm:ss}'));";
|
||||
|
||||
var criterion = Expression.Sql(sql);
|
||||
|
||||
c.Add(criterion);
|
||||
|
||||
return c.List().Count > 0;
|
||||
}
|
||||
|
||||
public List<Resource> GetAvailableResources(DateTime start, DateTime end)
|
||||
{
|
||||
var c = CreateCriteria<Resource>("r").Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), ActivationTypeId.Active));
|
||||
|
||||
/*
|
||||
* var detachedCriteria1 = DetachedCriteria.For<Employee2SchedulerAppointment>()
|
||||
.Add(Restrictions.In(Employee2SchedulerAppointment.PropertyName_Employee + ".Oid", pSelectedEmployees))
|
||||
.SetProjection(Projections.Property(Employee2SchedulerAppointment.PropertyName_SchedulerAppointment));
|
||||
var employee2SchedCrit = Subqueries.PropertyIn(BeWoEntityBase.PropertyName_Oid, detachedCriteria1);
|
||||
*/
|
||||
|
||||
var sql = $"Oid NOT IN (SELECT Oid FROM resource WHERE isactive = 1 AND Oid NOT IN (SELECT resourceoid FROM resource2newschapp r2n WHERE r2n.newschappoid NOT IN (SELECT oid FROM newschedulerappointment WHERE startdate > '{start:yyyy-MM-dd HH:mm:ss}' OR enddate < '{end:yyyy-MM-dd HH:mm:ss}')))";
|
||||
|
||||
var criterion = Expression.Sql(sql);
|
||||
|
||||
c.Add(criterion);
|
||||
|
||||
return c.List<Resource>().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prüft anhand der Oids von Ressourcen deren Verfügbarkeit in einem Zeitraum.
|
||||
/// Gibt die nicht verfügbaren Ressourcen zurück für eine detaillierte Fehlermeldung.
|
||||
/// </summary>
|
||||
/// <param name="resourceOids">Die Oids der zu überprüfenden Ressourcen</param>
|
||||
/// <returns>test</returns>
|
||||
public List<Resource> CheckAvailabilityOfResources(List<long> resourceOids, DateTime start, DateTime end, long? selectedAppointmentOid)
|
||||
{
|
||||
var c = CreateCriteria<Resource>("r").Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), ActivationTypeId.Active)).Add(Restrictions.In(nameof(BeWoEntityBase.Oid), resourceOids));
|
||||
|
||||
var excludingSelectedAppointment = selectedAppointmentOid.HasValue ? $"oid <> {selectedAppointmentOid} AND " : "";
|
||||
|
||||
var sql = "Oid IN " +
|
||||
"(SELECT resourceoid FROM resource2newschapp r2n WHERE r2n.newschappoid IN " +
|
||||
$"(SELECT oid FROM newschedulerappointment WHERE {excludingSelectedAppointment}('{start:yyyy-MM-dd HH:mm:ss}' > startdate OR '{end:yyyy-MM-dd HH:mm:ss}' > startdate) AND ('{start:yyyy-MM-dd HH:mm:ss}' < enddate OR '{end:yyyy-MM-dd HH:mm:ss}' < enddate)))";
|
||||
|
||||
var criterion = Expression.Sql(sql);
|
||||
|
||||
c.Add(criterion);
|
||||
|
||||
return c.List<Resource>().ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,11 @@ namespace BeWo.Service.DCEntityMapper
|
||||
pDataContract.Description = pEntity.Description;
|
||||
pDataContract.Color = pEntity.Color;
|
||||
|
||||
pDataContract.ActivationType = pEntity.IsActive;
|
||||
|
||||
pDataContract.IsSystemEntry = pEntity.SystemEntryID != null;
|
||||
|
||||
ValueListEntry2Object lCategory = pEntity.ValueList.FindSingleByType(ValueListEntryType.ResourceCategory);
|
||||
var lCategory = pEntity.ValueList.FindSingleByType(ValueListEntryType.ResourceCategory);
|
||||
|
||||
if (lCategory != null)
|
||||
{
|
||||
|
||||
@@ -200,5 +200,9 @@ namespace BeWo.Service.ServiceContracts
|
||||
[FaultContract(typeof(BeWoFault))]
|
||||
[OperationContract]
|
||||
void DeleteTestAppointments();
|
||||
|
||||
[FaultContract(typeof(BeWoFault))]
|
||||
[OperationContract]
|
||||
List<ResourceDC> CheckResourceAvailability(DateTime start, DateTime end, List<long> resourceOids, long? selectedAppointmentOid);
|
||||
}
|
||||
}
|
||||
@@ -2243,5 +2243,10 @@ namespace BeWo.Service.ServiceImplementations
|
||||
throw Utils.CreateBeWoFaultException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ResourceDC> CheckResourceAvailability(DateTime start, DateTime end, List<long> resourceOids, long? selectedAppointmentOid)
|
||||
{
|
||||
return MapperFactory.ResourceDC_Resource.MapToNewDCs(DAOFactory.SearchDAO.CheckAvailabilityOfResources(resourceOids, start, end, selectedAppointmentOid));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user