Files
BeWoPlaner/BeWoPlanerMobil/Views/Report/QuittierungsbelegsResultPartial.cshtml
Christian 5ae4e1a813 1. KI Spracherkennung eingebaut
2. MessageBox wird angezeigt, wenn Frist für Unterschriften abgelaufen
2026-04-01 00:53:57 +02:00

505 lines
25 KiB
Plaintext

@using BeWoPlanerMobil.Models
@using BeWoPlanerMobil.Util
@using BeWoPlanerMobil.Util.ReportUtils
@model BeWoPlanerMobil.Models.ReportModel
@{
if(TempData[TempDataConstants.DoLogoutKey] is bool doLogout && doLogout)
{
<text>
<script type="text/javascript">
$("#second-logout-form").submit();
</script>
</text>
}
}
<script type="text/javascript">
$(document).ready(
function() {
$(".collapse").on("shown.bs.collapse", function () {
window.saveCollapsibleState($(this).attr("id"), "@Url.Action("SaveCollapsibleStatus")");
});
$(".collapse").on("hidden.bs.collapse", function () {
window.saveCollapsibleState($(this).attr("id"), "@Url.Action("SaveCollapsibleStatus")");
});
}
);
function deleteCustomerSignatures(cardBodyId, resultIdentifier, customerName, timeSpan) {
cardHeaderButtonClick(cardBodyId);
showMessagePopupWithCallback("Unterschriften löschen", `Sind Sie sicher, die Unterschriften von ${customerName} im Zeitraum ${timeSpan} zu löschen?`, function () {
showSpinner();
$(`#delCSigForm-${resultIdentifier}`).submit();
}, false);
}
function deleteEmployeeSignature(cardBodyId, resultIdentifier, employeeName, customerName, timeSpan) {
cardHeaderButtonClick(cardBodyId);
showMessagePopupWithCallback("Unterschrift löschen", `Sind Sie sicher, die Unterschrift von ${employeeName} für ${customerName} im Zeitraum ${timeSpan} zu löschen?`, function () {
showSpinner();
$(`#delESigForm-${resultIdentifier}`).submit();
}, false);
}
function loadConfirmationReceiptSignatures(cardBodyId, identifier, isEmployee, isOverriding, canSign, customerOid) {
cardHeaderButtonClick(cardBodyId);
$("#report-form-container").hide();
showSpinner();
$("#report-signature-container").empty();
$("#report-signature-container").addClass("d-block");
try {
$("#loading-info-p").text("Lade Unterschriften ...");
$("#report-signature-container").load("@Url.Action("FetchConfirmationReceiptSignatures", "Report")",
{ identifier: identifier, isEmployee: isEmployee },
function () {
hideSpinner();
$("#loading-info-p").text("Lade ...");
if(canSign) {
$("#qb-sig-canvas-row, #qb-sig-canvas-container, #qb-sig-sketch-pad").show();
} else {
$("#qb-sig-canvas-row, #qb-sig-canvas-container, #qb-sig-sketch-pad, #qb-sig-save-btn, #qb-sig-clear-canvas-btn").hide();
}
updateCanvasSize($("#qb-sig-sketch-pad"));
const canvas = document.getElementById("qb-sig-sketch-pad");
var signaturePad = new SignaturePad(canvas, { backgroundColor: "rgba(255, 255, 255, 0)" });
const cancelButton = document.getElementById("qb-sig-cancel-btn");
const saveButton = document.getElementById("qb-sig-save-btn");
const clearButton = document.getElementById("qb-sig-clear-canvas-btn");
cancelButton.addEventListener("click",
function() {
cancelSignature(canSign, signaturePad, "qb-sig-sketch-pad", "report-signature-container", "qb-sig-override-alert");
});
saveButton.addEventListener("click",
function() {
const clonedCanvas = cloneCanvas(document.getElementById("qb-sig-sketch-pad"));
const trimmedCanvas = trimCanvas(clonedCanvas);
const context = trimmedCanvas.getContext("2d", {willReadFrequently: true});
context.globalCompositeOperation = "destination-over";
context.fillStyle = "white";
context.fillRect(0, 0, trimmedCanvas.width, trimmedCanvas.height);
const dataUrl = trimmedCanvas.toDataURL("image/png");
showSpinner();
$.post("@Url.Action("CreateSignatureForServiceOverview")", { base64SignatureString: dataUrl, customerOidString: customerOid, isCustomerSignature: !isEmployee, overwrite: isOverriding }).done(function (json) {
hideSpinner();
if (isEmptyOrSpaces(json)) {
showMessagePopupWithHtmlAndCallback("Unterschrift",
"Die Unterschrift wurde erfolgreich gespeichert.<br/><br/>Verändern Sie jedoch Einträge der Zeiterfassung in dem ausgewählten Zeitraum, muss die Unterschrift erneut geleistet werden.", false,
function () {
showSpinner();
$("#report-signatures-container").load("@Url.Action("LoadServiceOverview")", function() {
try {
hideSpinner();
$("#report-signature-container").removeClass("d-block");
$("#report-signature-container").addClass("d-none");
$("#report-form-container").show();
} catch (error) {
window.showErrorPopup(error);
}
});
},
true);
} else {
window.showMessagePopup("Fehler", json);
signaturePad.clear();
}
});
});
clearButton.addEventListener("click",
function() {
signaturePad.clear();
});
});
} catch (error) {
window.showErrorPopup(error);
}
}
function goToFirstQBListPage() {
showSpinner();
$("#report-signatures-container").load("@Url.Action("GoToFirstServiceOverviewPage")", hideSpinner);
}
function goToLastQBListPage() {
showSpinner();
$("#report-signatures-container").load("@Url.Action("GoToLastServiceOverviewPage")", hideSpinner);
}
function goToQBListPage(selectedPage) {
showSpinner();
$("#report-signatures-container").load("@Url.Action("LoadServiceOverviewPage")", {selectedPage: selectedPage}, hideSpinner);
}
</script>
<div class="mt-3">
<div class="alert alert-primary d-none" role="alert" id="warning-message-container">
</div>
@if(TempData[TempDataConstants.HasWarningMessageKey] != null)
{
<div class="alert alert-primary" role="alert">
Es wurden keine auswertbaren Einträge gefunden
</div>
}
else if(Model?.ConfirmationReceiptObject?.ConfirmationReceiptResultList?.Count > 0)
{
var previousPage = Model.CurrentQbEntryPage - 1 <= 0 ? 1 : Model.CurrentQbEntryPage - 1;
var nextPage = Model.CurrentQbEntryPage + 1 > Model.QbEntryPageCount ? Model.QbEntryPageCount : Model.CurrentQbEntryPage + 1;
var page = 1;
<div class="alert alert-info" role="alert">
@Model.ConfirmationReceiptObject.Information
</div>
<input type="hidden" id="service-record-count" value="@Model.ConfirmationReceiptObject.NumberOfServiceRecords" />
<input type="hidden" id="signature-canvas-information" value="@Model.ConfirmationReceiptObject.SignatureCanvasInformation" />
if(Model.CurrentQbEntryPage > 3 && Model.QbEntryPageCount > 5)
{
page = Model.CurrentQbEntryPage - 2;
if(page > Model.QbEntryPageCount - 4)
{
page = Model.QbEntryPageCount - 4;
}
if(page < 1)
{
page = 1;
}
}
var lastPage = page + 4;
if(lastPage > Model.QbEntryPageCount)
{
lastPage = Model.QbEntryPageCount;
}
var previousButtonsClass = Model.CurrentQbEntryPage == 1 ? "disabled" : string.Empty;
var nextButtonsClass = Model.CurrentQbEntryPage == Model.QbEntryPageCount ? "disabled" : string.Empty;
if(Model.QbEntryPageCount > 1)
{
<nav>
<ul class="pagination justify-content-center">
<li class="page-item @previousButtonsClass">
<button type="button" class="page-link" tab-index="-1" onclick="goToFirstQBListPage()">
<span class="fas fa-angle-double-left"></span>
</button>
</li>
<li class="page-item @previousButtonsClass">
<button type="button" class="page-link" tabindex="-1" onclick="goToQBListPage(@previousPage)">
<span class="fas fa-angle-left"></span>
</button>
</li>
@for(; page <= lastPage; page++)
{
var isActive = Model.CurrentQbEntryPage == page;
var activeClass = isActive ? "active" : string.Empty;
<li class="page-item @activeClass">
@if(isActive)
{
<span class="page-link" onclick="goToQBListPage(@page)">
@page
<span class="sr-only">(current)</span>
</span>
}
else
{
<button type="button" class="page-link" onclick="goToQBListPage(@page)">@page</button>
}
</li>
}
<li class="page-item @nextButtonsClass">
<button type="button" class="page-link" tabindex="-1" onclick="goToQBListPage(@nextPage)">
<span class="fas fa-angle-right"></span>
</button>
</li>
<li class="page-item @nextButtonsClass">
<button type="button" class="page-link" tabindex="-1" onclick="goToLastQBListPage()">
<span class="fas fa-angle-double-right"></span>
</button>
</li>
</ul>
</nav>
}
foreach(var result in Model.ConfirmationReceiptObject.ConfirmationReceiptResultList)
{
<div class="card w-100 mb-3">
<div class="card-header" onclick="cardHeaderClick2(this)">
@{
var employeeSignatureState = result.EmployeeSignatureState;
var customerSignatureState = result.CustomerSignatureState;
var canCustomerSign = customerSignatureState != SignatureState.All;
var canEmployeeSign = employeeSignatureState != SignatureState.All && employeeSignatureState != SignatureState.AllOwnServiceRecords; // || (employeeSignatureState != SignatureState.AllOwnServiceRecords);
var employeeName = Model.LoggedInEmployee.ToString();
var overwrite_ssp = (employeeSignatureState == SignatureState.All).ToString().ToLower();
var cardBodyId_ssp = $"#collapse-result-{result.Identifier}";
var timeSpan_ssp = Model.ConfirmationReceiptObject.TimeSpanString;
var hasNoOwnEntries = !Model.HasRightToProvideEmployeeSignatureForOthers && result.Items.All(item => !item.EmployeeOid.Equals(Model.LoggedInEmployee.EmployeeOid));
var disabledString = hasNoOwnEntries ? "disabled" : string.Empty;
var fristAbgelaufen = result.FristAbgelaufen ? "true" : "false";
}
<div class="row">
<div class="col-sm-auto mr-auto">
<div class="input-group">
<div class="input-group-prepend">
<i class="fas fa-chevron-down text-primary h-100" id="chevron-@result.Identifier"></i>
</div>
<p class="form-control text-primary border-0 bg-transparent" style="user-select: none !important;">
@result.CustomerName
</p>
</div>
</div>
<div class="col-sm-auto">
@using(Html.BeginForm("DeleteCustomerSignature", "Report", FormMethod.Post, new { id = "delCSigForm-" + result.Identifier }))
{
<input type="hidden" name="deleteCustomerSignaturesInfo" value="@result.Identifier" />
}
@using(Html.BeginForm("DeleteEmployeeSignature", "Report", FormMethod.Post, new { id = "delESigForm-" + result.Identifier }))
{
<input type="hidden" name="deleteEmployeeSignatureInfo" value="@result.Identifier" />
}
<div class="btn-toolbar">
<!-- w-auto -->
<div class="btn-group pr-1" role="group" style="width: 150px !important;">
@if(Model.HasRightToDeleteReceiptSignatures && result.CustomerSignatureOids.Any())
{
<button class="btn btn-danger mx-0" type="button" onclick="deleteCustomerSignatures('#collapse-result-@result.Identifier', '@result.Identifier', '@result.CustomerName', '@timeSpan_ssp')">
<span class="fas fa-trash"></span>
</button>
}
<button class="btn btn-bewo-customers" type="button" onclick="if(@fristAbgelaufen){showAlertMessageBoxWithoutCallback('Unterschreiben nicht möglich.', 'Die Frist, in der neue Einträge unterschrieben werden müssen, ist leider abgelaufen.');}else{loadConfirmationReceiptSignatures('@cardBodyId_ssp', '@result.Identifier', false, @result.HasCustomerSignature.ToString().ToLower(), @canCustomerSign.ToString().ToLower(), @result.CustomerOid);}">
<span class="fas fa-signature mr-0 pr-0"></span>
@if(customerSignatureState != SignatureState.All)
{
<span class="fa-stack align-middle mx-0 px-0" style="height: auto !important">
<i class="fas fa-check fa-stack-1x mx-0 px-0"></i>
<i class="fas fa-slash fa-stack-1x mx-0 px-0" style="color: tomato;"></i>
</span>
}
else
{
<span class="fas fa-check-double" style="color: yellowgreen !important"></span>
}
K
</button>
</div>
<!-- w-auto -->
<div class="btn-group" role="group" style="width: 150px !important;">
@if(Model.HasRightToDeleteReceiptSignatures && result.EmployeeSignatureOids.Any())
{
<button class="btn btn-danger mx-0" type="button" onclick="deleteEmployeeSignature('#collapse-result-@result.Identifier', '@result.Identifier', '@employeeName', '@result.CustomerName', '@timeSpan_ssp')">
<span class="fas fa-trash"></span>
</button>
}
<button class="btn btn-bewo-employee" @disabledString type="button" onclick="loadConfirmationReceiptSignatures('@cardBodyId_ssp', '@result.Identifier', true, @overwrite_ssp, @canEmployeeSign.ToString().ToLower(), @result.CustomerOid)">
<span class="fas fa-signature mr-0 pr-0"></span>
@if(employeeSignatureState == SignatureState.Some || employeeSignatureState == SignatureState.None)
{
<span class="fa-stack align-middle mx-0 px-0" style="height: auto !important">
<i class="fas fa-check fa-stack-1x mx-0 px-0"></i>
<i class="fas fa-slash fa-stack-1x mx-0 px-0" style="color: tomato;"></i>
</span>
}
else if(employeeSignatureState == SignatureState.AllOwnServiceRecords && !Model.HasRightToProvideEmployeeSignatureForOthers)
{
<span class="fas fa-ban" style="color: tomato;"></span>
}
else
{
<span class="fas fa-check-double" style="color: yellowgreen !important"></span>
}
M
</button>
</div>
</div>
</div>
</div>
</div>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, $"collapse-result-{result.Identifier}")" id="collapse-result-@result.Identifier">
<div class="card-body mx-0 px-0 pb-0">
<div class="container-fluid">
@foreach(var item in result.Items)
{
var isNotOwnEntry = !Model.HasRightToProvideEmployeeSignatureForOthers && !item.EmployeeOid.Equals(Model.LoggedInEmployee.EmployeeOid);
var headerTextColorClass = isNotOwnEntry ? "text-secondary" : "text-primary";
<div class="card w-100 mb-3">
<div class="card-header" onclick="cardHeaderClick('#chevron-@item.Identifier', '#collapse-item-@item.Identifier')">
<div class="d-inline-flex">
<i class="fas fa-chevron-down h-100 @headerTextColorClass" id="chevron-@item.Identifier"></i>
</div>
<div class="p2 d-inline-flex @headerTextColorClass h-100">
<button type="button" class="btn btn-link @headerTextColorClass">
@item.DateTimeString
</button>
@if(isNotOwnEntry)
{
<span class="fa-stack fa-1x text-secondary mt-1">
<i class="fas fa-signature fa-stack-1x"></i>
<i class="fas fa-ban fa-stack-2x"></i>
</span>
}
</div>
@{
var hasEmployeeSignatureTextColorClass = item.HasEmployeeSignature ? "text-bewo-employee" : "text-light";
}
<span class="fas fa-check h-100 @hasEmployeeSignatureTextColorClass float-right pt-2"></span>
<span class="float-right pt-2 text-light">m</span>
@if(item.HasCustomerSignature)
{
<span class="fas fa-check h-100 text-bewo-customers float-right pt-2"></span>
}
</div>
<div class="collapse @Html.GetCollapsibleClass(Model.Collapsibles2IsShown, $"collapse-item-{item.Identifier}")" id="collapse-item-@item.Identifier">
<div class="card-body">
<div class="container-fluid">
<div class="row">
<div class="col text-secondary">
Kontaktart:
</div>
<div class="col">
@item.Kontaktart
</div>
</div>
<div class="row">
<div class="col text-secondary">
Anzahl Klienten:
</div>
<div class="col">
@item.CustomersCount
</div>
</div>
<div class="row">
<div class="col text-secondary">
FLS in Minuten (ohne 1,2):
</div>
<div class="col">
@item.Minutes
</div>
</div>
<div class="row">
<div class="col text-secondary">
Mitarbeiter:
</div>
<div class="col">
@item.Employees
</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
</div>
}
page = Model.CurrentQbEntryPage - 2;
if(page > Model.QbEntryPageCount - 4)
{
page = Model.QbEntryPageCount - 4;
}
if(page < 1)
{
page = 1;
}
lastPage = page + 4;
if(lastPage > Model.QbEntryPageCount)
{
lastPage = Model.QbEntryPageCount;
}
if(Model.QbEntryPageCount > 1)
{
<nav>
<ul class="pagination justify-content-center">
<li class="page-item @previousButtonsClass">
<button type="button" class="page-link" tab-index="-1" onclick="goToFirstQBListPage()">
<span class="fas fa-angle-double-left"></span>
</button>
</li>
<li class="page-item @previousButtonsClass">
<button type="button" class="page-link" tabindex="-1" onclick="goToQBListPage(@previousPage)">
<span class="fas fa-angle-left"></span>
</button>
</li>
@for(; page <= lastPage; page++)
{
var isActive = Model.CurrentQbEntryPage == page;
var activeClass = isActive ? "active" : string.Empty;
<li class="page-item @activeClass">
@if(isActive)
{
<span class="page-link" onclick="goToQBListPage(@page)">
@page
<span class="sr-only">(current)</span>
</span>
}
else
{
<button type="button" class="page-link" onclick="goToQBListPage(@page)">@page</button>
}
</li>
}
<li class="page-item @nextButtonsClass">
<button type="button" class="page-link" tabindex="-1" onclick="goToQBListPage(@nextPage)">
<span class="fas fa-angle-right"></span>
</button>
</li>
<li class="page-item @nextButtonsClass">
<button type="button" class="page-link" tabindex="-1" onclick="goToLastQBListPage()">
<span class="fas fa-angle-double-right"></span>
</button>
</li>
</ul>
</nav>
}
}
</div>