+ Klientenfilter im Kalender-Modul: Rechte verfeinert
+ Auswertungsmodul angefangen. Nur im Debug-Modus sichtbar.

FaC:
+ In die Zeiterfassung übertragene Termine kriegen Icon auch, wenn nur der veraltete Flag "HasSerivceRecordEntry" auf true steht.
This commit is contained in:
2023-03-16 13:57:04 +01:00
parent 9d3daf7df7
commit d82e1ed290
16 changed files with 430 additions and 23 deletions

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using BeWo.Scheduler.ViewModel;
using BS.Shared.DataContracts;
namespace BeWo.Scheduler.Converter
@@ -12,9 +13,9 @@ namespace BeWo.Scheduler.Converter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is List<ServiceRecordDC> serviceRecordList)
if(value is CustomFieldStorage customFieldStorage)
{
return serviceRecordList.Any() ? Visibility.Visible : Visibility.Collapsed;
return customFieldStorage.ServiceRecordList.Any() || customFieldStorage.HasServiceRecordEntry ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;

View File

@@ -149,7 +149,7 @@
<dxschint:AppointmentImagesControl Grid.Column="1" Margin="0,0,4,0" ViewInfo="{Binding}" Orientation="Vertical" SnapsToDevicePixels="True" />
<!-- ToDo: Neuen Converter schreiben, der prüft, ob in der Liste ServiceRecords sind -->
<Image Grid.Row="0" Grid.Column="2" Margin="-4,-2,6,0"
Visibility="{Binding Path=CustomViewInfo[CustomFieldStorage].ServiceRecordList, Converter={StaticResource AptToServRecsIconVisibilityConverter}}" Source="/BeWoPlaner;component/Ressources/Icons/HistoryDisabled.png"
Visibility="{Binding Path=CustomViewInfo[CustomFieldStorage], Converter={StaticResource AptToServRecsIconVisibilityConverter}}" Source="/BeWoPlaner;component/Ressources/Icons/HistoryDisabled.png"
SnapsToDevicePixels="True" Height="20" Width="20" VerticalAlignment="Top" />
</Grid>
</DataTemplate>
@@ -279,7 +279,7 @@
<dxschint:AppointmentImagesControl Grid.Row="0" Grid.Column="4" Margin="0,4,10,0" ViewInfo="{Binding}"
Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right" />
<Image Grid.Row="0" Grid.Column="5" Margin="0,4,10,0"
Visibility="{Binding Path=CustomViewInfo[CustomFieldStorage].ServiceRecordList, Converter={StaticResource AptToServRecsIconVisibilityConverter}}"
Visibility="{Binding Path=CustomViewInfo[CustomFieldStorage], Converter={StaticResource AptToServRecsIconVisibilityConverter}}"
Source="/BeWoPlaner;component/Ressources/Icons/HistoryDisabled.png" SnapsToDevicePixels="True" Height="20" Width="20" VerticalAlignment="Top" />
</Grid>
</dxschint:HorizontalAppointmentContentPanel>
@@ -307,7 +307,7 @@
<dxschint:AppointmentContinueEndDateControl ViewInfo="{Binding}" Margin="0, 4, 12, 2" Foreground="{Binding Path=CustomViewInfo[CustomFieldStorage].ForegroundColor}" VerticalAlignment="Center" />
</StackPanel>
<Image Grid.Column="3" Grid.Row="0" Margin="0,0,4,0"
Visibility="{Binding Path=CustomViewInfo[CustomFieldStorage].ServiceRecordList, Converter={StaticResource AptToServRecsIconVisibilityConverter}}"
Visibility="{Binding Path=CustomViewInfo[CustomFieldStorage], Converter={StaticResource AptToServRecsIconVisibilityConverter}}"
Source="/BeWoPlaner;component/Ressources/Icons/HistoryDisabled.png" SnapsToDevicePixels="True" Height="17" Width="17" VerticalAlignment="Center" />
</Grid>
</DataTemplate>

View File

@@ -2376,7 +2376,7 @@ namespace BeWo.View
{
if(value is SchedulerAppointmentDC appointment)
{
return appointment.ServiceRecordList.Any() ? Visibility.Visible : Visibility.Collapsed;
return appointment.HasServiceRecordEntry || appointment.ServiceRecordList.Any() ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;

View File

@@ -198,11 +198,13 @@
<Compile Include="Controllers\CustomerController.cs" />
<Compile Include="Controllers\DevExpressSchedulerController.cs" />
<Compile Include="Controllers\ReportController.cs" />
<Compile Include="Controllers\ReportViewerController.cs" />
<Compile Include="Controllers\SchedulerController.cs" />
<Compile Include="Models\AbstractModel.cs" />
<Compile Include="Models\CustomerModel.cs" />
<Compile Include="Models\DevExpressSchedulerModel.cs" />
<Compile Include="Models\ReportModel.cs" />
<Compile Include="Models\ReportViewerModel.cs" />
<Compile Include="Models\SchedulerModel.cs" />
<Compile Include="Util\AppointmentListItem.cs" />
<Compile Include="Util\BeWoLoginState.cs" />
@@ -25467,6 +25469,8 @@
<Content Include="Views\Scheduler\CustomerFilteringModalContentPartial.cshtml" />
<Content Include="Views\Main\MultiBookingPartial.cshtml" />
<Content Include="Views\Report\QuittierungsbelegsResultPartial.cshtml" />
<Content Include="Views\ReportViewer\ReportViewer.cshtml" />
<Content Include="Views\ReportViewer\DocumentWebViewerPartial.cshtml" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />

View File

@@ -15,7 +15,7 @@
<Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
<WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
<WebStackScaffolding_IsLayoutPageSelected>False</WebStackScaffolding_IsLayoutPageSelected>
<WebStackScaffolding_IsPartialViewSelected>False</WebStackScaffolding_IsPartialViewSelected>
<WebStackScaffolding_IsPartialViewSelected>True</WebStackScaffolding_IsPartialViewSelected>
<WebStackScaffolding_IsReferencingScriptLibrariesSelected>False</WebStackScaffolding_IsReferencingScriptLibrariesSelected>
<WebStackScaffolding_LayoutPageFile>
</WebStackScaffolding_LayoutPageFile>

View File

@@ -22,6 +22,7 @@ namespace BeWoPlanerMobil.Controllers
protected readonly IUserService UserService = new MobileSessionFacade().UserService;
protected readonly IDownloadService DownloadService = new MobileSessionFacade().DownloadService;
protected readonly IReportService ReportService = new MobileSessionFacade().ReportService;
protected readonly IQueryService QueryService = new MobileSessionFacade().QueryService;
protected const string LeerzeichenFuerGetMethoden = " ";

View File

@@ -24,7 +24,6 @@ using BS.Shared.Services;
using DevExpress.XtraScheduler;
using DevExpress.XtraScheduler.Compatibility;
using Newtonsoft.Json;
using NHibernate.Criterion;
using static BS.Shared.ServiceRecordValidationResult;
using FormCollection = System.Web.Mvc.FormCollection;
using ServiceRecordDC = BS.Shared.DataContracts.ServiceRecordDC;
@@ -2490,6 +2489,12 @@ namespace BeWoPlanerMobil.Controllers
return AbstractModel.IsAllowedToSeeBills ? RedirectToActionPermanent("InitReports", "Report") : RedirectToMain();
}
[Authorize]
public ActionResult RedirectToReportViewer()
{
return RedirectToActionPermanent("ReportViewer", "ReportViewer");
}
public ActionResult RedirectToMain()
{
return RedirectToActionPermanent("Main", "Main");

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using BeWoPlanerMobil.Models;
using BeWoPlanerMobil.Service;
using BeWoPlanerMobil.Util;
using BS.Shared;
namespace BeWoPlanerMobil.Controllers
{
public class ReportViewerController : AbstractBaseController
{
private ReportViewerModel _Model;
public ReportViewerModel Model
{
get
{
if(!MobileSessionFacade.IsUserLoggedIn())
{
RedirectToActionPermanent("Index", "Login");
return null;
}
if(((ReportViewerModel)Session[ModelSessionConstants.ReportViewerModelKey])?.Employee is null)
{
_Model = new ReportViewerModel { Employee = MobileSessionFacade.LoggedInEmployee };
Session[ModelSessionConstants.ReportViewerModelKey] = _Model;
}
else
{
_Model = (ReportViewerModel)Session[ModelSessionConstants.ReportViewerModelKey];
}
return _Model;
}
}
public ActionResult ReportViewer()
{
var month = DateTime.Today.Month;
var year = DateTime.Today.Year;
var first = new DateTime(year, month, 1).AddMonths(-1);
Model.SelectedYear = Model.SelectedYear ?? first.Year;
Model.SelectedMonth = Model.SelectedMonth ?? first.Month;
Model.AllEmployees = EmployeeService.GetActiveCompactEmployeesForEmployee(MobileSessionFacade.LoggedInCompactEmployee.EmployeeOid);
Model.AllTeams = EmployeeService.GetAllActiveCompactTeamsForEmployee(MobileSessionFacade.LoggedInEmployee.EmployeeOid);
Model.ReportTypes = new List<SelectListItem>
{
new SelectListItem
{
Text = "Berichte",
Value = "0"
},
new SelectListItem
{
Text = "Mitarbeiterstundenkonto",
Value = "1"
}
};
Model.SelectedReportType = ReportType.Berichte;
Model.Queries = QueryService.GetAllQueriesOfType(QueryType.Public);
return View(Model);
}
[Authorize]
public ActionResult DocumentViewerPartial()
{
return PartialView("DocumentWebViewerPartial", Model);
}
[Authorize]
public ActionResult ExportDocumentViewer()
{
throw new NotImplementedException("Service dafür implementieren!");
}
}
}

View File

@@ -20,7 +20,7 @@ namespace BeWoPlanerMobil.Models
public static bool HasRightForGroupBookings => CheckRight(UserRightType.ServiceRecord_AllowCreatingGroupBooking);
public static bool HasRightToViewCustomerAppointments => CheckRight(UserRightType.KalenderKliententermineAlleAnsehen) && CheckRight(UserRightType.CustomerView_View) || CheckRight(UserRightType.ViewAll);
public static bool HasRightToViewCustomerAppointments => CheckRight(UserRightType.KalenderKliententermineAlleAnsehen) || CheckRight(UserRightType.CustomerView_View) || CheckRight(UserRightType.Customer_ViewMyCustomers) || CheckRight(UserRightType.Customer_ViewMyTeams);
public static bool HasRightToViewEmployeeAppointments => CheckRight(UserRightType.KalenderMitarbeitertermineAnsehen) || CheckRight(UserRightType.ViewAll);
public static bool HasRightToViewAllResourceAppointments => CheckRight(UserRightType.KalenderRessourcentermineAnsehen) || CheckRight(UserRightType.ViewAll);

View File

@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using DevExpress.XtraReports.UI;
namespace BeWoPlanerMobil.Models
{
public class ReportViewerModel : AbstractModel
{
public List<CompactEmployeeDC> AllEmployees { get; set; }
public List<CompactTeamDC> AllTeams { get; set; }
public List<QueryDC> Queries { get; set; }
[Display(Name = "Monat")]
public int? SelectedMonth { get; set; }
public List<SelectListItem> Months
{
get
{
var result = new List<SelectListItem>();
for(var i = 1; i < 13; i++)
{
result.Add(new SelectListItem
{
Value = i.ToString(),
Text = new DateTime(DateTime.Now.Year, i, 1).ToString("MMMM")
});
}
return result;
}
}
[Display(Name = "Jahr")]
public int? SelectedYear { get; set; }
public List<SelectListItem> Years
{
get
{
var result = new List<SelectListItem>();
for(var i = DateTime.Today.Year; i > DateTime.Today.Year - 11; i--)
{
result.Add(new SelectListItem
{
Value = i.ToString(),
Text = i.ToString()
});
}
return result;
}
}
[Display(Name="Bericht")]
public ReportType SelectedReportType { get; set; }
public List<SelectListItem> ReportTypes { get; set; }
[Display(Name = "Bericht")]
public long? SelectedCustomReport { get; set; }
public List<SelectListItem> CustomReports
{
get
{
var result = new List<SelectListItem>();
if(Queries is null)
{
return result;
}
foreach(var query in Queries)
{
result.Add(new SelectListItem { Text = query.Title, Value = query.Oid.ToString() });
}
return result;
}
}
[Display(Name="Mitarbeiter")]
public long? SelectedEmployeeOid { get; set; }
public List<SelectListItem> Employees
{
get
{
var result = new List<SelectListItem>();
if(AllEmployees is null)
{
return result;
}
foreach(var employee in AllEmployees)
{
result.Add(new SelectListItem { Text = employee.SimpleDescription, Value = employee.EmployeeOid.ToString() });
}
return result;
}
}
[Display(Name = "Team")]
public long? SelectedTeamOid { get; set; }
public List<SelectListItem> Teams
{
get
{
var result = new List<SelectListItem>();
if(AllTeams is null)
{
return result;
}
foreach(var team in AllTeams)
{
result.Add(new SelectListItem { Text = team.Name, Value = team.TeamOid.ToString() });
}
return result;
}
}
public XtraReport Report { get; set; }
}
public enum ReportType
{
Berichte = 0,
Mitarbeiterstundenkonto = 1
}
}

View File

@@ -29,6 +29,7 @@ namespace BeWoPlanerMobil.Service
UserService = new UserServiceImp();
DownloadService = new DownloadServiceImp();
ReportService = new ReportServiceImp();
QueryService = new QueryServiceImp();
}
public ICustomerService CustomerService { get; }
@@ -40,6 +41,7 @@ namespace BeWoPlanerMobil.Service
public IUserService UserService { get; }
public IDownloadService DownloadService { get; }
public IReportService ReportService { get; }
public IQueryService QueryService { get; }
public static ApplicationUser LoggedInUser
{

View File

@@ -0,0 +1,12 @@
@model BeWoPlanerMobil.Models.ReportViewerModel
@Html.DevExpress().DocumentViewer(settings =>{
// The following settings are required for a Document Viewer.
settings.Name = "documentViewer1";
settings.Report = Model.Report;
// Callback and export route values specify corresponding controllers and their actions.
// These settings are also required.
settings.CallbackRouteValues = new { Controller="ReportViewer", Action="DocumentWebViewerPartial" };
settings.ExportRouteValues = new { Controller="ReportViewer", Action="ExportDocumentWebViewer" };
}).GetHtml()

View File

@@ -0,0 +1,131 @@
@using BeWoPlanerMobil.Models
@model BeWoPlanerMobil.Models.ReportViewerModel
<!--
ToDo: Select für die Berichtsauswahl
Berichte
Mitarbeiterstundenkonto
-->
<script>
$(window).ready(function () {
var isEmployeeFormSelected = $("#filterForEmployeesRadio").prop("checked");
$("#employee-form").show();
$("#team-form").hide();
});
function changeReportElements() {
try {
var selectedCustomReportOid = $("#customReportSelect :selected").val();
} catch(error) {
showErrorPopup(error);
}
}
function reportFilterOnChange() {
try {
//team oder mitarbeiter
} catch (error) {
showErrorPopup(error);
}
}
function allEmployeesCbOnClick() {
try {
} catch (error) {
showErrorPopup(error);
}
}
function allTeamsCbOnClick() {
try {
} catch (error) {
showErrorPopup(error);
}
}
</script>
<div class="container-fluid my-3">
<div class="row">
<div class="col-sm-12 col-md-4 col-lg-3 col-xl-2">
<div class="row">
<div class="col">
@Html.DropDownListFor(model => model.SelectedReportType, Model.ReportTypes, new { @class = "custom-select" })
<hr />
</div>
</div>
<div class="row">
<div class="col">
@if(Model.SelectedReportType == ReportType.Berichte)
{
@Html.DropDownListFor(model => model.SelectedCustomReport, Model.CustomReports, new { @class = "custom-select", id = "customReportSelect" });
}
@if(Model.SelectedReportType == ReportType.Mitarbeiterstundenkonto)
{
<!--
ToDo: Formular anzeigen
RadioBoxes Nach Mitarbeiter auswählen / Nach Team auswerten
CheckBox Alle Mitarbeiter
DropDownListFor Mitarbeiter
-->
<div id="report-form-container">
<div class="form-row">
<div class="col">
<div class="form-check">
<div class="form-check">
<input class="form-check-input" type="radio" name="filterRadio" id="filterForEmployeesRadio" onchange="reportFilterOnChange()" checked />
<label for="filterForEmployeesRadio">Nach Mitarbeiter filtern</label>
</div>
</div>
<div class="form-check">
<div class="form-check">
<input class="form-check-input" type="radio" name="filterRadio" id="filterForTeamsRadio" onchange="reportFilterOnChange()" />
<label for="filterForTeamsRadio">Nach Teams filtern</label>
</div>
</div>
</div>
</div>
<div id="employee-form">
<div class="form-row">
<div class="col">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="all-employees-cb"/>
<label class="form-check-label" for="all-employees-cb" onclick="allEmployeesCbOnClick()">Alle Mitarbeiter</label>
</div>
</div>
</div>
</div>
<div id="team-form">
<div class="form-row">
<div class="col">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="all-teams-cb"/>
<label class="form-check-label" for="all-teams-cb" onclick="allTeamsCbOnClick()">Alle Teams</label>
</div>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
<div class="col-sm-12 col-md-8 col-lg-9 col-xl-10">
@if(!(Model.Report is null))
{
@Html.Partial("DocumentWebViewerPartial", Model);
}
</div>
</div>
</div>

View File

@@ -95,7 +95,7 @@
}
</script>
@if(AbstractModel.HasRightToViewCustomerAppointments && Model.AllCustomers.Any())
@if(AbstractModel.HasRightToViewCustomerSelectionInScheduler && Model.AllCustomers.Any())
{
<div class="modal" tabindex="-1" role="dialog" id="customers-popup2">
<div class="modal-dialog modal-dialog-scrollable" role="document">

View File

@@ -1,5 +1,6 @@
@using BeWoPlanerMobil.Controllers
@using BeWoPlanerMobil.Models
@using BeWoPlanerMobil.Util
<!DOCTYPE html>
<html>
<head>
@@ -278,17 +279,17 @@
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
@*@if(Html.IsInDebugMode())
{
using(Html.BeginForm("RedirectToDevExpressScheduler", "Main", FormMethod.Post))
{
<li class="nav-item">
<button class="btn btn-link text-light no-underline" onclick="showSpinner()">
<i class="fas fa-hand-middle-finger"></i>
Scheduler
</button>
</li>
}
}*@
{
using(Html.BeginForm("RedirectToDevExpressScheduler", "Main", FormMethod.Post))
{
<li class="nav-item">
<button class="btn btn-link text-light no-underline" onclick="showSpinner()">
<i class="fas fa-hand-middle-finger"></i>
Scheduler
</button>
</li>
}
}*@
@if(AbstractModel.IsAllowedToSeeCustomers)
{
@@ -332,7 +333,7 @@
{
<li class="nav-item">
<button class="btn btn-link text-light no-underline" onclick="showSpinner()">
<i class="fas fa-file-invoice text-bewo-report">
<i class="fas fa-chart-bar text-bewo-report">
</i>
Quittierungsbelege
@@ -341,6 +342,21 @@
}
}
@if(Html.IsInDebugMode())
{
using(Html.BeginForm("RedirectToReportViewer", "Main", FormMethod.Post))
{
<li class="nav-item">
<button class="btn btn-link text-light no-underline" onclick="showSpinner()">
<i class="fas fa-chart-bar text-bewo-report">
</i>
Auswertungen
</button>
</li>
}
}
<li class="nav-item">
<button class="btn btn-link text-light no-underline" onclick="showAboutPopup()">
<i class="fas fa-balance-scale text-primary"></i>

View File

@@ -48,6 +48,7 @@ namespace BeWo.Service.ServiceImplementations
}
catch (Exception e)
{
// ToDo: 14.03.2023 Fehler in MySql-Syntax von Berichten in Tabelle query!
throw Utils.CreateBeWoFaultException(e);
}
}
@@ -88,7 +89,7 @@ namespace BeWo.Service.ServiceImplementations
}
}
// Hack: We don´t use the ReportTypes in Webservice Calls,
// Hack: We don't use the ReportTypes in Webservice Calls,
// but the Client needs to know them for Calling ASP Sites
public void ReportTypes(ReportTypes pType)
{